15382d832SPeter Avalos /*
2*a8e38dc0SAntonio Huete Jimenez * $Id: textbox.c,v 1.128 2022/04/03 22:38:16 tom Exp $
35382d832SPeter Avalos *
45382d832SPeter Avalos * textbox.c -- implements the text box
55382d832SPeter Avalos *
6*a8e38dc0SAntonio Huete Jimenez * Copyright 2000-2021,2022 Thomas E. Dickey
75382d832SPeter Avalos *
85382d832SPeter Avalos * This program is free software; you can redistribute it and/or modify
95382d832SPeter Avalos * it under the terms of the GNU Lesser General Public License, version 2.1
105382d832SPeter Avalos * as published by the Free Software Foundation.
115382d832SPeter Avalos *
125382d832SPeter Avalos * This program is distributed in the hope that it will be useful, but
135382d832SPeter Avalos * WITHOUT ANY WARRANTY; without even the implied warranty of
145382d832SPeter Avalos * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
155382d832SPeter Avalos * Lesser General Public License for more details.
165382d832SPeter Avalos *
175382d832SPeter Avalos * You should have received a copy of the GNU Lesser General Public
185382d832SPeter Avalos * License along with this program; if not, write to
195382d832SPeter Avalos * Free Software Foundation, Inc.
205382d832SPeter Avalos * 51 Franklin St., Fifth Floor
215382d832SPeter Avalos * Boston, MA 02110, USA.
225382d832SPeter Avalos *
235382d832SPeter Avalos * An earlier version of this program lists as authors:
245382d832SPeter Avalos * Savio Lam (lam836@cs.cuhk.hk)
255382d832SPeter Avalos */
265382d832SPeter Avalos
27*a8e38dc0SAntonio Huete Jimenez #include <dlg_internals.h>
285382d832SPeter Avalos #include <dlg_keys.h>
295382d832SPeter Avalos
305382d832SPeter Avalos #define PAGE_LENGTH (height - 4)
315382d832SPeter Avalos #define PAGE_WIDTH (width - 2)
325382d832SPeter Avalos
335382d832SPeter Avalos typedef struct {
345382d832SPeter Avalos DIALOG_CALLBACK obj;
355382d832SPeter Avalos WINDOW *text;
365382d832SPeter Avalos const char **buttons;
375382d832SPeter Avalos int hscroll;
385382d832SPeter Avalos char line[MAX_LEN + 1];
395382d832SPeter Avalos int fd;
405382d832SPeter Avalos long file_size;
415382d832SPeter Avalos long fd_bytes_read;
425382d832SPeter Avalos long bytes_read;
435382d832SPeter Avalos long buffer_len;
445382d832SPeter Avalos bool begin_reached;
455382d832SPeter Avalos bool buffer_first;
465382d832SPeter Avalos bool end_reached;
475382d832SPeter Avalos long page_length; /* lines on the page which is shown */
485382d832SPeter Avalos long in_buf; /* ending index into buf[] for page */
495382d832SPeter Avalos char *buf;
505382d832SPeter Avalos } MY_OBJ;
515382d832SPeter Avalos
525382d832SPeter Avalos static long
lseek_obj(MY_OBJ * obj,long offset,int mode)535382d832SPeter Avalos lseek_obj(MY_OBJ * obj, long offset, int mode)
545382d832SPeter Avalos {
555382d832SPeter Avalos long fpos;
565382d832SPeter Avalos if ((fpos = (long) lseek(obj->fd, (off_t) offset, mode)) == -1) {
575382d832SPeter Avalos switch (mode) {
585382d832SPeter Avalos default:
595382d832SPeter Avalos case SEEK_CUR:
605382d832SPeter Avalos dlg_exiterr("Cannot get file position");
615382d832SPeter Avalos break;
625382d832SPeter Avalos case SEEK_END:
635382d832SPeter Avalos dlg_exiterr("Cannot seek to end of file");
645382d832SPeter Avalos break;
655382d832SPeter Avalos case SEEK_SET:
665382d832SPeter Avalos dlg_exiterr("Cannot set file position to %ld", offset);
675382d832SPeter Avalos break;
685382d832SPeter Avalos }
695382d832SPeter Avalos }
705382d832SPeter Avalos return fpos;
715382d832SPeter Avalos }
725382d832SPeter Avalos
735382d832SPeter Avalos static long
ftell_obj(MY_OBJ * obj)745382d832SPeter Avalos ftell_obj(MY_OBJ * obj)
755382d832SPeter Avalos {
765382d832SPeter Avalos return lseek_obj(obj, 0L, SEEK_CUR);
775382d832SPeter Avalos }
785382d832SPeter Avalos
795382d832SPeter Avalos static void
lseek_set(MY_OBJ * obj,long offset)805382d832SPeter Avalos lseek_set(MY_OBJ * obj, long offset)
815382d832SPeter Avalos {
825382d832SPeter Avalos long actual = lseek_obj(obj, offset, SEEK_SET);
835382d832SPeter Avalos
845382d832SPeter Avalos if (actual != offset) {
855382d832SPeter Avalos dlg_exiterr("Cannot set file position to %ld (actual %ld)\n",
865382d832SPeter Avalos offset, actual);
875382d832SPeter Avalos }
885382d832SPeter Avalos }
895382d832SPeter Avalos
905382d832SPeter Avalos static void
lseek_end(MY_OBJ * obj,long offset)915382d832SPeter Avalos lseek_end(MY_OBJ * obj, long offset)
925382d832SPeter Avalos {
935382d832SPeter Avalos long actual = lseek_obj(obj, offset, SEEK_END);
945382d832SPeter Avalos
955940c9abSDaniel Fojt if (offset == 0L && actual > offset) {
965382d832SPeter Avalos obj->file_size = actual;
975382d832SPeter Avalos }
985382d832SPeter Avalos }
995382d832SPeter Avalos
1005382d832SPeter Avalos static void
lseek_cur(MY_OBJ * obj,long offset)1015382d832SPeter Avalos lseek_cur(MY_OBJ * obj, long offset)
1025382d832SPeter Avalos {
1035382d832SPeter Avalos long actual = lseek_obj(obj, offset, SEEK_CUR);
1045382d832SPeter Avalos
1055382d832SPeter Avalos if (actual != offset) {
1065940c9abSDaniel Fojt DLG_TRACE(("# Lseek returned %ld, expected %ld\n", actual, offset));
1075382d832SPeter Avalos }
1085382d832SPeter Avalos }
1095382d832SPeter Avalos
1105382d832SPeter Avalos static char *
xalloc(size_t size)1115382d832SPeter Avalos xalloc(size_t size)
1125382d832SPeter Avalos {
1135382d832SPeter Avalos char *result = dlg_malloc(char, size);
1145382d832SPeter Avalos assert_ptr(result, "xalloc");
1155382d832SPeter Avalos return result;
1165382d832SPeter Avalos }
1175382d832SPeter Avalos
1185382d832SPeter Avalos /*
1195382d832SPeter Avalos * read_high() substitutes read() for tab->spaces conversion
1205382d832SPeter Avalos *
1215382d832SPeter Avalos * buffer_len, fd_bytes_read, bytes_read are modified
1225382d832SPeter Avalos * buf is allocated
1235382d832SPeter Avalos *
1245382d832SPeter Avalos * fd_bytes_read is the effective number of bytes read from file
1255382d832SPeter Avalos * bytes_read is the length of buf, that can be different if tab_correct
1265382d832SPeter Avalos */
1275382d832SPeter Avalos static void
read_high(MY_OBJ * obj,size_t size_read)1285382d832SPeter Avalos read_high(MY_OBJ * obj, size_t size_read)
1295382d832SPeter Avalos {
1305940c9abSDaniel Fojt char *buftab;
1315382d832SPeter Avalos
1325382d832SPeter Avalos /* Allocate space for read buffer */
1335382d832SPeter Avalos buftab = xalloc(size_read + 1);
1345382d832SPeter Avalos
1355382d832SPeter Avalos if ((obj->fd_bytes_read = read(obj->fd, buftab, size_read)) != -1) {
136*a8e38dc0SAntonio Huete Jimenez int j;
1375940c9abSDaniel Fojt long begin_line;
1385382d832SPeter Avalos
1395382d832SPeter Avalos buftab[obj->fd_bytes_read] = '\0'; /* mark end of valid data */
1405382d832SPeter Avalos
1415382d832SPeter Avalos if (dialog_vars.tab_correct) {
1425382d832SPeter Avalos
1435382d832SPeter Avalos /* calculate bytes_read by buftab and fd_bytes_read */
1445382d832SPeter Avalos obj->bytes_read = begin_line = 0;
1455382d832SPeter Avalos for (j = 0; j < obj->fd_bytes_read; j++)
1465382d832SPeter Avalos if (buftab[j] == TAB)
1475382d832SPeter Avalos obj->bytes_read += dialog_state.tab_len
1485382d832SPeter Avalos - ((obj->bytes_read - begin_line)
1495382d832SPeter Avalos % dialog_state.tab_len);
1505382d832SPeter Avalos else if (buftab[j] == '\n') {
1515382d832SPeter Avalos obj->bytes_read++;
1525382d832SPeter Avalos begin_line = obj->bytes_read;
1535382d832SPeter Avalos } else
1545382d832SPeter Avalos obj->bytes_read++;
1555382d832SPeter Avalos
1565382d832SPeter Avalos if (obj->bytes_read > obj->buffer_len) {
1575382d832SPeter Avalos if (obj->buffer_first)
1585382d832SPeter Avalos obj->buffer_first = FALSE; /* disp = 0 */
1595382d832SPeter Avalos else {
1605382d832SPeter Avalos free(obj->buf);
1615382d832SPeter Avalos }
1625382d832SPeter Avalos
1635382d832SPeter Avalos obj->buffer_len = obj->bytes_read;
1645382d832SPeter Avalos
1655382d832SPeter Avalos /* Allocate space for read buffer */
1665382d832SPeter Avalos obj->buf = xalloc((size_t) obj->buffer_len + 1);
1675382d832SPeter Avalos }
1685382d832SPeter Avalos
1695382d832SPeter Avalos } else {
1705382d832SPeter Avalos if (obj->buffer_first) {
1715382d832SPeter Avalos obj->buffer_first = FALSE;
1725382d832SPeter Avalos
1735382d832SPeter Avalos /* Allocate space for read buffer */
1745382d832SPeter Avalos obj->buf = xalloc(size_read + 1);
1755382d832SPeter Avalos }
1765382d832SPeter Avalos
1775382d832SPeter Avalos obj->bytes_read = obj->fd_bytes_read;
1785382d832SPeter Avalos }
1795382d832SPeter Avalos
1805382d832SPeter Avalos j = 0;
1815382d832SPeter Avalos begin_line = 0;
182*a8e38dc0SAntonio Huete Jimenez if (obj->buf != NULL) {
183*a8e38dc0SAntonio Huete Jimenez int i = 0;
184*a8e38dc0SAntonio Huete Jimenez
1855940c9abSDaniel Fojt while (j < obj->fd_bytes_read) {
1865940c9abSDaniel Fojt char ch;
1875940c9abSDaniel Fojt
188*a8e38dc0SAntonio Huete Jimenez if (((ch = buftab[j++]) == TAB)
189*a8e38dc0SAntonio Huete Jimenez && (dialog_vars.tab_correct != 0)) {
190*a8e38dc0SAntonio Huete Jimenez int n;
191*a8e38dc0SAntonio Huete Jimenez int tmpint = (dialog_state.tab_len
1925382d832SPeter Avalos - ((int) ((long) i - begin_line) % dialog_state.tab_len));
1935382d832SPeter Avalos for (n = 0; n < tmpint; n++)
1945382d832SPeter Avalos obj->buf[i++] = ' ';
1955382d832SPeter Avalos } else {
1965382d832SPeter Avalos if (ch == '\n')
1975382d832SPeter Avalos begin_line = i + 1;
1985382d832SPeter Avalos obj->buf[i++] = ch;
1995382d832SPeter Avalos }
2005940c9abSDaniel Fojt }
2015382d832SPeter Avalos
2025382d832SPeter Avalos obj->buf[i] = '\0'; /* mark end of valid data */
203*a8e38dc0SAntonio Huete Jimenez }
2045382d832SPeter Avalos
2055382d832SPeter Avalos }
2065382d832SPeter Avalos if (obj->bytes_read == -1)
2075382d832SPeter Avalos dlg_exiterr("Error reading file");
2085382d832SPeter Avalos free(buftab);
2095382d832SPeter Avalos }
2105382d832SPeter Avalos
2115382d832SPeter Avalos static long
find_first(MY_OBJ * obj,char * buffer,long length)2125382d832SPeter Avalos find_first(MY_OBJ * obj, char *buffer, long length)
2135382d832SPeter Avalos {
2145382d832SPeter Avalos long result = 0;
2155382d832SPeter Avalos
216*a8e38dc0SAntonio Huete Jimenez if (buffer != NULL) {
217*a8e38dc0SAntonio Huete Jimenez long recount = obj->page_length;
2185382d832SPeter Avalos while (length > 0) {
2195382d832SPeter Avalos if (buffer[length] == '\n') {
2205382d832SPeter Avalos if (--recount < 0) {
2215382d832SPeter Avalos result = length;
2225382d832SPeter Avalos break;
2235382d832SPeter Avalos }
2245382d832SPeter Avalos }
2255382d832SPeter Avalos --length;
2265382d832SPeter Avalos }
227*a8e38dc0SAntonio Huete Jimenez }
2285382d832SPeter Avalos return result;
2295382d832SPeter Avalos }
2305382d832SPeter Avalos
2315382d832SPeter Avalos static long
tabize(MY_OBJ * obj,long val,long * first_pos)2325382d832SPeter Avalos tabize(MY_OBJ * obj, long val, long *first_pos)
2335382d832SPeter Avalos {
2345382d832SPeter Avalos long fpos;
2355382d832SPeter Avalos long i, count, begin_line;
2365382d832SPeter Avalos char *buftab;
2375382d832SPeter Avalos
2385382d832SPeter Avalos if (!dialog_vars.tab_correct)
2395382d832SPeter Avalos return val;
2405382d832SPeter Avalos
2415382d832SPeter Avalos fpos = ftell_obj(obj);
2425382d832SPeter Avalos
2435382d832SPeter Avalos lseek_set(obj, fpos - obj->fd_bytes_read);
2445382d832SPeter Avalos
2455382d832SPeter Avalos /* Allocate space for read buffer */
2465382d832SPeter Avalos buftab = xalloc((size_t) val + 1);
2475382d832SPeter Avalos
2485382d832SPeter Avalos if ((read(obj->fd, buftab, (size_t) val)) == -1)
2495382d832SPeter Avalos dlg_exiterr("Error reading file in tabize().");
2505382d832SPeter Avalos
2515382d832SPeter Avalos begin_line = count = 0;
2525382d832SPeter Avalos if (first_pos != 0)
2535382d832SPeter Avalos *first_pos = 0;
2545382d832SPeter Avalos
2555382d832SPeter Avalos for (i = 0; i < val; i++) {
2565382d832SPeter Avalos if ((first_pos != 0) && (count >= val)) {
2575382d832SPeter Avalos *first_pos = find_first(obj, buftab, i);
2585382d832SPeter Avalos break;
2595382d832SPeter Avalos }
2605382d832SPeter Avalos if (buftab[i] == TAB)
2615382d832SPeter Avalos count += dialog_state.tab_len
2625382d832SPeter Avalos - ((count - begin_line) % dialog_state.tab_len);
2635382d832SPeter Avalos else if (buftab[i] == '\n') {
2645382d832SPeter Avalos count++;
2655382d832SPeter Avalos begin_line = count;
2665382d832SPeter Avalos } else
2675382d832SPeter Avalos count++;
2685382d832SPeter Avalos }
2695382d832SPeter Avalos
2705382d832SPeter Avalos lseek_set(obj, fpos);
2715382d832SPeter Avalos free(buftab);
2725382d832SPeter Avalos return count;
2735382d832SPeter Avalos }
2745382d832SPeter Avalos /*
2755382d832SPeter Avalos * Return current line of text.
2765382d832SPeter Avalos * 'page' should point to start of current line before calling, and will be
2775382d832SPeter Avalos * updated to point to start of next line.
2785382d832SPeter Avalos */
2795382d832SPeter Avalos static char *
get_line(MY_OBJ * obj)2805382d832SPeter Avalos get_line(MY_OBJ * obj)
2815382d832SPeter Avalos {
2825382d832SPeter Avalos int i = 0;
2835382d832SPeter Avalos
2845382d832SPeter Avalos obj->end_reached = FALSE;
285*a8e38dc0SAntonio Huete Jimenez if (obj->buf != NULL) {
2865382d832SPeter Avalos while (obj->buf[obj->in_buf] != '\n') {
2875382d832SPeter Avalos if (obj->buf[obj->in_buf] == '\0') { /* Either end of file or end of buffer reached */
288*a8e38dc0SAntonio Huete Jimenez long fpos = ftell_obj(obj);
2895382d832SPeter Avalos
2905382d832SPeter Avalos if (fpos < obj->file_size) { /* Not end of file yet */
2915382d832SPeter Avalos /* We've reached end of buffer, but not end of file yet, so
2925382d832SPeter Avalos * read next part of file into buffer
2935382d832SPeter Avalos */
2945382d832SPeter Avalos read_high(obj, BUF_SIZE);
2955382d832SPeter Avalos obj->in_buf = 0;
2965382d832SPeter Avalos } else {
2975382d832SPeter Avalos if (!obj->end_reached)
2985382d832SPeter Avalos obj->end_reached = TRUE;
2995382d832SPeter Avalos break;
3005382d832SPeter Avalos }
3015382d832SPeter Avalos } else if (i < MAX_LEN)
3025382d832SPeter Avalos obj->line[i++] = obj->buf[obj->in_buf++];
3035382d832SPeter Avalos else {
3045382d832SPeter Avalos if (i == MAX_LEN) /* Truncate lines longer than MAX_LEN characters */
3055382d832SPeter Avalos obj->line[i++] = '\0';
3065382d832SPeter Avalos obj->in_buf++;
3075382d832SPeter Avalos }
3085382d832SPeter Avalos }
309*a8e38dc0SAntonio Huete Jimenez }
3105382d832SPeter Avalos if (i <= MAX_LEN)
3115382d832SPeter Avalos obj->line[i] = '\0';
3125382d832SPeter Avalos if (!obj->end_reached)
3135382d832SPeter Avalos obj->in_buf++; /* move past '\n' */
3145382d832SPeter Avalos
3155382d832SPeter Avalos return obj->line;
3165382d832SPeter Avalos }
3175382d832SPeter Avalos
3185382d832SPeter Avalos static bool
match_string(MY_OBJ * obj,char * string)3195382d832SPeter Avalos match_string(MY_OBJ * obj, char *string)
3205382d832SPeter Avalos {
3215382d832SPeter Avalos char *match = get_line(obj);
3225382d832SPeter Avalos return strstr(match, string) != 0;
3235382d832SPeter Avalos }
3245382d832SPeter Avalos
3255382d832SPeter Avalos /*
3265382d832SPeter Avalos * Go back 'n' lines in text file. Called by dialog_textbox().
3275382d832SPeter Avalos * 'in_buf' will be updated to point to the desired line in 'buf'.
3285382d832SPeter Avalos */
3295382d832SPeter Avalos static void
back_lines(MY_OBJ * obj,long n)3305382d832SPeter Avalos back_lines(MY_OBJ * obj, long n)
3315382d832SPeter Avalos {
3325382d832SPeter Avalos int i;
3335382d832SPeter Avalos long fpos;
3345382d832SPeter Avalos long val_to_tabize;
3355382d832SPeter Avalos
3365382d832SPeter Avalos obj->begin_reached = FALSE;
3375382d832SPeter Avalos /* We have to distinguish between end_reached and !end_reached since at end
3385382d832SPeter Avalos * of file, the line is not ended by a '\n'. The code inside 'if'
3395382d832SPeter Avalos * basically does a '--in_buf' to move one character backward so as to
3405382d832SPeter Avalos * skip '\n' of the previous line */
3415382d832SPeter Avalos if (!obj->end_reached) {
3425382d832SPeter Avalos /* Either beginning of buffer or beginning of file reached? */
3435382d832SPeter Avalos
3445382d832SPeter Avalos if (obj->in_buf == 0) {
3455382d832SPeter Avalos fpos = ftell_obj(obj);
3465382d832SPeter Avalos
3475382d832SPeter Avalos if (fpos > obj->fd_bytes_read) { /* Not beginning of file yet */
3485382d832SPeter Avalos /* We've reached beginning of buffer, but not beginning of file
3495382d832SPeter Avalos * yet, so read previous part of file into buffer. Note that
3505382d832SPeter Avalos * we only move backward for BUF_SIZE/2 bytes, but not BUF_SIZE
3515382d832SPeter Avalos * bytes to avoid re-reading again in print_page() later
3525382d832SPeter Avalos */
3535382d832SPeter Avalos /* Really possible to move backward BUF_SIZE/2 bytes? */
3545382d832SPeter Avalos if (fpos < BUF_SIZE / 2 + obj->fd_bytes_read) {
3555382d832SPeter Avalos /* No, move less than */
3565382d832SPeter Avalos lseek_set(obj, 0L);
3575382d832SPeter Avalos val_to_tabize = fpos - obj->fd_bytes_read;
3585382d832SPeter Avalos } else { /* Move backward BUF_SIZE/2 bytes */
3595382d832SPeter Avalos lseek_cur(obj, -(BUF_SIZE / 2 + obj->fd_bytes_read));
3605382d832SPeter Avalos val_to_tabize = BUF_SIZE / 2;
3615382d832SPeter Avalos }
3625382d832SPeter Avalos read_high(obj, BUF_SIZE);
3635382d832SPeter Avalos
3645382d832SPeter Avalos obj->in_buf = tabize(obj, val_to_tabize, (long *) 0);
3655382d832SPeter Avalos
3665382d832SPeter Avalos } else { /* Beginning of file reached */
3675382d832SPeter Avalos obj->begin_reached = TRUE;
3685382d832SPeter Avalos return;
3695382d832SPeter Avalos }
3705382d832SPeter Avalos }
3715382d832SPeter Avalos obj->in_buf--;
372*a8e38dc0SAntonio Huete Jimenez if (obj->buf == NULL
373*a8e38dc0SAntonio Huete Jimenez || obj->in_buf < 0
374*a8e38dc0SAntonio Huete Jimenez || obj->in_buf >= obj->bytes_read
375*a8e38dc0SAntonio Huete Jimenez || obj->buf[obj->in_buf] != '\n')
3765382d832SPeter Avalos /* Something's wrong... */
3775382d832SPeter Avalos dlg_exiterr("Internal error in back_lines().");
3785382d832SPeter Avalos }
3795382d832SPeter Avalos
3805382d832SPeter Avalos /* Go back 'n' lines */
3815382d832SPeter Avalos for (i = 0; i < n; i++) {
3825382d832SPeter Avalos do {
3835382d832SPeter Avalos if (obj->in_buf == 0) {
3845382d832SPeter Avalos fpos = ftell_obj(obj);
3855382d832SPeter Avalos
3865382d832SPeter Avalos if (fpos > obj->fd_bytes_read) {
3875382d832SPeter Avalos /* Really possible to move backward BUF_SIZE/2 bytes? */
3885382d832SPeter Avalos if (fpos < BUF_SIZE / 2 + obj->fd_bytes_read) {
3895382d832SPeter Avalos /* No, move less than */
3905382d832SPeter Avalos lseek_set(obj, 0L);
3915382d832SPeter Avalos val_to_tabize = fpos - obj->fd_bytes_read;
3925382d832SPeter Avalos } else { /* Move backward BUF_SIZE/2 bytes */
3935382d832SPeter Avalos lseek_cur(obj, -(BUF_SIZE / 2 + obj->fd_bytes_read));
3945382d832SPeter Avalos val_to_tabize = BUF_SIZE / 2;
3955382d832SPeter Avalos }
3965382d832SPeter Avalos read_high(obj, BUF_SIZE);
3975382d832SPeter Avalos
3985382d832SPeter Avalos obj->in_buf = tabize(obj, val_to_tabize, (long *) 0);
3995382d832SPeter Avalos
4005382d832SPeter Avalos } else { /* Beginning of file reached */
4015382d832SPeter Avalos obj->begin_reached = TRUE;
4025382d832SPeter Avalos return;
4035382d832SPeter Avalos }
4045382d832SPeter Avalos }
4055382d832SPeter Avalos } while (obj->buf[--(obj->in_buf)] != '\n');
4065382d832SPeter Avalos }
4075382d832SPeter Avalos obj->in_buf++;
4085382d832SPeter Avalos }
4095382d832SPeter Avalos
4105382d832SPeter Avalos /*
4115382d832SPeter Avalos * Print a new line of text.
4125382d832SPeter Avalos */
4135382d832SPeter Avalos static void
print_line(MY_OBJ * obj,int row,int width)4145382d832SPeter Avalos print_line(MY_OBJ * obj, int row, int width)
4155382d832SPeter Avalos {
4165382d832SPeter Avalos if (wmove(obj->text, row, 0) != ERR) {
4175382d832SPeter Avalos int i, y, x;
4185382d832SPeter Avalos char *line = get_line(obj);
4195382d832SPeter Avalos const int *cols = dlg_index_columns(line);
4205382d832SPeter Avalos const int *indx = dlg_index_wchars(line);
4215382d832SPeter Avalos int limit = dlg_count_wchars(line);
4225382d832SPeter Avalos int first = 0;
4235382d832SPeter Avalos int last = limit;
4245382d832SPeter Avalos
4255382d832SPeter Avalos if (width > getmaxx(obj->text))
4265382d832SPeter Avalos width = getmaxx(obj->text);
4275382d832SPeter Avalos --width; /* for the leading ' ' */
4285382d832SPeter Avalos
4295382d832SPeter Avalos for (i = 0; i <= limit && cols[i] < obj->hscroll; ++i)
4305382d832SPeter Avalos first = i;
4315382d832SPeter Avalos
4325382d832SPeter Avalos for (i = first; (i <= limit) && ((cols[i] - cols[first]) < width); ++i)
4335382d832SPeter Avalos last = i;
4345382d832SPeter Avalos
4355382d832SPeter Avalos (void) waddch(obj->text, ' ');
4365382d832SPeter Avalos (void) waddnstr(obj->text, line + indx[first], indx[last] - indx[first]);
4375382d832SPeter Avalos
4385382d832SPeter Avalos getyx(obj->text, y, x);
4395382d832SPeter Avalos if (y == row) { /* Clear 'residue' of previous line */
4405382d832SPeter Avalos for (i = 0; i <= width - x; i++) {
4415382d832SPeter Avalos (void) waddch(obj->text, ' ');
4425382d832SPeter Avalos }
4435382d832SPeter Avalos }
4445382d832SPeter Avalos }
4455382d832SPeter Avalos }
4465382d832SPeter Avalos
4475382d832SPeter Avalos /*
4485382d832SPeter Avalos * Print a new page of text.
4495382d832SPeter Avalos */
4505382d832SPeter Avalos static void
print_page(MY_OBJ * obj,int height,int width)4515382d832SPeter Avalos print_page(MY_OBJ * obj, int height, int width)
4525382d832SPeter Avalos {
4535382d832SPeter Avalos int i, passed_end = 0;
4545382d832SPeter Avalos
4555382d832SPeter Avalos obj->page_length = 0;
4565382d832SPeter Avalos for (i = 0; i < height; i++) {
4575382d832SPeter Avalos print_line(obj, i, width);
4585382d832SPeter Avalos if (!passed_end)
4595382d832SPeter Avalos obj->page_length++;
4605382d832SPeter Avalos if (obj->end_reached && !passed_end)
4615382d832SPeter Avalos passed_end = 1;
4625382d832SPeter Avalos }
4635382d832SPeter Avalos (void) wnoutrefresh(obj->text);
4645382d832SPeter Avalos dlg_trace_win(obj->text);
4655382d832SPeter Avalos }
4665382d832SPeter Avalos
4675382d832SPeter Avalos /*
4685382d832SPeter Avalos * Print current position
4695382d832SPeter Avalos */
4705382d832SPeter Avalos static void
print_position(MY_OBJ * obj,WINDOW * win,int height,int width)4715382d832SPeter Avalos print_position(MY_OBJ * obj, WINDOW *win, int height, int width)
4725382d832SPeter Avalos {
4735382d832SPeter Avalos long fpos;
4745382d832SPeter Avalos long size;
4755382d832SPeter Avalos long first = -1;
4765382d832SPeter Avalos
4775382d832SPeter Avalos fpos = ftell_obj(obj);
4785382d832SPeter Avalos if (dialog_vars.tab_correct)
4795382d832SPeter Avalos size = tabize(obj, obj->in_buf, &first);
4805382d832SPeter Avalos else
4815382d832SPeter Avalos first = find_first(obj, obj->buf, size = obj->in_buf);
4825382d832SPeter Avalos
4835382d832SPeter Avalos dlg_draw_scrollbar(win,
4845382d832SPeter Avalos first,
4855382d832SPeter Avalos fpos - obj->fd_bytes_read + size,
4865382d832SPeter Avalos fpos - obj->fd_bytes_read + size,
4875382d832SPeter Avalos obj->file_size,
4885382d832SPeter Avalos 0, PAGE_WIDTH,
4895382d832SPeter Avalos 0, PAGE_LENGTH + 1,
4905382d832SPeter Avalos border_attr,
4915382d832SPeter Avalos border_attr);
4925382d832SPeter Avalos }
4935382d832SPeter Avalos
4945382d832SPeter Avalos /*
4955382d832SPeter Avalos * Display a dialog box and get the search term from user.
4965382d832SPeter Avalos */
4975382d832SPeter Avalos static int
get_search_term(WINDOW * dialog,char * input,int height,int width)4985382d832SPeter Avalos get_search_term(WINDOW *dialog, char *input, int height, int width)
4995382d832SPeter Avalos {
5005382d832SPeter Avalos /* *INDENT-OFF* */
5015382d832SPeter Avalos static DLG_KEYS_BINDING binding[] = {
5025382d832SPeter Avalos INPUTSTR_BINDINGS,
5035382d832SPeter Avalos HELPKEY_BINDINGS,
5045382d832SPeter Avalos ENTERKEY_BINDINGS,
5055382d832SPeter Avalos END_KEYS_BINDING
5065382d832SPeter Avalos };
5075382d832SPeter Avalos /* *INDENT-ON* */
5085382d832SPeter Avalos
5095382d832SPeter Avalos int old_x, old_y;
5105382d832SPeter Avalos int box_x, box_y;
5115382d832SPeter Avalos int box_height, box_width;
5125382d832SPeter Avalos int offset = 0;
5135382d832SPeter Avalos int key = 0;
5145382d832SPeter Avalos int fkey = 0;
5155382d832SPeter Avalos bool first = TRUE;
5165382d832SPeter Avalos int result = DLG_EXIT_UNKNOWN;
5175382d832SPeter Avalos const char *caption = _("Search");
5185382d832SPeter Avalos int len_caption = dlg_count_columns(caption);
5195382d832SPeter Avalos const int *indx;
5205382d832SPeter Avalos int limit;
5215382d832SPeter Avalos WINDOW *widget;
5225382d832SPeter Avalos
5235382d832SPeter Avalos getbegyx(dialog, old_y, old_x);
5245382d832SPeter Avalos
5255382d832SPeter Avalos box_height = 1 + (2 * MARGIN);
5265382d832SPeter Avalos box_width = len_caption + (2 * (MARGIN + 2));
5275382d832SPeter Avalos box_width = MAX(box_width, 30);
5285382d832SPeter Avalos box_width = MIN(box_width, getmaxx(dialog) - 2 * MARGIN);
5295382d832SPeter Avalos len_caption = MIN(len_caption, box_width - (2 * (MARGIN + 1)));
5305382d832SPeter Avalos
5315382d832SPeter Avalos box_x = (width - box_width) / 2;
5325382d832SPeter Avalos box_y = (height - box_height) / 2;
5335382d832SPeter Avalos widget = dlg_new_modal_window(dialog,
5345382d832SPeter Avalos box_height, box_width,
5355382d832SPeter Avalos old_y + box_y, old_x + box_x);
5365382d832SPeter Avalos keypad(widget, TRUE);
5375382d832SPeter Avalos dlg_register_window(widget, "searchbox", binding);
5385382d832SPeter Avalos
5395382d832SPeter Avalos dlg_draw_box2(widget, 0, 0, box_height, box_width,
5405382d832SPeter Avalos searchbox_attr,
5415382d832SPeter Avalos searchbox_border_attr,
5425382d832SPeter Avalos searchbox_border2_attr);
5435940c9abSDaniel Fojt dlg_attrset(widget, searchbox_title_attr);
5445382d832SPeter Avalos (void) wmove(widget, 0, (box_width - len_caption) / 2);
5455382d832SPeter Avalos
5465382d832SPeter Avalos indx = dlg_index_wchars(caption);
5475382d832SPeter Avalos limit = dlg_limit_columns(caption, len_caption, 0);
5485382d832SPeter Avalos (void) waddnstr(widget, caption + indx[0], indx[limit] - indx[0]);
5495382d832SPeter Avalos
5505382d832SPeter Avalos box_width -= 2;
5515382d832SPeter Avalos offset = dlg_count_columns(input);
5525382d832SPeter Avalos
5535382d832SPeter Avalos while (result == DLG_EXIT_UNKNOWN) {
5545382d832SPeter Avalos if (!first) {
5555382d832SPeter Avalos key = dlg_getc(widget, &fkey);
5565382d832SPeter Avalos if (fkey) {
5575382d832SPeter Avalos switch (fkey) {
5585382d832SPeter Avalos #ifdef KEY_RESIZE
5595382d832SPeter Avalos case KEY_RESIZE:
5605382d832SPeter Avalos result = DLG_EXIT_CANCEL;
5615382d832SPeter Avalos continue;
5625382d832SPeter Avalos #endif
5635382d832SPeter Avalos case DLGK_ENTER:
5645382d832SPeter Avalos result = DLG_EXIT_OK;
5655382d832SPeter Avalos continue;
5665382d832SPeter Avalos }
5675382d832SPeter Avalos } else if (key == ESC) {
5685382d832SPeter Avalos result = DLG_EXIT_ESC;
5695382d832SPeter Avalos continue;
5705382d832SPeter Avalos } else if (key == ERR) {
5715382d832SPeter Avalos napms(50);
5725382d832SPeter Avalos continue;
5735382d832SPeter Avalos }
5745382d832SPeter Avalos }
5755382d832SPeter Avalos if (dlg_edit_string(input, &offset, key, fkey, first)) {
5765382d832SPeter Avalos dlg_show_string(widget, input, offset, searchbox_attr,
5775382d832SPeter Avalos 1, 1, box_width, FALSE, first);
5785382d832SPeter Avalos first = FALSE;
5795382d832SPeter Avalos }
5805382d832SPeter Avalos }
5815382d832SPeter Avalos dlg_del_window(widget);
5825382d832SPeter Avalos return result;
5835382d832SPeter Avalos }
5845382d832SPeter Avalos
5855382d832SPeter Avalos static bool
perform_search(MY_OBJ * obj,int height,int width,int key,char * search_term)5865382d832SPeter Avalos perform_search(MY_OBJ * obj, int height, int width, int key, char *search_term)
5875382d832SPeter Avalos {
5885382d832SPeter Avalos int dir;
5895382d832SPeter Avalos bool moved = FALSE;
5905382d832SPeter Avalos
5915382d832SPeter Avalos /* set search direction */
5925382d832SPeter Avalos dir = (key == '/' || key == 'n') ? 1 : 0;
5935382d832SPeter Avalos if (dir ? !obj->end_reached : !obj->begin_reached) {
5945940c9abSDaniel Fojt long tempinx;
5955940c9abSDaniel Fojt long fpos;
5965940c9abSDaniel Fojt int result;
5975940c9abSDaniel Fojt bool found;
5985940c9abSDaniel Fojt bool temp, temp1;
5995940c9abSDaniel Fojt
6005382d832SPeter Avalos if (key == 'n' || key == 'N') {
6015382d832SPeter Avalos if (search_term[0] == '\0') { /* No search term yet */
6025382d832SPeter Avalos (void) beep();
6035382d832SPeter Avalos return FALSE;
6045382d832SPeter Avalos }
6055382d832SPeter Avalos /* Get search term from user */
6065382d832SPeter Avalos } else if ((result = get_search_term(obj->text, search_term,
6075382d832SPeter Avalos PAGE_LENGTH,
6085382d832SPeter Avalos PAGE_WIDTH)) != DLG_EXIT_OK
6095382d832SPeter Avalos || search_term[0] == '\0') {
6105382d832SPeter Avalos #ifdef KEY_RESIZE
6115382d832SPeter Avalos if (result == DLG_EXIT_CANCEL) {
6125382d832SPeter Avalos ungetch(key);
6135382d832SPeter Avalos ungetch(KEY_RESIZE);
6145382d832SPeter Avalos /* FALLTHRU */
6155382d832SPeter Avalos }
6165940c9abSDaniel Fojt #else
6175940c9abSDaniel Fojt (void) result;
6185382d832SPeter Avalos #endif
6195382d832SPeter Avalos /* ESC pressed, or no search term, reprint page to clear box */
6205940c9abSDaniel Fojt dlg_attrset(obj->text, dialog_attr);
6215382d832SPeter Avalos back_lines(obj, obj->page_length);
6225382d832SPeter Avalos return TRUE;
6235382d832SPeter Avalos }
6245382d832SPeter Avalos /* Save variables for restoring in case search term can't be found */
6255382d832SPeter Avalos tempinx = obj->in_buf;
6265382d832SPeter Avalos temp = obj->begin_reached;
6275382d832SPeter Avalos temp1 = obj->end_reached;
6285382d832SPeter Avalos fpos = ftell_obj(obj) - obj->fd_bytes_read;
6295382d832SPeter Avalos /* update 'in_buf' to point to next (previous) line before
6305382d832SPeter Avalos forward (backward) searching */
6315382d832SPeter Avalos back_lines(obj, (dir
6325382d832SPeter Avalos ? obj->page_length - 1
6335382d832SPeter Avalos : obj->page_length + 1));
6345382d832SPeter Avalos if (dir) { /* Forward search */
6355382d832SPeter Avalos while ((found = match_string(obj, search_term)) == FALSE) {
6365382d832SPeter Avalos if (obj->end_reached)
6375382d832SPeter Avalos break;
6385382d832SPeter Avalos }
6395382d832SPeter Avalos } else { /* Backward search */
6405382d832SPeter Avalos while ((found = match_string(obj, search_term)) == FALSE) {
6415382d832SPeter Avalos if (obj->begin_reached)
6425382d832SPeter Avalos break;
6435382d832SPeter Avalos back_lines(obj, 2L);
6445382d832SPeter Avalos }
6455382d832SPeter Avalos }
6465382d832SPeter Avalos if (found == FALSE) { /* not found */
6475382d832SPeter Avalos (void) beep();
6485382d832SPeter Avalos /* Restore program state to that before searching */
6495382d832SPeter Avalos lseek_set(obj, fpos);
6505382d832SPeter Avalos
6515382d832SPeter Avalos read_high(obj, BUF_SIZE);
6525382d832SPeter Avalos
6535382d832SPeter Avalos obj->in_buf = tempinx;
6545382d832SPeter Avalos obj->begin_reached = temp;
6555382d832SPeter Avalos obj->end_reached = temp1;
6565382d832SPeter Avalos /* move 'in_buf' to point to start of current page to
6575382d832SPeter Avalos * re-print current page. Note that 'in_buf' always points
6585382d832SPeter Avalos * to start of next page, so this is necessary
6595382d832SPeter Avalos */
6605382d832SPeter Avalos back_lines(obj, obj->page_length);
6615382d832SPeter Avalos } else { /* Search term found */
6625382d832SPeter Avalos back_lines(obj, 1L);
6635382d832SPeter Avalos }
6645382d832SPeter Avalos /* Reprint page */
6655940c9abSDaniel Fojt dlg_attrset(obj->text, dialog_attr);
6665382d832SPeter Avalos moved = TRUE;
6675382d832SPeter Avalos } else { /* no need to find */
6685382d832SPeter Avalos (void) beep();
6695382d832SPeter Avalos }
6705382d832SPeter Avalos return moved;
6715382d832SPeter Avalos }
6725382d832SPeter Avalos
6735382d832SPeter Avalos /*
6745382d832SPeter Avalos * Display text from a file in a dialog box.
6755382d832SPeter Avalos */
6765382d832SPeter Avalos int
dialog_textbox(const char * title,const char * filename,int height,int width)6775940c9abSDaniel Fojt dialog_textbox(const char *title, const char *filename, int height, int width)
6785382d832SPeter Avalos {
6795382d832SPeter Avalos /* *INDENT-OFF* */
6805382d832SPeter Avalos static DLG_KEYS_BINDING binding[] = {
6815382d832SPeter Avalos HELPKEY_BINDINGS,
6825382d832SPeter Avalos ENTERKEY_BINDINGS,
6835382d832SPeter Avalos DLG_KEYS_DATA( DLGK_GRID_DOWN, 'J' ),
6845382d832SPeter Avalos DLG_KEYS_DATA( DLGK_GRID_DOWN, 'j' ),
6855382d832SPeter Avalos DLG_KEYS_DATA( DLGK_GRID_DOWN, KEY_DOWN ),
6865382d832SPeter Avalos DLG_KEYS_DATA( DLGK_GRID_LEFT, 'H' ),
6875382d832SPeter Avalos DLG_KEYS_DATA( DLGK_GRID_LEFT, 'h' ),
6885382d832SPeter Avalos DLG_KEYS_DATA( DLGK_GRID_LEFT, KEY_LEFT ),
6895382d832SPeter Avalos DLG_KEYS_DATA( DLGK_GRID_RIGHT, 'L' ),
6905382d832SPeter Avalos DLG_KEYS_DATA( DLGK_GRID_RIGHT, 'l' ),
6915382d832SPeter Avalos DLG_KEYS_DATA( DLGK_GRID_RIGHT, KEY_RIGHT ),
6925382d832SPeter Avalos DLG_KEYS_DATA( DLGK_GRID_UP, 'K' ),
6935382d832SPeter Avalos DLG_KEYS_DATA( DLGK_GRID_UP, 'k' ),
6945382d832SPeter Avalos DLG_KEYS_DATA( DLGK_GRID_UP, KEY_UP ),
6955382d832SPeter Avalos DLG_KEYS_DATA( DLGK_PAGE_FIRST, 'g' ),
6965382d832SPeter Avalos DLG_KEYS_DATA( DLGK_PAGE_FIRST, KEY_HOME ),
6975382d832SPeter Avalos DLG_KEYS_DATA( DLGK_PAGE_LAST, 'G' ),
6985382d832SPeter Avalos DLG_KEYS_DATA( DLGK_PAGE_LAST, KEY_END ),
6995382d832SPeter Avalos DLG_KEYS_DATA( DLGK_PAGE_LAST, KEY_LL ),
7005940c9abSDaniel Fojt DLG_KEYS_DATA( DLGK_PAGE_NEXT, CHR_SPACE ),
7015382d832SPeter Avalos DLG_KEYS_DATA( DLGK_PAGE_NEXT, KEY_NPAGE ),
7025382d832SPeter Avalos DLG_KEYS_DATA( DLGK_PAGE_PREV, 'B' ),
7035382d832SPeter Avalos DLG_KEYS_DATA( DLGK_PAGE_PREV, 'b' ),
7045382d832SPeter Avalos DLG_KEYS_DATA( DLGK_PAGE_PREV, KEY_PPAGE ),
7055382d832SPeter Avalos DLG_KEYS_DATA( DLGK_BEGIN, '0' ),
7065382d832SPeter Avalos DLG_KEYS_DATA( DLGK_BEGIN, KEY_BEG ),
7075382d832SPeter Avalos DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
7085382d832SPeter Avalos DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
7095382d832SPeter Avalos END_KEYS_BINDING
7105382d832SPeter Avalos };
7115382d832SPeter Avalos /* *INDENT-ON* */
7125382d832SPeter Avalos
7135382d832SPeter Avalos #ifdef KEY_RESIZE
7145382d832SPeter Avalos int old_height = height;
7155382d832SPeter Avalos int old_width = width;
7165382d832SPeter Avalos #endif
7175382d832SPeter Avalos long fpos;
7185382d832SPeter Avalos int x, y, cur_x, cur_y;
7195940c9abSDaniel Fojt int key, fkey;
7205382d832SPeter Avalos int next = 0;
7215940c9abSDaniel Fojt int i, passed_end;
7225382d832SPeter Avalos char search_term[MAX_LEN + 1];
7235382d832SPeter Avalos MY_OBJ obj;
7245382d832SPeter Avalos WINDOW *dialog;
7255382d832SPeter Avalos bool moved;
7265382d832SPeter Avalos int result = DLG_EXIT_UNKNOWN;
7275382d832SPeter Avalos int button = dlg_default_button();
7285382d832SPeter Avalos int min_width = 12;
7295382d832SPeter Avalos
7305940c9abSDaniel Fojt DLG_TRACE(("# textbox args:\n"));
7315940c9abSDaniel Fojt DLG_TRACE2S("title", title);
7325940c9abSDaniel Fojt DLG_TRACE2S("filename", filename);
7335940c9abSDaniel Fojt DLG_TRACE2N("height", height);
7345940c9abSDaniel Fojt DLG_TRACE2N("width", width);
7355940c9abSDaniel Fojt
7365382d832SPeter Avalos search_term[0] = '\0'; /* no search term entered yet */
7375382d832SPeter Avalos
7385382d832SPeter Avalos memset(&obj, 0, sizeof(obj));
7395382d832SPeter Avalos
7405382d832SPeter Avalos obj.begin_reached = TRUE;
7415382d832SPeter Avalos obj.buffer_first = TRUE;
7425382d832SPeter Avalos obj.end_reached = FALSE;
7435382d832SPeter Avalos obj.buttons = dlg_exit_label();
7445382d832SPeter Avalos
7455382d832SPeter Avalos /* Open input file for reading */
7465940c9abSDaniel Fojt if ((obj.fd = open(filename, O_RDONLY)) == -1)
7475940c9abSDaniel Fojt dlg_exiterr("Can't open input file %s", filename);
7485382d832SPeter Avalos
7495382d832SPeter Avalos /* Get file size. Actually, 'file_size' is the real file size - 1,
7505382d832SPeter Avalos since it's only the last byte offset from the beginning */
7515382d832SPeter Avalos lseek_end(&obj, 0L);
7525382d832SPeter Avalos
7535382d832SPeter Avalos /* Restore file pointer to beginning of file after getting file size */
7545382d832SPeter Avalos lseek_set(&obj, 0L);
7555382d832SPeter Avalos
7565382d832SPeter Avalos read_high(&obj, BUF_SIZE);
7575382d832SPeter Avalos
7585382d832SPeter Avalos dlg_button_layout(obj.buttons, &min_width);
7595382d832SPeter Avalos
7605382d832SPeter Avalos #ifdef KEY_RESIZE
7615382d832SPeter Avalos retry:
7625382d832SPeter Avalos #endif
7635382d832SPeter Avalos moved = TRUE;
7645382d832SPeter Avalos
7655940c9abSDaniel Fojt dlg_auto_sizefile(title, filename, &height, &width, 2, min_width);
7665382d832SPeter Avalos dlg_print_size(height, width);
7675382d832SPeter Avalos dlg_ctl_size(height, width);
7685382d832SPeter Avalos
7695382d832SPeter Avalos x = dlg_box_x_ordinate(width);
7705382d832SPeter Avalos y = dlg_box_y_ordinate(height);
7715382d832SPeter Avalos
7725382d832SPeter Avalos dialog = dlg_new_window(height, width, y, x);
7735382d832SPeter Avalos dlg_register_window(dialog, "textbox", binding);
7745382d832SPeter Avalos dlg_register_buttons(dialog, "textbox", obj.buttons);
7755382d832SPeter Avalos
7765382d832SPeter Avalos dlg_mouse_setbase(x, y);
7775382d832SPeter Avalos
7785382d832SPeter Avalos /* Create window for text region, used for scrolling text */
7795382d832SPeter Avalos obj.text = dlg_sub_window(dialog, PAGE_LENGTH, PAGE_WIDTH, y + 1, x + 1);
7805382d832SPeter Avalos
7815382d832SPeter Avalos /* register the new window, along with its borders */
7825382d832SPeter Avalos dlg_mouse_mkbigregion(0, 0, PAGE_LENGTH + 2, width, KEY_MAX, 1, 1, 1 /* lines */ );
7835382d832SPeter Avalos dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr);
7845382d832SPeter Avalos dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr);
7855382d832SPeter Avalos dlg_draw_title(dialog, title);
7865382d832SPeter Avalos
7875382d832SPeter Avalos dlg_draw_buttons(dialog, PAGE_LENGTH + 2, 0, obj.buttons, button, FALSE, width);
7885382d832SPeter Avalos (void) wnoutrefresh(dialog);
7895382d832SPeter Avalos getyx(dialog, cur_y, cur_x); /* Save cursor position */
7905382d832SPeter Avalos
7915382d832SPeter Avalos dlg_attr_clear(obj.text, PAGE_LENGTH, PAGE_WIDTH, dialog_attr);
7925382d832SPeter Avalos
7935382d832SPeter Avalos while (result == DLG_EXIT_UNKNOWN) {
7945940c9abSDaniel Fojt int code;
7955382d832SPeter Avalos
7965382d832SPeter Avalos /*
7975382d832SPeter Avalos * Update the screen according to whether we shifted up/down by a line
7985382d832SPeter Avalos * or not.
7995382d832SPeter Avalos */
8005382d832SPeter Avalos if (moved) {
8015382d832SPeter Avalos if (next < 0) {
8025382d832SPeter Avalos (void) scrollok(obj.text, TRUE);
8035382d832SPeter Avalos (void) scroll(obj.text); /* Scroll text region up one line */
8045382d832SPeter Avalos (void) scrollok(obj.text, FALSE);
8055382d832SPeter Avalos print_line(&obj, PAGE_LENGTH - 1, PAGE_WIDTH);
8065382d832SPeter Avalos (void) wnoutrefresh(obj.text);
8075382d832SPeter Avalos } else if (next > 0) {
8085382d832SPeter Avalos /*
8095382d832SPeter Avalos * We don't call print_page() here but use scrolling to ensure
8105382d832SPeter Avalos * faster screen update. However, 'end_reached' and
8115382d832SPeter Avalos * 'page_length' should still be updated, and 'in_buf' should
8125382d832SPeter Avalos * point to start of next page. This is done by calling
8135382d832SPeter Avalos * get_line() in the following 'for' loop.
8145382d832SPeter Avalos */
8155382d832SPeter Avalos (void) scrollok(obj.text, TRUE);
8165382d832SPeter Avalos (void) wscrl(obj.text, -1); /* Scroll text region down one line */
8175382d832SPeter Avalos (void) scrollok(obj.text, FALSE);
8185382d832SPeter Avalos obj.page_length = 0;
8195382d832SPeter Avalos passed_end = 0;
8205382d832SPeter Avalos for (i = 0; i < PAGE_LENGTH; i++) {
8215382d832SPeter Avalos if (!i) {
8225382d832SPeter Avalos print_line(&obj, 0, PAGE_WIDTH); /* print first line of page */
8235382d832SPeter Avalos (void) wnoutrefresh(obj.text);
8245382d832SPeter Avalos } else
8255382d832SPeter Avalos (void) get_line(&obj); /* Called to update 'end_reached' and 'in_buf' */
8265382d832SPeter Avalos if (!passed_end)
8275382d832SPeter Avalos obj.page_length++;
8285382d832SPeter Avalos if (obj.end_reached && !passed_end)
8295382d832SPeter Avalos passed_end = 1;
8305382d832SPeter Avalos }
8315382d832SPeter Avalos } else {
8325382d832SPeter Avalos print_page(&obj, PAGE_LENGTH, PAGE_WIDTH);
8335382d832SPeter Avalos }
8345382d832SPeter Avalos print_position(&obj, dialog, height, width);
8355382d832SPeter Avalos (void) wmove(dialog, cur_y, cur_x); /* Restore cursor position */
8365382d832SPeter Avalos wrefresh(dialog);
8375382d832SPeter Avalos }
8385382d832SPeter Avalos moved = FALSE; /* assume we'll not move */
8395382d832SPeter Avalos next = 0; /* ...but not scroll by a line */
8405382d832SPeter Avalos
8415382d832SPeter Avalos key = dlg_mouse_wgetch(dialog, &fkey);
8425940c9abSDaniel Fojt if (dlg_result_key(key, fkey, &result)) {
8435940c9abSDaniel Fojt if (!dlg_ok_button_key(result, &button, &key, &fkey))
8445382d832SPeter Avalos break;
8455940c9abSDaniel Fojt }
8465382d832SPeter Avalos
8475382d832SPeter Avalos if (!fkey && (code = dlg_char_to_button(key, obj.buttons)) >= 0) {
8485382d832SPeter Avalos result = dlg_ok_buttoncode(code);
8495382d832SPeter Avalos break;
8505382d832SPeter Avalos }
8515382d832SPeter Avalos
8525382d832SPeter Avalos if (fkey) {
8535382d832SPeter Avalos switch (key) {
8545382d832SPeter Avalos default:
8555382d832SPeter Avalos if (is_DLGK_MOUSE(key)) {
8565382d832SPeter Avalos result = dlg_exit_buttoncode(key - M_EVENT);
8575382d832SPeter Avalos if (result < 0)
8585382d832SPeter Avalos result = DLG_EXIT_OK;
8595382d832SPeter Avalos } else {
8605382d832SPeter Avalos beep();
8615382d832SPeter Avalos }
8625382d832SPeter Avalos break;
8635382d832SPeter Avalos case DLGK_FIELD_NEXT:
8645382d832SPeter Avalos button = dlg_next_button(obj.buttons, button);
8655382d832SPeter Avalos if (button < 0)
8665382d832SPeter Avalos button = 0;
8675382d832SPeter Avalos dlg_draw_buttons(dialog,
8685382d832SPeter Avalos height - 2, 0,
8695382d832SPeter Avalos obj.buttons, button,
8705382d832SPeter Avalos FALSE, width);
8715382d832SPeter Avalos break;
8725382d832SPeter Avalos case DLGK_FIELD_PREV:
8735382d832SPeter Avalos button = dlg_prev_button(obj.buttons, button);
8745382d832SPeter Avalos if (button < 0)
8755382d832SPeter Avalos button = 0;
8765382d832SPeter Avalos dlg_draw_buttons(dialog,
8775382d832SPeter Avalos height - 2, 0,
8785382d832SPeter Avalos obj.buttons, button,
8795382d832SPeter Avalos FALSE, width);
8805382d832SPeter Avalos break;
8815382d832SPeter Avalos case DLGK_ENTER:
882*a8e38dc0SAntonio Huete Jimenez result = dlg_enter_buttoncode(button);
883*a8e38dc0SAntonio Huete Jimenez break;
884*a8e38dc0SAntonio Huete Jimenez case DLGK_LEAVE:
885*a8e38dc0SAntonio Huete Jimenez result = dlg_ok_buttoncode(button);
8865382d832SPeter Avalos break;
8875382d832SPeter Avalos case DLGK_PAGE_FIRST:
8885382d832SPeter Avalos if (!obj.begin_reached) {
8895382d832SPeter Avalos obj.begin_reached = 1;
8905382d832SPeter Avalos /* First page not in buffer? */
8915382d832SPeter Avalos fpos = ftell_obj(&obj);
8925382d832SPeter Avalos
8935382d832SPeter Avalos if (fpos > obj.fd_bytes_read) {
8945382d832SPeter Avalos /* Yes, we have to read it in */
8955382d832SPeter Avalos lseek_set(&obj, 0L);
8965382d832SPeter Avalos
8975382d832SPeter Avalos read_high(&obj, BUF_SIZE);
8985382d832SPeter Avalos }
8995382d832SPeter Avalos obj.in_buf = 0;
9005382d832SPeter Avalos moved = TRUE;
9015382d832SPeter Avalos }
9025382d832SPeter Avalos break;
9035382d832SPeter Avalos case DLGK_PAGE_LAST:
9045382d832SPeter Avalos obj.end_reached = TRUE;
9055382d832SPeter Avalos /* Last page not in buffer? */
9065382d832SPeter Avalos fpos = ftell_obj(&obj);
9075382d832SPeter Avalos
9085382d832SPeter Avalos if (fpos < obj.file_size) {
9095382d832SPeter Avalos /* Yes, we have to read it in */
9105382d832SPeter Avalos lseek_end(&obj, -BUF_SIZE);
9115382d832SPeter Avalos
9125382d832SPeter Avalos read_high(&obj, BUF_SIZE);
9135382d832SPeter Avalos }
9145382d832SPeter Avalos obj.in_buf = obj.bytes_read;
9155382d832SPeter Avalos back_lines(&obj, (long) PAGE_LENGTH);
9165382d832SPeter Avalos moved = TRUE;
9175382d832SPeter Avalos break;
9185382d832SPeter Avalos case DLGK_GRID_UP: /* Previous line */
9195382d832SPeter Avalos if (!obj.begin_reached) {
9205382d832SPeter Avalos back_lines(&obj, obj.page_length + 1);
9215382d832SPeter Avalos next = 1;
9225382d832SPeter Avalos moved = TRUE;
9235382d832SPeter Avalos }
9245382d832SPeter Avalos break;
9255382d832SPeter Avalos case DLGK_PAGE_PREV: /* Previous page */
9265382d832SPeter Avalos case DLGK_MOUSE(KEY_PPAGE):
9275382d832SPeter Avalos if (!obj.begin_reached) {
9285382d832SPeter Avalos back_lines(&obj, obj.page_length + PAGE_LENGTH);
9295382d832SPeter Avalos moved = TRUE;
9305382d832SPeter Avalos }
9315382d832SPeter Avalos break;
9325382d832SPeter Avalos case DLGK_GRID_DOWN: /* Next line */
9335382d832SPeter Avalos if (!obj.end_reached) {
9345382d832SPeter Avalos obj.begin_reached = 0;
9355382d832SPeter Avalos next = -1;
9365382d832SPeter Avalos moved = TRUE;
9375382d832SPeter Avalos }
9385382d832SPeter Avalos break;
9395382d832SPeter Avalos case DLGK_PAGE_NEXT: /* Next page */
9405382d832SPeter Avalos case DLGK_MOUSE(KEY_NPAGE):
9415382d832SPeter Avalos if (!obj.end_reached) {
9425382d832SPeter Avalos obj.begin_reached = 0;
9435382d832SPeter Avalos moved = TRUE;
9445382d832SPeter Avalos }
9455382d832SPeter Avalos break;
9465382d832SPeter Avalos case DLGK_BEGIN: /* Beginning of line */
9475382d832SPeter Avalos if (obj.hscroll > 0) {
9485382d832SPeter Avalos obj.hscroll = 0;
9495382d832SPeter Avalos /* Reprint current page to scroll horizontally */
9505382d832SPeter Avalos back_lines(&obj, obj.page_length);
9515382d832SPeter Avalos moved = TRUE;
9525382d832SPeter Avalos }
9535382d832SPeter Avalos break;
9545382d832SPeter Avalos case DLGK_GRID_LEFT: /* Scroll left */
9555382d832SPeter Avalos if (obj.hscroll > 0) {
9565382d832SPeter Avalos obj.hscroll--;
9575382d832SPeter Avalos /* Reprint current page to scroll horizontally */
9585382d832SPeter Avalos back_lines(&obj, obj.page_length);
9595382d832SPeter Avalos moved = TRUE;
9605382d832SPeter Avalos }
9615382d832SPeter Avalos break;
9625382d832SPeter Avalos case DLGK_GRID_RIGHT: /* Scroll right */
9635382d832SPeter Avalos if (obj.hscroll < MAX_LEN) {
9645382d832SPeter Avalos obj.hscroll++;
9655382d832SPeter Avalos /* Reprint current page to scroll horizontally */
9665382d832SPeter Avalos back_lines(&obj, obj.page_length);
9675382d832SPeter Avalos moved = TRUE;
9685382d832SPeter Avalos }
9695382d832SPeter Avalos break;
9705382d832SPeter Avalos #ifdef KEY_RESIZE
9715382d832SPeter Avalos case KEY_RESIZE:
9725940c9abSDaniel Fojt dlg_will_resize(dialog);
9735382d832SPeter Avalos /* reset data */
9745382d832SPeter Avalos height = old_height;
9755382d832SPeter Avalos width = old_width;
9765382d832SPeter Avalos back_lines(&obj, obj.page_length);
9775382d832SPeter Avalos /* repaint */
9785940c9abSDaniel Fojt _dlg_resize_cleanup(dialog);
9795382d832SPeter Avalos goto retry;
9805382d832SPeter Avalos #endif
9815382d832SPeter Avalos }
9825382d832SPeter Avalos } else {
9835382d832SPeter Avalos switch (key) {
9845382d832SPeter Avalos case '/': /* Forward search */
9855382d832SPeter Avalos case 'n': /* Repeat forward search */
9865382d832SPeter Avalos case '?': /* Backward search */
9875382d832SPeter Avalos case 'N': /* Repeat backward search */
9885382d832SPeter Avalos moved = perform_search(&obj, height, width, key, search_term);
9895382d832SPeter Avalos fkey = FALSE;
9905382d832SPeter Avalos break;
9915382d832SPeter Avalos default:
9925382d832SPeter Avalos beep();
9935382d832SPeter Avalos break;
9945382d832SPeter Avalos }
9955382d832SPeter Avalos }
9965382d832SPeter Avalos }
9975940c9abSDaniel Fojt dlg_add_last_key(-1);
9985382d832SPeter Avalos
9995382d832SPeter Avalos dlg_del_window(dialog);
10005382d832SPeter Avalos free(obj.buf);
10015382d832SPeter Avalos (void) close(obj.fd);
10025382d832SPeter Avalos dlg_mouse_free_regions();
10035382d832SPeter Avalos return result;
10045382d832SPeter Avalos }
1005