14c8945a0SNathan Whitehorn /* 2*7a1c0d96SNathan Whitehorn * $Id: textbox.c,v 1.99 2011/01/16 22:20:34 tom Exp $ 34c8945a0SNathan Whitehorn * 44c8945a0SNathan Whitehorn * textbox.c -- implements the text box 54c8945a0SNathan Whitehorn * 6*7a1c0d96SNathan Whitehorn * Copyright 2000-2010,2011 Thomas E. Dickey 74c8945a0SNathan Whitehorn * 84c8945a0SNathan Whitehorn * This program is free software; you can redistribute it and/or modify 94c8945a0SNathan Whitehorn * it under the terms of the GNU Lesser General Public License, version 2.1 104c8945a0SNathan Whitehorn * as published by the Free Software Foundation. 114c8945a0SNathan Whitehorn * 124c8945a0SNathan Whitehorn * This program is distributed in the hope that it will be useful, but 134c8945a0SNathan Whitehorn * WITHOUT ANY WARRANTY; without even the implied warranty of 144c8945a0SNathan Whitehorn * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 154c8945a0SNathan Whitehorn * Lesser General Public License for more details. 164c8945a0SNathan Whitehorn * 174c8945a0SNathan Whitehorn * You should have received a copy of the GNU Lesser General Public 184c8945a0SNathan Whitehorn * License along with this program; if not, write to 194c8945a0SNathan Whitehorn * Free Software Foundation, Inc. 204c8945a0SNathan Whitehorn * 51 Franklin St., Fifth Floor 214c8945a0SNathan Whitehorn * Boston, MA 02110, USA. 224c8945a0SNathan Whitehorn * 234c8945a0SNathan Whitehorn * An earlier version of this program lists as authors: 244c8945a0SNathan Whitehorn * Savio Lam (lam836@cs.cuhk.hk) 254c8945a0SNathan Whitehorn */ 264c8945a0SNathan Whitehorn 274c8945a0SNathan Whitehorn #include <dialog.h> 284c8945a0SNathan Whitehorn #include <dlg_keys.h> 294c8945a0SNathan Whitehorn 304c8945a0SNathan Whitehorn #define PAGE_LENGTH (height - 4) 314c8945a0SNathan Whitehorn #define PAGE_WIDTH (width - 2) 324c8945a0SNathan Whitehorn 334c8945a0SNathan Whitehorn typedef struct { 344c8945a0SNathan Whitehorn DIALOG_CALLBACK obj; 354c8945a0SNathan Whitehorn WINDOW *text; 364c8945a0SNathan Whitehorn const char **buttons; 374c8945a0SNathan Whitehorn int hscroll; 384c8945a0SNathan Whitehorn char line[MAX_LEN + 1]; 394c8945a0SNathan Whitehorn int fd; 404c8945a0SNathan Whitehorn long file_size; 414c8945a0SNathan Whitehorn long fd_bytes_read; 424c8945a0SNathan Whitehorn long bytes_read; 434c8945a0SNathan Whitehorn long buffer_len; 444c8945a0SNathan Whitehorn bool begin_reached; 454c8945a0SNathan Whitehorn bool buffer_first; 464c8945a0SNathan Whitehorn bool end_reached; 474c8945a0SNathan Whitehorn long page_length; /* lines on the page which is shown */ 484c8945a0SNathan Whitehorn long in_buf; /* ending index into buf[] for page */ 494c8945a0SNathan Whitehorn char *buf; 504c8945a0SNathan Whitehorn } MY_OBJ; 514c8945a0SNathan Whitehorn 524c8945a0SNathan Whitehorn static long 534c8945a0SNathan Whitehorn lseek_obj(MY_OBJ * obj, long offset, int mode) 544c8945a0SNathan Whitehorn { 554c8945a0SNathan Whitehorn long fpos; 564c8945a0SNathan Whitehorn if ((fpos = (long) lseek(obj->fd, (off_t) offset, mode)) == -1) { 574c8945a0SNathan Whitehorn switch (mode) { 584c8945a0SNathan Whitehorn case SEEK_CUR: 594c8945a0SNathan Whitehorn dlg_exiterr("Cannot get file position"); 604c8945a0SNathan Whitehorn break; 614c8945a0SNathan Whitehorn case SEEK_END: 624c8945a0SNathan Whitehorn dlg_exiterr("Cannot seek to end of file"); 634c8945a0SNathan Whitehorn break; 644c8945a0SNathan Whitehorn case SEEK_SET: 654c8945a0SNathan Whitehorn dlg_exiterr("Cannot set file position to %ld", offset); 664c8945a0SNathan Whitehorn break; 674c8945a0SNathan Whitehorn } 684c8945a0SNathan Whitehorn } 694c8945a0SNathan Whitehorn return fpos; 704c8945a0SNathan Whitehorn } 714c8945a0SNathan Whitehorn 724c8945a0SNathan Whitehorn static long 734c8945a0SNathan Whitehorn ftell_obj(MY_OBJ * obj) 744c8945a0SNathan Whitehorn { 75*7a1c0d96SNathan Whitehorn return lseek_obj(obj, 0L, SEEK_CUR); 764c8945a0SNathan Whitehorn } 774c8945a0SNathan Whitehorn 784c8945a0SNathan Whitehorn static char * 794c8945a0SNathan Whitehorn xalloc(size_t size) 804c8945a0SNathan Whitehorn { 814c8945a0SNathan Whitehorn char *result = dlg_malloc(char, size); 824c8945a0SNathan Whitehorn assert_ptr(result, "xalloc"); 834c8945a0SNathan Whitehorn return result; 844c8945a0SNathan Whitehorn } 854c8945a0SNathan Whitehorn 864c8945a0SNathan Whitehorn /* 874c8945a0SNathan Whitehorn * read_high() substitutes read() for tab->spaces conversion 884c8945a0SNathan Whitehorn * 894c8945a0SNathan Whitehorn * buffer_len, fd_bytes_read, bytes_read are modified 904c8945a0SNathan Whitehorn * buf is allocated 914c8945a0SNathan Whitehorn * 924c8945a0SNathan Whitehorn * fd_bytes_read is the effective number of bytes read from file 934c8945a0SNathan Whitehorn * bytes_read is the length of buf, that can be different if tab_correct 944c8945a0SNathan Whitehorn */ 954c8945a0SNathan Whitehorn static void 964c8945a0SNathan Whitehorn read_high(MY_OBJ * obj, size_t size_read) 974c8945a0SNathan Whitehorn { 984c8945a0SNathan Whitehorn char *buftab, ch; 994c8945a0SNathan Whitehorn int i = 0, j, n, tmpint; 1004c8945a0SNathan Whitehorn long begin_line; 1014c8945a0SNathan Whitehorn 1024c8945a0SNathan Whitehorn /* Allocate space for read buffer */ 1034c8945a0SNathan Whitehorn buftab = xalloc(size_read + 1); 1044c8945a0SNathan Whitehorn 1054c8945a0SNathan Whitehorn if ((obj->fd_bytes_read = read(obj->fd, buftab, size_read)) != -1) { 1064c8945a0SNathan Whitehorn 1074c8945a0SNathan Whitehorn buftab[obj->fd_bytes_read] = '\0'; /* mark end of valid data */ 1084c8945a0SNathan Whitehorn 1094c8945a0SNathan Whitehorn if (dialog_vars.tab_correct) { 1104c8945a0SNathan Whitehorn 1114c8945a0SNathan Whitehorn /* calculate bytes_read by buftab and fd_bytes_read */ 1124c8945a0SNathan Whitehorn obj->bytes_read = begin_line = 0; 1134c8945a0SNathan Whitehorn for (j = 0; j < obj->fd_bytes_read; j++) 1144c8945a0SNathan Whitehorn if (buftab[j] == TAB) 1154c8945a0SNathan Whitehorn obj->bytes_read += dialog_state.tab_len 1164c8945a0SNathan Whitehorn - ((obj->bytes_read - begin_line) 1174c8945a0SNathan Whitehorn % dialog_state.tab_len); 1184c8945a0SNathan Whitehorn else if (buftab[j] == '\n') { 1194c8945a0SNathan Whitehorn obj->bytes_read++; 1204c8945a0SNathan Whitehorn begin_line = obj->bytes_read; 1214c8945a0SNathan Whitehorn } else 1224c8945a0SNathan Whitehorn obj->bytes_read++; 1234c8945a0SNathan Whitehorn 1244c8945a0SNathan Whitehorn if (obj->bytes_read > obj->buffer_len) { 1254c8945a0SNathan Whitehorn if (obj->buffer_first) 1264c8945a0SNathan Whitehorn obj->buffer_first = FALSE; /* disp = 0 */ 1274c8945a0SNathan Whitehorn else { 1284c8945a0SNathan Whitehorn free(obj->buf); 1294c8945a0SNathan Whitehorn } 1304c8945a0SNathan Whitehorn 1314c8945a0SNathan Whitehorn obj->buffer_len = obj->bytes_read; 1324c8945a0SNathan Whitehorn 1334c8945a0SNathan Whitehorn /* Allocate space for read buffer */ 1344c8945a0SNathan Whitehorn obj->buf = xalloc((size_t) obj->buffer_len + 1); 1354c8945a0SNathan Whitehorn } 1364c8945a0SNathan Whitehorn 1374c8945a0SNathan Whitehorn } else { 1384c8945a0SNathan Whitehorn if (obj->buffer_first) { 1394c8945a0SNathan Whitehorn obj->buffer_first = FALSE; 1404c8945a0SNathan Whitehorn 1414c8945a0SNathan Whitehorn /* Allocate space for read buffer */ 1424c8945a0SNathan Whitehorn obj->buf = xalloc(size_read + 1); 1434c8945a0SNathan Whitehorn } 1444c8945a0SNathan Whitehorn 1454c8945a0SNathan Whitehorn obj->bytes_read = obj->fd_bytes_read; 1464c8945a0SNathan Whitehorn } 1474c8945a0SNathan Whitehorn 1484c8945a0SNathan Whitehorn j = 0; 1494c8945a0SNathan Whitehorn begin_line = 0; 1504c8945a0SNathan Whitehorn while (j < obj->fd_bytes_read) 1514c8945a0SNathan Whitehorn if (((ch = buftab[j++]) == TAB) && (dialog_vars.tab_correct != 0)) { 1524c8945a0SNathan Whitehorn tmpint = (dialog_state.tab_len 1534c8945a0SNathan Whitehorn - ((int) ((long) i - begin_line) % dialog_state.tab_len)); 1544c8945a0SNathan Whitehorn for (n = 0; n < tmpint; n++) 1554c8945a0SNathan Whitehorn obj->buf[i++] = ' '; 1564c8945a0SNathan Whitehorn } else { 1574c8945a0SNathan Whitehorn if (ch == '\n') 1584c8945a0SNathan Whitehorn begin_line = i + 1; 1594c8945a0SNathan Whitehorn obj->buf[i++] = ch; 1604c8945a0SNathan Whitehorn } 1614c8945a0SNathan Whitehorn 1624c8945a0SNathan Whitehorn obj->buf[i] = '\0'; /* mark end of valid data */ 1634c8945a0SNathan Whitehorn 1644c8945a0SNathan Whitehorn } 1654c8945a0SNathan Whitehorn if (obj->bytes_read == -1) 1664c8945a0SNathan Whitehorn dlg_exiterr("Error reading file"); 1674c8945a0SNathan Whitehorn free(buftab); 1684c8945a0SNathan Whitehorn } 1694c8945a0SNathan Whitehorn 1704c8945a0SNathan Whitehorn static long 1714c8945a0SNathan Whitehorn find_first(MY_OBJ * obj, char *buffer, long length) 1724c8945a0SNathan Whitehorn { 1734c8945a0SNathan Whitehorn long recount = obj->page_length; 1744c8945a0SNathan Whitehorn long result = 0; 1754c8945a0SNathan Whitehorn 1764c8945a0SNathan Whitehorn while (length > 0) { 1774c8945a0SNathan Whitehorn if (buffer[length] == '\n') { 1784c8945a0SNathan Whitehorn if (--recount < 0) { 1794c8945a0SNathan Whitehorn result = length; 1804c8945a0SNathan Whitehorn break; 1814c8945a0SNathan Whitehorn } 1824c8945a0SNathan Whitehorn } 1834c8945a0SNathan Whitehorn --length; 1844c8945a0SNathan Whitehorn } 1854c8945a0SNathan Whitehorn return result; 1864c8945a0SNathan Whitehorn } 1874c8945a0SNathan Whitehorn 1884c8945a0SNathan Whitehorn static long 1894c8945a0SNathan Whitehorn tabize(MY_OBJ * obj, long val, long *first_pos) 1904c8945a0SNathan Whitehorn { 1914c8945a0SNathan Whitehorn long fpos; 1924c8945a0SNathan Whitehorn long i, count, begin_line; 1934c8945a0SNathan Whitehorn char *buftab; 1944c8945a0SNathan Whitehorn 1954c8945a0SNathan Whitehorn if (!dialog_vars.tab_correct) 1964c8945a0SNathan Whitehorn return val; 1974c8945a0SNathan Whitehorn 1984c8945a0SNathan Whitehorn fpos = ftell_obj(obj); 1994c8945a0SNathan Whitehorn 2004c8945a0SNathan Whitehorn lseek_obj(obj, fpos - obj->fd_bytes_read, SEEK_SET); 2014c8945a0SNathan Whitehorn 2024c8945a0SNathan Whitehorn /* Allocate space for read buffer */ 2034c8945a0SNathan Whitehorn buftab = xalloc((size_t) val + 1); 2044c8945a0SNathan Whitehorn 2054c8945a0SNathan Whitehorn if ((read(obj->fd, buftab, (size_t) val)) == -1) 2064c8945a0SNathan Whitehorn dlg_exiterr("Error reading file in tabize()."); 2074c8945a0SNathan Whitehorn 2084c8945a0SNathan Whitehorn begin_line = count = 0; 2094c8945a0SNathan Whitehorn if (first_pos != 0) 2104c8945a0SNathan Whitehorn *first_pos = 0; 2114c8945a0SNathan Whitehorn 2124c8945a0SNathan Whitehorn for (i = 0; i < val; i++) { 2134c8945a0SNathan Whitehorn if ((first_pos != 0) && (count >= val)) { 2144c8945a0SNathan Whitehorn *first_pos = find_first(obj, buftab, i); 2154c8945a0SNathan Whitehorn break; 2164c8945a0SNathan Whitehorn } 2174c8945a0SNathan Whitehorn if (buftab[i] == TAB) 2184c8945a0SNathan Whitehorn count += dialog_state.tab_len 2194c8945a0SNathan Whitehorn - ((count - begin_line) % dialog_state.tab_len); 2204c8945a0SNathan Whitehorn else if (buftab[i] == '\n') { 2214c8945a0SNathan Whitehorn count++; 2224c8945a0SNathan Whitehorn begin_line = count; 2234c8945a0SNathan Whitehorn } else 2244c8945a0SNathan Whitehorn count++; 2254c8945a0SNathan Whitehorn } 2264c8945a0SNathan Whitehorn 2274c8945a0SNathan Whitehorn lseek_obj(obj, fpos, SEEK_SET); 2284c8945a0SNathan Whitehorn free(buftab); 2294c8945a0SNathan Whitehorn return count; 2304c8945a0SNathan Whitehorn } 2314c8945a0SNathan Whitehorn /* 2324c8945a0SNathan Whitehorn * Return current line of text. 2334c8945a0SNathan Whitehorn * 'page' should point to start of current line before calling, and will be 2344c8945a0SNathan Whitehorn * updated to point to start of next line. 2354c8945a0SNathan Whitehorn */ 2364c8945a0SNathan Whitehorn static char * 2374c8945a0SNathan Whitehorn get_line(MY_OBJ * obj) 2384c8945a0SNathan Whitehorn { 2394c8945a0SNathan Whitehorn int i = 0; 2404c8945a0SNathan Whitehorn long fpos; 2414c8945a0SNathan Whitehorn 2424c8945a0SNathan Whitehorn obj->end_reached = FALSE; 2434c8945a0SNathan Whitehorn while (obj->buf[obj->in_buf] != '\n') { 2444c8945a0SNathan Whitehorn if (obj->buf[obj->in_buf] == '\0') { /* Either end of file or end of buffer reached */ 2454c8945a0SNathan Whitehorn fpos = ftell_obj(obj); 2464c8945a0SNathan Whitehorn 2474c8945a0SNathan Whitehorn if (fpos < obj->file_size) { /* Not end of file yet */ 2484c8945a0SNathan Whitehorn /* We've reached end of buffer, but not end of file yet, so 2494c8945a0SNathan Whitehorn * read next part of file into buffer 2504c8945a0SNathan Whitehorn */ 2514c8945a0SNathan Whitehorn read_high(obj, BUF_SIZE); 2524c8945a0SNathan Whitehorn obj->in_buf = 0; 2534c8945a0SNathan Whitehorn } else { 2544c8945a0SNathan Whitehorn if (!obj->end_reached) 2554c8945a0SNathan Whitehorn obj->end_reached = TRUE; 2564c8945a0SNathan Whitehorn break; 2574c8945a0SNathan Whitehorn } 2584c8945a0SNathan Whitehorn } else if (i < MAX_LEN) 2594c8945a0SNathan Whitehorn obj->line[i++] = obj->buf[obj->in_buf++]; 2604c8945a0SNathan Whitehorn else { 2614c8945a0SNathan Whitehorn if (i == MAX_LEN) /* Truncate lines longer than MAX_LEN characters */ 2624c8945a0SNathan Whitehorn obj->line[i++] = '\0'; 2634c8945a0SNathan Whitehorn obj->in_buf++; 2644c8945a0SNathan Whitehorn } 2654c8945a0SNathan Whitehorn } 2664c8945a0SNathan Whitehorn if (i <= MAX_LEN) 2674c8945a0SNathan Whitehorn obj->line[i] = '\0'; 2684c8945a0SNathan Whitehorn if (!obj->end_reached) 2694c8945a0SNathan Whitehorn obj->in_buf++; /* move past '\n' */ 2704c8945a0SNathan Whitehorn 2714c8945a0SNathan Whitehorn return obj->line; 2724c8945a0SNathan Whitehorn } 2734c8945a0SNathan Whitehorn 2744c8945a0SNathan Whitehorn static bool 2754c8945a0SNathan Whitehorn match_string(MY_OBJ * obj, char *string) 2764c8945a0SNathan Whitehorn { 2774c8945a0SNathan Whitehorn char *match = get_line(obj); 2784c8945a0SNathan Whitehorn return strstr(match, string) != 0; 2794c8945a0SNathan Whitehorn } 2804c8945a0SNathan Whitehorn 2814c8945a0SNathan Whitehorn /* 2824c8945a0SNathan Whitehorn * Go back 'n' lines in text file. Called by dialog_textbox(). 2834c8945a0SNathan Whitehorn * 'in_buf' will be updated to point to the desired line in 'buf'. 2844c8945a0SNathan Whitehorn */ 2854c8945a0SNathan Whitehorn static void 2864c8945a0SNathan Whitehorn back_lines(MY_OBJ * obj, long n) 2874c8945a0SNathan Whitehorn { 2884c8945a0SNathan Whitehorn int i; 2894c8945a0SNathan Whitehorn long fpos; 2904c8945a0SNathan Whitehorn long val_to_tabize; 2914c8945a0SNathan Whitehorn 2924c8945a0SNathan Whitehorn obj->begin_reached = FALSE; 2934c8945a0SNathan Whitehorn /* We have to distinguish between end_reached and !end_reached since at end 2944c8945a0SNathan Whitehorn * of file, the line is not ended by a '\n'. The code inside 'if' 2954c8945a0SNathan Whitehorn * basically does a '--in_buf' to move one character backward so as to 2964c8945a0SNathan Whitehorn * skip '\n' of the previous line */ 2974c8945a0SNathan Whitehorn if (!obj->end_reached) { 2984c8945a0SNathan Whitehorn /* Either beginning of buffer or beginning of file reached? */ 2994c8945a0SNathan Whitehorn 3004c8945a0SNathan Whitehorn if (obj->in_buf == 0) { 3014c8945a0SNathan Whitehorn fpos = ftell_obj(obj); 3024c8945a0SNathan Whitehorn 3034c8945a0SNathan Whitehorn if (fpos > obj->fd_bytes_read) { /* Not beginning of file yet */ 3044c8945a0SNathan Whitehorn /* We've reached beginning of buffer, but not beginning of file 3054c8945a0SNathan Whitehorn * yet, so read previous part of file into buffer. Note that 3064c8945a0SNathan Whitehorn * we only move backward for BUF_SIZE/2 bytes, but not BUF_SIZE 3074c8945a0SNathan Whitehorn * bytes to avoid re-reading again in print_page() later 3084c8945a0SNathan Whitehorn */ 3094c8945a0SNathan Whitehorn /* Really possible to move backward BUF_SIZE/2 bytes? */ 3104c8945a0SNathan Whitehorn if (fpos < BUF_SIZE / 2 + obj->fd_bytes_read) { 3114c8945a0SNathan Whitehorn /* No, move less than */ 312*7a1c0d96SNathan Whitehorn lseek_obj(obj, 0L, SEEK_SET); 3134c8945a0SNathan Whitehorn val_to_tabize = fpos - obj->fd_bytes_read; 3144c8945a0SNathan Whitehorn } else { /* Move backward BUF_SIZE/2 bytes */ 3154c8945a0SNathan Whitehorn lseek_obj(obj, -(BUF_SIZE / 2 + obj->fd_bytes_read), SEEK_CUR); 3164c8945a0SNathan Whitehorn val_to_tabize = BUF_SIZE / 2; 3174c8945a0SNathan Whitehorn } 3184c8945a0SNathan Whitehorn read_high(obj, BUF_SIZE); 3194c8945a0SNathan Whitehorn 3204c8945a0SNathan Whitehorn obj->in_buf = tabize(obj, val_to_tabize, (long *) 0); 3214c8945a0SNathan Whitehorn 3224c8945a0SNathan Whitehorn } else { /* Beginning of file reached */ 3234c8945a0SNathan Whitehorn obj->begin_reached = TRUE; 3244c8945a0SNathan Whitehorn return; 3254c8945a0SNathan Whitehorn } 3264c8945a0SNathan Whitehorn } 3274c8945a0SNathan Whitehorn obj->in_buf--; 3284c8945a0SNathan Whitehorn if (obj->buf[obj->in_buf] != '\n') 3294c8945a0SNathan Whitehorn /* Something's wrong... */ 3304c8945a0SNathan Whitehorn dlg_exiterr("Internal error in back_lines()."); 3314c8945a0SNathan Whitehorn } 3324c8945a0SNathan Whitehorn 3334c8945a0SNathan Whitehorn /* Go back 'n' lines */ 3344c8945a0SNathan Whitehorn for (i = 0; i < n; i++) { 3354c8945a0SNathan Whitehorn do { 3364c8945a0SNathan Whitehorn if (obj->in_buf == 0) { 3374c8945a0SNathan Whitehorn fpos = ftell_obj(obj); 3384c8945a0SNathan Whitehorn 3394c8945a0SNathan Whitehorn if (fpos > obj->fd_bytes_read) { 3404c8945a0SNathan Whitehorn /* Really possible to move backward BUF_SIZE/2 bytes? */ 3414c8945a0SNathan Whitehorn if (fpos < BUF_SIZE / 2 + obj->fd_bytes_read) { 3424c8945a0SNathan Whitehorn /* No, move less than */ 343*7a1c0d96SNathan Whitehorn lseek_obj(obj, 0L, SEEK_SET); 3444c8945a0SNathan Whitehorn val_to_tabize = fpos - obj->fd_bytes_read; 3454c8945a0SNathan Whitehorn } else { /* Move backward BUF_SIZE/2 bytes */ 3464c8945a0SNathan Whitehorn lseek_obj(obj, -(BUF_SIZE / 2 + obj->fd_bytes_read), SEEK_CUR); 3474c8945a0SNathan Whitehorn val_to_tabize = BUF_SIZE / 2; 3484c8945a0SNathan Whitehorn } 3494c8945a0SNathan Whitehorn read_high(obj, BUF_SIZE); 3504c8945a0SNathan Whitehorn 3514c8945a0SNathan Whitehorn obj->in_buf = tabize(obj, val_to_tabize, (long *) 0); 3524c8945a0SNathan Whitehorn 3534c8945a0SNathan Whitehorn } else { /* Beginning of file reached */ 3544c8945a0SNathan Whitehorn obj->begin_reached = TRUE; 3554c8945a0SNathan Whitehorn return; 3564c8945a0SNathan Whitehorn } 3574c8945a0SNathan Whitehorn } 3584c8945a0SNathan Whitehorn } while (obj->buf[--(obj->in_buf)] != '\n'); 3594c8945a0SNathan Whitehorn } 3604c8945a0SNathan Whitehorn obj->in_buf++; 3614c8945a0SNathan Whitehorn } 3624c8945a0SNathan Whitehorn 3634c8945a0SNathan Whitehorn /* 3644c8945a0SNathan Whitehorn * Print a new line of text. 3654c8945a0SNathan Whitehorn */ 3664c8945a0SNathan Whitehorn static void 3674c8945a0SNathan Whitehorn print_line(MY_OBJ * obj, int row, int width) 3684c8945a0SNathan Whitehorn { 3694c8945a0SNathan Whitehorn if (wmove(obj->text, row, 0) != ERR) { 3704c8945a0SNathan Whitehorn int i, y, x; 3714c8945a0SNathan Whitehorn char *line = get_line(obj); 3724c8945a0SNathan Whitehorn const int *cols = dlg_index_columns(line); 3734c8945a0SNathan Whitehorn const int *indx = dlg_index_wchars(line); 3744c8945a0SNathan Whitehorn int limit = dlg_count_wchars(line); 3754c8945a0SNathan Whitehorn int first = 0; 3764c8945a0SNathan Whitehorn int last = limit; 3774c8945a0SNathan Whitehorn 3784c8945a0SNathan Whitehorn if (width > getmaxx(obj->text)) 3794c8945a0SNathan Whitehorn width = getmaxx(obj->text); 3804c8945a0SNathan Whitehorn --width; /* for the leading ' ' */ 3814c8945a0SNathan Whitehorn 3824c8945a0SNathan Whitehorn for (i = 0; i <= limit && cols[i] < obj->hscroll; ++i) 3834c8945a0SNathan Whitehorn first = i; 3844c8945a0SNathan Whitehorn 3854c8945a0SNathan Whitehorn for (i = first; (i <= limit) && ((cols[i] - cols[first]) < width); ++i) 3864c8945a0SNathan Whitehorn last = i; 3874c8945a0SNathan Whitehorn 3884c8945a0SNathan Whitehorn (void) waddch(obj->text, ' '); 3894c8945a0SNathan Whitehorn (void) waddnstr(obj->text, line + indx[first], indx[last] - indx[first]); 3904c8945a0SNathan Whitehorn 3914c8945a0SNathan Whitehorn getyx(obj->text, y, x); 3924c8945a0SNathan Whitehorn if (y == row) { /* Clear 'residue' of previous line */ 3934c8945a0SNathan Whitehorn for (i = 0; i <= width - x; i++) { 3944c8945a0SNathan Whitehorn (void) waddch(obj->text, ' '); 3954c8945a0SNathan Whitehorn } 3964c8945a0SNathan Whitehorn } 3974c8945a0SNathan Whitehorn } 3984c8945a0SNathan Whitehorn } 3994c8945a0SNathan Whitehorn 4004c8945a0SNathan Whitehorn /* 4014c8945a0SNathan Whitehorn * Print a new page of text. 4024c8945a0SNathan Whitehorn */ 4034c8945a0SNathan Whitehorn static void 4044c8945a0SNathan Whitehorn print_page(MY_OBJ * obj, int height, int width) 4054c8945a0SNathan Whitehorn { 4064c8945a0SNathan Whitehorn int i, passed_end = 0; 4074c8945a0SNathan Whitehorn 4084c8945a0SNathan Whitehorn obj->page_length = 0; 4094c8945a0SNathan Whitehorn for (i = 0; i < height; i++) { 4104c8945a0SNathan Whitehorn print_line(obj, i, width); 4114c8945a0SNathan Whitehorn if (!passed_end) 4124c8945a0SNathan Whitehorn obj->page_length++; 4134c8945a0SNathan Whitehorn if (obj->end_reached && !passed_end) 4144c8945a0SNathan Whitehorn passed_end = 1; 4154c8945a0SNathan Whitehorn } 4164c8945a0SNathan Whitehorn (void) wnoutrefresh(obj->text); 4174c8945a0SNathan Whitehorn } 4184c8945a0SNathan Whitehorn 4194c8945a0SNathan Whitehorn /* 4204c8945a0SNathan Whitehorn * Print current position 4214c8945a0SNathan Whitehorn */ 4224c8945a0SNathan Whitehorn static void 4234c8945a0SNathan Whitehorn print_position(MY_OBJ * obj, WINDOW *win, int height, int width) 4244c8945a0SNathan Whitehorn { 4254c8945a0SNathan Whitehorn long fpos; 4264c8945a0SNathan Whitehorn long size; 4274c8945a0SNathan Whitehorn long first = -1; 4284c8945a0SNathan Whitehorn 4294c8945a0SNathan Whitehorn fpos = ftell_obj(obj); 4304c8945a0SNathan Whitehorn if (dialog_vars.tab_correct) 4314c8945a0SNathan Whitehorn size = tabize(obj, obj->in_buf, &first); 4324c8945a0SNathan Whitehorn else 4334c8945a0SNathan Whitehorn first = find_first(obj, obj->buf, size = obj->in_buf); 4344c8945a0SNathan Whitehorn 4354c8945a0SNathan Whitehorn dlg_draw_scrollbar(win, 4364c8945a0SNathan Whitehorn first, 4374c8945a0SNathan Whitehorn fpos - obj->fd_bytes_read + size, 4384c8945a0SNathan Whitehorn fpos - obj->fd_bytes_read + size, 4394c8945a0SNathan Whitehorn obj->file_size, 4404c8945a0SNathan Whitehorn 0, PAGE_WIDTH, 4414c8945a0SNathan Whitehorn 0, PAGE_LENGTH + 1, 4424c8945a0SNathan Whitehorn border_attr, 4434c8945a0SNathan Whitehorn border_attr); 4444c8945a0SNathan Whitehorn } 4454c8945a0SNathan Whitehorn 4464c8945a0SNathan Whitehorn /* 4474c8945a0SNathan Whitehorn * Display a dialog box and get the search term from user. 4484c8945a0SNathan Whitehorn */ 4494c8945a0SNathan Whitehorn static int 4504c8945a0SNathan Whitehorn get_search_term(WINDOW *dialog, char *input, int height, int width) 4514c8945a0SNathan Whitehorn { 4524c8945a0SNathan Whitehorn /* *INDENT-OFF* */ 4534c8945a0SNathan Whitehorn static DLG_KEYS_BINDING binding[] = { 4544c8945a0SNathan Whitehorn INPUTSTR_BINDINGS, 4554c8945a0SNathan Whitehorn ENTERKEY_BINDINGS, 4564c8945a0SNathan Whitehorn END_KEYS_BINDING 4574c8945a0SNathan Whitehorn }; 4584c8945a0SNathan Whitehorn /* *INDENT-ON* */ 4594c8945a0SNathan Whitehorn 4604c8945a0SNathan Whitehorn int old_x, old_y; 4614c8945a0SNathan Whitehorn int box_x, box_y; 4624c8945a0SNathan Whitehorn int box_height, box_width; 4634c8945a0SNathan Whitehorn int offset = 0; 4644c8945a0SNathan Whitehorn int key = 0; 4654c8945a0SNathan Whitehorn int fkey = 0; 4664c8945a0SNathan Whitehorn bool first = TRUE; 4674c8945a0SNathan Whitehorn int result = DLG_EXIT_UNKNOWN; 468*7a1c0d96SNathan Whitehorn const char *caption = _("Search"); 4694c8945a0SNathan Whitehorn int len_caption = dlg_count_columns(caption); 4704c8945a0SNathan Whitehorn const int *indx; 4714c8945a0SNathan Whitehorn int limit; 4724c8945a0SNathan Whitehorn WINDOW *widget; 4734c8945a0SNathan Whitehorn 4744c8945a0SNathan Whitehorn getbegyx(dialog, old_y, old_x); 4754c8945a0SNathan Whitehorn 4764c8945a0SNathan Whitehorn box_height = 1 + (2 * MARGIN); 4774c8945a0SNathan Whitehorn box_width = len_caption + (2 * (MARGIN + 2)); 4784c8945a0SNathan Whitehorn box_width = MAX(box_width, 30); 4794c8945a0SNathan Whitehorn box_width = MIN(box_width, getmaxx(dialog) - 2 * MARGIN); 4804c8945a0SNathan Whitehorn len_caption = MIN(len_caption, box_width - (2 * (MARGIN + 1))); 4814c8945a0SNathan Whitehorn 4824c8945a0SNathan Whitehorn box_x = (width - box_width) / 2; 4834c8945a0SNathan Whitehorn box_y = (height - box_height) / 2; 4844c8945a0SNathan Whitehorn widget = dlg_new_modal_window(dialog, 4854c8945a0SNathan Whitehorn box_height, box_width, 4864c8945a0SNathan Whitehorn old_y + box_y, old_x + box_x); 4874c8945a0SNathan Whitehorn keypad(widget, TRUE); 4884c8945a0SNathan Whitehorn dlg_register_window(widget, "searchbox", binding); 4894c8945a0SNathan Whitehorn 4904c8945a0SNathan Whitehorn dlg_draw_box(widget, 0, 0, box_height, box_width, 4914c8945a0SNathan Whitehorn searchbox_attr, 4924c8945a0SNathan Whitehorn searchbox_border_attr); 4934c8945a0SNathan Whitehorn wattrset(widget, searchbox_title_attr); 4944c8945a0SNathan Whitehorn (void) wmove(widget, 0, (box_width - len_caption) / 2); 4954c8945a0SNathan Whitehorn 4964c8945a0SNathan Whitehorn indx = dlg_index_wchars(caption); 4974c8945a0SNathan Whitehorn limit = dlg_limit_columns(caption, len_caption, 0); 4984c8945a0SNathan Whitehorn (void) waddnstr(widget, caption + indx[0], indx[limit] - indx[0]); 4994c8945a0SNathan Whitehorn 5004c8945a0SNathan Whitehorn box_y++; 5014c8945a0SNathan Whitehorn box_x++; 5024c8945a0SNathan Whitehorn box_width -= 2; 5034c8945a0SNathan Whitehorn offset = dlg_count_columns(input); 5044c8945a0SNathan Whitehorn 5054c8945a0SNathan Whitehorn while (result == DLG_EXIT_UNKNOWN) { 5064c8945a0SNathan Whitehorn if (!first) { 5074c8945a0SNathan Whitehorn key = dlg_getc(widget, &fkey); 5084c8945a0SNathan Whitehorn if (fkey) { 5094c8945a0SNathan Whitehorn switch (fkey) { 5104c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 5114c8945a0SNathan Whitehorn case KEY_RESIZE: 5124c8945a0SNathan Whitehorn result = DLG_EXIT_CANCEL; 5134c8945a0SNathan Whitehorn continue; 5144c8945a0SNathan Whitehorn #endif 5154c8945a0SNathan Whitehorn case DLGK_ENTER: 5164c8945a0SNathan Whitehorn result = DLG_EXIT_OK; 5174c8945a0SNathan Whitehorn continue; 5184c8945a0SNathan Whitehorn } 5194c8945a0SNathan Whitehorn } else if (key == ESC) { 5204c8945a0SNathan Whitehorn result = DLG_EXIT_ESC; 5214c8945a0SNathan Whitehorn continue; 5224c8945a0SNathan Whitehorn } else if (key == ERR) { 5234c8945a0SNathan Whitehorn napms(50); 5244c8945a0SNathan Whitehorn continue; 5254c8945a0SNathan Whitehorn } 5264c8945a0SNathan Whitehorn } 5274c8945a0SNathan Whitehorn if (dlg_edit_string(input, &offset, key, fkey, first)) { 5284c8945a0SNathan Whitehorn dlg_show_string(widget, input, offset, searchbox_attr, 5294c8945a0SNathan Whitehorn 1, 1, box_width, FALSE, first); 5304c8945a0SNathan Whitehorn first = FALSE; 5314c8945a0SNathan Whitehorn } 5324c8945a0SNathan Whitehorn } 5334c8945a0SNathan Whitehorn dlg_del_window(widget); 5344c8945a0SNathan Whitehorn return result; 5354c8945a0SNathan Whitehorn } 5364c8945a0SNathan Whitehorn 5374c8945a0SNathan Whitehorn static bool 5384c8945a0SNathan Whitehorn perform_search(MY_OBJ * obj, int height, int width, int key, char *search_term) 5394c8945a0SNathan Whitehorn { 5404c8945a0SNathan Whitehorn int dir; 5414c8945a0SNathan Whitehorn long tempinx; 5424c8945a0SNathan Whitehorn long fpos; 5434c8945a0SNathan Whitehorn int result; 5444c8945a0SNathan Whitehorn bool found; 5454c8945a0SNathan Whitehorn bool temp, temp1; 5464c8945a0SNathan Whitehorn bool moved = FALSE; 5474c8945a0SNathan Whitehorn 5484c8945a0SNathan Whitehorn /* set search direction */ 5494c8945a0SNathan Whitehorn dir = (key == '/' || key == 'n') ? 1 : 0; 5504c8945a0SNathan Whitehorn if (dir ? !obj->end_reached : !obj->begin_reached) { 5514c8945a0SNathan Whitehorn if (key == 'n' || key == 'N') { 5524c8945a0SNathan Whitehorn if (search_term[0] == '\0') { /* No search term yet */ 5534c8945a0SNathan Whitehorn (void) beep(); 5544c8945a0SNathan Whitehorn return FALSE; 5554c8945a0SNathan Whitehorn } 5564c8945a0SNathan Whitehorn /* Get search term from user */ 5574c8945a0SNathan Whitehorn } else if ((result = get_search_term(obj->text, search_term, 5584c8945a0SNathan Whitehorn PAGE_LENGTH, 5594c8945a0SNathan Whitehorn PAGE_WIDTH)) != DLG_EXIT_OK 5604c8945a0SNathan Whitehorn || search_term[0] == '\0') { 5614c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 5624c8945a0SNathan Whitehorn if (result == DLG_EXIT_CANCEL) { 5634c8945a0SNathan Whitehorn ungetch(key); 5644c8945a0SNathan Whitehorn ungetch(KEY_RESIZE); 5654c8945a0SNathan Whitehorn /* FALLTHRU */ 5664c8945a0SNathan Whitehorn } 5674c8945a0SNathan Whitehorn #endif 5684c8945a0SNathan Whitehorn /* ESC pressed, or no search term, reprint page to clear box */ 5694c8945a0SNathan Whitehorn wattrset(obj->text, dialog_attr); 5704c8945a0SNathan Whitehorn back_lines(obj, obj->page_length); 5714c8945a0SNathan Whitehorn return TRUE; 5724c8945a0SNathan Whitehorn } 5734c8945a0SNathan Whitehorn /* Save variables for restoring in case search term can't be found */ 5744c8945a0SNathan Whitehorn tempinx = obj->in_buf; 5754c8945a0SNathan Whitehorn temp = obj->begin_reached; 5764c8945a0SNathan Whitehorn temp1 = obj->end_reached; 5774c8945a0SNathan Whitehorn fpos = ftell_obj(obj) - obj->fd_bytes_read; 5784c8945a0SNathan Whitehorn /* update 'in_buf' to point to next (previous) line before 5794c8945a0SNathan Whitehorn forward (backward) searching */ 5804c8945a0SNathan Whitehorn back_lines(obj, (dir 5814c8945a0SNathan Whitehorn ? obj->page_length - 1 5824c8945a0SNathan Whitehorn : obj->page_length + 1)); 5834c8945a0SNathan Whitehorn found = FALSE; 5844c8945a0SNathan Whitehorn if (dir) { /* Forward search */ 5854c8945a0SNathan Whitehorn while ((found = match_string(obj, search_term)) == FALSE) { 5864c8945a0SNathan Whitehorn if (obj->end_reached) 5874c8945a0SNathan Whitehorn break; 5884c8945a0SNathan Whitehorn } 5894c8945a0SNathan Whitehorn } else { /* Backward search */ 5904c8945a0SNathan Whitehorn while ((found = match_string(obj, search_term)) == FALSE) { 5914c8945a0SNathan Whitehorn if (obj->begin_reached) 5924c8945a0SNathan Whitehorn break; 593*7a1c0d96SNathan Whitehorn back_lines(obj, 2L); 5944c8945a0SNathan Whitehorn } 5954c8945a0SNathan Whitehorn } 5964c8945a0SNathan Whitehorn if (found == FALSE) { /* not found */ 5974c8945a0SNathan Whitehorn (void) beep(); 5984c8945a0SNathan Whitehorn /* Restore program state to that before searching */ 5994c8945a0SNathan Whitehorn lseek_obj(obj, fpos, SEEK_SET); 6004c8945a0SNathan Whitehorn 6014c8945a0SNathan Whitehorn read_high(obj, BUF_SIZE); 6024c8945a0SNathan Whitehorn 6034c8945a0SNathan Whitehorn obj->in_buf = tempinx; 6044c8945a0SNathan Whitehorn obj->begin_reached = temp; 6054c8945a0SNathan Whitehorn obj->end_reached = temp1; 6064c8945a0SNathan Whitehorn /* move 'in_buf' to point to start of current page to 6074c8945a0SNathan Whitehorn * re-print current page. Note that 'in_buf' always points 6084c8945a0SNathan Whitehorn * to start of next page, so this is necessary 6094c8945a0SNathan Whitehorn */ 6104c8945a0SNathan Whitehorn back_lines(obj, obj->page_length); 6114c8945a0SNathan Whitehorn } else { /* Search term found */ 612*7a1c0d96SNathan Whitehorn back_lines(obj, 1L); 6134c8945a0SNathan Whitehorn } 6144c8945a0SNathan Whitehorn /* Reprint page */ 6154c8945a0SNathan Whitehorn wattrset(obj->text, dialog_attr); 6164c8945a0SNathan Whitehorn moved = TRUE; 6174c8945a0SNathan Whitehorn } else { /* no need to find */ 6184c8945a0SNathan Whitehorn (void) beep(); 6194c8945a0SNathan Whitehorn } 6204c8945a0SNathan Whitehorn return moved; 6214c8945a0SNathan Whitehorn } 6224c8945a0SNathan Whitehorn 6234c8945a0SNathan Whitehorn /* 6244c8945a0SNathan Whitehorn * Display text from a file in a dialog box. 6254c8945a0SNathan Whitehorn */ 6264c8945a0SNathan Whitehorn int 6274c8945a0SNathan Whitehorn dialog_textbox(const char *title, const char *file, int height, int width) 6284c8945a0SNathan Whitehorn { 6294c8945a0SNathan Whitehorn /* *INDENT-OFF* */ 6304c8945a0SNathan Whitehorn static DLG_KEYS_BINDING binding[] = { 6314c8945a0SNathan Whitehorn ENTERKEY_BINDINGS, 6324c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, 'J' ), 6334c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, 'j' ), 6344c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, KEY_DOWN ), 6354c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, 'H' ), 6364c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, 'h' ), 6374c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, KEY_LEFT ), 6384c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, 'L' ), 6394c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, 'l' ), 6404c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, KEY_RIGHT ), 6414c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_UP, 'K' ), 6424c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_UP, 'k' ), 6434c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_UP, KEY_UP ), 6444c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_FIRST, 'g' ), 6454c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_FIRST, KEY_HOME ), 6464c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_LAST, 'G' ), 6474c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_LAST, KEY_END ), 6484c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_LAST, KEY_LL ), 6494c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_NEXT, ' ' ), 6504c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_NEXT, KEY_NPAGE ), 6514c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_PREV, 'B' ), 6524c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_PREV, 'b' ), 6534c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_PREV, KEY_PPAGE ), 6544c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_BEGIN, '0' ), 6554c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_BEGIN, KEY_BEG ), 6564c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ), 6574c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ), 6584c8945a0SNathan Whitehorn END_KEYS_BINDING 6594c8945a0SNathan Whitehorn }; 6604c8945a0SNathan Whitehorn /* *INDENT-ON* */ 6614c8945a0SNathan Whitehorn 6624c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 6634c8945a0SNathan Whitehorn int old_height = height; 6644c8945a0SNathan Whitehorn int old_width = width; 6654c8945a0SNathan Whitehorn #endif 6664c8945a0SNathan Whitehorn long fpos; 6674c8945a0SNathan Whitehorn int x, y, cur_x, cur_y; 6684c8945a0SNathan Whitehorn int key = 0, fkey; 6694c8945a0SNathan Whitehorn int next = 0; 6704c8945a0SNathan Whitehorn int i, code, passed_end; 6714c8945a0SNathan Whitehorn char search_term[MAX_LEN + 1]; 6724c8945a0SNathan Whitehorn MY_OBJ obj; 6734c8945a0SNathan Whitehorn WINDOW *dialog; 6744c8945a0SNathan Whitehorn bool moved; 6754c8945a0SNathan Whitehorn int result = DLG_EXIT_UNKNOWN; 6764c8945a0SNathan Whitehorn int button = dialog_vars.extra_button ? dlg_defaultno_button() : 0; 6774c8945a0SNathan Whitehorn int min_width = 12; 6784c8945a0SNathan Whitehorn 6794c8945a0SNathan Whitehorn search_term[0] = '\0'; /* no search term entered yet */ 6804c8945a0SNathan Whitehorn 6814c8945a0SNathan Whitehorn memset(&obj, 0, sizeof(obj)); 6824c8945a0SNathan Whitehorn 6834c8945a0SNathan Whitehorn obj.begin_reached = TRUE; 6844c8945a0SNathan Whitehorn obj.buffer_first = TRUE; 6854c8945a0SNathan Whitehorn obj.end_reached = FALSE; 6864c8945a0SNathan Whitehorn obj.buttons = dlg_exit_label(); 6874c8945a0SNathan Whitehorn 6884c8945a0SNathan Whitehorn /* Open input file for reading */ 6894c8945a0SNathan Whitehorn if ((obj.fd = open(file, O_RDONLY)) == -1) 6904c8945a0SNathan Whitehorn dlg_exiterr("Can't open input file %s", file); 6914c8945a0SNathan Whitehorn 6924c8945a0SNathan Whitehorn /* Get file size. Actually, 'file_size' is the real file size - 1, 6934c8945a0SNathan Whitehorn since it's only the last byte offset from the beginning */ 694*7a1c0d96SNathan Whitehorn obj.file_size = lseek_obj(&obj, 0L, SEEK_END); 6954c8945a0SNathan Whitehorn 6964c8945a0SNathan Whitehorn /* Restore file pointer to beginning of file after getting file size */ 697*7a1c0d96SNathan Whitehorn lseek_obj(&obj, 0L, SEEK_SET); 6984c8945a0SNathan Whitehorn 6994c8945a0SNathan Whitehorn read_high(&obj, BUF_SIZE); 7004c8945a0SNathan Whitehorn 7014c8945a0SNathan Whitehorn dlg_button_layout(obj.buttons, &min_width); 7024c8945a0SNathan Whitehorn 7034c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 7044c8945a0SNathan Whitehorn retry: 7054c8945a0SNathan Whitehorn #endif 7064c8945a0SNathan Whitehorn moved = TRUE; 7074c8945a0SNathan Whitehorn 7084c8945a0SNathan Whitehorn dlg_auto_sizefile(title, file, &height, &width, 2, min_width); 7094c8945a0SNathan Whitehorn dlg_print_size(height, width); 7104c8945a0SNathan Whitehorn dlg_ctl_size(height, width); 7114c8945a0SNathan Whitehorn 7124c8945a0SNathan Whitehorn x = dlg_box_x_ordinate(width); 7134c8945a0SNathan Whitehorn y = dlg_box_y_ordinate(height); 7144c8945a0SNathan Whitehorn 7154c8945a0SNathan Whitehorn dialog = dlg_new_window(height, width, y, x); 7164c8945a0SNathan Whitehorn dlg_register_window(dialog, "textbox", binding); 7174c8945a0SNathan Whitehorn dlg_register_buttons(dialog, "textbox", obj.buttons); 7184c8945a0SNathan Whitehorn 7194c8945a0SNathan Whitehorn dlg_mouse_setbase(x, y); 7204c8945a0SNathan Whitehorn 7214c8945a0SNathan Whitehorn /* Create window for text region, used for scrolling text */ 7224c8945a0SNathan Whitehorn obj.text = dlg_sub_window(dialog, PAGE_LENGTH, PAGE_WIDTH, y + 1, x + 1); 7234c8945a0SNathan Whitehorn 7244c8945a0SNathan Whitehorn /* register the new window, along with its borders */ 7254c8945a0SNathan Whitehorn dlg_mouse_mkbigregion(0, 0, PAGE_LENGTH + 2, width, KEY_MAX, 1, 1, 1 /* lines */ ); 7264c8945a0SNathan Whitehorn dlg_draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); 7274c8945a0SNathan Whitehorn dlg_draw_bottom_box(dialog); 7284c8945a0SNathan Whitehorn dlg_draw_title(dialog, title); 7294c8945a0SNathan Whitehorn 7304c8945a0SNathan Whitehorn dlg_draw_buttons(dialog, PAGE_LENGTH + 2, 0, obj.buttons, button, FALSE, width); 7314c8945a0SNathan Whitehorn (void) wnoutrefresh(dialog); 7324c8945a0SNathan Whitehorn getyx(dialog, cur_y, cur_x); /* Save cursor position */ 7334c8945a0SNathan Whitehorn 7344c8945a0SNathan Whitehorn dlg_attr_clear(obj.text, PAGE_LENGTH, PAGE_WIDTH, dialog_attr); 7354c8945a0SNathan Whitehorn 7364c8945a0SNathan Whitehorn while (result == DLG_EXIT_UNKNOWN) { 7374c8945a0SNathan Whitehorn 7384c8945a0SNathan Whitehorn /* 7394c8945a0SNathan Whitehorn * Update the screen according to whether we shifted up/down by a line 7404c8945a0SNathan Whitehorn * or not. 7414c8945a0SNathan Whitehorn */ 7424c8945a0SNathan Whitehorn if (moved) { 7434c8945a0SNathan Whitehorn if (next < 0) { 7444c8945a0SNathan Whitehorn (void) scrollok(obj.text, TRUE); 7454c8945a0SNathan Whitehorn (void) scroll(obj.text); /* Scroll text region up one line */ 7464c8945a0SNathan Whitehorn (void) scrollok(obj.text, FALSE); 7474c8945a0SNathan Whitehorn print_line(&obj, PAGE_LENGTH - 1, PAGE_WIDTH); 7484c8945a0SNathan Whitehorn (void) wnoutrefresh(obj.text); 7494c8945a0SNathan Whitehorn } else if (next > 0) { 7504c8945a0SNathan Whitehorn /* 7514c8945a0SNathan Whitehorn * We don't call print_page() here but use scrolling to ensure 7524c8945a0SNathan Whitehorn * faster screen update. However, 'end_reached' and 7534c8945a0SNathan Whitehorn * 'page_length' should still be updated, and 'in_buf' should 7544c8945a0SNathan Whitehorn * point to start of next page. This is done by calling 7554c8945a0SNathan Whitehorn * get_line() in the following 'for' loop. 7564c8945a0SNathan Whitehorn */ 7574c8945a0SNathan Whitehorn (void) scrollok(obj.text, TRUE); 7584c8945a0SNathan Whitehorn (void) wscrl(obj.text, -1); /* Scroll text region down one line */ 7594c8945a0SNathan Whitehorn (void) scrollok(obj.text, FALSE); 7604c8945a0SNathan Whitehorn obj.page_length = 0; 7614c8945a0SNathan Whitehorn passed_end = 0; 7624c8945a0SNathan Whitehorn for (i = 0; i < PAGE_LENGTH; i++) { 7634c8945a0SNathan Whitehorn if (!i) { 7644c8945a0SNathan Whitehorn print_line(&obj, 0, PAGE_WIDTH); /* print first line of page */ 7654c8945a0SNathan Whitehorn (void) wnoutrefresh(obj.text); 7664c8945a0SNathan Whitehorn } else 7674c8945a0SNathan Whitehorn (void) get_line(&obj); /* Called to update 'end_reached' and 'in_buf' */ 7684c8945a0SNathan Whitehorn if (!passed_end) 7694c8945a0SNathan Whitehorn obj.page_length++; 7704c8945a0SNathan Whitehorn if (obj.end_reached && !passed_end) 7714c8945a0SNathan Whitehorn passed_end = 1; 7724c8945a0SNathan Whitehorn } 7734c8945a0SNathan Whitehorn } else { 7744c8945a0SNathan Whitehorn print_page(&obj, PAGE_LENGTH, PAGE_WIDTH); 7754c8945a0SNathan Whitehorn } 7764c8945a0SNathan Whitehorn print_position(&obj, dialog, height, width); 7774c8945a0SNathan Whitehorn (void) wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 7784c8945a0SNathan Whitehorn wrefresh(dialog); 7794c8945a0SNathan Whitehorn } 7804c8945a0SNathan Whitehorn moved = FALSE; /* assume we'll not move */ 7814c8945a0SNathan Whitehorn next = 0; /* ...but not scroll by a line */ 7824c8945a0SNathan Whitehorn 7834c8945a0SNathan Whitehorn key = dlg_mouse_wgetch(dialog, &fkey); 7844c8945a0SNathan Whitehorn if (dlg_result_key(key, fkey, &result)) 7854c8945a0SNathan Whitehorn break; 7864c8945a0SNathan Whitehorn 7874c8945a0SNathan Whitehorn if (!fkey && (code = dlg_char_to_button(key, obj.buttons)) >= 0) { 7884c8945a0SNathan Whitehorn result = dlg_ok_buttoncode(code); 7894c8945a0SNathan Whitehorn break; 7904c8945a0SNathan Whitehorn } 7914c8945a0SNathan Whitehorn 7924c8945a0SNathan Whitehorn if (fkey) { 7934c8945a0SNathan Whitehorn switch (key) { 7944c8945a0SNathan Whitehorn default: 7954c8945a0SNathan Whitehorn if (is_DLGK_MOUSE(key)) { 7964c8945a0SNathan Whitehorn result = dlg_exit_buttoncode(key - M_EVENT); 7974c8945a0SNathan Whitehorn if (result < 0) 7984c8945a0SNathan Whitehorn result = DLG_EXIT_OK; 7994c8945a0SNathan Whitehorn } else { 8004c8945a0SNathan Whitehorn beep(); 8014c8945a0SNathan Whitehorn } 8024c8945a0SNathan Whitehorn break; 8034c8945a0SNathan Whitehorn case DLGK_FIELD_NEXT: 8044c8945a0SNathan Whitehorn button = dlg_next_button(obj.buttons, button); 8054c8945a0SNathan Whitehorn if (button < 0) 8064c8945a0SNathan Whitehorn button = 0; 8074c8945a0SNathan Whitehorn dlg_draw_buttons(dialog, 8084c8945a0SNathan Whitehorn height - 2, 0, 8094c8945a0SNathan Whitehorn obj.buttons, button, 8104c8945a0SNathan Whitehorn FALSE, width); 8114c8945a0SNathan Whitehorn break; 8124c8945a0SNathan Whitehorn case DLGK_FIELD_PREV: 8134c8945a0SNathan Whitehorn button = dlg_prev_button(obj.buttons, button); 8144c8945a0SNathan Whitehorn if (button < 0) 8154c8945a0SNathan Whitehorn button = 0; 8164c8945a0SNathan Whitehorn dlg_draw_buttons(dialog, 8174c8945a0SNathan Whitehorn height - 2, 0, 8184c8945a0SNathan Whitehorn obj.buttons, button, 8194c8945a0SNathan Whitehorn FALSE, width); 8204c8945a0SNathan Whitehorn break; 8214c8945a0SNathan Whitehorn case DLGK_ENTER: 8224c8945a0SNathan Whitehorn result = dlg_exit_buttoncode(button); 8234c8945a0SNathan Whitehorn break; 8244c8945a0SNathan Whitehorn case DLGK_PAGE_FIRST: 8254c8945a0SNathan Whitehorn if (!obj.begin_reached) { 8264c8945a0SNathan Whitehorn obj.begin_reached = 1; 8274c8945a0SNathan Whitehorn /* First page not in buffer? */ 8284c8945a0SNathan Whitehorn fpos = ftell_obj(&obj); 8294c8945a0SNathan Whitehorn 8304c8945a0SNathan Whitehorn if (fpos > obj.fd_bytes_read) { 8314c8945a0SNathan Whitehorn /* Yes, we have to read it in */ 832*7a1c0d96SNathan Whitehorn lseek_obj(&obj, 0L, SEEK_SET); 8334c8945a0SNathan Whitehorn 8344c8945a0SNathan Whitehorn read_high(&obj, BUF_SIZE); 8354c8945a0SNathan Whitehorn } 8364c8945a0SNathan Whitehorn obj.in_buf = 0; 8374c8945a0SNathan Whitehorn moved = TRUE; 8384c8945a0SNathan Whitehorn } 8394c8945a0SNathan Whitehorn break; 8404c8945a0SNathan Whitehorn case DLGK_PAGE_LAST: 8414c8945a0SNathan Whitehorn obj.end_reached = TRUE; 8424c8945a0SNathan Whitehorn /* Last page not in buffer? */ 8434c8945a0SNathan Whitehorn fpos = ftell_obj(&obj); 8444c8945a0SNathan Whitehorn 8454c8945a0SNathan Whitehorn if (fpos < obj.file_size) { 8464c8945a0SNathan Whitehorn /* Yes, we have to read it in */ 8474c8945a0SNathan Whitehorn lseek_obj(&obj, -BUF_SIZE, SEEK_END); 8484c8945a0SNathan Whitehorn 8494c8945a0SNathan Whitehorn read_high(&obj, BUF_SIZE); 8504c8945a0SNathan Whitehorn } 8514c8945a0SNathan Whitehorn obj.in_buf = obj.bytes_read; 852*7a1c0d96SNathan Whitehorn back_lines(&obj, (long) PAGE_LENGTH); 8534c8945a0SNathan Whitehorn moved = TRUE; 8544c8945a0SNathan Whitehorn break; 8554c8945a0SNathan Whitehorn case DLGK_GRID_UP: /* Previous line */ 8564c8945a0SNathan Whitehorn if (!obj.begin_reached) { 8574c8945a0SNathan Whitehorn back_lines(&obj, obj.page_length + 1); 8584c8945a0SNathan Whitehorn next = 1; 8594c8945a0SNathan Whitehorn moved = TRUE; 8604c8945a0SNathan Whitehorn } 8614c8945a0SNathan Whitehorn break; 8624c8945a0SNathan Whitehorn case DLGK_PAGE_PREV: /* Previous page */ 8634c8945a0SNathan Whitehorn case DLGK_MOUSE(KEY_PPAGE): 8644c8945a0SNathan Whitehorn if (!obj.begin_reached) { 8654c8945a0SNathan Whitehorn back_lines(&obj, obj.page_length + PAGE_LENGTH); 8664c8945a0SNathan Whitehorn moved = TRUE; 8674c8945a0SNathan Whitehorn } 8684c8945a0SNathan Whitehorn break; 8694c8945a0SNathan Whitehorn case DLGK_GRID_DOWN: /* Next line */ 8704c8945a0SNathan Whitehorn if (!obj.end_reached) { 8714c8945a0SNathan Whitehorn obj.begin_reached = 0; 8724c8945a0SNathan Whitehorn next = -1; 8734c8945a0SNathan Whitehorn moved = TRUE; 8744c8945a0SNathan Whitehorn } 8754c8945a0SNathan Whitehorn break; 8764c8945a0SNathan Whitehorn case DLGK_PAGE_NEXT: /* Next page */ 8774c8945a0SNathan Whitehorn case DLGK_MOUSE(KEY_NPAGE): 8784c8945a0SNathan Whitehorn if (!obj.end_reached) { 8794c8945a0SNathan Whitehorn obj.begin_reached = 0; 8804c8945a0SNathan Whitehorn moved = TRUE; 8814c8945a0SNathan Whitehorn } 8824c8945a0SNathan Whitehorn break; 8834c8945a0SNathan Whitehorn case DLGK_BEGIN: /* Beginning of line */ 8844c8945a0SNathan Whitehorn if (obj.hscroll > 0) { 8854c8945a0SNathan Whitehorn obj.hscroll = 0; 8864c8945a0SNathan Whitehorn /* Reprint current page to scroll horizontally */ 8874c8945a0SNathan Whitehorn back_lines(&obj, obj.page_length); 8884c8945a0SNathan Whitehorn moved = TRUE; 8894c8945a0SNathan Whitehorn } 8904c8945a0SNathan Whitehorn break; 8914c8945a0SNathan Whitehorn case DLGK_GRID_LEFT: /* Scroll left */ 8924c8945a0SNathan Whitehorn if (obj.hscroll > 0) { 8934c8945a0SNathan Whitehorn obj.hscroll--; 8944c8945a0SNathan Whitehorn /* Reprint current page to scroll horizontally */ 8954c8945a0SNathan Whitehorn back_lines(&obj, obj.page_length); 8964c8945a0SNathan Whitehorn moved = TRUE; 8974c8945a0SNathan Whitehorn } 8984c8945a0SNathan Whitehorn break; 8994c8945a0SNathan Whitehorn case DLGK_GRID_RIGHT: /* Scroll right */ 9004c8945a0SNathan Whitehorn if (obj.hscroll < MAX_LEN) { 9014c8945a0SNathan Whitehorn obj.hscroll++; 9024c8945a0SNathan Whitehorn /* Reprint current page to scroll horizontally */ 9034c8945a0SNathan Whitehorn back_lines(&obj, obj.page_length); 9044c8945a0SNathan Whitehorn moved = TRUE; 9054c8945a0SNathan Whitehorn } 9064c8945a0SNathan Whitehorn break; 9074c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 9084c8945a0SNathan Whitehorn case KEY_RESIZE: 9094c8945a0SNathan Whitehorn /* reset data */ 9104c8945a0SNathan Whitehorn height = old_height; 9114c8945a0SNathan Whitehorn width = old_width; 9124c8945a0SNathan Whitehorn back_lines(&obj, obj.page_length); 9134c8945a0SNathan Whitehorn moved = TRUE; 9144c8945a0SNathan Whitehorn /* repaint */ 9154c8945a0SNathan Whitehorn dlg_clear(); 9164c8945a0SNathan Whitehorn dlg_del_window(dialog); 9174c8945a0SNathan Whitehorn refresh(); 9184c8945a0SNathan Whitehorn dlg_mouse_free_regions(); 9194c8945a0SNathan Whitehorn goto retry; 9204c8945a0SNathan Whitehorn #endif 9214c8945a0SNathan Whitehorn } 9224c8945a0SNathan Whitehorn } else { 9234c8945a0SNathan Whitehorn switch (key) { 9244c8945a0SNathan Whitehorn case '/': /* Forward search */ 9254c8945a0SNathan Whitehorn case 'n': /* Repeat forward search */ 9264c8945a0SNathan Whitehorn case '?': /* Backward search */ 9274c8945a0SNathan Whitehorn case 'N': /* Repeat backward search */ 9284c8945a0SNathan Whitehorn moved = perform_search(&obj, height, width, key, search_term); 9294c8945a0SNathan Whitehorn fkey = FALSE; 9304c8945a0SNathan Whitehorn break; 9314c8945a0SNathan Whitehorn default: 9324c8945a0SNathan Whitehorn beep(); 9334c8945a0SNathan Whitehorn break; 9344c8945a0SNathan Whitehorn } 9354c8945a0SNathan Whitehorn } 9364c8945a0SNathan Whitehorn } 9374c8945a0SNathan Whitehorn 9384c8945a0SNathan Whitehorn dlg_del_window(dialog); 9394c8945a0SNathan Whitehorn free(obj.buf); 9404c8945a0SNathan Whitehorn (void) close(obj.fd); 9414c8945a0SNathan Whitehorn dlg_mouse_free_regions(); 9424c8945a0SNathan Whitehorn return result; 9434c8945a0SNathan Whitehorn } 944