home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / scripts / kconfig / lxdialog / textbox.c < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  8.9 KB  |  392 lines

  1. /*
  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);
  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. }
  392.