int ecce_mode = FALSE;
char *prompt = "Ecce> ";
int update_required = TRUE;
int ecce_command_echo_required = FALSE;
char command_line[128] = { '\0' };

void redraw_all(void)
{
    if ((!ecce_mode) && ((LAST_DISPLAY_LINE != LINES-1) || (DISPLAY_RIGHTMOST_COLUMN != COLS))) {
      // *should* repaint the screen any time the keyboard is idle and
      // the display size has changed.  Unfortunately it doesn't until
      // the next keypress.  Not sure why.  But better to leave this in
      // slightly broken than omit resizing altogether, which is severely
      // broken ...

// I think perhaps get extended ncurses keycode 0x019A may be an
// indication of a change of window size???  - check the docs...
//  YEP!!!  It's called "KEY_RESIZE" :-) add it into next release

      LAST_DISPLAY_LINE = LINES-1;
      DISPLAY_RIGHTMOST_COLUMN = COLS;
      update_required = TRUE;

      // TO DO: we might also update 'preferred_display_line' in case it dropped off the end
    }

    usleep(10000); // makes the difference between a load-average of 1 and tiny!
                   // without this, we get ERR calls as fast as the system can generate them

    // we do all the screen overlay text here in the one place for simplicity.
    // currently have ecce errors, ecce command-line input, and "Learning" etc messages.

    if (update_required || ecce_command_echo_required) {
      int x;
      update_display(pp, preferred_display_line);
      if (*ecce_err != '\0') { // any pending ecce errors should be displayed.
         char *s;              // they'll disappear on the next screen update.
         int x = DISPLAY_LEFTMOST_COLUMN;

         move(LAST_DISPLAY_LINE, 0); // overlay but don't resize.
         s=ecce_err;                 // *slightly* awkward if we are on the last line
         highlight();
         for (;;) {
           if (*s == '\0') break;
           if (*s == '\n') break;
           addch(*s++);
         }
         while (x++ < DISPLAY_RIGHTMOST_COLUMN) addch(' ');
         normal();
         *ecce_err = '\0'; // will be removed on next screen refresh
      } else if (ecce_mode) {
        int clen, plen;

        clen = strlen(command_line);
        plen = strlen(prompt);

        // need generic routine for
        // handling input line.  Must be ready for "F!" so that
        // it prompts for the find/replace strings, for when we
        // bind commands like f// to a single key...
        // ideal solution would be recursive-edit minibuffer

	move(LAST_DISPLAY_LINE+1, DISPLAY_LEFTMOST_COLUMN);
        normal(); for (x = 0; x < plen; x++) addch(prompt[x]);
        highlight(); for (x = 0; x < clen; x++) addch(command_line[x]);
        normal(); for (x = DISPLAY_LEFTMOST_COLUMN+plen+clen; x < DISPLAY_RIGHTMOST_COLUMN; x++) addch(' ');
        move(LAST_DISPLAY_LINE+1, DISPLAY_LEFTMOST_COLUMN+clen+plen);
      }

// note these two are mutually exclusive
#define LEARNING "Learning Macro"
#define ASKKEY "Assign to next key:"
#define scr_message(text) move(0, DISPLAY_LEFTMOST_COLUMN); highlight(); for (x = 0; x < strlen(text); x++) addch(text[x]); addch(' '); normal();

      if (learn) {
        scr_message(LEARNING);
      } else if (waiting_for_key) {
        scr_message(ASKKEY);
      }

      refresh(); // refresh actually sends the text to the screen.
      update_required = FALSE; // don't allow more updates until something requires it.
    }
}

int screen_edit(int command)
{
  static int savedmac[128]; // sort out size limitations later
  static int *savedmacp = savedmac;
  static int nextc = 0;
  static int correction = 0;

      if (command == ERR) {
#ifdef NEVER
... MORE WORK NEEDED HERE - scrolls slowly, but problems if updates turned off
    need to add update_required flags to ecinner?

also need code in ecinner to explicitly move preferred_display_line, eg
cursor right becomes   (>?,(m@?)?)
cursor down is         (}?@?)

@ fails when it is already on the bottom display line
(likewise @- on the top line)

- does this allow 'top of page' by ({@-)0   ?
#endif
        if (ecce_command_echo_required || update_required) redraw_all();
        ecce_command_echo_required = FALSE; update_required = FALSE;
        return(TRUE);
      }

      if (ecce_mode) {
        int x, clen, plen = 6;
	if (command == 127 || command == 8) {
          if (nextc > 0) --nextc;
          command_line[nextc] = '\0';
        } else if (command == 'U'&31) {
          command_line[nextc=0] = '\0';
        } else if ((' ' <= command) && (command <= '~')) { // TO DO: i18n
          command_line[nextc++] = command;
          if (nextc == 127) nextc = 126; // truncate
          command_line[nextc] = '\0';
        } else if (command == '\r') {
          command_line[nextc] = '\0';
          ecce_mode = FALSE;
          preferred_display_line += correction; correction = 0;  // this line at least does require update
          LAST_DISPLAY_LINE += 1;
          // execute the command here
          ecinner(command_line);
          nextc = 0;
          command_line[nextc] = '\0';
          // target_col = -1;
          update_required = TRUE; // later can leave it to ecce to set this flag
        }
        ecce_command_echo_required = TRUE; // do we have to refresh here in ecce mode?  Does ERR still force redraw?
        return(TRUE);
      }

  // NOT ECCE MODE
  if (command == 27) {
    int x, plen = strlen(prompt);
    command_line[nextc = 0] = '\0';
    if (preferred_display_line == LAST_DISPLAY_LINE) preferred_display_line -= (correction = 1);
    LAST_DISPLAY_LINE -= 1;
    ecce_mode = TRUE;
    update_required = TRUE;
    return(TRUE);
  } else if ((' ' <= command) && (command <= '~')) { // todo i18n
    // temp crude hack to bind keys to 'self-insert' a la emacs
    if (command == '/') ecinner("i./."); else ecinnerf("i/%c/", command);
    update_required = TRUE;
    return(TRUE);
  }

  // no keys should get here as all the valid ones expand to ecce macros...
  {
    // Debug info: unknown key?
    move(0, DISPLAY_RIGHTMOST_COLUMN-9);
    {char *hex = "0123456789ABCDEF";
     highlight();
     addch(hex[(command>>28)&15]);
     addch(hex[(command>>24)&15]);
     addch(hex[(command>>20)&15]);
     addch(hex[(command>>16)&15]);
     addch(hex[(command>>12)&15]);
     addch(hex[(command>>8)&15]);
     addch(hex[(command>>4)&15]);
     addch(hex[command&15]);
     normal();
    }
  }
  return(TRUE);
}
