|
|
1.1 ! root 1: /* ! 2: * textbox.c -- implements the text box ! 3: * ! 4: * ORIGINAL AUTHOR: Savio Lam ([email protected]) ! 5: * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap ([email protected]) ! 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); ! 29: ! 30: static int hscroll; ! 31: static int begin_reached, end_reached, page_length; ! 32: static const char *buf; ! 33: static const char *page; ! 34: ! 35: /* ! 36: * refresh window content ! 37: */ ! 38: static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, ! 39: int cur_y, int cur_x) ! 40: { ! 41: print_page(box, boxh, boxw); ! 42: print_position(dialog); ! 43: wmove(dialog, cur_y, cur_x); /* Restore cursor position */ ! 44: wrefresh(dialog); ! 45: } ! 46: ! 47: ! 48: /* ! 49: * Display text from a file in a dialog box. ! 50: */ ! 51: int dialog_textbox(const char *title, const char *tbuf, ! 52: int initial_height, int initial_width) ! 53: { ! 54: int i, x, y, cur_x, cur_y, key = 0; ! 55: int height, width, boxh, boxw; ! 56: int passed_end; ! 57: WINDOW *dialog, *box; ! 58: ! 59: begin_reached = 1; ! 60: end_reached = 0; ! 61: page_length = 0; ! 62: hscroll = 0; ! 63: buf = tbuf; ! 64: page = buf; /* page is pointer to start of page to be displayed */ ! 65: ! 66: do_resize: ! 67: getmaxyx(stdscr, height, width); ! 68: if (height < 8 || width < 8) ! 69: return -ERRDISPLAYTOOSMALL; ! 70: if (initial_height != 0) ! 71: height = initial_height; ! 72: else ! 73: if (height > 4) ! 74: height -= 4; ! 75: else ! 76: height = 0; ! 77: if (initial_width != 0) ! 78: width = initial_width; ! 79: else ! 80: if (width > 5) ! 81: width -= 5; ! 82: else ! 83: width = 0; ! 84: ! 85: /* center dialog box on screen */ ! 86: x = (COLS - width) / 2; ! 87: y = (LINES - height) / 2; ! 88: ! 89: draw_shadow(stdscr, y, x, height, width); ! 90: ! 91: dialog = newwin(height, width, y, x); ! 92: keypad(dialog, TRUE); ! 93: ! 94: /* Create window for box region, used for scrolling text */ ! 95: boxh = height - 4; ! 96: boxw = width - 2; ! 97: box = subwin(dialog, boxh, boxw, y + 1, x + 1); ! 98: wattrset(box, dlg.dialog.atr); ! 99: wbkgdset(box, dlg.dialog.atr & A_COLOR); ! 100: ! 101: keypad(box, TRUE); ! 102: ! 103: /* register the new window, along with its borders */ ! 104: draw_box(dialog, 0, 0, height, width, ! 105: dlg.dialog.atr, dlg.border.atr); ! 106: ! 107: wattrset(dialog, dlg.border.atr); ! 108: mvwaddch(dialog, height - 3, 0, ACS_LTEE); ! 109: for (i = 0; i < width - 2; i++) ! 110: waddch(dialog, ACS_HLINE); ! 111: wattrset(dialog, dlg.dialog.atr); ! 112: wbkgdset(dialog, dlg.dialog.atr & A_COLOR); ! 113: waddch(dialog, ACS_RTEE); ! 114: ! 115: print_title(dialog, title, width); ! 116: ! 117: print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE); ! 118: wnoutrefresh(dialog); ! 119: getyx(dialog, cur_y, cur_x); /* Save cursor position */ ! 120: ! 121: /* Print first page of text */ ! 122: attr_clear(box, boxh, boxw, dlg.dialog.atr); ! 123: refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); ! 124: ! 125: while ((key != KEY_ESC) && (key != '\n')) { ! 126: key = wgetch(dialog); ! 127: switch (key) { ! 128: case 'E': /* Exit */ ! 129: case 'e': ! 130: case 'X': ! 131: case 'x': ! 132: delwin(box); ! 133: delwin(dialog); ! 134: return 0; ! 135: case 'g': /* First page */ ! 136: case KEY_HOME: ! 137: if (!begin_reached) { ! 138: begin_reached = 1; ! 139: page = buf; ! 140: refresh_text_box(dialog, box, boxh, boxw, ! 141: cur_y, cur_x); ! 142: } ! 143: break; ! 144: case 'G': /* Last page */ ! 145: case KEY_END: ! 146: ! 147: end_reached = 1; ! 148: /* point to last char in buf */ ! 149: page = buf + strlen(buf); ! 150: back_lines(boxh); ! 151: refresh_text_box(dialog, box, boxh, boxw, ! 152: cur_y, cur_x); ! 153: break; ! 154: case 'K': /* Previous line */ ! 155: case 'k': ! 156: case KEY_UP: ! 157: if (!begin_reached) { ! 158: back_lines(page_length + 1); ! 159: ! 160: /* We don't call print_page() here but use ! 161: * scrolling to ensure faster screen update. ! 162: * However, 'end_reached' and 'page_length' ! 163: * should still be updated, and 'page' should ! 164: * point to start of next page. This is done ! 165: * by calling get_line() in the following ! 166: * 'for' loop. */ ! 167: scrollok(box, TRUE); ! 168: wscrl(box, -1); /* Scroll box region down one line */ ! 169: scrollok(box, FALSE); ! 170: page_length = 0; ! 171: passed_end = 0; ! 172: for (i = 0; i < boxh; i++) { ! 173: if (!i) { ! 174: /* print first line of page */ ! 175: print_line(box, 0, boxw); ! 176: wnoutrefresh(box); ! 177: } else ! 178: /* Called to update 'end_reached' and 'page' */ ! 179: get_line(); ! 180: if (!passed_end) ! 181: page_length++; ! 182: if (end_reached && !passed_end) ! 183: passed_end = 1; ! 184: } ! 185: ! 186: print_position(dialog); ! 187: wmove(dialog, cur_y, cur_x); /* Restore cursor position */ ! 188: wrefresh(dialog); ! 189: } ! 190: break; ! 191: case 'B': /* Previous page */ ! 192: case 'b': ! 193: case KEY_PPAGE: ! 194: if (begin_reached) ! 195: break; ! 196: back_lines(page_length + boxh); ! 197: refresh_text_box(dialog, box, boxh, boxw, ! 198: cur_y, cur_x); ! 199: break; ! 200: case 'J': /* Next line */ ! 201: case 'j': ! 202: case KEY_DOWN: ! 203: if (!end_reached) { ! 204: begin_reached = 0; ! 205: scrollok(box, TRUE); ! 206: scroll(box); /* Scroll box region up one line */ ! 207: scrollok(box, FALSE); ! 208: print_line(box, boxh - 1, boxw); ! 209: wnoutrefresh(box); ! 210: print_position(dialog); ! 211: wmove(dialog, cur_y, cur_x); /* Restore cursor position */ ! 212: wrefresh(dialog); ! 213: } ! 214: break; ! 215: case KEY_NPAGE: /* Next page */ ! 216: case ' ': ! 217: if (end_reached) ! 218: break; ! 219: ! 220: begin_reached = 0; ! 221: refresh_text_box(dialog, box, boxh, boxw, ! 222: cur_y, cur_x); ! 223: break; ! 224: case '0': /* Beginning of line */ ! 225: case 'H': /* Scroll left */ ! 226: case 'h': ! 227: case KEY_LEFT: ! 228: if (hscroll <= 0) ! 229: break; ! 230: ! 231: if (key == '0') ! 232: hscroll = 0; ! 233: else ! 234: hscroll--; ! 235: /* Reprint current page to scroll horizontally */ ! 236: back_lines(page_length); ! 237: refresh_text_box(dialog, box, boxh, boxw, ! 238: cur_y, cur_x); ! 239: break; ! 240: case 'L': /* Scroll right */ ! 241: case 'l': ! 242: case KEY_RIGHT: ! 243: if (hscroll >= MAX_LEN) ! 244: break; ! 245: hscroll++; ! 246: /* Reprint current page to scroll horizontally */ ! 247: back_lines(page_length); ! 248: refresh_text_box(dialog, box, boxh, boxw, ! 249: cur_y, cur_x); ! 250: break; ! 251: case KEY_ESC: ! 252: key = on_key_esc(dialog); ! 253: break; ! 254: case KEY_RESIZE: ! 255: back_lines(height); ! 256: delwin(box); ! 257: delwin(dialog); ! 258: on_key_resize(); ! 259: goto do_resize; ! 260: } ! 261: } ! 262: delwin(box); ! 263: delwin(dialog); ! 264: return key; /* ESC pressed */ ! 265: } ! 266: ! 267: /* ! 268: * Go back 'n' lines in text. Called by dialog_textbox(). ! 269: * 'page' will be updated to point to the desired line in 'buf'. ! 270: */ ! 271: static void back_lines(int n) ! 272: { ! 273: int i; ! 274: ! 275: begin_reached = 0; ! 276: /* Go back 'n' lines */ ! 277: for (i = 0; i < n; i++) { ! 278: if (*page == '\0') { ! 279: if (end_reached) { ! 280: end_reached = 0; ! 281: continue; ! 282: } ! 283: } ! 284: if (page == buf) { ! 285: begin_reached = 1; ! 286: return; ! 287: } ! 288: page--; ! 289: do { ! 290: if (page == buf) { ! 291: begin_reached = 1; ! 292: return; ! 293: } ! 294: page--; ! 295: } while (*page != '\n'); ! 296: page++; ! 297: } ! 298: } ! 299: ! 300: /* ! 301: * Print a new page of text. Called by dialog_textbox(). ! 302: */ ! 303: static void print_page(WINDOW * win, int height, int width) ! 304: { ! 305: int i, passed_end = 0; ! 306: ! 307: page_length = 0; ! 308: for (i = 0; i < height; i++) { ! 309: print_line(win, i, width); ! 310: if (!passed_end) ! 311: page_length++; ! 312: if (end_reached && !passed_end) ! 313: passed_end = 1; ! 314: } ! 315: wnoutrefresh(win); ! 316: } ! 317: ! 318: /* ! 319: * Print a new line of text. Called by dialog_textbox() and print_page(). ! 320: */ ! 321: static void print_line(WINDOW * win, int row, int width) ! 322: { ! 323: int y, x; ! 324: char *line; ! 325: ! 326: line = get_line(); ! 327: line += MIN(strlen(line), hscroll); /* Scroll horizontally */ ! 328: wmove(win, row, 0); /* move cursor to correct line */ ! 329: waddch(win, ' '); ! 330: waddnstr(win, line, MIN(strlen(line), width - 2)); ! 331: ! 332: getyx(win, y, x); ! 333: /* Clear 'residue' of previous line */ ! 334: #if OLD_NCURSES ! 335: { ! 336: int i; ! 337: for (i = 0; i < width - x; i++) ! 338: waddch(win, ' '); ! 339: } ! 340: #else ! 341: wclrtoeol(win); ! 342: #endif ! 343: } ! 344: ! 345: /* ! 346: * Return current line of text. Called by dialog_textbox() and print_line(). ! 347: * 'page' should point to start of current line before calling, and will be ! 348: * updated to point to start of next line. ! 349: */ ! 350: static char *get_line(void) ! 351: { ! 352: int i = 0; ! 353: static char line[MAX_LEN + 1]; ! 354: ! 355: end_reached = 0; ! 356: while (*page != '\n') { ! 357: if (*page == '\0') { ! 358: if (!end_reached) { ! 359: end_reached = 1; ! 360: break; ! 361: } ! 362: } else if (i < MAX_LEN) ! 363: line[i++] = *(page++); ! 364: else { ! 365: /* Truncate lines longer than MAX_LEN characters */ ! 366: if (i == MAX_LEN) ! 367: line[i++] = '\0'; ! 368: page++; ! 369: } ! 370: } ! 371: if (i <= MAX_LEN) ! 372: line[i] = '\0'; ! 373: if (!end_reached) ! 374: page++; /* move pass '\n' */ ! 375: ! 376: return line; ! 377: } ! 378: ! 379: /* ! 380: * Print current position ! 381: */ ! 382: static void print_position(WINDOW * win) ! 383: { ! 384: int percent; ! 385: ! 386: wattrset(win, dlg.position_indicator.atr); ! 387: wbkgdset(win, dlg.position_indicator.atr & A_COLOR); ! 388: percent = (page - buf) * 100 / strlen(buf); ! 389: wmove(win, getmaxy(win) - 3, getmaxx(win) - 9); ! 390: wprintw(win, "(%3d%%)", percent); ! 391: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.