OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [extra/] [config/] [textbox.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/*
2
 *  textbox.c -- implements the text box
3
 *
4
 *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
5
 *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
6
 *
7
 *  This program is free software; you can redistribute it and/or
8
 *  modify it under the terms of the GNU General Public License
9
 *  as published by the Free Software Foundation; either version 2
10
 *  of the License, or (at your option) any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program; if not, write to the Free Software
19
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
 */
21
 
22
#include "dialog.h"
23
 
24
static void back_lines (int n);
25
static void print_page (WINDOW * win, int height, int width);
26
static void print_line (WINDOW * win, int row, int width);
27
static char *get_line (void);
28
static void print_position (WINDOW * win, int height, int width);
29
 
30
static int hscroll = 0, fd, file_size, bytes_read;
31
static int begin_reached = 1, end_reached = 0, page_length;
32
static char *buf, *page;
33
 
34
/*
35
 * Display text from a file in a dialog box.
36
 */
37
int
38
dialog_textbox (const char *title, const char *file, int height, int width)
39
{
40
    int i, x, y, cur_x, cur_y, fpos, key = 0;
41
    int passed_end;
42
    char search_term[MAX_LEN + 1];
43
    WINDOW *dialog, *text;
44
 
45
    search_term[0] = '\0';       /* no search term entered yet */
46
 
47
    /* Open input file for reading */
48
    if ((fd = open (file, O_RDONLY)) == -1) {
49
        endwin ();
50
        fprintf (stderr,
51
                 "\nCan't open input file in dialog_textbox().\n");
52
        exit (-1);
53
    }
54
    /* Get file size. Actually, 'file_size' is the real file size - 1,
55
       since it's only the last byte offset from the beginning */
56
    if ((file_size = lseek (fd, 0, SEEK_END)) == -1) {
57
        endwin ();
58
        fprintf (stderr, "\nError getting file size in dialog_textbox().\n");
59
        exit (-1);
60
    }
61
    /* Restore file pointer to beginning of file after getting file size */
62
    if (lseek (fd, 0, SEEK_SET) == -1) {
63
        endwin ();
64
        fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n");
65
        exit (-1);
66
    }
67
    /* Allocate space for read buffer */
68
    if ((buf = malloc (BUF_SIZE + 1)) == NULL) {
69
        endwin ();
70
        fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n");
71
        exit (-1);
72
    }
73
    if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
74
        endwin ();
75
        fprintf (stderr, "\nError reading file in dialog_textbox().\n");
76
        exit (-1);
77
    }
78
    buf[bytes_read] = '\0';     /* mark end of valid data */
79
    page = buf;                 /* page is pointer to start of page to be displayed */
80
 
81
    /* center dialog box on screen */
82
    x = (COLS - width) / 2;
83
    y = (LINES - height) / 2;
84
 
85
 
86
    draw_shadow (stdscr, y, x, height, width);
87
 
88
    dialog = newwin (height, width, y, x);
89
    keypad (dialog, TRUE);
90
 
91
    /* Create window for text region, used for scrolling text */
92
    text = subwin (dialog, height - 4, width - 2, y + 1, x + 1);
93
    wattrset (text, dialog_attr);
94
    wbkgdset (text, dialog_attr & A_COLOR);
95
 
96
    keypad (text, TRUE);
97
 
98
    /* register the new window, along with its borders */
99
    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
100
 
101
    wattrset (dialog, border_attr);
102
    mvwaddch (dialog, height-3, 0, ACS_LTEE);
103
    for (i = 0; i < width - 2; i++)
104
        waddch (dialog, ACS_HLINE);
105
    wattrset (dialog, dialog_attr);
106
    wbkgdset (dialog, dialog_attr & A_COLOR);
107
    waddch (dialog, ACS_RTEE);
108
 
109
    if (title != NULL && strlen(title) >= width-2 ) {
110
        /* truncate long title -- mec */
111
        char * title2 = malloc(width-2+1);
112
        memcpy( title2, title, width-2 );
113
        title2[width-2] = '\0';
114
        title = title2;
115
    }
116
 
117
    if (title != NULL) {
118
        wattrset (dialog, title_attr);
119
        mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
120
        waddstr (dialog, (char *)title);
121
        waddch (dialog, ' ');
122
    }
123
    print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
124
    wnoutrefresh (dialog);
125
    getyx (dialog, cur_y, cur_x);       /* Save cursor position */
126
 
127
    /* Print first page of text */
128
    attr_clear (text, height - 4, width - 2, dialog_attr);
129
    print_page (text, height - 4, width - 2);
130
    print_position (dialog, height, width);
131
    wmove (dialog, cur_y, cur_x);       /* Restore cursor position */
132
    wrefresh (dialog);
133
 
134
    while ((key != ESC) && (key != '\n')) {
135
        key = wgetch (dialog);
136
        switch (key) {
137
        case 'E':               /* Exit */
138
        case 'e':
139
        case 'X':
140
        case 'x':
141
            delwin (dialog);
142
            free (buf);
143
            close (fd);
144
            return 0;
145
        case 'g':               /* First page */
146
        case KEY_HOME:
147
            if (!begin_reached) {
148
                begin_reached = 1;
149
                /* First page not in buffer? */
150
                if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
151
                    endwin ();
152
                    fprintf (stderr,
153
                      "\nError moving file pointer in dialog_textbox().\n");
154
                    exit (-1);
155
                }
156
                if (fpos > bytes_read) {        /* Yes, we have to read it in */
157
                    if (lseek (fd, 0, SEEK_SET) == -1) {
158
                        endwin ();
159
                        fprintf (stderr, "\nError moving file pointer in "
160
                                 "dialog_textbox().\n");
161
                        exit (-1);
162
                    }
163
                    if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
164
                        endwin ();
165
                        fprintf (stderr,
166
                             "\nError reading file in dialog_textbox().\n");
167
                        exit (-1);
168
                    }
169
                    buf[bytes_read] = '\0';
170
                }
171
                page = buf;
172
                print_page (text, height - 4, width - 2);
173
                print_position (dialog, height, width);
174
                wmove (dialog, cur_y, cur_x);   /* Restore cursor position */
175
                wrefresh (dialog);
176
            }
177
            break;
178
        case 'G':               /* Last page */
179
        case KEY_END:
180
 
181
            end_reached = 1;
182
            /* Last page not in buffer? */
183
            if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
184
                endwin ();
185
                fprintf (stderr,
186
                      "\nError moving file pointer in dialog_textbox().\n");
187
                exit (-1);
188
            }
189
            if (fpos < file_size) {     /* Yes, we have to read it in */
190
                if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) {
191
                    endwin ();
192
                    fprintf (stderr,
193
                      "\nError moving file pointer in dialog_textbox().\n");
194
                    exit (-1);
195
                }
196
                if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
197
                    endwin ();
198
                    fprintf (stderr,
199
                             "\nError reading file in dialog_textbox().\n");
200
                    exit (-1);
201
                }
202
                buf[bytes_read] = '\0';
203
            }
204
            page = buf + bytes_read;
205
            back_lines (height - 4);
206
            print_page (text, height - 4, width - 2);
207
            print_position (dialog, height, width);
208
            wmove (dialog, cur_y, cur_x);       /* Restore cursor position */
209
            wrefresh (dialog);
210
            break;
211
        case 'K':               /* Previous line */
212
        case 'k':
213
        case KEY_UP:
214
            if (!begin_reached) {
215
                back_lines (page_length + 1);
216
 
217
                /* We don't call print_page() here but use scrolling to ensure
218
                   faster screen update. However, 'end_reached' and
219
                   'page_length' should still be updated, and 'page' should
220
                   point to start of next page. This is done by calling
221
                   get_line() in the following 'for' loop. */
222
                scrollok (text, TRUE);
223
                wscrl (text, -1);       /* Scroll text region down one line */
224
                scrollok (text, FALSE);
225
                page_length = 0;
226
                passed_end = 0;
227
                for (i = 0; i < height - 4; i++) {
228
                    if (!i) {
229
                        /* print first line of page */
230
                        print_line (text, 0, width - 2);
231
                        wnoutrefresh (text);
232
                    } else
233
                        /* Called to update 'end_reached' and 'page' */
234
                        get_line ();
235
                    if (!passed_end)
236
                        page_length++;
237
                    if (end_reached && !passed_end)
238
                        passed_end = 1;
239
                }
240
 
241
                print_position (dialog, height, width);
242
                wmove (dialog, cur_y, cur_x);   /* Restore cursor position */
243
                wrefresh (dialog);
244
            }
245
            break;
246
        case 'B':               /* Previous page */
247
        case 'b':
248
        case KEY_PPAGE:
249
            if (begin_reached)
250
                break;
251
            back_lines (page_length + height - 4);
252
            print_page (text, height - 4, width - 2);
253
            print_position (dialog, height, width);
254
            wmove (dialog, cur_y, cur_x);
255
            wrefresh (dialog);
256
            break;
257
        case 'J':               /* Next line */
258
        case 'j':
259
        case KEY_DOWN:
260
            if (!end_reached) {
261
                begin_reached = 0;
262
                scrollok (text, TRUE);
263
                scroll (text);  /* Scroll text region up one line */
264
                scrollok (text, FALSE);
265
                print_line (text, height - 5, width - 2);
266
                wnoutrefresh (text);
267
                print_position (dialog, height, width);
268
                wmove (dialog, cur_y, cur_x);   /* Restore cursor position */
269
                wrefresh (dialog);
270
            }
271
            break;
272
        case KEY_NPAGE:         /* Next page */
273
        case ' ':
274
            if (end_reached)
275
                break;
276
 
277
            begin_reached = 0;
278
            print_page (text, height - 4, width - 2);
279
            print_position (dialog, height, width);
280
            wmove (dialog, cur_y, cur_x);
281
            wrefresh (dialog);
282
            break;
283
        case '0':               /* Beginning of line */
284
        case 'H':               /* Scroll left */
285
        case 'h':
286
        case KEY_LEFT:
287
            if (hscroll <= 0)
288
                break;
289
 
290
            if (key == '0')
291
                hscroll = 0;
292
            else
293
                hscroll--;
294
            /* Reprint current page to scroll horizontally */
295
            back_lines (page_length);
296
            print_page (text, height - 4, width - 2);
297
            wmove (dialog, cur_y, cur_x);
298
            wrefresh (dialog);
299
            break;
300
        case 'L':               /* Scroll right */
301
        case 'l':
302
        case KEY_RIGHT:
303
            if (hscroll >= MAX_LEN)
304
                break;
305
            hscroll++;
306
            /* Reprint current page to scroll horizontally */
307
            back_lines (page_length);
308
            print_page (text, height - 4, width - 2);
309
            wmove (dialog, cur_y, cur_x);
310
            wrefresh (dialog);
311
            break;
312
        case ESC:
313
            break;
314
        }
315
    }
316
 
317
    delwin (dialog);
318
    free (buf);
319
    close (fd);
320
    return 1;                   /* ESC pressed */
321
}
322
 
323
/*
324
 * Go back 'n' lines in text file. Called by dialog_textbox().
325
 * 'page' will be updated to point to the desired line in 'buf'.
326
 */
327
static void
328
back_lines (int n)
329
{
330
    int i, fpos;
331
 
332
    begin_reached = 0;
333
    /* We have to distinguish between end_reached and !end_reached
334
       since at end of file, the line is not ended by a '\n'.
335
       The code inside 'if' basically does a '--page' to move one
336
       character backward so as to skip '\n' of the previous line */
337
    if (!end_reached) {
338
        /* Either beginning of buffer or beginning of file reached? */
339
        if (page == buf) {
340
            if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
341
                endwin ();
342
                fprintf (stderr, "\nError moving file pointer in "
343
                         "back_lines().\n");
344
                exit (-1);
345
            }
346
            if (fpos > bytes_read) {    /* Not beginning of file yet */
347
                /* We've reached beginning of buffer, but not beginning of
348
                   file yet, so read previous part of file into buffer.
349
                   Note that we only move backward for BUF_SIZE/2 bytes,
350
                   but not BUF_SIZE bytes to avoid re-reading again in
351
                   print_page() later */
352
                /* Really possible to move backward BUF_SIZE/2 bytes? */
353
                if (fpos < BUF_SIZE / 2 + bytes_read) {
354
                    /* No, move less then */
355
                    if (lseek (fd, 0, SEEK_SET) == -1) {
356
                        endwin ();
357
                        fprintf (stderr, "\nError moving file pointer in "
358
                                 "back_lines().\n");
359
                        exit (-1);
360
                    }
361
                    page = buf + fpos - bytes_read;
362
                } else {        /* Move backward BUF_SIZE/2 bytes */
363
                    if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR)
364
                        == -1) {
365
                        endwin ();
366
                        fprintf (stderr, "\nError moving file pointer "
367
                                 "in back_lines().\n");
368
                        exit (-1);
369
                    }
370
                    page = buf + BUF_SIZE / 2;
371
                }
372
                if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
373
                    endwin ();
374
                    fprintf (stderr, "\nError reading file in back_lines().\n");
375
                    exit (-1);
376
                }
377
                buf[bytes_read] = '\0';
378
            } else {            /* Beginning of file reached */
379
                begin_reached = 1;
380
                return;
381
            }
382
        }
383
        if (*(--page) != '\n') {        /* '--page' here */
384
            /* Something's wrong... */
385
            endwin ();
386
            fprintf (stderr, "\nInternal error in back_lines().\n");
387
            exit (-1);
388
        }
389
    }
390
    /* Go back 'n' lines */
391
    for (i = 0; i < n; i++)
392
        do {
393
            if (page == buf) {
394
                if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
395
                    endwin ();
396
                    fprintf (stderr,
397
                          "\nError moving file pointer in back_lines().\n");
398
                    exit (-1);
399
                }
400
                if (fpos > bytes_read) {
401
                    /* Really possible to move backward BUF_SIZE/2 bytes? */
402
                    if (fpos < BUF_SIZE / 2 + bytes_read) {
403
                        /* No, move less then */
404
                        if (lseek (fd, 0, SEEK_SET) == -1) {
405
                            endwin ();
406
                            fprintf (stderr, "\nError moving file pointer "
407
                                     "in back_lines().\n");
408
                            exit (-1);
409
                        }
410
                        page = buf + fpos - bytes_read;
411
                    } else {    /* Move backward BUF_SIZE/2 bytes */
412
                        if (lseek (fd, -(BUF_SIZE / 2 + bytes_read),
413
                                   SEEK_CUR) == -1) {
414
                            endwin ();
415
                            fprintf (stderr, "\nError moving file pointer"
416
                                     " in back_lines().\n");
417
                            exit (-1);
418
                        }
419
                        page = buf + BUF_SIZE / 2;
420
                    }
421
                    if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
422
                        endwin ();
423
                        fprintf (stderr, "\nError reading file in "
424
                                 "back_lines().\n");
425
                        exit (-1);
426
                    }
427
                    buf[bytes_read] = '\0';
428
                } else {        /* Beginning of file reached */
429
                    begin_reached = 1;
430
                    return;
431
                }
432
            }
433
        } while (*(--page) != '\n');
434
    page++;
435
}
436
 
437
/*
438
 * Print a new page of text. Called by dialog_textbox().
439
 */
440
static void
441
print_page (WINDOW * win, int height, int width)
442
{
443
    int i, passed_end = 0;
444
 
445
    page_length = 0;
446
    for (i = 0; i < height; i++) {
447
        print_line (win, i, width);
448
        if (!passed_end)
449
            page_length++;
450
        if (end_reached && !passed_end)
451
            passed_end = 1;
452
    }
453
    wnoutrefresh (win);
454
}
455
 
456
/*
457
 * Print a new line of text. Called by dialog_textbox() and print_page().
458
 */
459
static void
460
print_line (WINDOW * win, int row, int width)
461
{
462
    int y, x;
463
    char *line;
464
 
465
    line = get_line ();
466
    line += MIN (strlen (line), hscroll);       /* Scroll horizontally */
467
    wmove (win, row, 0); /* move cursor to correct line */
468
    waddch (win, ' ');
469
    waddnstr (win, line, MIN (strlen (line), width - 2));
470
 
471
    getyx (win, y, x);
472
    /* Clear 'residue' of previous line */
473
#if OLD_NCURSES
474
    {
475
        int i;
476
        for (i = 0; i < width - x; i++)
477
            waddch (win, ' ');
478
    }
479
#else
480
    wclrtoeol(win);
481
#endif
482
}
483
 
484
/*
485
 * Return current line of text. Called by dialog_textbox() and print_line().
486
 * 'page' should point to start of current line before calling, and will be
487
 * updated to point to start of next line.
488
 */
489
static char *
490
get_line (void)
491
{
492
    int i = 0, fpos;
493
    static char line[MAX_LEN + 1];
494
 
495
    end_reached = 0;
496
    while (*page != '\n') {
497
        if (*page == '\0') {
498
            /* Either end of file or end of buffer reached */
499
            if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
500
                endwin ();
501
                fprintf (stderr, "\nError moving file pointer in "
502
                         "get_line().\n");
503
                exit (-1);
504
            }
505
            if (fpos < file_size) {     /* Not end of file yet */
506
                /* We've reached end of buffer, but not end of file yet,
507
                   so read next part of file into buffer */
508
                if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
509
                    endwin ();
510
                    fprintf (stderr, "\nError reading file in get_line().\n");
511
                    exit (-1);
512
                }
513
                buf[bytes_read] = '\0';
514
                page = buf;
515
            } else {
516
                if (!end_reached)
517
                    end_reached = 1;
518
                break;
519
            }
520
        } else if (i < MAX_LEN)
521
            line[i++] = *(page++);
522
        else {
523
            /* Truncate lines longer than MAX_LEN characters */
524
            if (i == MAX_LEN)
525
                line[i++] = '\0';
526
            page++;
527
        }
528
    }
529
    if (i <= MAX_LEN)
530
        line[i] = '\0';
531
    if (!end_reached)
532
        page++;                 /* move pass '\n' */
533
 
534
    return line;
535
}
536
 
537
/*
538
 * Print current position
539
 */
540
static void
541
print_position (WINDOW * win, int height, int width)
542
{
543
    int fpos, percent;
544
 
545
    if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
546
        endwin ();
547
        fprintf (stderr, "\nError moving file pointer in print_position().\n");
548
        exit (-1);
549
    }
550
    wattrset (win, position_indicator_attr);
551
    wbkgdset (win, position_indicator_attr & A_COLOR);
552
    percent = !file_size ?
553
        100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
554
    wmove (win, height - 3, width - 9);
555
    wprintw (win, "(%3d%%)", percent);
556
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.