14c8945a0SNathan Whitehorn /* 2*2a3e3873SBaptiste Daroussin * $Id: textbox.c,v 1.110 2012/12/01 01:48:08 tom Exp $ 34c8945a0SNathan Whitehorn * 44c8945a0SNathan Whitehorn * textbox.c -- implements the text box 54c8945a0SNathan Whitehorn * 6*2a3e3873SBaptiste Daroussin * Copyright 2000-2011,2012 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) { 58*2a3e3873SBaptiste Daroussin default: 594c8945a0SNathan Whitehorn case SEEK_CUR: 604c8945a0SNathan Whitehorn dlg_exiterr("Cannot get file position"); 614c8945a0SNathan Whitehorn break; 624c8945a0SNathan Whitehorn case SEEK_END: 634c8945a0SNathan Whitehorn dlg_exiterr("Cannot seek to end of file"); 644c8945a0SNathan Whitehorn break; 654c8945a0SNathan Whitehorn case SEEK_SET: 664c8945a0SNathan Whitehorn dlg_exiterr("Cannot set file position to %ld", offset); 674c8945a0SNathan Whitehorn break; 684c8945a0SNathan Whitehorn } 694c8945a0SNathan Whitehorn } 704c8945a0SNathan Whitehorn return fpos; 714c8945a0SNathan Whitehorn } 724c8945a0SNathan Whitehorn 734c8945a0SNathan Whitehorn static long 744c8945a0SNathan Whitehorn ftell_obj(MY_OBJ * obj) 754c8945a0SNathan Whitehorn { 767a1c0d96SNathan Whitehorn return lseek_obj(obj, 0L, SEEK_CUR); 774c8945a0SNathan Whitehorn } 784c8945a0SNathan Whitehorn 79*2a3e3873SBaptiste Daroussin static void 80*2a3e3873SBaptiste Daroussin lseek_set(MY_OBJ * obj, long offset) 81*2a3e3873SBaptiste Daroussin { 82*2a3e3873SBaptiste Daroussin long actual = lseek_obj(obj, offset, SEEK_SET); 83*2a3e3873SBaptiste Daroussin 84*2a3e3873SBaptiste Daroussin if (actual != offset) { 85*2a3e3873SBaptiste Daroussin dlg_exiterr("Cannot set file position to %ld (actual %ld)\n", 86*2a3e3873SBaptiste Daroussin offset, actual); 87*2a3e3873SBaptiste Daroussin } 88*2a3e3873SBaptiste Daroussin } 89*2a3e3873SBaptiste Daroussin 90*2a3e3873SBaptiste Daroussin static void 91*2a3e3873SBaptiste Daroussin lseek_end(MY_OBJ * obj, long offset) 92*2a3e3873SBaptiste Daroussin { 93*2a3e3873SBaptiste Daroussin long actual = lseek_obj(obj, offset, SEEK_END); 94*2a3e3873SBaptiste Daroussin 95*2a3e3873SBaptiste Daroussin if (actual > offset) { 96*2a3e3873SBaptiste Daroussin obj->file_size = actual; 97*2a3e3873SBaptiste Daroussin } 98*2a3e3873SBaptiste Daroussin } 99*2a3e3873SBaptiste Daroussin 100*2a3e3873SBaptiste Daroussin static void 101*2a3e3873SBaptiste Daroussin lseek_cur(MY_OBJ * obj, long offset) 102*2a3e3873SBaptiste Daroussin { 103*2a3e3873SBaptiste Daroussin long actual = lseek_obj(obj, offset, SEEK_CUR); 104*2a3e3873SBaptiste Daroussin 105*2a3e3873SBaptiste Daroussin if (actual != offset) { 106*2a3e3873SBaptiste Daroussin dlg_trace_msg("Lseek returned %ld, expected %ld\n", actual, offset); 107*2a3e3873SBaptiste Daroussin } 108*2a3e3873SBaptiste Daroussin } 109*2a3e3873SBaptiste Daroussin 1104c8945a0SNathan Whitehorn static char * 1114c8945a0SNathan Whitehorn xalloc(size_t size) 1124c8945a0SNathan Whitehorn { 1134c8945a0SNathan Whitehorn char *result = dlg_malloc(char, size); 1144c8945a0SNathan Whitehorn assert_ptr(result, "xalloc"); 1154c8945a0SNathan Whitehorn return result; 1164c8945a0SNathan Whitehorn } 1174c8945a0SNathan Whitehorn 1184c8945a0SNathan Whitehorn /* 1194c8945a0SNathan Whitehorn * read_high() substitutes read() for tab->spaces conversion 1204c8945a0SNathan Whitehorn * 1214c8945a0SNathan Whitehorn * buffer_len, fd_bytes_read, bytes_read are modified 1224c8945a0SNathan Whitehorn * buf is allocated 1234c8945a0SNathan Whitehorn * 1244c8945a0SNathan Whitehorn * fd_bytes_read is the effective number of bytes read from file 1254c8945a0SNathan Whitehorn * bytes_read is the length of buf, that can be different if tab_correct 1264c8945a0SNathan Whitehorn */ 1274c8945a0SNathan Whitehorn static void 1284c8945a0SNathan Whitehorn read_high(MY_OBJ * obj, size_t size_read) 1294c8945a0SNathan Whitehorn { 1304c8945a0SNathan Whitehorn char *buftab, ch; 1314c8945a0SNathan Whitehorn int i = 0, j, n, tmpint; 1324c8945a0SNathan Whitehorn long begin_line; 1334c8945a0SNathan Whitehorn 1344c8945a0SNathan Whitehorn /* Allocate space for read buffer */ 1354c8945a0SNathan Whitehorn buftab = xalloc(size_read + 1); 1364c8945a0SNathan Whitehorn 1374c8945a0SNathan Whitehorn if ((obj->fd_bytes_read = read(obj->fd, buftab, size_read)) != -1) { 1384c8945a0SNathan Whitehorn 1394c8945a0SNathan Whitehorn buftab[obj->fd_bytes_read] = '\0'; /* mark end of valid data */ 1404c8945a0SNathan Whitehorn 1414c8945a0SNathan Whitehorn if (dialog_vars.tab_correct) { 1424c8945a0SNathan Whitehorn 1434c8945a0SNathan Whitehorn /* calculate bytes_read by buftab and fd_bytes_read */ 1444c8945a0SNathan Whitehorn obj->bytes_read = begin_line = 0; 1454c8945a0SNathan Whitehorn for (j = 0; j < obj->fd_bytes_read; j++) 1464c8945a0SNathan Whitehorn if (buftab[j] == TAB) 1474c8945a0SNathan Whitehorn obj->bytes_read += dialog_state.tab_len 1484c8945a0SNathan Whitehorn - ((obj->bytes_read - begin_line) 1494c8945a0SNathan Whitehorn % dialog_state.tab_len); 1504c8945a0SNathan Whitehorn else if (buftab[j] == '\n') { 1514c8945a0SNathan Whitehorn obj->bytes_read++; 1524c8945a0SNathan Whitehorn begin_line = obj->bytes_read; 1534c8945a0SNathan Whitehorn } else 1544c8945a0SNathan Whitehorn obj->bytes_read++; 1554c8945a0SNathan Whitehorn 1564c8945a0SNathan Whitehorn if (obj->bytes_read > obj->buffer_len) { 1574c8945a0SNathan Whitehorn if (obj->buffer_first) 1584c8945a0SNathan Whitehorn obj->buffer_first = FALSE; /* disp = 0 */ 1594c8945a0SNathan Whitehorn else { 1604c8945a0SNathan Whitehorn free(obj->buf); 1614c8945a0SNathan Whitehorn } 1624c8945a0SNathan Whitehorn 1634c8945a0SNathan Whitehorn obj->buffer_len = obj->bytes_read; 1644c8945a0SNathan Whitehorn 1654c8945a0SNathan Whitehorn /* Allocate space for read buffer */ 1664c8945a0SNathan Whitehorn obj->buf = xalloc((size_t) obj->buffer_len + 1); 1674c8945a0SNathan Whitehorn } 1684c8945a0SNathan Whitehorn 1694c8945a0SNathan Whitehorn } else { 1704c8945a0SNathan Whitehorn if (obj->buffer_first) { 1714c8945a0SNathan Whitehorn obj->buffer_first = FALSE; 1724c8945a0SNathan Whitehorn 1734c8945a0SNathan Whitehorn /* Allocate space for read buffer */ 1744c8945a0SNathan Whitehorn obj->buf = xalloc(size_read + 1); 1754c8945a0SNathan Whitehorn } 1764c8945a0SNathan Whitehorn 1774c8945a0SNathan Whitehorn obj->bytes_read = obj->fd_bytes_read; 1784c8945a0SNathan Whitehorn } 1794c8945a0SNathan Whitehorn 1804c8945a0SNathan Whitehorn j = 0; 1814c8945a0SNathan Whitehorn begin_line = 0; 1824c8945a0SNathan Whitehorn while (j < obj->fd_bytes_read) 1834c8945a0SNathan Whitehorn if (((ch = buftab[j++]) == TAB) && (dialog_vars.tab_correct != 0)) { 1844c8945a0SNathan Whitehorn tmpint = (dialog_state.tab_len 1854c8945a0SNathan Whitehorn - ((int) ((long) i - begin_line) % dialog_state.tab_len)); 1864c8945a0SNathan Whitehorn for (n = 0; n < tmpint; n++) 1874c8945a0SNathan Whitehorn obj->buf[i++] = ' '; 1884c8945a0SNathan Whitehorn } else { 1894c8945a0SNathan Whitehorn if (ch == '\n') 1904c8945a0SNathan Whitehorn begin_line = i + 1; 1914c8945a0SNathan Whitehorn obj->buf[i++] = ch; 1924c8945a0SNathan Whitehorn } 1934c8945a0SNathan Whitehorn 1944c8945a0SNathan Whitehorn obj->buf[i] = '\0'; /* mark end of valid data */ 1954c8945a0SNathan Whitehorn 1964c8945a0SNathan Whitehorn } 1974c8945a0SNathan Whitehorn if (obj->bytes_read == -1) 1984c8945a0SNathan Whitehorn dlg_exiterr("Error reading file"); 1994c8945a0SNathan Whitehorn free(buftab); 2004c8945a0SNathan Whitehorn } 2014c8945a0SNathan Whitehorn 2024c8945a0SNathan Whitehorn static long 2034c8945a0SNathan Whitehorn find_first(MY_OBJ * obj, char *buffer, long length) 2044c8945a0SNathan Whitehorn { 2054c8945a0SNathan Whitehorn long recount = obj->page_length; 2064c8945a0SNathan Whitehorn long result = 0; 2074c8945a0SNathan Whitehorn 2084c8945a0SNathan Whitehorn while (length > 0) { 2094c8945a0SNathan Whitehorn if (buffer[length] == '\n') { 2104c8945a0SNathan Whitehorn if (--recount < 0) { 2114c8945a0SNathan Whitehorn result = length; 2124c8945a0SNathan Whitehorn break; 2134c8945a0SNathan Whitehorn } 2144c8945a0SNathan Whitehorn } 2154c8945a0SNathan Whitehorn --length; 2164c8945a0SNathan Whitehorn } 2174c8945a0SNathan Whitehorn return result; 2184c8945a0SNathan Whitehorn } 2194c8945a0SNathan Whitehorn 2204c8945a0SNathan Whitehorn static long 2214c8945a0SNathan Whitehorn tabize(MY_OBJ * obj, long val, long *first_pos) 2224c8945a0SNathan Whitehorn { 2234c8945a0SNathan Whitehorn long fpos; 2244c8945a0SNathan Whitehorn long i, count, begin_line; 2254c8945a0SNathan Whitehorn char *buftab; 2264c8945a0SNathan Whitehorn 2274c8945a0SNathan Whitehorn if (!dialog_vars.tab_correct) 2284c8945a0SNathan Whitehorn return val; 2294c8945a0SNathan Whitehorn 2304c8945a0SNathan Whitehorn fpos = ftell_obj(obj); 2314c8945a0SNathan Whitehorn 232*2a3e3873SBaptiste Daroussin lseek_set(obj, fpos - obj->fd_bytes_read); 2334c8945a0SNathan Whitehorn 2344c8945a0SNathan Whitehorn /* Allocate space for read buffer */ 2354c8945a0SNathan Whitehorn buftab = xalloc((size_t) val + 1); 2364c8945a0SNathan Whitehorn 2374c8945a0SNathan Whitehorn if ((read(obj->fd, buftab, (size_t) val)) == -1) 2384c8945a0SNathan Whitehorn dlg_exiterr("Error reading file in tabize()."); 2394c8945a0SNathan Whitehorn 2404c8945a0SNathan Whitehorn begin_line = count = 0; 2414c8945a0SNathan Whitehorn if (first_pos != 0) 2424c8945a0SNathan Whitehorn *first_pos = 0; 2434c8945a0SNathan Whitehorn 2444c8945a0SNathan Whitehorn for (i = 0; i < val; i++) { 2454c8945a0SNathan Whitehorn if ((first_pos != 0) && (count >= val)) { 2464c8945a0SNathan Whitehorn *first_pos = find_first(obj, buftab, i); 2474c8945a0SNathan Whitehorn break; 2484c8945a0SNathan Whitehorn } 2494c8945a0SNathan Whitehorn if (buftab[i] == TAB) 2504c8945a0SNathan Whitehorn count += dialog_state.tab_len 2514c8945a0SNathan Whitehorn - ((count - begin_line) % dialog_state.tab_len); 2524c8945a0SNathan Whitehorn else if (buftab[i] == '\n') { 2534c8945a0SNathan Whitehorn count++; 2544c8945a0SNathan Whitehorn begin_line = count; 2554c8945a0SNathan Whitehorn } else 2564c8945a0SNathan Whitehorn count++; 2574c8945a0SNathan Whitehorn } 2584c8945a0SNathan Whitehorn 259*2a3e3873SBaptiste Daroussin lseek_set(obj, fpos); 2604c8945a0SNathan Whitehorn free(buftab); 2614c8945a0SNathan Whitehorn return count; 2624c8945a0SNathan Whitehorn } 2634c8945a0SNathan Whitehorn /* 2644c8945a0SNathan Whitehorn * Return current line of text. 2654c8945a0SNathan Whitehorn * 'page' should point to start of current line before calling, and will be 2664c8945a0SNathan Whitehorn * updated to point to start of next line. 2674c8945a0SNathan Whitehorn */ 2684c8945a0SNathan Whitehorn static char * 2694c8945a0SNathan Whitehorn get_line(MY_OBJ * obj) 2704c8945a0SNathan Whitehorn { 2714c8945a0SNathan Whitehorn int i = 0; 2724c8945a0SNathan Whitehorn long fpos; 2734c8945a0SNathan Whitehorn 2744c8945a0SNathan Whitehorn obj->end_reached = FALSE; 2754c8945a0SNathan Whitehorn while (obj->buf[obj->in_buf] != '\n') { 2764c8945a0SNathan Whitehorn if (obj->buf[obj->in_buf] == '\0') { /* Either end of file or end of buffer reached */ 2774c8945a0SNathan Whitehorn fpos = ftell_obj(obj); 2784c8945a0SNathan Whitehorn 2794c8945a0SNathan Whitehorn if (fpos < obj->file_size) { /* Not end of file yet */ 2804c8945a0SNathan Whitehorn /* We've reached end of buffer, but not end of file yet, so 2814c8945a0SNathan Whitehorn * read next part of file into buffer 2824c8945a0SNathan Whitehorn */ 2834c8945a0SNathan Whitehorn read_high(obj, BUF_SIZE); 2844c8945a0SNathan Whitehorn obj->in_buf = 0; 2854c8945a0SNathan Whitehorn } else { 2864c8945a0SNathan Whitehorn if (!obj->end_reached) 2874c8945a0SNathan Whitehorn obj->end_reached = TRUE; 2884c8945a0SNathan Whitehorn break; 2894c8945a0SNathan Whitehorn } 2904c8945a0SNathan Whitehorn } else if (i < MAX_LEN) 2914c8945a0SNathan Whitehorn obj->line[i++] = obj->buf[obj->in_buf++]; 2924c8945a0SNathan Whitehorn else { 2934c8945a0SNathan Whitehorn if (i == MAX_LEN) /* Truncate lines longer than MAX_LEN characters */ 2944c8945a0SNathan Whitehorn obj->line[i++] = '\0'; 2954c8945a0SNathan Whitehorn obj->in_buf++; 2964c8945a0SNathan Whitehorn } 2974c8945a0SNathan Whitehorn } 2984c8945a0SNathan Whitehorn if (i <= MAX_LEN) 2994c8945a0SNathan Whitehorn obj->line[i] = '\0'; 3004c8945a0SNathan Whitehorn if (!obj->end_reached) 3014c8945a0SNathan Whitehorn obj->in_buf++; /* move past '\n' */ 3024c8945a0SNathan Whitehorn 3034c8945a0SNathan Whitehorn return obj->line; 3044c8945a0SNathan Whitehorn } 3054c8945a0SNathan Whitehorn 3064c8945a0SNathan Whitehorn static bool 3074c8945a0SNathan Whitehorn match_string(MY_OBJ * obj, char *string) 3084c8945a0SNathan Whitehorn { 3094c8945a0SNathan Whitehorn char *match = get_line(obj); 3104c8945a0SNathan Whitehorn return strstr(match, string) != 0; 3114c8945a0SNathan Whitehorn } 3124c8945a0SNathan Whitehorn 3134c8945a0SNathan Whitehorn /* 3144c8945a0SNathan Whitehorn * Go back 'n' lines in text file. Called by dialog_textbox(). 3154c8945a0SNathan Whitehorn * 'in_buf' will be updated to point to the desired line in 'buf'. 3164c8945a0SNathan Whitehorn */ 3174c8945a0SNathan Whitehorn static void 3184c8945a0SNathan Whitehorn back_lines(MY_OBJ * obj, long n) 3194c8945a0SNathan Whitehorn { 3204c8945a0SNathan Whitehorn int i; 3214c8945a0SNathan Whitehorn long fpos; 3224c8945a0SNathan Whitehorn long val_to_tabize; 3234c8945a0SNathan Whitehorn 3244c8945a0SNathan Whitehorn obj->begin_reached = FALSE; 3254c8945a0SNathan Whitehorn /* We have to distinguish between end_reached and !end_reached since at end 3264c8945a0SNathan Whitehorn * of file, the line is not ended by a '\n'. The code inside 'if' 3274c8945a0SNathan Whitehorn * basically does a '--in_buf' to move one character backward so as to 3284c8945a0SNathan Whitehorn * skip '\n' of the previous line */ 3294c8945a0SNathan Whitehorn if (!obj->end_reached) { 3304c8945a0SNathan Whitehorn /* Either beginning of buffer or beginning of file reached? */ 3314c8945a0SNathan Whitehorn 3324c8945a0SNathan Whitehorn if (obj->in_buf == 0) { 3334c8945a0SNathan Whitehorn fpos = ftell_obj(obj); 3344c8945a0SNathan Whitehorn 3354c8945a0SNathan Whitehorn if (fpos > obj->fd_bytes_read) { /* Not beginning of file yet */ 3364c8945a0SNathan Whitehorn /* We've reached beginning of buffer, but not beginning of file 3374c8945a0SNathan Whitehorn * yet, so read previous part of file into buffer. Note that 3384c8945a0SNathan Whitehorn * we only move backward for BUF_SIZE/2 bytes, but not BUF_SIZE 3394c8945a0SNathan Whitehorn * bytes to avoid re-reading again in print_page() later 3404c8945a0SNathan Whitehorn */ 3414c8945a0SNathan Whitehorn /* Really possible to move backward BUF_SIZE/2 bytes? */ 3424c8945a0SNathan Whitehorn if (fpos < BUF_SIZE / 2 + obj->fd_bytes_read) { 3434c8945a0SNathan Whitehorn /* No, move less than */ 344*2a3e3873SBaptiste Daroussin lseek_set(obj, 0L); 3454c8945a0SNathan Whitehorn val_to_tabize = fpos - obj->fd_bytes_read; 3464c8945a0SNathan Whitehorn } else { /* Move backward BUF_SIZE/2 bytes */ 347*2a3e3873SBaptiste Daroussin lseek_cur(obj, -(BUF_SIZE / 2 + obj->fd_bytes_read)); 3484c8945a0SNathan Whitehorn val_to_tabize = BUF_SIZE / 2; 3494c8945a0SNathan Whitehorn } 3504c8945a0SNathan Whitehorn read_high(obj, BUF_SIZE); 3514c8945a0SNathan Whitehorn 3524c8945a0SNathan Whitehorn obj->in_buf = tabize(obj, val_to_tabize, (long *) 0); 3534c8945a0SNathan Whitehorn 3544c8945a0SNathan Whitehorn } else { /* Beginning of file reached */ 3554c8945a0SNathan Whitehorn obj->begin_reached = TRUE; 3564c8945a0SNathan Whitehorn return; 3574c8945a0SNathan Whitehorn } 3584c8945a0SNathan Whitehorn } 3594c8945a0SNathan Whitehorn obj->in_buf--; 3604c8945a0SNathan Whitehorn if (obj->buf[obj->in_buf] != '\n') 3614c8945a0SNathan Whitehorn /* Something's wrong... */ 3624c8945a0SNathan Whitehorn dlg_exiterr("Internal error in back_lines()."); 3634c8945a0SNathan Whitehorn } 3644c8945a0SNathan Whitehorn 3654c8945a0SNathan Whitehorn /* Go back 'n' lines */ 3664c8945a0SNathan Whitehorn for (i = 0; i < n; i++) { 3674c8945a0SNathan Whitehorn do { 3684c8945a0SNathan Whitehorn if (obj->in_buf == 0) { 3694c8945a0SNathan Whitehorn fpos = ftell_obj(obj); 3704c8945a0SNathan Whitehorn 3714c8945a0SNathan Whitehorn if (fpos > obj->fd_bytes_read) { 3724c8945a0SNathan Whitehorn /* Really possible to move backward BUF_SIZE/2 bytes? */ 3734c8945a0SNathan Whitehorn if (fpos < BUF_SIZE / 2 + obj->fd_bytes_read) { 3744c8945a0SNathan Whitehorn /* No, move less than */ 375*2a3e3873SBaptiste Daroussin lseek_set(obj, 0L); 3764c8945a0SNathan Whitehorn val_to_tabize = fpos - obj->fd_bytes_read; 3774c8945a0SNathan Whitehorn } else { /* Move backward BUF_SIZE/2 bytes */ 378*2a3e3873SBaptiste Daroussin lseek_cur(obj, -(BUF_SIZE / 2 + obj->fd_bytes_read)); 3794c8945a0SNathan Whitehorn val_to_tabize = BUF_SIZE / 2; 3804c8945a0SNathan Whitehorn } 3814c8945a0SNathan Whitehorn read_high(obj, BUF_SIZE); 3824c8945a0SNathan Whitehorn 3834c8945a0SNathan Whitehorn obj->in_buf = tabize(obj, val_to_tabize, (long *) 0); 3844c8945a0SNathan Whitehorn 3854c8945a0SNathan Whitehorn } else { /* Beginning of file reached */ 3864c8945a0SNathan Whitehorn obj->begin_reached = TRUE; 3874c8945a0SNathan Whitehorn return; 3884c8945a0SNathan Whitehorn } 3894c8945a0SNathan Whitehorn } 3904c8945a0SNathan Whitehorn } while (obj->buf[--(obj->in_buf)] != '\n'); 3914c8945a0SNathan Whitehorn } 3924c8945a0SNathan Whitehorn obj->in_buf++; 3934c8945a0SNathan Whitehorn } 3944c8945a0SNathan Whitehorn 3954c8945a0SNathan Whitehorn /* 3964c8945a0SNathan Whitehorn * Print a new line of text. 3974c8945a0SNathan Whitehorn */ 3984c8945a0SNathan Whitehorn static void 3994c8945a0SNathan Whitehorn print_line(MY_OBJ * obj, int row, int width) 4004c8945a0SNathan Whitehorn { 4014c8945a0SNathan Whitehorn if (wmove(obj->text, row, 0) != ERR) { 4024c8945a0SNathan Whitehorn int i, y, x; 4034c8945a0SNathan Whitehorn char *line = get_line(obj); 4044c8945a0SNathan Whitehorn const int *cols = dlg_index_columns(line); 4054c8945a0SNathan Whitehorn const int *indx = dlg_index_wchars(line); 4064c8945a0SNathan Whitehorn int limit = dlg_count_wchars(line); 4074c8945a0SNathan Whitehorn int first = 0; 4084c8945a0SNathan Whitehorn int last = limit; 4094c8945a0SNathan Whitehorn 4104c8945a0SNathan Whitehorn if (width > getmaxx(obj->text)) 4114c8945a0SNathan Whitehorn width = getmaxx(obj->text); 4124c8945a0SNathan Whitehorn --width; /* for the leading ' ' */ 4134c8945a0SNathan Whitehorn 4144c8945a0SNathan Whitehorn for (i = 0; i <= limit && cols[i] < obj->hscroll; ++i) 4154c8945a0SNathan Whitehorn first = i; 4164c8945a0SNathan Whitehorn 4174c8945a0SNathan Whitehorn for (i = first; (i <= limit) && ((cols[i] - cols[first]) < width); ++i) 4184c8945a0SNathan Whitehorn last = i; 4194c8945a0SNathan Whitehorn 4204c8945a0SNathan Whitehorn (void) waddch(obj->text, ' '); 4214c8945a0SNathan Whitehorn (void) waddnstr(obj->text, line + indx[first], indx[last] - indx[first]); 4224c8945a0SNathan Whitehorn 4234c8945a0SNathan Whitehorn getyx(obj->text, y, x); 4244c8945a0SNathan Whitehorn if (y == row) { /* Clear 'residue' of previous line */ 4254c8945a0SNathan Whitehorn for (i = 0; i <= width - x; i++) { 4264c8945a0SNathan Whitehorn (void) waddch(obj->text, ' '); 4274c8945a0SNathan Whitehorn } 4284c8945a0SNathan Whitehorn } 4294c8945a0SNathan Whitehorn } 4304c8945a0SNathan Whitehorn } 4314c8945a0SNathan Whitehorn 4324c8945a0SNathan Whitehorn /* 4334c8945a0SNathan Whitehorn * Print a new page of text. 4344c8945a0SNathan Whitehorn */ 4354c8945a0SNathan Whitehorn static void 4364c8945a0SNathan Whitehorn print_page(MY_OBJ * obj, int height, int width) 4374c8945a0SNathan Whitehorn { 4384c8945a0SNathan Whitehorn int i, passed_end = 0; 4394c8945a0SNathan Whitehorn 4404c8945a0SNathan Whitehorn obj->page_length = 0; 4414c8945a0SNathan Whitehorn for (i = 0; i < height; i++) { 4424c8945a0SNathan Whitehorn print_line(obj, i, width); 4434c8945a0SNathan Whitehorn if (!passed_end) 4444c8945a0SNathan Whitehorn obj->page_length++; 4454c8945a0SNathan Whitehorn if (obj->end_reached && !passed_end) 4464c8945a0SNathan Whitehorn passed_end = 1; 4474c8945a0SNathan Whitehorn } 4484c8945a0SNathan Whitehorn (void) wnoutrefresh(obj->text); 449*2a3e3873SBaptiste Daroussin dlg_trace_win(obj->text); 4504c8945a0SNathan Whitehorn } 4514c8945a0SNathan Whitehorn 4524c8945a0SNathan Whitehorn /* 4534c8945a0SNathan Whitehorn * Print current position 4544c8945a0SNathan Whitehorn */ 4554c8945a0SNathan Whitehorn static void 4564c8945a0SNathan Whitehorn print_position(MY_OBJ * obj, WINDOW *win, int height, int width) 4574c8945a0SNathan Whitehorn { 4584c8945a0SNathan Whitehorn long fpos; 4594c8945a0SNathan Whitehorn long size; 4604c8945a0SNathan Whitehorn long first = -1; 4614c8945a0SNathan Whitehorn 4624c8945a0SNathan Whitehorn fpos = ftell_obj(obj); 4634c8945a0SNathan Whitehorn if (dialog_vars.tab_correct) 4644c8945a0SNathan Whitehorn size = tabize(obj, obj->in_buf, &first); 4654c8945a0SNathan Whitehorn else 4664c8945a0SNathan Whitehorn first = find_first(obj, obj->buf, size = obj->in_buf); 4674c8945a0SNathan Whitehorn 4684c8945a0SNathan Whitehorn dlg_draw_scrollbar(win, 4694c8945a0SNathan Whitehorn first, 4704c8945a0SNathan Whitehorn fpos - obj->fd_bytes_read + size, 4714c8945a0SNathan Whitehorn fpos - obj->fd_bytes_read + size, 4724c8945a0SNathan Whitehorn obj->file_size, 4734c8945a0SNathan Whitehorn 0, PAGE_WIDTH, 4744c8945a0SNathan Whitehorn 0, PAGE_LENGTH + 1, 4754c8945a0SNathan Whitehorn border_attr, 4764c8945a0SNathan Whitehorn border_attr); 4774c8945a0SNathan Whitehorn } 4784c8945a0SNathan Whitehorn 4794c8945a0SNathan Whitehorn /* 4804c8945a0SNathan Whitehorn * Display a dialog box and get the search term from user. 4814c8945a0SNathan Whitehorn */ 4824c8945a0SNathan Whitehorn static int 4834c8945a0SNathan Whitehorn get_search_term(WINDOW *dialog, char *input, int height, int width) 4844c8945a0SNathan Whitehorn { 4854c8945a0SNathan Whitehorn /* *INDENT-OFF* */ 4864c8945a0SNathan Whitehorn static DLG_KEYS_BINDING binding[] = { 4874c8945a0SNathan Whitehorn INPUTSTR_BINDINGS, 488682c9e0fSNathan Whitehorn HELPKEY_BINDINGS, 4894c8945a0SNathan Whitehorn ENTERKEY_BINDINGS, 4904c8945a0SNathan Whitehorn END_KEYS_BINDING 4914c8945a0SNathan Whitehorn }; 4924c8945a0SNathan Whitehorn /* *INDENT-ON* */ 4934c8945a0SNathan Whitehorn 4944c8945a0SNathan Whitehorn int old_x, old_y; 4954c8945a0SNathan Whitehorn int box_x, box_y; 4964c8945a0SNathan Whitehorn int box_height, box_width; 4974c8945a0SNathan Whitehorn int offset = 0; 4984c8945a0SNathan Whitehorn int key = 0; 4994c8945a0SNathan Whitehorn int fkey = 0; 5004c8945a0SNathan Whitehorn bool first = TRUE; 5014c8945a0SNathan Whitehorn int result = DLG_EXIT_UNKNOWN; 5027a1c0d96SNathan Whitehorn const char *caption = _("Search"); 5034c8945a0SNathan Whitehorn int len_caption = dlg_count_columns(caption); 5044c8945a0SNathan Whitehorn const int *indx; 5054c8945a0SNathan Whitehorn int limit; 5064c8945a0SNathan Whitehorn WINDOW *widget; 5074c8945a0SNathan Whitehorn 5084c8945a0SNathan Whitehorn getbegyx(dialog, old_y, old_x); 5094c8945a0SNathan Whitehorn 5104c8945a0SNathan Whitehorn box_height = 1 + (2 * MARGIN); 5114c8945a0SNathan Whitehorn box_width = len_caption + (2 * (MARGIN + 2)); 5124c8945a0SNathan Whitehorn box_width = MAX(box_width, 30); 5134c8945a0SNathan Whitehorn box_width = MIN(box_width, getmaxx(dialog) - 2 * MARGIN); 5144c8945a0SNathan Whitehorn len_caption = MIN(len_caption, box_width - (2 * (MARGIN + 1))); 5154c8945a0SNathan Whitehorn 5164c8945a0SNathan Whitehorn box_x = (width - box_width) / 2; 5174c8945a0SNathan Whitehorn box_y = (height - box_height) / 2; 5184c8945a0SNathan Whitehorn widget = dlg_new_modal_window(dialog, 5194c8945a0SNathan Whitehorn box_height, box_width, 5204c8945a0SNathan Whitehorn old_y + box_y, old_x + box_x); 5214c8945a0SNathan Whitehorn keypad(widget, TRUE); 5224c8945a0SNathan Whitehorn dlg_register_window(widget, "searchbox", binding); 5234c8945a0SNathan Whitehorn 524*2a3e3873SBaptiste Daroussin dlg_draw_box2(widget, 0, 0, box_height, box_width, 5254c8945a0SNathan Whitehorn searchbox_attr, 526*2a3e3873SBaptiste Daroussin searchbox_border_attr, 527*2a3e3873SBaptiste Daroussin searchbox_border2_attr); 528*2a3e3873SBaptiste Daroussin (void) wattrset(widget, searchbox_title_attr); 5294c8945a0SNathan Whitehorn (void) wmove(widget, 0, (box_width - len_caption) / 2); 5304c8945a0SNathan Whitehorn 5314c8945a0SNathan Whitehorn indx = dlg_index_wchars(caption); 5324c8945a0SNathan Whitehorn limit = dlg_limit_columns(caption, len_caption, 0); 5334c8945a0SNathan Whitehorn (void) waddnstr(widget, caption + indx[0], indx[limit] - indx[0]); 5344c8945a0SNathan Whitehorn 5354c8945a0SNathan Whitehorn box_width -= 2; 5364c8945a0SNathan Whitehorn offset = dlg_count_columns(input); 5374c8945a0SNathan Whitehorn 5384c8945a0SNathan Whitehorn while (result == DLG_EXIT_UNKNOWN) { 5394c8945a0SNathan Whitehorn if (!first) { 5404c8945a0SNathan Whitehorn key = dlg_getc(widget, &fkey); 5414c8945a0SNathan Whitehorn if (fkey) { 5424c8945a0SNathan Whitehorn switch (fkey) { 5434c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 5444c8945a0SNathan Whitehorn case KEY_RESIZE: 5454c8945a0SNathan Whitehorn result = DLG_EXIT_CANCEL; 5464c8945a0SNathan Whitehorn continue; 5474c8945a0SNathan Whitehorn #endif 5484c8945a0SNathan Whitehorn case DLGK_ENTER: 5494c8945a0SNathan Whitehorn result = DLG_EXIT_OK; 5504c8945a0SNathan Whitehorn continue; 5514c8945a0SNathan Whitehorn } 5524c8945a0SNathan Whitehorn } else if (key == ESC) { 5534c8945a0SNathan Whitehorn result = DLG_EXIT_ESC; 5544c8945a0SNathan Whitehorn continue; 5554c8945a0SNathan Whitehorn } else if (key == ERR) { 5564c8945a0SNathan Whitehorn napms(50); 5574c8945a0SNathan Whitehorn continue; 5584c8945a0SNathan Whitehorn } 5594c8945a0SNathan Whitehorn } 5604c8945a0SNathan Whitehorn if (dlg_edit_string(input, &offset, key, fkey, first)) { 5614c8945a0SNathan Whitehorn dlg_show_string(widget, input, offset, searchbox_attr, 5624c8945a0SNathan Whitehorn 1, 1, box_width, FALSE, first); 5634c8945a0SNathan Whitehorn first = FALSE; 5644c8945a0SNathan Whitehorn } 5654c8945a0SNathan Whitehorn } 5664c8945a0SNathan Whitehorn dlg_del_window(widget); 5674c8945a0SNathan Whitehorn return result; 5684c8945a0SNathan Whitehorn } 5694c8945a0SNathan Whitehorn 5704c8945a0SNathan Whitehorn static bool 5714c8945a0SNathan Whitehorn perform_search(MY_OBJ * obj, int height, int width, int key, char *search_term) 5724c8945a0SNathan Whitehorn { 5734c8945a0SNathan Whitehorn int dir; 5744c8945a0SNathan Whitehorn long tempinx; 5754c8945a0SNathan Whitehorn long fpos; 5764c8945a0SNathan Whitehorn int result; 5774c8945a0SNathan Whitehorn bool found; 5784c8945a0SNathan Whitehorn bool temp, temp1; 5794c8945a0SNathan Whitehorn bool moved = FALSE; 5804c8945a0SNathan Whitehorn 5814c8945a0SNathan Whitehorn /* set search direction */ 5824c8945a0SNathan Whitehorn dir = (key == '/' || key == 'n') ? 1 : 0; 5834c8945a0SNathan Whitehorn if (dir ? !obj->end_reached : !obj->begin_reached) { 5844c8945a0SNathan Whitehorn if (key == 'n' || key == 'N') { 5854c8945a0SNathan Whitehorn if (search_term[0] == '\0') { /* No search term yet */ 5864c8945a0SNathan Whitehorn (void) beep(); 5874c8945a0SNathan Whitehorn return FALSE; 5884c8945a0SNathan Whitehorn } 5894c8945a0SNathan Whitehorn /* Get search term from user */ 5904c8945a0SNathan Whitehorn } else if ((result = get_search_term(obj->text, search_term, 5914c8945a0SNathan Whitehorn PAGE_LENGTH, 5924c8945a0SNathan Whitehorn PAGE_WIDTH)) != DLG_EXIT_OK 5934c8945a0SNathan Whitehorn || search_term[0] == '\0') { 5944c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 5954c8945a0SNathan Whitehorn if (result == DLG_EXIT_CANCEL) { 5964c8945a0SNathan Whitehorn ungetch(key); 5974c8945a0SNathan Whitehorn ungetch(KEY_RESIZE); 5984c8945a0SNathan Whitehorn /* FALLTHRU */ 5994c8945a0SNathan Whitehorn } 6004c8945a0SNathan Whitehorn #endif 6014c8945a0SNathan Whitehorn /* ESC pressed, or no search term, reprint page to clear box */ 602*2a3e3873SBaptiste Daroussin (void) wattrset(obj->text, dialog_attr); 6034c8945a0SNathan Whitehorn back_lines(obj, obj->page_length); 6044c8945a0SNathan Whitehorn return TRUE; 6054c8945a0SNathan Whitehorn } 6064c8945a0SNathan Whitehorn /* Save variables for restoring in case search term can't be found */ 6074c8945a0SNathan Whitehorn tempinx = obj->in_buf; 6084c8945a0SNathan Whitehorn temp = obj->begin_reached; 6094c8945a0SNathan Whitehorn temp1 = obj->end_reached; 6104c8945a0SNathan Whitehorn fpos = ftell_obj(obj) - obj->fd_bytes_read; 6114c8945a0SNathan Whitehorn /* update 'in_buf' to point to next (previous) line before 6124c8945a0SNathan Whitehorn forward (backward) searching */ 6134c8945a0SNathan Whitehorn back_lines(obj, (dir 6144c8945a0SNathan Whitehorn ? obj->page_length - 1 6154c8945a0SNathan Whitehorn : obj->page_length + 1)); 6164c8945a0SNathan Whitehorn if (dir) { /* Forward search */ 6174c8945a0SNathan Whitehorn while ((found = match_string(obj, search_term)) == FALSE) { 6184c8945a0SNathan Whitehorn if (obj->end_reached) 6194c8945a0SNathan Whitehorn break; 6204c8945a0SNathan Whitehorn } 6214c8945a0SNathan Whitehorn } else { /* Backward search */ 6224c8945a0SNathan Whitehorn while ((found = match_string(obj, search_term)) == FALSE) { 6234c8945a0SNathan Whitehorn if (obj->begin_reached) 6244c8945a0SNathan Whitehorn break; 6257a1c0d96SNathan Whitehorn back_lines(obj, 2L); 6264c8945a0SNathan Whitehorn } 6274c8945a0SNathan Whitehorn } 6284c8945a0SNathan Whitehorn if (found == FALSE) { /* not found */ 6294c8945a0SNathan Whitehorn (void) beep(); 6304c8945a0SNathan Whitehorn /* Restore program state to that before searching */ 631*2a3e3873SBaptiste Daroussin lseek_set(obj, fpos); 6324c8945a0SNathan Whitehorn 6334c8945a0SNathan Whitehorn read_high(obj, BUF_SIZE); 6344c8945a0SNathan Whitehorn 6354c8945a0SNathan Whitehorn obj->in_buf = tempinx; 6364c8945a0SNathan Whitehorn obj->begin_reached = temp; 6374c8945a0SNathan Whitehorn obj->end_reached = temp1; 6384c8945a0SNathan Whitehorn /* move 'in_buf' to point to start of current page to 6394c8945a0SNathan Whitehorn * re-print current page. Note that 'in_buf' always points 6404c8945a0SNathan Whitehorn * to start of next page, so this is necessary 6414c8945a0SNathan Whitehorn */ 6424c8945a0SNathan Whitehorn back_lines(obj, obj->page_length); 6434c8945a0SNathan Whitehorn } else { /* Search term found */ 6447a1c0d96SNathan Whitehorn back_lines(obj, 1L); 6454c8945a0SNathan Whitehorn } 6464c8945a0SNathan Whitehorn /* Reprint page */ 647*2a3e3873SBaptiste Daroussin (void) wattrset(obj->text, dialog_attr); 6484c8945a0SNathan Whitehorn moved = TRUE; 6494c8945a0SNathan Whitehorn } else { /* no need to find */ 6504c8945a0SNathan Whitehorn (void) beep(); 6514c8945a0SNathan Whitehorn } 6524c8945a0SNathan Whitehorn return moved; 6534c8945a0SNathan Whitehorn } 6544c8945a0SNathan Whitehorn 6554c8945a0SNathan Whitehorn /* 6564c8945a0SNathan Whitehorn * Display text from a file in a dialog box. 6574c8945a0SNathan Whitehorn */ 6584c8945a0SNathan Whitehorn int 6594c8945a0SNathan Whitehorn dialog_textbox(const char *title, const char *file, int height, int width) 6604c8945a0SNathan Whitehorn { 6614c8945a0SNathan Whitehorn /* *INDENT-OFF* */ 6624c8945a0SNathan Whitehorn static DLG_KEYS_BINDING binding[] = { 663682c9e0fSNathan Whitehorn HELPKEY_BINDINGS, 6644c8945a0SNathan Whitehorn ENTERKEY_BINDINGS, 6654c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, 'J' ), 6664c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, 'j' ), 6674c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, KEY_DOWN ), 6684c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, 'H' ), 6694c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, 'h' ), 6704c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, KEY_LEFT ), 6714c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, 'L' ), 6724c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, 'l' ), 6734c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, KEY_RIGHT ), 6744c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_UP, 'K' ), 6754c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_UP, 'k' ), 6764c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_GRID_UP, KEY_UP ), 6774c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_FIRST, 'g' ), 6784c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_FIRST, KEY_HOME ), 6794c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_LAST, 'G' ), 6804c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_LAST, KEY_END ), 6814c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_LAST, KEY_LL ), 6824c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_NEXT, ' ' ), 6834c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_NEXT, KEY_NPAGE ), 6844c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_PREV, 'B' ), 6854c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_PREV, 'b' ), 6864c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_PREV, KEY_PPAGE ), 6874c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_BEGIN, '0' ), 6884c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_BEGIN, KEY_BEG ), 6894c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ), 6904c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ), 6914c8945a0SNathan Whitehorn END_KEYS_BINDING 6924c8945a0SNathan Whitehorn }; 6934c8945a0SNathan Whitehorn /* *INDENT-ON* */ 6944c8945a0SNathan Whitehorn 6954c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 6964c8945a0SNathan Whitehorn int old_height = height; 6974c8945a0SNathan Whitehorn int old_width = width; 6984c8945a0SNathan Whitehorn #endif 6994c8945a0SNathan Whitehorn long fpos; 7004c8945a0SNathan Whitehorn int x, y, cur_x, cur_y; 7014c8945a0SNathan Whitehorn int key = 0, fkey; 7024c8945a0SNathan Whitehorn int next = 0; 7034c8945a0SNathan Whitehorn int i, code, passed_end; 7044c8945a0SNathan Whitehorn char search_term[MAX_LEN + 1]; 7054c8945a0SNathan Whitehorn MY_OBJ obj; 7064c8945a0SNathan Whitehorn WINDOW *dialog; 7074c8945a0SNathan Whitehorn bool moved; 7084c8945a0SNathan Whitehorn int result = DLG_EXIT_UNKNOWN; 709*2a3e3873SBaptiste Daroussin int button = dlg_default_button(); 7104c8945a0SNathan Whitehorn int min_width = 12; 7114c8945a0SNathan Whitehorn 7124c8945a0SNathan Whitehorn search_term[0] = '\0'; /* no search term entered yet */ 7134c8945a0SNathan Whitehorn 7144c8945a0SNathan Whitehorn memset(&obj, 0, sizeof(obj)); 7154c8945a0SNathan Whitehorn 7164c8945a0SNathan Whitehorn obj.begin_reached = TRUE; 7174c8945a0SNathan Whitehorn obj.buffer_first = TRUE; 7184c8945a0SNathan Whitehorn obj.end_reached = FALSE; 7194c8945a0SNathan Whitehorn obj.buttons = dlg_exit_label(); 7204c8945a0SNathan Whitehorn 7214c8945a0SNathan Whitehorn /* Open input file for reading */ 7224c8945a0SNathan Whitehorn if ((obj.fd = open(file, O_RDONLY)) == -1) 7234c8945a0SNathan Whitehorn dlg_exiterr("Can't open input file %s", file); 7244c8945a0SNathan Whitehorn 7254c8945a0SNathan Whitehorn /* Get file size. Actually, 'file_size' is the real file size - 1, 7264c8945a0SNathan Whitehorn since it's only the last byte offset from the beginning */ 727*2a3e3873SBaptiste Daroussin lseek_end(&obj, 0L); 7284c8945a0SNathan Whitehorn 7294c8945a0SNathan Whitehorn /* Restore file pointer to beginning of file after getting file size */ 730*2a3e3873SBaptiste Daroussin lseek_set(&obj, 0L); 7314c8945a0SNathan Whitehorn 7324c8945a0SNathan Whitehorn read_high(&obj, BUF_SIZE); 7334c8945a0SNathan Whitehorn 7344c8945a0SNathan Whitehorn dlg_button_layout(obj.buttons, &min_width); 7354c8945a0SNathan Whitehorn 7364c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 7374c8945a0SNathan Whitehorn retry: 7384c8945a0SNathan Whitehorn #endif 7394c8945a0SNathan Whitehorn moved = TRUE; 7404c8945a0SNathan Whitehorn 7414c8945a0SNathan Whitehorn dlg_auto_sizefile(title, file, &height, &width, 2, min_width); 7424c8945a0SNathan Whitehorn dlg_print_size(height, width); 7434c8945a0SNathan Whitehorn dlg_ctl_size(height, width); 7444c8945a0SNathan Whitehorn 7454c8945a0SNathan Whitehorn x = dlg_box_x_ordinate(width); 7464c8945a0SNathan Whitehorn y = dlg_box_y_ordinate(height); 7474c8945a0SNathan Whitehorn 7484c8945a0SNathan Whitehorn dialog = dlg_new_window(height, width, y, x); 7494c8945a0SNathan Whitehorn dlg_register_window(dialog, "textbox", binding); 7504c8945a0SNathan Whitehorn dlg_register_buttons(dialog, "textbox", obj.buttons); 7514c8945a0SNathan Whitehorn 7524c8945a0SNathan Whitehorn dlg_mouse_setbase(x, y); 7534c8945a0SNathan Whitehorn 7544c8945a0SNathan Whitehorn /* Create window for text region, used for scrolling text */ 7554c8945a0SNathan Whitehorn obj.text = dlg_sub_window(dialog, PAGE_LENGTH, PAGE_WIDTH, y + 1, x + 1); 7564c8945a0SNathan Whitehorn 7574c8945a0SNathan Whitehorn /* register the new window, along with its borders */ 7584c8945a0SNathan Whitehorn dlg_mouse_mkbigregion(0, 0, PAGE_LENGTH + 2, width, KEY_MAX, 1, 1, 1 /* lines */ ); 759*2a3e3873SBaptiste Daroussin dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr); 760*2a3e3873SBaptiste Daroussin dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr); 7614c8945a0SNathan Whitehorn dlg_draw_title(dialog, title); 7624c8945a0SNathan Whitehorn 7634c8945a0SNathan Whitehorn dlg_draw_buttons(dialog, PAGE_LENGTH + 2, 0, obj.buttons, button, FALSE, width); 7644c8945a0SNathan Whitehorn (void) wnoutrefresh(dialog); 7654c8945a0SNathan Whitehorn getyx(dialog, cur_y, cur_x); /* Save cursor position */ 7664c8945a0SNathan Whitehorn 7674c8945a0SNathan Whitehorn dlg_attr_clear(obj.text, PAGE_LENGTH, PAGE_WIDTH, dialog_attr); 7684c8945a0SNathan Whitehorn 7694c8945a0SNathan Whitehorn while (result == DLG_EXIT_UNKNOWN) { 7704c8945a0SNathan Whitehorn 7714c8945a0SNathan Whitehorn /* 7724c8945a0SNathan Whitehorn * Update the screen according to whether we shifted up/down by a line 7734c8945a0SNathan Whitehorn * or not. 7744c8945a0SNathan Whitehorn */ 7754c8945a0SNathan Whitehorn if (moved) { 7764c8945a0SNathan Whitehorn if (next < 0) { 7774c8945a0SNathan Whitehorn (void) scrollok(obj.text, TRUE); 7784c8945a0SNathan Whitehorn (void) scroll(obj.text); /* Scroll text region up one line */ 7794c8945a0SNathan Whitehorn (void) scrollok(obj.text, FALSE); 7804c8945a0SNathan Whitehorn print_line(&obj, PAGE_LENGTH - 1, PAGE_WIDTH); 7814c8945a0SNathan Whitehorn (void) wnoutrefresh(obj.text); 7824c8945a0SNathan Whitehorn } else if (next > 0) { 7834c8945a0SNathan Whitehorn /* 7844c8945a0SNathan Whitehorn * We don't call print_page() here but use scrolling to ensure 7854c8945a0SNathan Whitehorn * faster screen update. However, 'end_reached' and 7864c8945a0SNathan Whitehorn * 'page_length' should still be updated, and 'in_buf' should 7874c8945a0SNathan Whitehorn * point to start of next page. This is done by calling 7884c8945a0SNathan Whitehorn * get_line() in the following 'for' loop. 7894c8945a0SNathan Whitehorn */ 7904c8945a0SNathan Whitehorn (void) scrollok(obj.text, TRUE); 7914c8945a0SNathan Whitehorn (void) wscrl(obj.text, -1); /* Scroll text region down one line */ 7924c8945a0SNathan Whitehorn (void) scrollok(obj.text, FALSE); 7934c8945a0SNathan Whitehorn obj.page_length = 0; 7944c8945a0SNathan Whitehorn passed_end = 0; 7954c8945a0SNathan Whitehorn for (i = 0; i < PAGE_LENGTH; i++) { 7964c8945a0SNathan Whitehorn if (!i) { 7974c8945a0SNathan Whitehorn print_line(&obj, 0, PAGE_WIDTH); /* print first line of page */ 7984c8945a0SNathan Whitehorn (void) wnoutrefresh(obj.text); 7994c8945a0SNathan Whitehorn } else 8004c8945a0SNathan Whitehorn (void) get_line(&obj); /* Called to update 'end_reached' and 'in_buf' */ 8014c8945a0SNathan Whitehorn if (!passed_end) 8024c8945a0SNathan Whitehorn obj.page_length++; 8034c8945a0SNathan Whitehorn if (obj.end_reached && !passed_end) 8044c8945a0SNathan Whitehorn passed_end = 1; 8054c8945a0SNathan Whitehorn } 8064c8945a0SNathan Whitehorn } else { 8074c8945a0SNathan Whitehorn print_page(&obj, PAGE_LENGTH, PAGE_WIDTH); 8084c8945a0SNathan Whitehorn } 8094c8945a0SNathan Whitehorn print_position(&obj, dialog, height, width); 8104c8945a0SNathan Whitehorn (void) wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 8114c8945a0SNathan Whitehorn wrefresh(dialog); 8124c8945a0SNathan Whitehorn } 8134c8945a0SNathan Whitehorn moved = FALSE; /* assume we'll not move */ 8144c8945a0SNathan Whitehorn next = 0; /* ...but not scroll by a line */ 8154c8945a0SNathan Whitehorn 8164c8945a0SNathan Whitehorn key = dlg_mouse_wgetch(dialog, &fkey); 8174c8945a0SNathan Whitehorn if (dlg_result_key(key, fkey, &result)) 8184c8945a0SNathan Whitehorn break; 8194c8945a0SNathan Whitehorn 8204c8945a0SNathan Whitehorn if (!fkey && (code = dlg_char_to_button(key, obj.buttons)) >= 0) { 8214c8945a0SNathan Whitehorn result = dlg_ok_buttoncode(code); 8224c8945a0SNathan Whitehorn break; 8234c8945a0SNathan Whitehorn } 8244c8945a0SNathan Whitehorn 8254c8945a0SNathan Whitehorn if (fkey) { 8264c8945a0SNathan Whitehorn switch (key) { 8274c8945a0SNathan Whitehorn default: 8284c8945a0SNathan Whitehorn if (is_DLGK_MOUSE(key)) { 8294c8945a0SNathan Whitehorn result = dlg_exit_buttoncode(key - M_EVENT); 8304c8945a0SNathan Whitehorn if (result < 0) 8314c8945a0SNathan Whitehorn result = DLG_EXIT_OK; 8324c8945a0SNathan Whitehorn } else { 8334c8945a0SNathan Whitehorn beep(); 8344c8945a0SNathan Whitehorn } 8354c8945a0SNathan Whitehorn break; 8364c8945a0SNathan Whitehorn case DLGK_FIELD_NEXT: 8374c8945a0SNathan Whitehorn button = dlg_next_button(obj.buttons, button); 8384c8945a0SNathan Whitehorn if (button < 0) 8394c8945a0SNathan Whitehorn button = 0; 8404c8945a0SNathan Whitehorn dlg_draw_buttons(dialog, 8414c8945a0SNathan Whitehorn height - 2, 0, 8424c8945a0SNathan Whitehorn obj.buttons, button, 8434c8945a0SNathan Whitehorn FALSE, width); 8444c8945a0SNathan Whitehorn break; 8454c8945a0SNathan Whitehorn case DLGK_FIELD_PREV: 8464c8945a0SNathan Whitehorn button = dlg_prev_button(obj.buttons, button); 8474c8945a0SNathan Whitehorn if (button < 0) 8484c8945a0SNathan Whitehorn button = 0; 8494c8945a0SNathan Whitehorn dlg_draw_buttons(dialog, 8504c8945a0SNathan Whitehorn height - 2, 0, 8514c8945a0SNathan Whitehorn obj.buttons, button, 8524c8945a0SNathan Whitehorn FALSE, width); 8534c8945a0SNathan Whitehorn break; 8544c8945a0SNathan Whitehorn case DLGK_ENTER: 855682c9e0fSNathan Whitehorn if (dialog_vars.nook) 856682c9e0fSNathan Whitehorn result = DLG_EXIT_OK; 857682c9e0fSNathan Whitehorn else 8584c8945a0SNathan Whitehorn result = dlg_exit_buttoncode(button); 8594c8945a0SNathan Whitehorn break; 8604c8945a0SNathan Whitehorn case DLGK_PAGE_FIRST: 8614c8945a0SNathan Whitehorn if (!obj.begin_reached) { 8624c8945a0SNathan Whitehorn obj.begin_reached = 1; 8634c8945a0SNathan Whitehorn /* First page not in buffer? */ 8644c8945a0SNathan Whitehorn fpos = ftell_obj(&obj); 8654c8945a0SNathan Whitehorn 8664c8945a0SNathan Whitehorn if (fpos > obj.fd_bytes_read) { 8674c8945a0SNathan Whitehorn /* Yes, we have to read it in */ 868*2a3e3873SBaptiste Daroussin lseek_set(&obj, 0L); 8694c8945a0SNathan Whitehorn 8704c8945a0SNathan Whitehorn read_high(&obj, BUF_SIZE); 8714c8945a0SNathan Whitehorn } 8724c8945a0SNathan Whitehorn obj.in_buf = 0; 8734c8945a0SNathan Whitehorn moved = TRUE; 8744c8945a0SNathan Whitehorn } 8754c8945a0SNathan Whitehorn break; 8764c8945a0SNathan Whitehorn case DLGK_PAGE_LAST: 8774c8945a0SNathan Whitehorn obj.end_reached = TRUE; 8784c8945a0SNathan Whitehorn /* Last page not in buffer? */ 8794c8945a0SNathan Whitehorn fpos = ftell_obj(&obj); 8804c8945a0SNathan Whitehorn 8814c8945a0SNathan Whitehorn if (fpos < obj.file_size) { 8824c8945a0SNathan Whitehorn /* Yes, we have to read it in */ 883*2a3e3873SBaptiste Daroussin lseek_end(&obj, -BUF_SIZE); 8844c8945a0SNathan Whitehorn 8854c8945a0SNathan Whitehorn read_high(&obj, BUF_SIZE); 8864c8945a0SNathan Whitehorn } 8874c8945a0SNathan Whitehorn obj.in_buf = obj.bytes_read; 8887a1c0d96SNathan Whitehorn back_lines(&obj, (long) PAGE_LENGTH); 8894c8945a0SNathan Whitehorn moved = TRUE; 8904c8945a0SNathan Whitehorn break; 8914c8945a0SNathan Whitehorn case DLGK_GRID_UP: /* Previous line */ 8924c8945a0SNathan Whitehorn if (!obj.begin_reached) { 8934c8945a0SNathan Whitehorn back_lines(&obj, obj.page_length + 1); 8944c8945a0SNathan Whitehorn next = 1; 8954c8945a0SNathan Whitehorn moved = TRUE; 8964c8945a0SNathan Whitehorn } 8974c8945a0SNathan Whitehorn break; 8984c8945a0SNathan Whitehorn case DLGK_PAGE_PREV: /* Previous page */ 8994c8945a0SNathan Whitehorn case DLGK_MOUSE(KEY_PPAGE): 9004c8945a0SNathan Whitehorn if (!obj.begin_reached) { 9014c8945a0SNathan Whitehorn back_lines(&obj, obj.page_length + PAGE_LENGTH); 9024c8945a0SNathan Whitehorn moved = TRUE; 9034c8945a0SNathan Whitehorn } 9044c8945a0SNathan Whitehorn break; 9054c8945a0SNathan Whitehorn case DLGK_GRID_DOWN: /* Next line */ 9064c8945a0SNathan Whitehorn if (!obj.end_reached) { 9074c8945a0SNathan Whitehorn obj.begin_reached = 0; 9084c8945a0SNathan Whitehorn next = -1; 9094c8945a0SNathan Whitehorn moved = TRUE; 9104c8945a0SNathan Whitehorn } 9114c8945a0SNathan Whitehorn break; 9124c8945a0SNathan Whitehorn case DLGK_PAGE_NEXT: /* Next page */ 9134c8945a0SNathan Whitehorn case DLGK_MOUSE(KEY_NPAGE): 9144c8945a0SNathan Whitehorn if (!obj.end_reached) { 9154c8945a0SNathan Whitehorn obj.begin_reached = 0; 9164c8945a0SNathan Whitehorn moved = TRUE; 9174c8945a0SNathan Whitehorn } 9184c8945a0SNathan Whitehorn break; 9194c8945a0SNathan Whitehorn case DLGK_BEGIN: /* Beginning of line */ 9204c8945a0SNathan Whitehorn if (obj.hscroll > 0) { 9214c8945a0SNathan Whitehorn obj.hscroll = 0; 9224c8945a0SNathan Whitehorn /* Reprint current page to scroll horizontally */ 9234c8945a0SNathan Whitehorn back_lines(&obj, obj.page_length); 9244c8945a0SNathan Whitehorn moved = TRUE; 9254c8945a0SNathan Whitehorn } 9264c8945a0SNathan Whitehorn break; 9274c8945a0SNathan Whitehorn case DLGK_GRID_LEFT: /* Scroll left */ 9284c8945a0SNathan Whitehorn if (obj.hscroll > 0) { 9294c8945a0SNathan Whitehorn obj.hscroll--; 9304c8945a0SNathan Whitehorn /* Reprint current page to scroll horizontally */ 9314c8945a0SNathan Whitehorn back_lines(&obj, obj.page_length); 9324c8945a0SNathan Whitehorn moved = TRUE; 9334c8945a0SNathan Whitehorn } 9344c8945a0SNathan Whitehorn break; 9354c8945a0SNathan Whitehorn case DLGK_GRID_RIGHT: /* Scroll right */ 9364c8945a0SNathan Whitehorn if (obj.hscroll < MAX_LEN) { 9374c8945a0SNathan Whitehorn obj.hscroll++; 9384c8945a0SNathan Whitehorn /* Reprint current page to scroll horizontally */ 9394c8945a0SNathan Whitehorn back_lines(&obj, obj.page_length); 9404c8945a0SNathan Whitehorn moved = TRUE; 9414c8945a0SNathan Whitehorn } 9424c8945a0SNathan Whitehorn break; 9434c8945a0SNathan Whitehorn #ifdef KEY_RESIZE 9444c8945a0SNathan Whitehorn case KEY_RESIZE: 9454c8945a0SNathan Whitehorn /* reset data */ 9464c8945a0SNathan Whitehorn height = old_height; 9474c8945a0SNathan Whitehorn width = old_width; 9484c8945a0SNathan Whitehorn back_lines(&obj, obj.page_length); 9494c8945a0SNathan Whitehorn /* repaint */ 9504c8945a0SNathan Whitehorn dlg_clear(); 9514c8945a0SNathan Whitehorn dlg_del_window(dialog); 9524c8945a0SNathan Whitehorn refresh(); 9534c8945a0SNathan Whitehorn dlg_mouse_free_regions(); 9544c8945a0SNathan Whitehorn goto retry; 9554c8945a0SNathan Whitehorn #endif 9564c8945a0SNathan Whitehorn } 9574c8945a0SNathan Whitehorn } else { 9584c8945a0SNathan Whitehorn switch (key) { 9594c8945a0SNathan Whitehorn case '/': /* Forward search */ 9604c8945a0SNathan Whitehorn case 'n': /* Repeat forward search */ 9614c8945a0SNathan Whitehorn case '?': /* Backward search */ 9624c8945a0SNathan Whitehorn case 'N': /* Repeat backward search */ 9634c8945a0SNathan Whitehorn moved = perform_search(&obj, height, width, key, search_term); 9644c8945a0SNathan Whitehorn fkey = FALSE; 9654c8945a0SNathan Whitehorn break; 9664c8945a0SNathan Whitehorn default: 9674c8945a0SNathan Whitehorn beep(); 9684c8945a0SNathan Whitehorn break; 9694c8945a0SNathan Whitehorn } 9704c8945a0SNathan Whitehorn } 9714c8945a0SNathan Whitehorn } 9724c8945a0SNathan Whitehorn 9734c8945a0SNathan Whitehorn dlg_del_window(dialog); 9744c8945a0SNathan Whitehorn free(obj.buf); 9754c8945a0SNathan Whitehorn (void) close(obj.fd); 9764c8945a0SNathan Whitehorn dlg_mouse_free_regions(); 9774c8945a0SNathan Whitehorn return result; 9784c8945a0SNathan Whitehorn } 979