+ int code = OK;
+
+ if (polled) {
+ bool done = FALSE;
+ bool first = TRUE;
+ int y = 0, x = 0;
+ int n;
+ int mark = 0;
+ int used = 0;
+ const int gap = 2;
+
+ timeout(20); /* no one types 50CPS... */
+ while (!done) {
+ int limit;
+ int ch = getch();
+
+ buffer[used] = '\0';
+
+ limit = show_prompt(underline, clocked);
+ if (first) {
+ getyx(stdscr, y, x);
+ first = FALSE;
+ } else {
+ int left = 0;
+
+ /*
+ * if the screen is too narrow to show the whole buffer,
+ * shift the editing point left/right as needed.
+ */
+ move(y, x);
+ if ((used + gap) > limit) {
+ while ((mark - left + gap) > limit) {
+ left += limit / 2;
+ }
+ }
+ printw("%.*s", limit, buffer + left);
+ move(y, x + mark - left);
+ }
+
+ switch (ch) {
+ case ERR:
+ continue;
+ case '\004':
+ code = ERR;
+ done = TRUE;
+ break;
+ case KEY_ENTER:
+ case '\n':
+ done = TRUE;
+ break;
+ case KEY_BACKSPACE:
+ case '\b':
+ if (used) {
+ if (mark < used) {
+ /* getnstr does not do this */
+ if (mark > 0) {
+ --mark;
+ for (n = mark; n < used; ++n) {
+ buffer[n] = buffer[n + 1];
+ }
+ } else {
+ flash();
+ }
+ } else {
+ /* getnstr does this */
+ mark = --used;
+ buffer[used] = '\0';
+ }
+ } else {
+ flash();
+ }
+ break;
+ /*
+ * Unlike getnstr, this function can move the cursor into the
+ * middle of the buffer and insert/delete at that point.
+ */
+ case KEY_HOME:
+ mark = 0;
+ break;
+ case KEY_END:
+ mark = used;
+ break;
+ case KEY_LEFT:
+ if (mark > 0) {
+ mark--;
+ } else {
+ flash();
+ }
+ break;
+ case KEY_RIGHT:
+ if (mark < used) {
+ mark++;
+ } else {
+ flash();
+ }
+ break;
+#ifdef KEY_EVENT
+ case KEY_EVENT:
+ continue;
+#endif
+#ifdef KEY_RESIZE
+ case KEY_RESIZE:
+ /*
+ * Unlike getnstr, this function "knows" what the whole screen
+ * is supposed to look like, and can handle resize events.
+ */
+ continue;
+#endif
+ case '\t':
+ ch = ' ';
+ /* FALLTHRU */
+ default:
+ if (ch >= KEY_MIN) {
+ flash();
+ continue;
+ }
+ if (mark < used) {
+ /* getnstr does not do this... */
+ for (n = used + 1; n > mark; --n) {
+ buffer[n] = buffer[n - 1];
+ }
+ buffer[mark] = (char) ch;
+ used++;
+ mark++;
+ } else {
+ /* getnstr does this part */
+ buffer[used] = (char) ch;
+ mark = ++used;
+ }
+ break;
+ }
+ }
+ } else {
+ show_prompt(underline, clocked);