1217309Snwhitehorn/* 2251843Sbapt * $Id: textbox.c,v 1.110 2012/12/01 01:48:08 tom Exp $ 3217309Snwhitehorn * 4220749Snwhitehorn * textbox.c -- implements the text box 5217309Snwhitehorn * 6251843Sbapt * Copyright 2000-2011,2012 Thomas E. Dickey 7217309Snwhitehorn * 8217309Snwhitehorn * This program is free software; you can redistribute it and/or modify 9217309Snwhitehorn * it under the terms of the GNU Lesser General Public License, version 2.1 10217309Snwhitehorn * as published by the Free Software Foundation. 11217309Snwhitehorn * 12217309Snwhitehorn * This program is distributed in the hope that it will be useful, but 13217309Snwhitehorn * WITHOUT ANY WARRANTY; without even the implied warranty of 14217309Snwhitehorn * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15217309Snwhitehorn * Lesser General Public License for more details. 16217309Snwhitehorn * 17217309Snwhitehorn * You should have received a copy of the GNU Lesser General Public 18217309Snwhitehorn * License along with this program; if not, write to 19217309Snwhitehorn * Free Software Foundation, Inc. 20217309Snwhitehorn * 51 Franklin St., Fifth Floor 21217309Snwhitehorn * Boston, MA 02110, USA. 22217309Snwhitehorn * 23217309Snwhitehorn * An earlier version of this program lists as authors: 24217309Snwhitehorn * Savio Lam (lam836@cs.cuhk.hk) 25217309Snwhitehorn */ 26217309Snwhitehorn 27217309Snwhitehorn#include <dialog.h> 28217309Snwhitehorn#include <dlg_keys.h> 29217309Snwhitehorn 30217309Snwhitehorn#define PAGE_LENGTH (height - 4) 31217309Snwhitehorn#define PAGE_WIDTH (width - 2) 32217309Snwhitehorn 33217309Snwhitehorntypedef struct { 34217309Snwhitehorn DIALOG_CALLBACK obj; 35217309Snwhitehorn WINDOW *text; 36217309Snwhitehorn const char **buttons; 37217309Snwhitehorn int hscroll; 38217309Snwhitehorn char line[MAX_LEN + 1]; 39217309Snwhitehorn int fd; 40217309Snwhitehorn long file_size; 41217309Snwhitehorn long fd_bytes_read; 42217309Snwhitehorn long bytes_read; 43217309Snwhitehorn long buffer_len; 44217309Snwhitehorn bool begin_reached; 45217309Snwhitehorn bool buffer_first; 46217309Snwhitehorn bool end_reached; 47217309Snwhitehorn long page_length; /* lines on the page which is shown */ 48217309Snwhitehorn long in_buf; /* ending index into buf[] for page */ 49217309Snwhitehorn char *buf; 50217309Snwhitehorn} MY_OBJ; 51217309Snwhitehorn 52217309Snwhitehornstatic long 53217309Snwhitehornlseek_obj(MY_OBJ * obj, long offset, int mode) 54217309Snwhitehorn{ 55217309Snwhitehorn long fpos; 56217309Snwhitehorn if ((fpos = (long) lseek(obj->fd, (off_t) offset, mode)) == -1) { 57217309Snwhitehorn switch (mode) { 58251843Sbapt default: 59217309Snwhitehorn case SEEK_CUR: 60217309Snwhitehorn dlg_exiterr("Cannot get file position"); 61217309Snwhitehorn break; 62217309Snwhitehorn case SEEK_END: 63217309Snwhitehorn dlg_exiterr("Cannot seek to end of file"); 64217309Snwhitehorn break; 65217309Snwhitehorn case SEEK_SET: 66217309Snwhitehorn dlg_exiterr("Cannot set file position to %ld", offset); 67217309Snwhitehorn break; 68217309Snwhitehorn } 69217309Snwhitehorn } 70217309Snwhitehorn return fpos; 71217309Snwhitehorn} 72217309Snwhitehorn 73217309Snwhitehornstatic long 74217309Snwhitehornftell_obj(MY_OBJ * obj) 75217309Snwhitehorn{ 76220749Snwhitehorn return lseek_obj(obj, 0L, SEEK_CUR); 77217309Snwhitehorn} 78217309Snwhitehorn 79251843Sbaptstatic void 80251843Sbaptlseek_set(MY_OBJ * obj, long offset) 81251843Sbapt{ 82251843Sbapt long actual = lseek_obj(obj, offset, SEEK_SET); 83251843Sbapt 84251843Sbapt if (actual != offset) { 85251843Sbapt dlg_exiterr("Cannot set file position to %ld (actual %ld)\n", 86251843Sbapt offset, actual); 87251843Sbapt } 88251843Sbapt} 89251843Sbapt 90251843Sbaptstatic void 91251843Sbaptlseek_end(MY_OBJ * obj, long offset) 92251843Sbapt{ 93251843Sbapt long actual = lseek_obj(obj, offset, SEEK_END); 94251843Sbapt 95251843Sbapt if (actual > offset) { 96251843Sbapt obj->file_size = actual; 97251843Sbapt } 98251843Sbapt} 99251843Sbapt 100251843Sbaptstatic void 101251843Sbaptlseek_cur(MY_OBJ * obj, long offset) 102251843Sbapt{ 103251843Sbapt long actual = lseek_obj(obj, offset, SEEK_CUR); 104251843Sbapt 105251843Sbapt if (actual != offset) { 106251843Sbapt dlg_trace_msg("Lseek returned %ld, expected %ld\n", actual, offset); 107251843Sbapt } 108251843Sbapt} 109251843Sbapt 110217309Snwhitehornstatic char * 111217309Snwhitehornxalloc(size_t size) 112217309Snwhitehorn{ 113217309Snwhitehorn char *result = dlg_malloc(char, size); 114217309Snwhitehorn assert_ptr(result, "xalloc"); 115217309Snwhitehorn return result; 116217309Snwhitehorn} 117217309Snwhitehorn 118217309Snwhitehorn/* 119217309Snwhitehorn * read_high() substitutes read() for tab->spaces conversion 120217309Snwhitehorn * 121217309Snwhitehorn * buffer_len, fd_bytes_read, bytes_read are modified 122217309Snwhitehorn * buf is allocated 123217309Snwhitehorn * 124217309Snwhitehorn * fd_bytes_read is the effective number of bytes read from file 125217309Snwhitehorn * bytes_read is the length of buf, that can be different if tab_correct 126217309Snwhitehorn */ 127217309Snwhitehornstatic void 128217309Snwhitehornread_high(MY_OBJ * obj, size_t size_read) 129217309Snwhitehorn{ 130217309Snwhitehorn char *buftab, ch; 131217309Snwhitehorn int i = 0, j, n, tmpint; 132217309Snwhitehorn long begin_line; 133217309Snwhitehorn 134217309Snwhitehorn /* Allocate space for read buffer */ 135217309Snwhitehorn buftab = xalloc(size_read + 1); 136217309Snwhitehorn 137217309Snwhitehorn if ((obj->fd_bytes_read = read(obj->fd, buftab, size_read)) != -1) { 138217309Snwhitehorn 139217309Snwhitehorn buftab[obj->fd_bytes_read] = '\0'; /* mark end of valid data */ 140217309Snwhitehorn 141217309Snwhitehorn if (dialog_vars.tab_correct) { 142217309Snwhitehorn 143217309Snwhitehorn /* calculate bytes_read by buftab and fd_bytes_read */ 144217309Snwhitehorn obj->bytes_read = begin_line = 0; 145217309Snwhitehorn for (j = 0; j < obj->fd_bytes_read; j++) 146217309Snwhitehorn if (buftab[j] == TAB) 147217309Snwhitehorn obj->bytes_read += dialog_state.tab_len 148217309Snwhitehorn - ((obj->bytes_read - begin_line) 149217309Snwhitehorn % dialog_state.tab_len); 150217309Snwhitehorn else if (buftab[j] == '\n') { 151217309Snwhitehorn obj->bytes_read++; 152217309Snwhitehorn begin_line = obj->bytes_read; 153217309Snwhitehorn } else 154217309Snwhitehorn obj->bytes_read++; 155217309Snwhitehorn 156217309Snwhitehorn if (obj->bytes_read > obj->buffer_len) { 157217309Snwhitehorn if (obj->buffer_first) 158217309Snwhitehorn obj->buffer_first = FALSE; /* disp = 0 */ 159217309Snwhitehorn else { 160217309Snwhitehorn free(obj->buf); 161217309Snwhitehorn } 162217309Snwhitehorn 163217309Snwhitehorn obj->buffer_len = obj->bytes_read; 164217309Snwhitehorn 165217309Snwhitehorn /* Allocate space for read buffer */ 166217309Snwhitehorn obj->buf = xalloc((size_t) obj->buffer_len + 1); 167217309Snwhitehorn } 168217309Snwhitehorn 169217309Snwhitehorn } else { 170217309Snwhitehorn if (obj->buffer_first) { 171217309Snwhitehorn obj->buffer_first = FALSE; 172217309Snwhitehorn 173217309Snwhitehorn /* Allocate space for read buffer */ 174217309Snwhitehorn obj->buf = xalloc(size_read + 1); 175217309Snwhitehorn } 176217309Snwhitehorn 177217309Snwhitehorn obj->bytes_read = obj->fd_bytes_read; 178217309Snwhitehorn } 179217309Snwhitehorn 180217309Snwhitehorn j = 0; 181217309Snwhitehorn begin_line = 0; 182217309Snwhitehorn while (j < obj->fd_bytes_read) 183217309Snwhitehorn if (((ch = buftab[j++]) == TAB) && (dialog_vars.tab_correct != 0)) { 184217309Snwhitehorn tmpint = (dialog_state.tab_len 185217309Snwhitehorn - ((int) ((long) i - begin_line) % dialog_state.tab_len)); 186217309Snwhitehorn for (n = 0; n < tmpint; n++) 187217309Snwhitehorn obj->buf[i++] = ' '; 188217309Snwhitehorn } else { 189217309Snwhitehorn if (ch == '\n') 190217309Snwhitehorn begin_line = i + 1; 191217309Snwhitehorn obj->buf[i++] = ch; 192217309Snwhitehorn } 193217309Snwhitehorn 194217309Snwhitehorn obj->buf[i] = '\0'; /* mark end of valid data */ 195217309Snwhitehorn 196217309Snwhitehorn } 197217309Snwhitehorn if (obj->bytes_read == -1) 198217309Snwhitehorn dlg_exiterr("Error reading file"); 199217309Snwhitehorn free(buftab); 200217309Snwhitehorn} 201217309Snwhitehorn 202217309Snwhitehornstatic long 203217309Snwhitehornfind_first(MY_OBJ * obj, char *buffer, long length) 204217309Snwhitehorn{ 205217309Snwhitehorn long recount = obj->page_length; 206217309Snwhitehorn long result = 0; 207217309Snwhitehorn 208217309Snwhitehorn while (length > 0) { 209217309Snwhitehorn if (buffer[length] == '\n') { 210217309Snwhitehorn if (--recount < 0) { 211217309Snwhitehorn result = length; 212217309Snwhitehorn break; 213217309Snwhitehorn } 214217309Snwhitehorn } 215217309Snwhitehorn --length; 216217309Snwhitehorn } 217217309Snwhitehorn return result; 218217309Snwhitehorn} 219217309Snwhitehorn 220217309Snwhitehornstatic long 221217309Snwhitehorntabize(MY_OBJ * obj, long val, long *first_pos) 222217309Snwhitehorn{ 223217309Snwhitehorn long fpos; 224217309Snwhitehorn long i, count, begin_line; 225217309Snwhitehorn char *buftab; 226217309Snwhitehorn 227217309Snwhitehorn if (!dialog_vars.tab_correct) 228217309Snwhitehorn return val; 229217309Snwhitehorn 230217309Snwhitehorn fpos = ftell_obj(obj); 231217309Snwhitehorn 232251843Sbapt lseek_set(obj, fpos - obj->fd_bytes_read); 233217309Snwhitehorn 234217309Snwhitehorn /* Allocate space for read buffer */ 235217309Snwhitehorn buftab = xalloc((size_t) val + 1); 236217309Snwhitehorn 237217309Snwhitehorn if ((read(obj->fd, buftab, (size_t) val)) == -1) 238217309Snwhitehorn dlg_exiterr("Error reading file in tabize()."); 239217309Snwhitehorn 240217309Snwhitehorn begin_line = count = 0; 241217309Snwhitehorn if (first_pos != 0) 242217309Snwhitehorn *first_pos = 0; 243217309Snwhitehorn 244217309Snwhitehorn for (i = 0; i < val; i++) { 245217309Snwhitehorn if ((first_pos != 0) && (count >= val)) { 246217309Snwhitehorn *first_pos = find_first(obj, buftab, i); 247217309Snwhitehorn break; 248217309Snwhitehorn } 249217309Snwhitehorn if (buftab[i] == TAB) 250217309Snwhitehorn count += dialog_state.tab_len 251217309Snwhitehorn - ((count - begin_line) % dialog_state.tab_len); 252217309Snwhitehorn else if (buftab[i] == '\n') { 253217309Snwhitehorn count++; 254217309Snwhitehorn begin_line = count; 255217309Snwhitehorn } else 256217309Snwhitehorn count++; 257217309Snwhitehorn } 258217309Snwhitehorn 259251843Sbapt lseek_set(obj, fpos); 260217309Snwhitehorn free(buftab); 261217309Snwhitehorn return count; 262217309Snwhitehorn} 263217309Snwhitehorn/* 264217309Snwhitehorn * Return current line of text. 265217309Snwhitehorn * 'page' should point to start of current line before calling, and will be 266217309Snwhitehorn * updated to point to start of next line. 267217309Snwhitehorn */ 268217309Snwhitehornstatic char * 269217309Snwhitehornget_line(MY_OBJ * obj) 270217309Snwhitehorn{ 271217309Snwhitehorn int i = 0; 272217309Snwhitehorn long fpos; 273217309Snwhitehorn 274217309Snwhitehorn obj->end_reached = FALSE; 275217309Snwhitehorn while (obj->buf[obj->in_buf] != '\n') { 276217309Snwhitehorn if (obj->buf[obj->in_buf] == '\0') { /* Either end of file or end of buffer reached */ 277217309Snwhitehorn fpos = ftell_obj(obj); 278217309Snwhitehorn 279217309Snwhitehorn if (fpos < obj->file_size) { /* Not end of file yet */ 280217309Snwhitehorn /* We've reached end of buffer, but not end of file yet, so 281217309Snwhitehorn * read next part of file into buffer 282217309Snwhitehorn */ 283217309Snwhitehorn read_high(obj, BUF_SIZE); 284217309Snwhitehorn obj->in_buf = 0; 285217309Snwhitehorn } else { 286217309Snwhitehorn if (!obj->end_reached) 287217309Snwhitehorn obj->end_reached = TRUE; 288217309Snwhitehorn break; 289217309Snwhitehorn } 290217309Snwhitehorn } else if (i < MAX_LEN) 291217309Snwhitehorn obj->line[i++] = obj->buf[obj->in_buf++]; 292217309Snwhitehorn else { 293217309Snwhitehorn if (i == MAX_LEN) /* Truncate lines longer than MAX_LEN characters */ 294217309Snwhitehorn obj->line[i++] = '\0'; 295217309Snwhitehorn obj->in_buf++; 296217309Snwhitehorn } 297217309Snwhitehorn } 298217309Snwhitehorn if (i <= MAX_LEN) 299217309Snwhitehorn obj->line[i] = '\0'; 300217309Snwhitehorn if (!obj->end_reached) 301217309Snwhitehorn obj->in_buf++; /* move past '\n' */ 302217309Snwhitehorn 303217309Snwhitehorn return obj->line; 304217309Snwhitehorn} 305217309Snwhitehorn 306217309Snwhitehornstatic bool 307217309Snwhitehornmatch_string(MY_OBJ * obj, char *string) 308217309Snwhitehorn{ 309217309Snwhitehorn char *match = get_line(obj); 310217309Snwhitehorn return strstr(match, string) != 0; 311217309Snwhitehorn} 312217309Snwhitehorn 313217309Snwhitehorn/* 314217309Snwhitehorn * Go back 'n' lines in text file. Called by dialog_textbox(). 315217309Snwhitehorn * 'in_buf' will be updated to point to the desired line in 'buf'. 316217309Snwhitehorn */ 317217309Snwhitehornstatic void 318217309Snwhitehornback_lines(MY_OBJ * obj, long n) 319217309Snwhitehorn{ 320217309Snwhitehorn int i; 321217309Snwhitehorn long fpos; 322217309Snwhitehorn long val_to_tabize; 323217309Snwhitehorn 324217309Snwhitehorn obj->begin_reached = FALSE; 325217309Snwhitehorn /* We have to distinguish between end_reached and !end_reached since at end 326217309Snwhitehorn * of file, the line is not ended by a '\n'. The code inside 'if' 327217309Snwhitehorn * basically does a '--in_buf' to move one character backward so as to 328217309Snwhitehorn * skip '\n' of the previous line */ 329217309Snwhitehorn if (!obj->end_reached) { 330217309Snwhitehorn /* Either beginning of buffer or beginning of file reached? */ 331217309Snwhitehorn 332217309Snwhitehorn if (obj->in_buf == 0) { 333217309Snwhitehorn fpos = ftell_obj(obj); 334217309Snwhitehorn 335217309Snwhitehorn if (fpos > obj->fd_bytes_read) { /* Not beginning of file yet */ 336217309Snwhitehorn /* We've reached beginning of buffer, but not beginning of file 337217309Snwhitehorn * yet, so read previous part of file into buffer. Note that 338217309Snwhitehorn * we only move backward for BUF_SIZE/2 bytes, but not BUF_SIZE 339217309Snwhitehorn * bytes to avoid re-reading again in print_page() later 340217309Snwhitehorn */ 341217309Snwhitehorn /* Really possible to move backward BUF_SIZE/2 bytes? */ 342217309Snwhitehorn if (fpos < BUF_SIZE / 2 + obj->fd_bytes_read) { 343217309Snwhitehorn /* No, move less than */ 344251843Sbapt lseek_set(obj, 0L); 345217309Snwhitehorn val_to_tabize = fpos - obj->fd_bytes_read; 346217309Snwhitehorn } else { /* Move backward BUF_SIZE/2 bytes */ 347251843Sbapt lseek_cur(obj, -(BUF_SIZE / 2 + obj->fd_bytes_read)); 348217309Snwhitehorn val_to_tabize = BUF_SIZE / 2; 349217309Snwhitehorn } 350217309Snwhitehorn read_high(obj, BUF_SIZE); 351217309Snwhitehorn 352217309Snwhitehorn obj->in_buf = tabize(obj, val_to_tabize, (long *) 0); 353217309Snwhitehorn 354217309Snwhitehorn } else { /* Beginning of file reached */ 355217309Snwhitehorn obj->begin_reached = TRUE; 356217309Snwhitehorn return; 357217309Snwhitehorn } 358217309Snwhitehorn } 359217309Snwhitehorn obj->in_buf--; 360217309Snwhitehorn if (obj->buf[obj->in_buf] != '\n') 361217309Snwhitehorn /* Something's wrong... */ 362217309Snwhitehorn dlg_exiterr("Internal error in back_lines()."); 363217309Snwhitehorn } 364217309Snwhitehorn 365217309Snwhitehorn /* Go back 'n' lines */ 366217309Snwhitehorn for (i = 0; i < n; i++) { 367217309Snwhitehorn do { 368217309Snwhitehorn if (obj->in_buf == 0) { 369217309Snwhitehorn fpos = ftell_obj(obj); 370217309Snwhitehorn 371217309Snwhitehorn if (fpos > obj->fd_bytes_read) { 372217309Snwhitehorn /* Really possible to move backward BUF_SIZE/2 bytes? */ 373217309Snwhitehorn if (fpos < BUF_SIZE / 2 + obj->fd_bytes_read) { 374217309Snwhitehorn /* No, move less than */ 375251843Sbapt lseek_set(obj, 0L); 376217309Snwhitehorn val_to_tabize = fpos - obj->fd_bytes_read; 377217309Snwhitehorn } else { /* Move backward BUF_SIZE/2 bytes */ 378251843Sbapt lseek_cur(obj, -(BUF_SIZE / 2 + obj->fd_bytes_read)); 379217309Snwhitehorn val_to_tabize = BUF_SIZE / 2; 380217309Snwhitehorn } 381217309Snwhitehorn read_high(obj, BUF_SIZE); 382217309Snwhitehorn 383217309Snwhitehorn obj->in_buf = tabize(obj, val_to_tabize, (long *) 0); 384217309Snwhitehorn 385217309Snwhitehorn } else { /* Beginning of file reached */ 386217309Snwhitehorn obj->begin_reached = TRUE; 387217309Snwhitehorn return; 388217309Snwhitehorn } 389217309Snwhitehorn } 390217309Snwhitehorn } while (obj->buf[--(obj->in_buf)] != '\n'); 391217309Snwhitehorn } 392217309Snwhitehorn obj->in_buf++; 393217309Snwhitehorn} 394217309Snwhitehorn 395217309Snwhitehorn/* 396217309Snwhitehorn * Print a new line of text. 397217309Snwhitehorn */ 398217309Snwhitehornstatic void 399217309Snwhitehornprint_line(MY_OBJ * obj, int row, int width) 400217309Snwhitehorn{ 401217309Snwhitehorn if (wmove(obj->text, row, 0) != ERR) { 402217309Snwhitehorn int i, y, x; 403217309Snwhitehorn char *line = get_line(obj); 404217309Snwhitehorn const int *cols = dlg_index_columns(line); 405217309Snwhitehorn const int *indx = dlg_index_wchars(line); 406217309Snwhitehorn int limit = dlg_count_wchars(line); 407217309Snwhitehorn int first = 0; 408217309Snwhitehorn int last = limit; 409217309Snwhitehorn 410217309Snwhitehorn if (width > getmaxx(obj->text)) 411217309Snwhitehorn width = getmaxx(obj->text); 412217309Snwhitehorn --width; /* for the leading ' ' */ 413217309Snwhitehorn 414217309Snwhitehorn for (i = 0; i <= limit && cols[i] < obj->hscroll; ++i) 415217309Snwhitehorn first = i; 416217309Snwhitehorn 417217309Snwhitehorn for (i = first; (i <= limit) && ((cols[i] - cols[first]) < width); ++i) 418217309Snwhitehorn last = i; 419217309Snwhitehorn 420217309Snwhitehorn (void) waddch(obj->text, ' '); 421217309Snwhitehorn (void) waddnstr(obj->text, line + indx[first], indx[last] - indx[first]); 422217309Snwhitehorn 423217309Snwhitehorn getyx(obj->text, y, x); 424217309Snwhitehorn if (y == row) { /* Clear 'residue' of previous line */ 425217309Snwhitehorn for (i = 0; i <= width - x; i++) { 426217309Snwhitehorn (void) waddch(obj->text, ' '); 427217309Snwhitehorn } 428217309Snwhitehorn } 429217309Snwhitehorn } 430217309Snwhitehorn} 431217309Snwhitehorn 432217309Snwhitehorn/* 433217309Snwhitehorn * Print a new page of text. 434217309Snwhitehorn */ 435217309Snwhitehornstatic void 436217309Snwhitehornprint_page(MY_OBJ * obj, int height, int width) 437217309Snwhitehorn{ 438217309Snwhitehorn int i, passed_end = 0; 439217309Snwhitehorn 440217309Snwhitehorn obj->page_length = 0; 441217309Snwhitehorn for (i = 0; i < height; i++) { 442217309Snwhitehorn print_line(obj, i, width); 443217309Snwhitehorn if (!passed_end) 444217309Snwhitehorn obj->page_length++; 445217309Snwhitehorn if (obj->end_reached && !passed_end) 446217309Snwhitehorn passed_end = 1; 447217309Snwhitehorn } 448217309Snwhitehorn (void) wnoutrefresh(obj->text); 449251843Sbapt dlg_trace_win(obj->text); 450217309Snwhitehorn} 451217309Snwhitehorn 452217309Snwhitehorn/* 453217309Snwhitehorn * Print current position 454217309Snwhitehorn */ 455217309Snwhitehornstatic void 456217309Snwhitehornprint_position(MY_OBJ * obj, WINDOW *win, int height, int width) 457217309Snwhitehorn{ 458217309Snwhitehorn long fpos; 459217309Snwhitehorn long size; 460217309Snwhitehorn long first = -1; 461217309Snwhitehorn 462217309Snwhitehorn fpos = ftell_obj(obj); 463217309Snwhitehorn if (dialog_vars.tab_correct) 464217309Snwhitehorn size = tabize(obj, obj->in_buf, &first); 465217309Snwhitehorn else 466217309Snwhitehorn first = find_first(obj, obj->buf, size = obj->in_buf); 467217309Snwhitehorn 468217309Snwhitehorn dlg_draw_scrollbar(win, 469217309Snwhitehorn first, 470217309Snwhitehorn fpos - obj->fd_bytes_read + size, 471217309Snwhitehorn fpos - obj->fd_bytes_read + size, 472217309Snwhitehorn obj->file_size, 473217309Snwhitehorn 0, PAGE_WIDTH, 474217309Snwhitehorn 0, PAGE_LENGTH + 1, 475217309Snwhitehorn border_attr, 476217309Snwhitehorn border_attr); 477217309Snwhitehorn} 478217309Snwhitehorn 479217309Snwhitehorn/* 480217309Snwhitehorn * Display a dialog box and get the search term from user. 481217309Snwhitehorn */ 482217309Snwhitehornstatic int 483217309Snwhitehornget_search_term(WINDOW *dialog, char *input, int height, int width) 484217309Snwhitehorn{ 485217309Snwhitehorn /* *INDENT-OFF* */ 486217309Snwhitehorn static DLG_KEYS_BINDING binding[] = { 487217309Snwhitehorn INPUTSTR_BINDINGS, 488224014Snwhitehorn HELPKEY_BINDINGS, 489217309Snwhitehorn ENTERKEY_BINDINGS, 490217309Snwhitehorn END_KEYS_BINDING 491217309Snwhitehorn }; 492217309Snwhitehorn /* *INDENT-ON* */ 493217309Snwhitehorn 494217309Snwhitehorn int old_x, old_y; 495217309Snwhitehorn int box_x, box_y; 496217309Snwhitehorn int box_height, box_width; 497217309Snwhitehorn int offset = 0; 498217309Snwhitehorn int key = 0; 499217309Snwhitehorn int fkey = 0; 500217309Snwhitehorn bool first = TRUE; 501217309Snwhitehorn int result = DLG_EXIT_UNKNOWN; 502220749Snwhitehorn const char *caption = _("Search"); 503217309Snwhitehorn int len_caption = dlg_count_columns(caption); 504217309Snwhitehorn const int *indx; 505217309Snwhitehorn int limit; 506217309Snwhitehorn WINDOW *widget; 507217309Snwhitehorn 508217309Snwhitehorn getbegyx(dialog, old_y, old_x); 509217309Snwhitehorn 510217309Snwhitehorn box_height = 1 + (2 * MARGIN); 511217309Snwhitehorn box_width = len_caption + (2 * (MARGIN + 2)); 512217309Snwhitehorn box_width = MAX(box_width, 30); 513217309Snwhitehorn box_width = MIN(box_width, getmaxx(dialog) - 2 * MARGIN); 514217309Snwhitehorn len_caption = MIN(len_caption, box_width - (2 * (MARGIN + 1))); 515217309Snwhitehorn 516217309Snwhitehorn box_x = (width - box_width) / 2; 517217309Snwhitehorn box_y = (height - box_height) / 2; 518217309Snwhitehorn widget = dlg_new_modal_window(dialog, 519217309Snwhitehorn box_height, box_width, 520217309Snwhitehorn old_y + box_y, old_x + box_x); 521217309Snwhitehorn keypad(widget, TRUE); 522217309Snwhitehorn dlg_register_window(widget, "searchbox", binding); 523217309Snwhitehorn 524251843Sbapt dlg_draw_box2(widget, 0, 0, box_height, box_width, 525251843Sbapt searchbox_attr, 526251843Sbapt searchbox_border_attr, 527251843Sbapt searchbox_border2_attr); 528251843Sbapt (void) wattrset(widget, searchbox_title_attr); 529217309Snwhitehorn (void) wmove(widget, 0, (box_width - len_caption) / 2); 530217309Snwhitehorn 531217309Snwhitehorn indx = dlg_index_wchars(caption); 532217309Snwhitehorn limit = dlg_limit_columns(caption, len_caption, 0); 533217309Snwhitehorn (void) waddnstr(widget, caption + indx[0], indx[limit] - indx[0]); 534217309Snwhitehorn 535217309Snwhitehorn box_width -= 2; 536217309Snwhitehorn offset = dlg_count_columns(input); 537217309Snwhitehorn 538217309Snwhitehorn while (result == DLG_EXIT_UNKNOWN) { 539217309Snwhitehorn if (!first) { 540217309Snwhitehorn key = dlg_getc(widget, &fkey); 541217309Snwhitehorn if (fkey) { 542217309Snwhitehorn switch (fkey) { 543217309Snwhitehorn#ifdef KEY_RESIZE 544217309Snwhitehorn case KEY_RESIZE: 545217309Snwhitehorn result = DLG_EXIT_CANCEL; 546217309Snwhitehorn continue; 547217309Snwhitehorn#endif 548217309Snwhitehorn case DLGK_ENTER: 549217309Snwhitehorn result = DLG_EXIT_OK; 550217309Snwhitehorn continue; 551217309Snwhitehorn } 552217309Snwhitehorn } else if (key == ESC) { 553217309Snwhitehorn result = DLG_EXIT_ESC; 554217309Snwhitehorn continue; 555217309Snwhitehorn } else if (key == ERR) { 556217309Snwhitehorn napms(50); 557217309Snwhitehorn continue; 558217309Snwhitehorn } 559217309Snwhitehorn } 560217309Snwhitehorn if (dlg_edit_string(input, &offset, key, fkey, first)) { 561217309Snwhitehorn dlg_show_string(widget, input, offset, searchbox_attr, 562217309Snwhitehorn 1, 1, box_width, FALSE, first); 563217309Snwhitehorn first = FALSE; 564217309Snwhitehorn } 565217309Snwhitehorn } 566217309Snwhitehorn dlg_del_window(widget); 567217309Snwhitehorn return result; 568217309Snwhitehorn} 569217309Snwhitehorn 570217309Snwhitehornstatic bool 571217309Snwhitehornperform_search(MY_OBJ * obj, int height, int width, int key, char *search_term) 572217309Snwhitehorn{ 573217309Snwhitehorn int dir; 574217309Snwhitehorn long tempinx; 575217309Snwhitehorn long fpos; 576217309Snwhitehorn int result; 577217309Snwhitehorn bool found; 578217309Snwhitehorn bool temp, temp1; 579217309Snwhitehorn bool moved = FALSE; 580217309Snwhitehorn 581217309Snwhitehorn /* set search direction */ 582217309Snwhitehorn dir = (key == '/' || key == 'n') ? 1 : 0; 583217309Snwhitehorn if (dir ? !obj->end_reached : !obj->begin_reached) { 584217309Snwhitehorn if (key == 'n' || key == 'N') { 585217309Snwhitehorn if (search_term[0] == '\0') { /* No search term yet */ 586217309Snwhitehorn (void) beep(); 587217309Snwhitehorn return FALSE; 588217309Snwhitehorn } 589217309Snwhitehorn /* Get search term from user */ 590217309Snwhitehorn } else if ((result = get_search_term(obj->text, search_term, 591217309Snwhitehorn PAGE_LENGTH, 592217309Snwhitehorn PAGE_WIDTH)) != DLG_EXIT_OK 593217309Snwhitehorn || search_term[0] == '\0') { 594217309Snwhitehorn#ifdef KEY_RESIZE 595217309Snwhitehorn if (result == DLG_EXIT_CANCEL) { 596217309Snwhitehorn ungetch(key); 597217309Snwhitehorn ungetch(KEY_RESIZE); 598217309Snwhitehorn /* FALLTHRU */ 599217309Snwhitehorn } 600217309Snwhitehorn#endif 601217309Snwhitehorn /* ESC pressed, or no search term, reprint page to clear box */ 602251843Sbapt (void) wattrset(obj->text, dialog_attr); 603217309Snwhitehorn back_lines(obj, obj->page_length); 604217309Snwhitehorn return TRUE; 605217309Snwhitehorn } 606217309Snwhitehorn /* Save variables for restoring in case search term can't be found */ 607217309Snwhitehorn tempinx = obj->in_buf; 608217309Snwhitehorn temp = obj->begin_reached; 609217309Snwhitehorn temp1 = obj->end_reached; 610217309Snwhitehorn fpos = ftell_obj(obj) - obj->fd_bytes_read; 611217309Snwhitehorn /* update 'in_buf' to point to next (previous) line before 612217309Snwhitehorn forward (backward) searching */ 613217309Snwhitehorn back_lines(obj, (dir 614217309Snwhitehorn ? obj->page_length - 1 615217309Snwhitehorn : obj->page_length + 1)); 616217309Snwhitehorn if (dir) { /* Forward search */ 617217309Snwhitehorn while ((found = match_string(obj, search_term)) == FALSE) { 618217309Snwhitehorn if (obj->end_reached) 619217309Snwhitehorn break; 620217309Snwhitehorn } 621217309Snwhitehorn } else { /* Backward search */ 622217309Snwhitehorn while ((found = match_string(obj, search_term)) == FALSE) { 623217309Snwhitehorn if (obj->begin_reached) 624217309Snwhitehorn break; 625220749Snwhitehorn back_lines(obj, 2L); 626217309Snwhitehorn } 627217309Snwhitehorn } 628217309Snwhitehorn if (found == FALSE) { /* not found */ 629217309Snwhitehorn (void) beep(); 630217309Snwhitehorn /* Restore program state to that before searching */ 631251843Sbapt lseek_set(obj, fpos); 632217309Snwhitehorn 633217309Snwhitehorn read_high(obj, BUF_SIZE); 634217309Snwhitehorn 635217309Snwhitehorn obj->in_buf = tempinx; 636217309Snwhitehorn obj->begin_reached = temp; 637217309Snwhitehorn obj->end_reached = temp1; 638217309Snwhitehorn /* move 'in_buf' to point to start of current page to 639217309Snwhitehorn * re-print current page. Note that 'in_buf' always points 640217309Snwhitehorn * to start of next page, so this is necessary 641217309Snwhitehorn */ 642217309Snwhitehorn back_lines(obj, obj->page_length); 643217309Snwhitehorn } else { /* Search term found */ 644220749Snwhitehorn back_lines(obj, 1L); 645217309Snwhitehorn } 646217309Snwhitehorn /* Reprint page */ 647251843Sbapt (void) wattrset(obj->text, dialog_attr); 648217309Snwhitehorn moved = TRUE; 649217309Snwhitehorn } else { /* no need to find */ 650217309Snwhitehorn (void) beep(); 651217309Snwhitehorn } 652217309Snwhitehorn return moved; 653217309Snwhitehorn} 654217309Snwhitehorn 655217309Snwhitehorn/* 656217309Snwhitehorn * Display text from a file in a dialog box. 657217309Snwhitehorn */ 658217309Snwhitehornint 659217309Snwhitehorndialog_textbox(const char *title, const char *file, int height, int width) 660217309Snwhitehorn{ 661217309Snwhitehorn /* *INDENT-OFF* */ 662217309Snwhitehorn static DLG_KEYS_BINDING binding[] = { 663224014Snwhitehorn HELPKEY_BINDINGS, 664217309Snwhitehorn ENTERKEY_BINDINGS, 665217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, 'J' ), 666217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, 'j' ), 667217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, KEY_DOWN ), 668217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, 'H' ), 669217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, 'h' ), 670217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, KEY_LEFT ), 671217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, 'L' ), 672217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, 'l' ), 673217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, KEY_RIGHT ), 674217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_UP, 'K' ), 675217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_UP, 'k' ), 676217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_UP, KEY_UP ), 677217309Snwhitehorn DLG_KEYS_DATA( DLGK_PAGE_FIRST, 'g' ), 678217309Snwhitehorn DLG_KEYS_DATA( DLGK_PAGE_FIRST, KEY_HOME ), 679217309Snwhitehorn DLG_KEYS_DATA( DLGK_PAGE_LAST, 'G' ), 680217309Snwhitehorn DLG_KEYS_DATA( DLGK_PAGE_LAST, KEY_END ), 681217309Snwhitehorn DLG_KEYS_DATA( DLGK_PAGE_LAST, KEY_LL ), 682217309Snwhitehorn DLG_KEYS_DATA( DLGK_PAGE_NEXT, ' ' ), 683217309Snwhitehorn DLG_KEYS_DATA( DLGK_PAGE_NEXT, KEY_NPAGE ), 684217309Snwhitehorn DLG_KEYS_DATA( DLGK_PAGE_PREV, 'B' ), 685217309Snwhitehorn DLG_KEYS_DATA( DLGK_PAGE_PREV, 'b' ), 686217309Snwhitehorn DLG_KEYS_DATA( DLGK_PAGE_PREV, KEY_PPAGE ), 687217309Snwhitehorn DLG_KEYS_DATA( DLGK_BEGIN, '0' ), 688217309Snwhitehorn DLG_KEYS_DATA( DLGK_BEGIN, KEY_BEG ), 689217309Snwhitehorn DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ), 690217309Snwhitehorn DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ), 691217309Snwhitehorn END_KEYS_BINDING 692217309Snwhitehorn }; 693217309Snwhitehorn /* *INDENT-ON* */ 694217309Snwhitehorn 695217309Snwhitehorn#ifdef KEY_RESIZE 696217309Snwhitehorn int old_height = height; 697217309Snwhitehorn int old_width = width; 698217309Snwhitehorn#endif 699217309Snwhitehorn long fpos; 700217309Snwhitehorn int x, y, cur_x, cur_y; 701217309Snwhitehorn int key = 0, fkey; 702217309Snwhitehorn int next = 0; 703217309Snwhitehorn int i, code, passed_end; 704217309Snwhitehorn char search_term[MAX_LEN + 1]; 705217309Snwhitehorn MY_OBJ obj; 706217309Snwhitehorn WINDOW *dialog; 707217309Snwhitehorn bool moved; 708217309Snwhitehorn int result = DLG_EXIT_UNKNOWN; 709251843Sbapt int button = dlg_default_button(); 710217309Snwhitehorn int min_width = 12; 711217309Snwhitehorn 712217309Snwhitehorn search_term[0] = '\0'; /* no search term entered yet */ 713217309Snwhitehorn 714217309Snwhitehorn memset(&obj, 0, sizeof(obj)); 715217309Snwhitehorn 716217309Snwhitehorn obj.begin_reached = TRUE; 717217309Snwhitehorn obj.buffer_first = TRUE; 718217309Snwhitehorn obj.end_reached = FALSE; 719217309Snwhitehorn obj.buttons = dlg_exit_label(); 720217309Snwhitehorn 721217309Snwhitehorn /* Open input file for reading */ 722217309Snwhitehorn if ((obj.fd = open(file, O_RDONLY)) == -1) 723217309Snwhitehorn dlg_exiterr("Can't open input file %s", file); 724217309Snwhitehorn 725217309Snwhitehorn /* Get file size. Actually, 'file_size' is the real file size - 1, 726217309Snwhitehorn since it's only the last byte offset from the beginning */ 727251843Sbapt lseek_end(&obj, 0L); 728217309Snwhitehorn 729217309Snwhitehorn /* Restore file pointer to beginning of file after getting file size */ 730251843Sbapt lseek_set(&obj, 0L); 731217309Snwhitehorn 732217309Snwhitehorn read_high(&obj, BUF_SIZE); 733217309Snwhitehorn 734217309Snwhitehorn dlg_button_layout(obj.buttons, &min_width); 735217309Snwhitehorn 736217309Snwhitehorn#ifdef KEY_RESIZE 737217309Snwhitehorn retry: 738217309Snwhitehorn#endif 739217309Snwhitehorn moved = TRUE; 740217309Snwhitehorn 741217309Snwhitehorn dlg_auto_sizefile(title, file, &height, &width, 2, min_width); 742217309Snwhitehorn dlg_print_size(height, width); 743217309Snwhitehorn dlg_ctl_size(height, width); 744217309Snwhitehorn 745217309Snwhitehorn x = dlg_box_x_ordinate(width); 746217309Snwhitehorn y = dlg_box_y_ordinate(height); 747217309Snwhitehorn 748217309Snwhitehorn dialog = dlg_new_window(height, width, y, x); 749217309Snwhitehorn dlg_register_window(dialog, "textbox", binding); 750217309Snwhitehorn dlg_register_buttons(dialog, "textbox", obj.buttons); 751217309Snwhitehorn 752217309Snwhitehorn dlg_mouse_setbase(x, y); 753217309Snwhitehorn 754217309Snwhitehorn /* Create window for text region, used for scrolling text */ 755217309Snwhitehorn obj.text = dlg_sub_window(dialog, PAGE_LENGTH, PAGE_WIDTH, y + 1, x + 1); 756217309Snwhitehorn 757217309Snwhitehorn /* register the new window, along with its borders */ 758217309Snwhitehorn dlg_mouse_mkbigregion(0, 0, PAGE_LENGTH + 2, width, KEY_MAX, 1, 1, 1 /* lines */ ); 759251843Sbapt dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr); 760251843Sbapt dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr); 761217309Snwhitehorn dlg_draw_title(dialog, title); 762217309Snwhitehorn 763217309Snwhitehorn dlg_draw_buttons(dialog, PAGE_LENGTH + 2, 0, obj.buttons, button, FALSE, width); 764217309Snwhitehorn (void) wnoutrefresh(dialog); 765217309Snwhitehorn getyx(dialog, cur_y, cur_x); /* Save cursor position */ 766217309Snwhitehorn 767217309Snwhitehorn dlg_attr_clear(obj.text, PAGE_LENGTH, PAGE_WIDTH, dialog_attr); 768217309Snwhitehorn 769217309Snwhitehorn while (result == DLG_EXIT_UNKNOWN) { 770217309Snwhitehorn 771217309Snwhitehorn /* 772217309Snwhitehorn * Update the screen according to whether we shifted up/down by a line 773217309Snwhitehorn * or not. 774217309Snwhitehorn */ 775217309Snwhitehorn if (moved) { 776217309Snwhitehorn if (next < 0) { 777217309Snwhitehorn (void) scrollok(obj.text, TRUE); 778217309Snwhitehorn (void) scroll(obj.text); /* Scroll text region up one line */ 779217309Snwhitehorn (void) scrollok(obj.text, FALSE); 780217309Snwhitehorn print_line(&obj, PAGE_LENGTH - 1, PAGE_WIDTH); 781217309Snwhitehorn (void) wnoutrefresh(obj.text); 782217309Snwhitehorn } else if (next > 0) { 783217309Snwhitehorn /* 784217309Snwhitehorn * We don't call print_page() here but use scrolling to ensure 785217309Snwhitehorn * faster screen update. However, 'end_reached' and 786217309Snwhitehorn * 'page_length' should still be updated, and 'in_buf' should 787217309Snwhitehorn * point to start of next page. This is done by calling 788217309Snwhitehorn * get_line() in the following 'for' loop. 789217309Snwhitehorn */ 790217309Snwhitehorn (void) scrollok(obj.text, TRUE); 791217309Snwhitehorn (void) wscrl(obj.text, -1); /* Scroll text region down one line */ 792217309Snwhitehorn (void) scrollok(obj.text, FALSE); 793217309Snwhitehorn obj.page_length = 0; 794217309Snwhitehorn passed_end = 0; 795217309Snwhitehorn for (i = 0; i < PAGE_LENGTH; i++) { 796217309Snwhitehorn if (!i) { 797217309Snwhitehorn print_line(&obj, 0, PAGE_WIDTH); /* print first line of page */ 798217309Snwhitehorn (void) wnoutrefresh(obj.text); 799217309Snwhitehorn } else 800217309Snwhitehorn (void) get_line(&obj); /* Called to update 'end_reached' and 'in_buf' */ 801217309Snwhitehorn if (!passed_end) 802217309Snwhitehorn obj.page_length++; 803217309Snwhitehorn if (obj.end_reached && !passed_end) 804217309Snwhitehorn passed_end = 1; 805217309Snwhitehorn } 806217309Snwhitehorn } else { 807217309Snwhitehorn print_page(&obj, PAGE_LENGTH, PAGE_WIDTH); 808217309Snwhitehorn } 809217309Snwhitehorn print_position(&obj, dialog, height, width); 810217309Snwhitehorn (void) wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 811217309Snwhitehorn wrefresh(dialog); 812217309Snwhitehorn } 813217309Snwhitehorn moved = FALSE; /* assume we'll not move */ 814217309Snwhitehorn next = 0; /* ...but not scroll by a line */ 815217309Snwhitehorn 816217309Snwhitehorn key = dlg_mouse_wgetch(dialog, &fkey); 817217309Snwhitehorn if (dlg_result_key(key, fkey, &result)) 818217309Snwhitehorn break; 819217309Snwhitehorn 820217309Snwhitehorn if (!fkey && (code = dlg_char_to_button(key, obj.buttons)) >= 0) { 821217309Snwhitehorn result = dlg_ok_buttoncode(code); 822217309Snwhitehorn break; 823217309Snwhitehorn } 824217309Snwhitehorn 825217309Snwhitehorn if (fkey) { 826217309Snwhitehorn switch (key) { 827217309Snwhitehorn default: 828217309Snwhitehorn if (is_DLGK_MOUSE(key)) { 829217309Snwhitehorn result = dlg_exit_buttoncode(key - M_EVENT); 830217309Snwhitehorn if (result < 0) 831217309Snwhitehorn result = DLG_EXIT_OK; 832217309Snwhitehorn } else { 833217309Snwhitehorn beep(); 834217309Snwhitehorn } 835217309Snwhitehorn break; 836217309Snwhitehorn case DLGK_FIELD_NEXT: 837217309Snwhitehorn button = dlg_next_button(obj.buttons, button); 838217309Snwhitehorn if (button < 0) 839217309Snwhitehorn button = 0; 840217309Snwhitehorn dlg_draw_buttons(dialog, 841217309Snwhitehorn height - 2, 0, 842217309Snwhitehorn obj.buttons, button, 843217309Snwhitehorn FALSE, width); 844217309Snwhitehorn break; 845217309Snwhitehorn case DLGK_FIELD_PREV: 846217309Snwhitehorn button = dlg_prev_button(obj.buttons, button); 847217309Snwhitehorn if (button < 0) 848217309Snwhitehorn button = 0; 849217309Snwhitehorn dlg_draw_buttons(dialog, 850217309Snwhitehorn height - 2, 0, 851217309Snwhitehorn obj.buttons, button, 852217309Snwhitehorn FALSE, width); 853217309Snwhitehorn break; 854217309Snwhitehorn case DLGK_ENTER: 855224014Snwhitehorn if (dialog_vars.nook) 856224014Snwhitehorn result = DLG_EXIT_OK; 857224014Snwhitehorn else 858224014Snwhitehorn result = dlg_exit_buttoncode(button); 859217309Snwhitehorn break; 860217309Snwhitehorn case DLGK_PAGE_FIRST: 861217309Snwhitehorn if (!obj.begin_reached) { 862217309Snwhitehorn obj.begin_reached = 1; 863217309Snwhitehorn /* First page not in buffer? */ 864217309Snwhitehorn fpos = ftell_obj(&obj); 865217309Snwhitehorn 866217309Snwhitehorn if (fpos > obj.fd_bytes_read) { 867217309Snwhitehorn /* Yes, we have to read it in */ 868251843Sbapt lseek_set(&obj, 0L); 869217309Snwhitehorn 870217309Snwhitehorn read_high(&obj, BUF_SIZE); 871217309Snwhitehorn } 872217309Snwhitehorn obj.in_buf = 0; 873217309Snwhitehorn moved = TRUE; 874217309Snwhitehorn } 875217309Snwhitehorn break; 876217309Snwhitehorn case DLGK_PAGE_LAST: 877217309Snwhitehorn obj.end_reached = TRUE; 878217309Snwhitehorn /* Last page not in buffer? */ 879217309Snwhitehorn fpos = ftell_obj(&obj); 880217309Snwhitehorn 881217309Snwhitehorn if (fpos < obj.file_size) { 882217309Snwhitehorn /* Yes, we have to read it in */ 883251843Sbapt lseek_end(&obj, -BUF_SIZE); 884217309Snwhitehorn 885217309Snwhitehorn read_high(&obj, BUF_SIZE); 886217309Snwhitehorn } 887217309Snwhitehorn obj.in_buf = obj.bytes_read; 888220749Snwhitehorn back_lines(&obj, (long) PAGE_LENGTH); 889217309Snwhitehorn moved = TRUE; 890217309Snwhitehorn break; 891217309Snwhitehorn case DLGK_GRID_UP: /* Previous line */ 892217309Snwhitehorn if (!obj.begin_reached) { 893217309Snwhitehorn back_lines(&obj, obj.page_length + 1); 894217309Snwhitehorn next = 1; 895217309Snwhitehorn moved = TRUE; 896217309Snwhitehorn } 897217309Snwhitehorn break; 898217309Snwhitehorn case DLGK_PAGE_PREV: /* Previous page */ 899217309Snwhitehorn case DLGK_MOUSE(KEY_PPAGE): 900217309Snwhitehorn if (!obj.begin_reached) { 901217309Snwhitehorn back_lines(&obj, obj.page_length + PAGE_LENGTH); 902217309Snwhitehorn moved = TRUE; 903217309Snwhitehorn } 904217309Snwhitehorn break; 905217309Snwhitehorn case DLGK_GRID_DOWN: /* Next line */ 906217309Snwhitehorn if (!obj.end_reached) { 907217309Snwhitehorn obj.begin_reached = 0; 908217309Snwhitehorn next = -1; 909217309Snwhitehorn moved = TRUE; 910217309Snwhitehorn } 911217309Snwhitehorn break; 912217309Snwhitehorn case DLGK_PAGE_NEXT: /* Next page */ 913217309Snwhitehorn case DLGK_MOUSE(KEY_NPAGE): 914217309Snwhitehorn if (!obj.end_reached) { 915217309Snwhitehorn obj.begin_reached = 0; 916217309Snwhitehorn moved = TRUE; 917217309Snwhitehorn } 918217309Snwhitehorn break; 919217309Snwhitehorn case DLGK_BEGIN: /* Beginning of line */ 920217309Snwhitehorn if (obj.hscroll > 0) { 921217309Snwhitehorn obj.hscroll = 0; 922217309Snwhitehorn /* Reprint current page to scroll horizontally */ 923217309Snwhitehorn back_lines(&obj, obj.page_length); 924217309Snwhitehorn moved = TRUE; 925217309Snwhitehorn } 926217309Snwhitehorn break; 927217309Snwhitehorn case DLGK_GRID_LEFT: /* Scroll left */ 928217309Snwhitehorn if (obj.hscroll > 0) { 929217309Snwhitehorn obj.hscroll--; 930217309Snwhitehorn /* Reprint current page to scroll horizontally */ 931217309Snwhitehorn back_lines(&obj, obj.page_length); 932217309Snwhitehorn moved = TRUE; 933217309Snwhitehorn } 934217309Snwhitehorn break; 935217309Snwhitehorn case DLGK_GRID_RIGHT: /* Scroll right */ 936217309Snwhitehorn if (obj.hscroll < MAX_LEN) { 937217309Snwhitehorn obj.hscroll++; 938217309Snwhitehorn /* Reprint current page to scroll horizontally */ 939217309Snwhitehorn back_lines(&obj, obj.page_length); 940217309Snwhitehorn moved = TRUE; 941217309Snwhitehorn } 942217309Snwhitehorn break; 943217309Snwhitehorn#ifdef KEY_RESIZE 944217309Snwhitehorn case KEY_RESIZE: 945217309Snwhitehorn /* reset data */ 946217309Snwhitehorn height = old_height; 947217309Snwhitehorn width = old_width; 948217309Snwhitehorn back_lines(&obj, obj.page_length); 949217309Snwhitehorn /* repaint */ 950217309Snwhitehorn dlg_clear(); 951217309Snwhitehorn dlg_del_window(dialog); 952217309Snwhitehorn refresh(); 953217309Snwhitehorn dlg_mouse_free_regions(); 954217309Snwhitehorn goto retry; 955217309Snwhitehorn#endif 956217309Snwhitehorn } 957217309Snwhitehorn } else { 958217309Snwhitehorn switch (key) { 959217309Snwhitehorn case '/': /* Forward search */ 960217309Snwhitehorn case 'n': /* Repeat forward search */ 961217309Snwhitehorn case '?': /* Backward search */ 962217309Snwhitehorn case 'N': /* Repeat backward search */ 963217309Snwhitehorn moved = perform_search(&obj, height, width, key, search_term); 964217309Snwhitehorn fkey = FALSE; 965217309Snwhitehorn break; 966217309Snwhitehorn default: 967217309Snwhitehorn beep(); 968217309Snwhitehorn break; 969217309Snwhitehorn } 970217309Snwhitehorn } 971217309Snwhitehorn } 972217309Snwhitehorn 973217309Snwhitehorn dlg_del_window(dialog); 974217309Snwhitehorn free(obj.buf); 975217309Snwhitehorn (void) close(obj.fd); 976217309Snwhitehorn dlg_mouse_free_regions(); 977217309Snwhitehorn return result; 978217309Snwhitehorn} 979