kconfig/nconf: Fix hang when editing symbol with a long prompt
[pandora-kernel.git] / scripts / kconfig / nconf.gui.c
index f8137b3..52f9dd6 100644 (file)
@@ -356,7 +356,7 @@ int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
 
 int dialog_inputbox(WINDOW *main_window,
                const char *title, const char *prompt,
-               const char *init, char *result, int result_len)
+               const char *init, char **resultp, int *result_len)
 {
        int prompt_lines = 0;
        int prompt_width = 0;
@@ -364,10 +364,18 @@ int dialog_inputbox(WINDOW *main_window,
        WINDOW *prompt_win;
        WINDOW *form_win;
        PANEL *panel;
-       int i, x, y;
+       int i, x, y, lines, columns, win_lines, win_cols;
        int res = -1;
        int cursor_position = strlen(init);
+       int cursor_form_win;
+       char *result = *resultp;
+
+       getmaxyx(stdscr, lines, columns);
 
+       if (strlen(init)+1 > *result_len) {
+               *result_len = strlen(init)+1;
+               *resultp = result = realloc(result, *result_len);
+       }
 
        /* find the widest line of msg: */
        prompt_lines = get_line_no(prompt);
@@ -380,14 +388,19 @@ int dialog_inputbox(WINDOW *main_window,
        if (title)
                prompt_width = max(prompt_width, strlen(title));
 
+       win_lines = min(prompt_lines+6, lines-2);
+       win_cols = min(prompt_width+7, columns-2);
+       prompt_lines = max(win_lines-6, 0);
+       prompt_width = max(win_cols-7, 0);
+
        /* place dialog in middle of screen */
-       y = (LINES-(prompt_lines+4))/2;
-       x = (COLS-(prompt_width+4))/2;
+       y = (lines-win_lines)/2;
+       x = (columns-win_cols)/2;
 
-       strncpy(result, init, result_len);
+       strncpy(result, init, *result_len);
 
        /* create the windows */
-       win = newwin(prompt_lines+6, prompt_width+7, y, x);
+       win = newwin(win_lines, win_cols, y, x);
        prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2);
        form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
        keypad(form_win, TRUE);
@@ -405,7 +418,9 @@ int dialog_inputbox(WINDOW *main_window,
        fill_window(prompt_win, prompt);
 
        mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
-       mvwprintw(form_win, 0, 0, "%s", result);
+       cursor_form_win = min(cursor_position, prompt_width-1);
+       mvwprintw(form_win, 0, 0, "%s",
+                 result + cursor_position-cursor_form_win);
 
        /* create panels */
        panel = new_panel(win);
@@ -431,6 +446,8 @@ int dialog_inputbox(WINDOW *main_window,
                                                &result[cursor_position],
                                                len-cursor_position+1);
                                cursor_position--;
+                               cursor_form_win--;
+                               len--;
                        }
                        break;
                case KEY_DC:
@@ -438,38 +455,63 @@ int dialog_inputbox(WINDOW *main_window,
                                memmove(&result[cursor_position],
                                                &result[cursor_position+1],
                                                len-cursor_position+1);
+                               len--;
                        }
                        break;
                case KEY_UP:
                case KEY_RIGHT:
-                       if (cursor_position < len &&
-                           cursor_position < min(result_len, prompt_width))
+                       if (cursor_position < len) {
                                cursor_position++;
+                               cursor_form_win++;
+                       }
                        break;
                case KEY_DOWN:
                case KEY_LEFT:
-                       if (cursor_position > 0)
+                       if (cursor_position > 0) {
                                cursor_position--;
+                               cursor_form_win--;
+                       }
+                       break;
+               case KEY_HOME:
+                       cursor_position = 0;
+                       cursor_form_win = 0;
+                       break;
+               case KEY_END:
+                       cursor_position = len;
+                       cursor_form_win = min(cursor_position, prompt_width-1);
                        break;
                default:
-                       if ((isgraph(res) || isspace(res)) &&
-                                       len-2 < result_len) {
+                       if ((isgraph(res) || isspace(res))) {
+                               /* one for new char, one for '\0' */
+                               if (len+2 > *result_len) {
+                                       *result_len = len+2;
+                                       *resultp = result = realloc(result,
+                                                               *result_len);
+                               }
                                /* insert the char at the proper position */
                                memmove(&result[cursor_position+1],
                                                &result[cursor_position],
-                                               len+1);
+                                               len-cursor_position+1);
                                result[cursor_position] = res;
                                cursor_position++;
+                               cursor_form_win++;
+                               len++;
                        } else {
-                               mvprintw(0, 0, "unknow key: %d\n", res);
+                               mvprintw(0, 0, "unknown key: %d\n", res);
                        }
                        break;
                }
+               if (cursor_form_win < 0)
+                       cursor_form_win = 0;
+               else if (cursor_form_win > prompt_width-1)
+                       cursor_form_win = prompt_width-1;
+
                wmove(form_win, 0, 0);
                wclrtoeol(form_win);
                mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
-               mvwprintw(form_win, 0, 0, "%s", result);
-               wmove(form_win, 0, cursor_position);
+               mvwprintw(form_win, 0, 0, "%s",
+                       result + cursor_position-cursor_form_win);
+               wmove(form_win, 0, cursor_form_win);
                touchwin(win);
                refresh_all_windows(main_window);