13515Sache/* 23515Sache * textbox.c -- implements the text box 33515Sache * 43515Sache * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) 53515Sache * 63515Sache * This program is free software; you can redistribute it and/or 73515Sache * modify it under the terms of the GNU General Public License 83515Sache * as published by the Free Software Foundation; either version 2 93515Sache * of the License, or (at your option) any later version. 103515Sache * 113515Sache * This program is distributed in the hope that it will be useful, 123515Sache * but WITHOUT ANY WARRANTY; without even the implied warranty of 133515Sache * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 143515Sache * GNU General Public License for more details. 153515Sache * 163515Sache * You should have received a copy of the GNU General Public License 173515Sache * along with this program; if not, write to the Free Software 183515Sache * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 193515Sache */ 203515Sache 21114603Sobrien#include <sys/cdefs.h> 22114603Sobrien__FBSDID("$FreeBSD$"); 233515Sache 243740Sache#include <dialog.h> 253515Sache#include "dialog.priv.h" 263515Sache 273515Sache 283515Sachestatic void back_lines(int n); 293515Sachestatic void print_page(WINDOW *win, int height, int width); 303515Sachestatic void print_line(WINDOW *win, int row, int width); 313515Sachestatic unsigned char *get_line(void); 323515Sachestatic int get_search_term(WINDOW *win, unsigned char *search_term, int height, int width); 333515Sachestatic void print_position(WINDOW *win, int height, int width); 343515Sache 353515Sache 363515Sachestatic int hscroll = 0, fd, file_size, bytes_read, begin_reached = 1, 373515Sache end_reached = 0, page_length; 383515Sachestatic unsigned char *buf, *page; 393515Sache 403515Sache 413515Sache/* 423515Sache * Display text from a file in a dialog box. 433515Sache */ 443515Sacheint dialog_textbox(unsigned char *title, unsigned char *file, int height, int width) 453515Sache{ 463515Sache int i, x, y, cur_x, cur_y, fpos, key = 0, dir, temp, temp1; 473515Sache#ifdef HAVE_NCURSES 483515Sache int passed_end; 493515Sache#endif 503515Sache unsigned char search_term[MAX_LEN+1], *tempptr, *found; 513515Sache WINDOW *dialog, *text; 523515Sache 534565Sache if (height < 0 || width < 0) { 544565Sache fprintf(stderr, "\nAutosizing is impossible in dialog_textbox().\n"); 557237Sjkh return(-1); 564565Sache } 574565Sache 583515Sache search_term[0] = '\0'; /* no search term entered yet */ 593515Sache 603515Sache /* Open input file for reading */ 613515Sache if ((fd = open(file, O_RDONLY)) == -1) { 626458Sache fprintf(stderr, "\nCan't open input file <%s>in dialog_textbox().\n", file); 637237Sjkh return(-1); 643515Sache } 653515Sache /* Get file size. Actually, 'file_size' is the real file size - 1, 663515Sache since it's only the last byte offset from the beginning */ 673515Sache if ((file_size = lseek(fd, 0, SEEK_END)) == -1) { 683515Sache fprintf(stderr, "\nError getting file size in dialog_textbox().\n"); 697237Sjkh return(-1); 703515Sache } 713515Sache /* Restore file pointer to beginning of file after getting file size */ 723515Sache if (lseek(fd, 0, SEEK_SET) == -1) { 733515Sache fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); 747237Sjkh return(-1); 753515Sache } 763515Sache /* Allocate space for read buffer */ 773515Sache if ((buf = malloc(BUF_SIZE+1)) == NULL) { 783515Sache endwin(); 793515Sache fprintf(stderr, "\nCan't allocate memory in dialog_textbox().\n"); 803515Sache exit(-1); 813515Sache } 823515Sache if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { 833515Sache fprintf(stderr, "\nError reading file in dialog_textbox().\n"); 847237Sjkh return(-1); 853515Sache } 863515Sache buf[bytes_read] = '\0'; /* mark end of valid data */ 873515Sache page = buf; /* page is pointer to start of page to be displayed */ 883515Sache 894658Sache if (width > COLS) 904658Sache width = COLS; 914658Sache if (height > LINES) 924658Sache height = LINES; 933515Sache /* center dialog box on screen */ 9413135Sjkh x = DialogX ? DialogX : (COLS - width)/2; 9513135Sjkh y = DialogY ? DialogY : (LINES - height)/2; 963515Sache 973515Sache#ifdef HAVE_NCURSES 983515Sache if (use_shadow) 993515Sache draw_shadow(stdscr, y, x, height, width); 1003515Sache#endif 1013515Sache dialog = newwin(height, width, y, x); 1024024Sache if (dialog == NULL) { 1034024Sache endwin(); 1044024Sache fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x); 1054024Sache exit(1); 1064024Sache } 1073515Sache keypad(dialog, TRUE); 1083515Sache 1093515Sache /* Create window for text region, used for scrolling text */ 1103515Sache/* text = newwin(height-4, width-2, y+1, x+1); */ 1113515Sache text = subwin(dialog, height-4, width-2, y+1, x+1); 1124024Sache if (text == NULL) { 1134024Sache endwin(); 1144024Sache fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", height-4,width-2,y+1,x+1); 1154024Sache exit(1); 1164024Sache } 1173515Sache keypad(text, TRUE); 1183515Sache 1193515Sache draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); 1203515Sache 1213515Sache wattrset(dialog, border_attr); 1223515Sache wmove(dialog, height-3, 0); 1233515Sache waddch(dialog, ACS_LTEE); 1243515Sache for (i = 0; i < width-2; i++) 1253515Sache waddch(dialog, ACS_HLINE); 1263515Sache wattrset(dialog, dialog_attr); 1273515Sache waddch(dialog, ACS_RTEE); 1283515Sache wmove(dialog, height-2, 1); 1293515Sache for (i = 0; i < width-2; i++) 1303515Sache waddch(dialog, ' '); 1313515Sache 1323515Sache if (title != NULL) { 1333515Sache wattrset(dialog, title_attr); 1343515Sache wmove(dialog, 0, (width - strlen(title))/2 - 1); 1353515Sache waddch(dialog, ' '); 1363515Sache waddstr(dialog, title); 1373515Sache waddch(dialog, ' '); 1383515Sache } 1396458Sache display_helpline(dialog, height-1, width); 1406458Sache 14120359Sjkh print_button(dialog, " OK ", height-2, width/2-6, TRUE); 1423515Sache wnoutrefresh(dialog); 1433515Sache getyx(dialog, cur_y, cur_x); /* Save cursor position */ 1443515Sache 1453515Sache /* Print first page of text */ 1463515Sache attr_clear(text, height-4, width-2, dialog_attr); 1473515Sache print_page(text, height-4, width-2); 1483515Sache print_position(dialog, height, width); 1493515Sache wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 1503515Sache wrefresh(dialog); 1513515Sache 15279843Seric while ((key != ESC) && (key != '\n') && (key != '\r') && (key != ' ')) { 1533515Sache key = wgetch(dialog); 1543515Sache switch (key) { 1553515Sache case 'E': /* Exit */ 1563515Sache case 'e': 1573515Sache delwin(dialog); 1583515Sache free(buf); 1593515Sache close(fd); 1603515Sache return 0; 1613515Sache case 'g': /* First page */ 1623515Sache case KEY_HOME: 1633515Sache if (!begin_reached) { 1643515Sache begin_reached = 1; 1653515Sache /* First page not in buffer? */ 1663515Sache if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { 1673515Sache endwin(); 1683515Sache fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); 1693515Sache exit(-1); 1703515Sache } 1713515Sache if (fpos > bytes_read) { /* Yes, we have to read it in */ 1723515Sache if (lseek(fd, 0, SEEK_SET) == -1) { 1733515Sache endwin(); 1743515Sache fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); 1753515Sache exit(-1); 1763515Sache } 1773515Sache if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { 1783515Sache endwin(); 1793515Sache fprintf(stderr, "\nError reading file in dialog_textbox().\n"); 1803515Sache exit(-1); 1813515Sache } 1823515Sache buf[bytes_read] = '\0'; 1833515Sache } 1843515Sache page = buf; 1853515Sache print_page(text, height-4, width-2); 1863515Sache print_position(dialog, height, width); 1873515Sache wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 1883515Sache wrefresh(dialog); 1893515Sache } 1903515Sache break; 1913515Sache case 'G': /* Last page */ 1923515Sache#ifdef HAVE_NCURSES 1933515Sache case KEY_END: 1943515Sache#endif 1953515Sache end_reached = 1; 1963515Sache /* Last page not in buffer? */ 1973515Sache if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { 1983515Sache endwin(); 1993515Sache fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); 2003515Sache exit(-1); 2013515Sache } 2023515Sache if (fpos < file_size) { /* Yes, we have to read it in */ 2033515Sache if (lseek(fd, -BUF_SIZE, SEEK_END) == -1) { 2043515Sache endwin(); 2053515Sache fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); 2063515Sache exit(-1); 2073515Sache } 2083515Sache if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { 2093515Sache endwin(); 2103515Sache fprintf(stderr, "\nError reading file in dialog_textbox().\n"); 2113515Sache exit(-1); 2123515Sache } 2133515Sache buf[bytes_read] = '\0'; 2143515Sache } 2153515Sache page = buf + bytes_read; 2163515Sache back_lines(height-4); 2173515Sache print_page(text, height-4, width-2); 2183515Sache print_position(dialog, height, width); 2193515Sache wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 2203515Sache wrefresh(dialog); 2213515Sache break; 2223515Sache case 'K': /* Previous line */ 2233515Sache case 'k': 22421697Sjkh case '\020': /* ^P */ 2253515Sache case KEY_UP: 2263515Sache if (!begin_reached) { 2273515Sache back_lines(page_length+1); 2283515Sache#ifdef HAVE_NCURSES 2293515Sache /* We don't call print_page() here but use scrolling to ensure 2303515Sache faster screen update. However, 'end_reached' and 'page_length' 2313515Sache should still be updated, and 'page' should point to start of 2323515Sache next page. This is done by calling get_line() in the following 2333515Sache 'for' loop. */ 2343515Sache scrollok(text, TRUE); 2353515Sache wscrl(text, -1); /* Scroll text region down one line */ 2363515Sache scrollok(text, FALSE); 2373515Sache page_length = 0; 2383515Sache passed_end = 0; 2393515Sache for (i = 0; i < height-4; i++) { 2403515Sache if (!i) { 2413515Sache print_line(text, 0, width-2); /* print first line of page */ 2423515Sache wnoutrefresh(text); 2433515Sache } 2443515Sache else 2453515Sache get_line(); /* Called to update 'end_reached' and 'page' */ 2463515Sache if (!passed_end) 2473515Sache page_length++; 2483515Sache if (end_reached && !passed_end) 2493515Sache passed_end = 1; 2503515Sache } 2513515Sache#else 2523515Sache print_page(text, height-4, width-2); 2533515Sache#endif 2543515Sache print_position(dialog, height, width); 2553515Sache wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 2563515Sache wrefresh(dialog); 2573515Sache } 2583515Sache break; 2593515Sache case 'B': /* Previous page */ 2603515Sache case 'b': 2613515Sache case KEY_PPAGE: 2623515Sache if (!begin_reached) { 2633515Sache back_lines(page_length + height-4); 2643515Sache print_page(text, height-4, width-2); 2653515Sache print_position(dialog, height, width); 2663515Sache wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 2673515Sache wrefresh(dialog); 2683515Sache } 2693515Sache break; 2703515Sache case 'J': /* Next line */ 2713515Sache case 'j': 27221697Sjkh case '\016': /* ^N */ 2733515Sache case KEY_DOWN: 2743515Sache if (!end_reached) { 2753515Sache begin_reached = 0; 2763515Sache scrollok(text, TRUE); 2773515Sache scroll(text); /* Scroll text region up one line */ 2783515Sache scrollok(text, FALSE); 2793515Sache print_line(text, height-5, width-2); 2803515Sache#ifndef HAVE_NCURSES 2813515Sache wmove(text, height-5, 0); 2823515Sache waddch(text, ' '); 2833515Sache wmove(text, height-5, width-3); 2843515Sache waddch(text, ' '); 2853515Sache#endif 2863515Sache wnoutrefresh(text); 2873515Sache print_position(dialog, height, width); 2883515Sache wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 2893515Sache wrefresh(dialog); 2903515Sache } 2913515Sache break; 29280372Seric case 'F': /* Next page */ 29380372Seric case 'f': 2943515Sache case KEY_NPAGE: 2953515Sache if (!end_reached) { 2963515Sache begin_reached = 0; 2973515Sache print_page(text, height-4, width-2); 2983515Sache print_position(dialog, height, width); 2993515Sache wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 3003515Sache wrefresh(dialog); 3013515Sache } 3023515Sache break; 3033515Sache case '0': /* Beginning of line */ 3043515Sache case 'H': /* Scroll left */ 3053515Sache case 'h': 3063515Sache case KEY_LEFT: 3073515Sache if (hscroll > 0) { 3083515Sache if (key == '0') 3093515Sache hscroll = 0; 3103515Sache else 3113515Sache hscroll--; 3123515Sache /* Reprint current page to scroll horizontally */ 3133515Sache back_lines(page_length); 3143515Sache print_page(text, height-4, width-2); 3153515Sache wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 3163515Sache wrefresh(dialog); 3173515Sache } 3183515Sache break; 3193515Sache case 'L': /* Scroll right */ 3203515Sache case 'l': 3213515Sache case KEY_RIGHT: 3223515Sache if (hscroll < MAX_LEN) { 3233515Sache hscroll++; 3243515Sache /* Reprint current page to scroll horizontally */ 3253515Sache back_lines(page_length); 3263515Sache print_page(text, height-4, width-2); 3273515Sache wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 3283515Sache wrefresh(dialog); 3293515Sache } 3303515Sache break; 3313515Sache case '/': /* Forward search */ 3323515Sache case 'n': /* Repeat forward search */ 3333515Sache case '?': /* Backward search */ 3343515Sache case 'N': /* Repeat backward search */ 3353515Sache /* set search direction */ 3363515Sache dir = (key == '/' || key == 'n') ? 1 : 0; 3373515Sache if (dir ? !end_reached : !begin_reached) { 3383515Sache if (key == 'n' || key == 'N') { 3393515Sache if (search_term[0] == '\0') { /* No search term yet */ 3403515Sache fprintf(stderr, "\a"); /* beep */ 3413515Sache break; 3423515Sache } 3433515Sache } 3443515Sache else /* Get search term from user */ 3453515Sache if (get_search_term(text, search_term, height-4, width-2) == -1) { 3463515Sache /* ESC pressed in get_search_term(). Reprint page to clear box */ 3473515Sache wattrset(text, dialog_attr); 3483515Sache back_lines(page_length); 3493515Sache print_page(text, height-4, width-2); 3503515Sache wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 3513515Sache wrefresh(dialog); 3523515Sache break; 3533515Sache } 3543515Sache /* Save variables for restoring in case search term can't be found */ 3553515Sache tempptr = page; 3563515Sache temp = begin_reached; 3573515Sache temp1 = end_reached; 3583515Sache if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { 3593515Sache endwin(); 3603515Sache fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); 3613515Sache exit(-1); 3623515Sache } 3633515Sache fpos -= bytes_read; 3643515Sache /* update 'page' to point to next (previous) line before 3653515Sache forward (backward) searching */ 3663515Sache back_lines(dir ? page_length-1 : page_length+1); 3673515Sache found = NULL; 3683515Sache if (dir) /* Forward search */ 3693515Sache while((found = strstr(get_line(), search_term)) == NULL) { 3703515Sache if (end_reached) 3713515Sache break; 3723515Sache } 3733515Sache else /* Backward search */ 3743515Sache while((found = strstr(get_line(), search_term)) == NULL) { 3753515Sache if (begin_reached) 3763515Sache break; 3773515Sache back_lines(2); 3783515Sache } 3793515Sache if (found == NULL) { /* not found */ 3803515Sache fprintf(stderr, "\a"); /* beep */ 3813515Sache /* Restore program state to that before searching */ 3823515Sache if (lseek(fd, fpos, SEEK_SET) == -1) { 3833515Sache endwin(); 3843515Sache fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); 3853515Sache exit(-1); 3863515Sache } 3873515Sache if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { 3883515Sache endwin(); 3893515Sache fprintf(stderr, "\nError reading file in dialog_textbox().\n"); 3903515Sache exit(-1); 3913515Sache } 3923515Sache buf[bytes_read] = '\0'; 3933515Sache page = tempptr; 3943515Sache begin_reached = temp; 3953515Sache end_reached = temp1; 3963515Sache /* move 'page' to point to start of current page in order to 3973515Sache re-print current page. Note that 'page' always points to 3983515Sache start of next page, so this is necessary */ 3993515Sache back_lines(page_length); 4003515Sache } 4013515Sache else /* Search term found */ 4023515Sache back_lines(1); 4033515Sache /* Reprint page */ 4043515Sache wattrset(text, dialog_attr); 4053515Sache print_page(text, height-4, width-2); 4063515Sache if (found != NULL) 4073515Sache print_position(dialog, height, width); 4083515Sache wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 4093515Sache wrefresh(dialog); 4103515Sache } 4113515Sache else /* no need to find */ 4123515Sache fprintf(stderr, "\a"); /* beep */ 4133515Sache break; 4143515Sache case ESC: 4153515Sache break; 4166458Sache case KEY_F(1): 4176458Sache display_helpfile(); 4186458Sache break; 4193515Sache } 4203515Sache } 4213515Sache 4223515Sache delwin(dialog); 4233515Sache free(buf); 4243515Sache close(fd); 42598195Sdougb return (key == ESC ? -1 : 0); 4263515Sache} 4273515Sache/* End of dialog_textbox() */ 4283515Sache 4293515Sache 4303515Sache/* 4313515Sache * Go back 'n' lines in text file. Called by dialog_textbox(). 4323515Sache * 'page' will be updated to point to the desired line in 'buf'. 4333515Sache */ 4343515Sachestatic void back_lines(int n) 4353515Sache{ 4363515Sache int i, fpos; 4373515Sache 4383515Sache begin_reached = 0; 4393515Sache /* We have to distinguish between end_reached and !end_reached since at end 4403515Sache of file, the line is not ended by a '\n'. The code inside 'if' basically 4413515Sache does a '--page' to move one character backward so as to skip '\n' of the 4423515Sache previous line */ 4433515Sache if (!end_reached) { 4443515Sache /* Either beginning of buffer or beginning of file reached? */ 4453515Sache if (page == buf) { 4463515Sache if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { 4473515Sache endwin(); 4483515Sache fprintf(stderr, "\nError moving file pointer in back_lines().\n"); 4493515Sache exit(-1); 4503515Sache } 4513515Sache if (fpos > bytes_read) { /* Not beginning of file yet */ 4523515Sache /* We've reached beginning of buffer, but not beginning of file yet, 4533515Sache so read previous part of file into buffer. Note that we only 4543515Sache move backward for BUF_SIZE/2 bytes, but not BUF_SIZE bytes to 4553515Sache avoid re-reading again in print_page() later */ 4563515Sache /* Really possible to move backward BUF_SIZE/2 bytes? */ 4573515Sache if (fpos < BUF_SIZE/2 + bytes_read) { 4583515Sache /* No, move less then */ 4593515Sache if (lseek(fd, 0, SEEK_SET) == -1) { 4603515Sache endwin(); 4613515Sache fprintf(stderr, "\nError moving file pointer in back_lines().\n"); 4623515Sache exit(-1); 4633515Sache } 4643515Sache page = buf + fpos - bytes_read; 4653515Sache } 4663515Sache else { /* Move backward BUF_SIZE/2 bytes */ 4673515Sache if (lseek(fd, -(BUF_SIZE/2 + bytes_read), SEEK_CUR) == -1) { 4683515Sache endwin(); 4693515Sache fprintf(stderr, "\nError moving file pointer in back_lines().\n"); 4703515Sache exit(-1); 4713515Sache } 4723515Sache page = buf + BUF_SIZE/2; 4733515Sache } 4743515Sache if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { 4753515Sache endwin(); 4763515Sache fprintf(stderr, "\nError reading file in back_lines().\n"); 4773515Sache exit(-1); 4783515Sache } 4793515Sache buf[bytes_read] = '\0'; 4803515Sache } 4813515Sache else { /* Beginning of file reached */ 4823515Sache begin_reached = 1; 4833515Sache return; 4843515Sache } 4853515Sache } 4863515Sache if (*(--page) != '\n') { /* '--page' here */ 4873515Sache /* Something's wrong... */ 4883515Sache endwin(); 4893515Sache fprintf(stderr, "\nInternal error in back_lines().\n"); 4903515Sache exit(-1); 4913515Sache } 4923515Sache } 4933515Sache 4943515Sache /* Go back 'n' lines */ 4953515Sache for (i = 0; i < n; i++) 4963515Sache do { 4973515Sache if (page == buf) { 4983515Sache if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { 4993515Sache endwin(); 5003515Sache fprintf(stderr, "\nError moving file pointer in back_lines().\n"); 5013515Sache exit(-1); 5023515Sache } 5033515Sache if (fpos > bytes_read) { 5043515Sache /* Really possible to move backward BUF_SIZE/2 bytes? */ 5053515Sache if (fpos < BUF_SIZE/2 + bytes_read) { 5063515Sache /* No, move less then */ 5073515Sache if (lseek(fd, 0, SEEK_SET) == -1) { 5083515Sache endwin(); 5093515Sache fprintf(stderr, "\nError moving file pointer in back_lines().\n"); 5103515Sache exit(-1); 5113515Sache } 5123515Sache page = buf + fpos - bytes_read; 5133515Sache } 5143515Sache else { /* Move backward BUF_SIZE/2 bytes */ 5153515Sache if (lseek(fd, -(BUF_SIZE/2 + bytes_read), SEEK_CUR) == -1) { 5163515Sache endwin(); 5173515Sache fprintf(stderr, "\nError moving file pointer in back_lines().\n"); 5183515Sache exit(-1); 5193515Sache } 5203515Sache page = buf + BUF_SIZE/2; 5213515Sache } 5223515Sache if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { 5233515Sache endwin(); 5243515Sache fprintf(stderr, "\nError reading file in back_lines().\n"); 5253515Sache exit(-1); 5263515Sache } 5273515Sache buf[bytes_read] = '\0'; 5283515Sache } 5293515Sache else { /* Beginning of file reached */ 5303515Sache begin_reached = 1; 5313515Sache return; 5323515Sache } 5333515Sache } 5343515Sache } while (*(--page) != '\n'); 5353515Sache page++; 5363515Sache} 5373515Sache/* End of back_lines() */ 5383515Sache 5393515Sache 5403515Sache/* 5413515Sache * Print a new page of text. Called by dialog_textbox(). 5423515Sache */ 5433515Sachestatic void print_page(WINDOW *win, int height, int width) 5443515Sache{ 5453515Sache int i, passed_end = 0; 5463515Sache 5473515Sache page_length = 0; 5483515Sache for (i = 0; i < height; i++) { 5493515Sache print_line(win, i, width); 5503515Sache if (!passed_end) 5513515Sache page_length++; 5523515Sache if (end_reached && !passed_end) 5533515Sache passed_end = 1; 5543515Sache } 5553515Sache wnoutrefresh(win); 5563515Sache} 5573515Sache/* End of print_page() */ 5583515Sache 5593515Sache 5603515Sache/* 5613515Sache * Print a new line of text. Called by dialog_textbox() and print_page(). 5623515Sache */ 5633515Sachestatic void print_line(WINDOW *win, int row, int width) 5643515Sache{ 5653515Sache int i, y, x; 5663515Sache unsigned char *line; 5673515Sache 5683515Sache line = get_line(); 5693515Sache line += MIN(strlen(line),hscroll); /* Scroll horizontally */ 5703515Sache wmove(win, row, 0); /* move cursor to correct line */ 5713515Sache waddch(win,' '); 5723515Sache#ifdef HAVE_NCURSES 5733515Sache waddnstr(win, line, MIN(strlen(line),width-2)); 5743515Sache#else 5753515Sache line[MIN(strlen(line),width-2)] = '\0'; 5763515Sache waddstr(win, line); 5773515Sache#endif 5783515Sache 5793515Sache getyx(win, y, x); 5803515Sache /* Clear 'residue' of previous line */ 5813515Sache for (i = 0; i < width-x; i++) 5823515Sache waddch(win, ' '); 5833515Sache} 5843515Sache/* End of print_line() */ 5853515Sache 5863515Sache 5873515Sache/* 5883515Sache * Return current line of text. Called by dialog_textbox() and print_line(). 5893515Sache * 'page' should point to start of current line before calling, and will be 5903515Sache * updated to point to start of next line. 5913515Sache */ 5923515Sachestatic unsigned char *get_line(void) 5933515Sache{ 5943515Sache int i = 0, fpos; 5953515Sache static unsigned char line[MAX_LEN+1]; 5963515Sache 5973515Sache end_reached = 0; 5983515Sache while (*page != '\n') { 5993515Sache if (*page == '\0') { /* Either end of file or end of buffer reached */ 6003515Sache if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { 6013515Sache endwin(); 6023515Sache fprintf(stderr, "\nError moving file pointer in get_line().\n"); 6033515Sache exit(-1); 6043515Sache } 6053515Sache if (fpos < file_size) { /* Not end of file yet */ 6063515Sache /* We've reached end of buffer, but not end of file yet, so read next 6073515Sache part of file into buffer */ 6083515Sache if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { 6093515Sache endwin(); 6103515Sache fprintf(stderr, "\nError reading file in get_line().\n"); 6113515Sache exit(-1); 6123515Sache } 6133515Sache buf[bytes_read] = '\0'; 6143515Sache page = buf; 6153515Sache } 6163515Sache else { 6173515Sache if (!end_reached) 6183515Sache end_reached = 1; 6193515Sache break; 6203515Sache } 6213515Sache } 6223515Sache else 6233515Sache if (i < MAX_LEN) 6243515Sache line[i++] = *(page++); 6253515Sache else { 6263515Sache if (i == MAX_LEN) /* Truncate lines longer than MAX_LEN characters */ 6273515Sache line[i++] = '\0'; 6283515Sache page++; 6293515Sache } 6303515Sache } 6313515Sache if (i <= MAX_LEN) 6323515Sache line[i] = '\0'; 6333515Sache if (!end_reached) 6343515Sache page++; /* move pass '\n' */ 6353515Sache 6363515Sache return line; 6373515Sache} 6383515Sache/* End of get_line() */ 6393515Sache 6403515Sache 6413515Sache/* 6423515Sache * Display a dialog box and get the search term from user 6433515Sache */ 6443515Sachestatic int get_search_term(WINDOW *win, unsigned char *search_term, int height, int width) 6453515Sache{ 6463754Sache int x, y, key = 0, first, 6473515Sache box_height = 3, box_width = 30; 6483515Sache 6493515Sache x = (width - box_width)/2; 6503515Sache y = (height - box_height)/2; 6513515Sache#ifdef HAVE_NCURSES 6523515Sache if (use_shadow) 6533515Sache draw_shadow(win, y, x, box_height, box_width); 6543515Sache#endif 6553515Sache draw_box(win, y, x, box_height, box_width, dialog_attr, searchbox_border_attr); 6563515Sache wattrset(win, searchbox_title_attr); 6573515Sache wmove(win, y, x+box_width/2-4); 6583515Sache waddstr(win, " Search "); 6594591Sache wattrset(win, dialog_attr); 6603515Sache 6613515Sache search_term[0] = '\0'; 6623754Sache 6633754Sache first = 1; 6643515Sache while (key != ESC) { 66520442Sjkh key = line_edit(win, y+1, x+1, -1, box_width-2, searchbox_attr, first, search_term, 0); 6663754Sache first = 0; 6673515Sache switch (key) { 6683515Sache case '\n': 6693515Sache if (search_term[0] != '\0') 6703515Sache return 0; 6713515Sache break; 6723515Sache case ESC: 6733754Sache break; 6743515Sache } 6753515Sache } 6763515Sache 6773515Sache return -1; /* ESC pressed */ 6783515Sache} 6793515Sache/* End of get_search_term() */ 6803515Sache 6813515Sache 6823515Sache/* 6833515Sache * Print current position 6843515Sache */ 6853515Sachestatic void print_position(WINDOW *win, int height, int width) 6863515Sache{ 6873515Sache int fpos, percent; 6883515Sache 6893515Sache if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { 6903515Sache endwin(); 6913515Sache fprintf(stderr, "\nError moving file pointer in print_position().\n"); 6923515Sache exit(-1); 6933515Sache } 6943515Sache wattrset(win, position_indicator_attr); 6953515Sache percent = !file_size ? 100 : ((fpos-bytes_read+page-buf)*100)/file_size; 6963515Sache wmove(win, height-3, width-9); 6973515Sache wprintw(win, "(%3d%%)", percent); 6983515Sache} 6993515Sache/* End of print_position() */ 700