2 * --- T2-COPYRIGHT-NOTE-BEGIN ---
3 * This copyright note is auto-generated by ./scripts/Create-CopyPatch.
5 * T2 SDE: misc/confdialog/textbox.c
6 * Copyright (C) 2004 - 2005 The T2 SDE Project
7 * Copyright (C) 1998 - 2003 ROCK Linux Project
9 * More information can be found in the files COPYING and README.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License. A copy of the
14 * GNU General Public License can be found in the file COPYING.
15 * --- T2-COPYRIGHT-NOTE-END ---
18 * textbox.c -- implements the text box
20 * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
21 * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
22 * MODIFIED FOR ROCK LINUX CONFIG BY: Clifford Wolf (clifford@clifford.at)
24 * This program is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU General Public License
26 * as published by the Free Software Foundation; either version 2
27 * of the License, or (at your option) any later version.
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
34 * You should have received a copy of the GNU General Public License
35 * along with this program; if not, write to the Free Software
36 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
41 static void back_lines (int n
);
42 static void print_page (WINDOW
* win
, int height
, int width
);
43 static void print_line (WINDOW
* win
, int row
, int width
);
44 static char *get_line (void);
45 static void print_position (WINDOW
* win
, int height
, int width
);
47 static int hscroll
= 0, fd
, file_size
, bytes_read
;
48 static int begin_reached
= 1, end_reached
= 0, page_length
;
49 static char *buf
, *page
;
52 * Display text from a file in a dialog box.
55 dialog_textbox (const char *title
, const char *file
, int height
, int width
)
57 int i
, x
, y
, cur_x
, cur_y
, fpos
, key
= 0;
59 char search_term
[MAX_LEN
+ 1];
60 WINDOW
*dialog
, *text
;
62 search_term
[0] = '\0'; /* no search term entered yet */
64 /* Open input file for reading */
65 if ((fd
= open (file
, O_RDONLY
)) == -1) {
68 "\nCan't open input file in dialog_textbox().\n");
71 /* Get file size. Actually, 'file_size' is the real file size - 1,
72 since it's only the last byte offset from the beginning */
73 if ((file_size
= lseek (fd
, 0, SEEK_END
)) == -1) {
75 fprintf (stderr
, "\nError getting file size in dialog_textbox().\n");
78 /* Restore file pointer to beginning of file after getting file size */
79 if (lseek (fd
, 0, SEEK_SET
) == -1) {
81 fprintf (stderr
, "\nError moving file pointer in dialog_textbox().\n");
84 /* Allocate space for read buffer */
85 if ((buf
= malloc (BUF_SIZE
+ 1)) == NULL
) {
87 fprintf (stderr
, "\nCan't allocate memory in dialog_textbox().\n");
90 if ((bytes_read
= read (fd
, buf
, BUF_SIZE
)) == -1) {
92 fprintf (stderr
, "\nError reading file in dialog_textbox().\n");
95 buf
[bytes_read
] = '\0'; /* mark end of valid data */
96 page
= buf
; /* page is pointer to start of page to be displayed */
98 /* center dialog box on screen */
99 x
= (COLS
- width
) / 2;
100 y
= (LINES
- height
) / 2;
103 draw_shadow (stdscr
, y
, x
, height
, width
);
105 dialog
= newwin (height
, width
, y
, x
);
106 keypad (dialog
, TRUE
);
108 /* Create window for text region, used for scrolling text */
109 text
= subwin (dialog
, height
- 4, width
- 2, y
+ 1, x
+ 1);
110 wattrset (text
, dialog_attr
);
111 wbkgdset (text
, dialog_attr
& A_COLOR
);
115 /* register the new window, along with its borders */
116 draw_box (dialog
, 0, 0, height
, width
, dialog_attr
, border_attr
);
118 wattrset (dialog
, border_attr
);
119 mvwaddch (dialog
, height
-3, 0, ACS_LTEE
);
120 for (i
= 0; i
< width
- 2; i
++)
121 waddch (dialog
, ACS_HLINE
);
122 wattrset (dialog
, dialog_attr
);
123 wbkgdset (dialog
, dialog_attr
& A_COLOR
);
124 waddch (dialog
, ACS_RTEE
);
126 if (title
!= NULL
&& strlen(title
) >= width
-2 ) {
127 /* truncate long title -- mec */
128 char * title2
= malloc(width
-2+1);
129 memcpy( title2
, title
, width
-2 );
130 title2
[width
-2] = '\0';
135 wattrset (dialog
, title_attr
);
136 mvwaddch (dialog
, 0, (width
- strlen(title
))/2 - 1, ' ');
137 waddstr (dialog
, (char *)title
);
138 waddch (dialog
, ' ');
140 print_button (dialog
, " Exit ", height
- 2, width
/ 2 - 4, TRUE
);
141 wnoutrefresh (dialog
);
142 getyx (dialog
, cur_y
, cur_x
); /* Save cursor position */
144 /* Print first page of text */
145 attr_clear (text
, height
- 4, width
- 2, dialog_attr
);
146 print_page (text
, height
- 4, width
- 2);
147 print_position (dialog
, height
, width
);
148 wmove (dialog
, cur_y
, cur_x
); /* Restore cursor position */
151 while ((key
!= ESC
) && (key
!= '\n')) {
152 key
= wgetch (dialog
);
162 case 'g': /* First page */
164 if (!begin_reached
) {
166 /* First page not in buffer? */
167 if ((fpos
= lseek (fd
, 0, SEEK_CUR
)) == -1) {
170 "\nError moving file pointer in dialog_textbox().\n");
173 if (fpos
> bytes_read
) { /* Yes, we have to read it in */
174 if (lseek (fd
, 0, SEEK_SET
) == -1) {
176 fprintf (stderr
, "\nError moving file pointer in "
177 "dialog_textbox().\n");
180 if ((bytes_read
= read (fd
, buf
, BUF_SIZE
)) == -1) {
183 "\nError reading file in dialog_textbox().\n");
186 buf
[bytes_read
] = '\0';
189 print_page (text
, height
- 4, width
- 2);
190 print_position (dialog
, height
, width
);
191 wmove (dialog
, cur_y
, cur_x
); /* Restore cursor position */
195 case 'G': /* Last page */
199 /* Last page not in buffer? */
200 if ((fpos
= lseek (fd
, 0, SEEK_CUR
)) == -1) {
203 "\nError moving file pointer in dialog_textbox().\n");
206 if (fpos
< file_size
) { /* Yes, we have to read it in */
207 if (lseek (fd
, -BUF_SIZE
, SEEK_END
) == -1) {
210 "\nError moving file pointer in dialog_textbox().\n");
213 if ((bytes_read
= read (fd
, buf
, BUF_SIZE
)) == -1) {
216 "\nError reading file in dialog_textbox().\n");
219 buf
[bytes_read
] = '\0';
221 page
= buf
+ bytes_read
;
222 back_lines (height
- 4);
223 print_page (text
, height
- 4, width
- 2);
224 print_position (dialog
, height
, width
);
225 wmove (dialog
, cur_y
, cur_x
); /* Restore cursor position */
228 case 'K': /* Previous line */
231 if (!begin_reached
) {
232 back_lines (page_length
+ 1);
234 /* We don't call print_page() here but use scrolling to ensure
235 faster screen update. However, 'end_reached' and
236 'page_length' should still be updated, and 'page' should
237 point to start of next page. This is done by calling
238 get_line() in the following 'for' loop. */
239 scrollok (text
, TRUE
);
240 wscrl (text
, -1); /* Scroll text region down one line */
241 scrollok (text
, FALSE
);
244 for (i
= 0; i
< height
- 4; i
++) {
246 /* print first line of page */
247 print_line (text
, 0, width
- 2);
250 /* Called to update 'end_reached' and 'page' */
254 if (end_reached
&& !passed_end
)
258 print_position (dialog
, height
, width
);
259 wmove (dialog
, cur_y
, cur_x
); /* Restore cursor position */
263 case 'B': /* Previous page */
268 back_lines (page_length
+ height
- 4);
269 print_page (text
, height
- 4, width
- 2);
270 print_position (dialog
, height
, width
);
271 wmove (dialog
, cur_y
, cur_x
);
274 case 'J': /* Next line */
279 scrollok (text
, TRUE
);
280 scroll (text
); /* Scroll text region up one line */
281 scrollok (text
, FALSE
);
282 print_line (text
, height
- 5, width
- 2);
284 print_position (dialog
, height
, width
);
285 wmove (dialog
, cur_y
, cur_x
); /* Restore cursor position */
289 case KEY_NPAGE
: /* Next page */
295 print_page (text
, height
- 4, width
- 2);
296 print_position (dialog
, height
, width
);
297 wmove (dialog
, cur_y
, cur_x
);
300 case '0': /* Beginning of line */
301 case 'H': /* Scroll left */
311 /* Reprint current page to scroll horizontally */
312 back_lines (page_length
);
313 print_page (text
, height
- 4, width
- 2);
314 wmove (dialog
, cur_y
, cur_x
);
317 case 'L': /* Scroll right */
320 if (hscroll
>= MAX_LEN
)
323 /* Reprint current page to scroll horizontally */
324 back_lines (page_length
);
325 print_page (text
, height
- 4, width
- 2);
326 wmove (dialog
, cur_y
, cur_x
);
337 return -1; /* ESC pressed */
341 * Go back 'n' lines in text file. Called by dialog_textbox().
342 * 'page' will be updated to point to the desired line in 'buf'.
350 /* We have to distinguish between end_reached and !end_reached
351 since at end of file, the line is not ended by a '\n'.
352 The code inside 'if' basically does a '--page' to move one
353 character backward so as to skip '\n' of the previous line */
355 /* Either beginning of buffer or beginning of file reached? */
357 if ((fpos
= lseek (fd
, 0, SEEK_CUR
)) == -1) {
359 fprintf (stderr
, "\nError moving file pointer in "
363 if (fpos
> bytes_read
) { /* Not beginning of file yet */
364 /* We've reached beginning of buffer, but not beginning of
365 file yet, so read previous part of file into buffer.
366 Note that we only move backward for BUF_SIZE/2 bytes,
367 but not BUF_SIZE bytes to avoid re-reading again in
368 print_page() later */
369 /* Really possible to move backward BUF_SIZE/2 bytes? */
370 if (fpos
< BUF_SIZE
/ 2 + bytes_read
) {
371 /* No, move less then */
372 if (lseek (fd
, 0, SEEK_SET
) == -1) {
374 fprintf (stderr
, "\nError moving file pointer in "
378 page
= buf
+ fpos
- bytes_read
;
379 } else { /* Move backward BUF_SIZE/2 bytes */
380 if (lseek (fd
, -(BUF_SIZE
/ 2 + bytes_read
), SEEK_CUR
)
383 fprintf (stderr
, "\nError moving file pointer "
384 "in back_lines().\n");
387 page
= buf
+ BUF_SIZE
/ 2;
389 if ((bytes_read
= read (fd
, buf
, BUF_SIZE
)) == -1) {
391 fprintf (stderr
, "\nError reading file in back_lines().\n");
394 buf
[bytes_read
] = '\0';
395 } else { /* Beginning of file reached */
400 if (*(--page
) != '\n') { /* '--page' here */
401 /* Something's wrong... */
403 fprintf (stderr
, "\nInternal error in back_lines().\n");
407 /* Go back 'n' lines */
408 for (i
= 0; i
< n
; i
++)
411 if ((fpos
= lseek (fd
, 0, SEEK_CUR
)) == -1) {
414 "\nError moving file pointer in back_lines().\n");
417 if (fpos
> bytes_read
) {
418 /* Really possible to move backward BUF_SIZE/2 bytes? */
419 if (fpos
< BUF_SIZE
/ 2 + bytes_read
) {
420 /* No, move less then */
421 if (lseek (fd
, 0, SEEK_SET
) == -1) {
423 fprintf (stderr
, "\nError moving file pointer "
424 "in back_lines().\n");
427 page
= buf
+ fpos
- bytes_read
;
428 } else { /* Move backward BUF_SIZE/2 bytes */
429 if (lseek (fd
, -(BUF_SIZE
/ 2 + bytes_read
),
432 fprintf (stderr
, "\nError moving file pointer"
433 " in back_lines().\n");
436 page
= buf
+ BUF_SIZE
/ 2;
438 if ((bytes_read
= read (fd
, buf
, BUF_SIZE
)) == -1) {
440 fprintf (stderr
, "\nError reading file in "
444 buf
[bytes_read
] = '\0';
445 } else { /* Beginning of file reached */
450 } while (*(--page
) != '\n');
455 * Print a new page of text. Called by dialog_textbox().
458 print_page (WINDOW
* win
, int height
, int width
)
460 int i
, passed_end
= 0;
463 for (i
= 0; i
< height
; i
++) {
464 print_line (win
, i
, width
);
467 if (end_reached
&& !passed_end
)
474 * Print a new line of text. Called by dialog_textbox() and print_page().
477 print_line (WINDOW
* win
, int row
, int width
)
483 line
+= MIN (strlen (line
), hscroll
); /* Scroll horizontally */
484 wmove (win
, row
, 0); /* move cursor to correct line */
486 waddnstr (win
, line
, MIN (strlen (line
), width
- 2));
489 /* Clear 'residue' of previous line */
493 for (i
= 0; i
< width
- x
; i
++)
502 * Return current line of text. Called by dialog_textbox() and print_line().
503 * 'page' should point to start of current line before calling, and will be
504 * updated to point to start of next line.
510 static char line
[MAX_LEN
+ 1];
513 while (*page
!= '\n') {
515 /* Either end of file or end of buffer reached */
516 if ((fpos
= lseek (fd
, 0, SEEK_CUR
)) == -1) {
518 fprintf (stderr
, "\nError moving file pointer in "
522 if (fpos
< file_size
) { /* Not end of file yet */
523 /* We've reached end of buffer, but not end of file yet,
524 so read next part of file into buffer */
525 if ((bytes_read
= read (fd
, buf
, BUF_SIZE
)) == -1) {
527 fprintf (stderr
, "\nError reading file in get_line().\n");
530 buf
[bytes_read
] = '\0';
537 } else if (i
< MAX_LEN
)
538 line
[i
++] = *(page
++);
540 /* Truncate lines longer than MAX_LEN characters */
549 page
++; /* move pass '\n' */
555 * Print current position
558 print_position (WINDOW
* win
, int height
, int width
)
562 if ((fpos
= lseek (fd
, 0, SEEK_CUR
)) == -1) {
564 fprintf (stderr
, "\nError moving file pointer in print_position().\n");
567 wattrset (win
, position_indicator_attr
);
568 wbkgdset (win
, position_indicator_attr
& A_COLOR
);
569 percent
= !file_size
?
570 100 : ((fpos
- bytes_read
+ page
- buf
) * 100) / file_size
;
571 wmove (win
, height
- 3, width
- 9);
572 wprintw (win
, "(%3d%%)", percent
);