- int code;
-
- attron(A_BOLD);
- printw("Command: ");
- attron(underline);
- code = getnstr(buffer, length);
- /*
- * If this returns anything except ERR/OK, it would be one of ncurses's
- * extensions. Fill the buffer with something harmless that the shell
- * will execute as a comment.
- */
+ int limit = COLS;
+
+ move(0, 0);
+ attrset(A_NORMAL);
+ clrtoeol();
+ attrset(A_BOLD);
+ addstr("Command: ");
+
+ limit -= getcurx(stdscr);
+
+ if (clocked) {
+ if (limit >= 3) {
+ time_t now = time((time_t *) 0);
+ struct tm *my = localtime(&now);
+ char buffer[80];
+ int skip, y, x;
+ int margin;
+
+ sprintf(buffer, "%02d:%02d:%02d",
+ my->tm_hour,
+ my->tm_min,
+ my->tm_sec);
+
+ if (limit > 9) {
+ skip = 0;
+ } else if (limit > 6) {
+ skip = 3;
+ } else {
+ skip = 6;
+ }
+ /*
+ * Write the clock message on the right-margin so we can show the
+ * results of resizing the screen.
+ */
+ getyx(stdscr, y, x);
+ margin = (int) strlen(buffer) - skip;
+ limit -= margin;
+ move(0, COLS - margin);
+ addstr(buffer);
+ move(y, x);
+ }
+ }
+ attron((chtype) underline);
+ return limit;
+}
+
+static int
+new_command(char *buffer, int length, int underline, bool clocked, bool polled)
+{
+ int code = OK;
+ int limit;
+
+ if (polled) {
+ bool done = FALSE;
+ bool first = TRUE;
+ int y, x;
+ int n;
+ int mark = 0;
+ int used = 0;
+ const int gap = 2;
+
+ timeout(20); /* no one types 50CPS... */
+ while (!done) {
+ 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;