static void vi_insert_mode()

in system/vi/vi.c [5175:5443]


static void vi_insert_mode(FAR struct vi_s *vi)
{
  off_t start = vi->curpos;
  int ch;

  viinfo("Enter insert mode\n");

  /* Print insert message */

  vi_clearbottomline(vi);
  vi_write(vi, g_fmtinsert, sizeof(g_fmtinsert));
  vi_setcursor(vi, vi->cursor.row, vi->cursor.column);
  vi->redrawline = true;

  /* Loop while we are in insert mode */

  while (vi->mode == MODE_INSERT || vi->mode == MODE_REPLACE)
    {
      /* Make sure that the display reflects the current state */

      if (vi->redrawline || vi->drawtoeos || vi->fullredraw)
        {
          vi_showtext(vi);
        }

      /* Display the line and col number */

      vi_showlinecol(vi);
      vi_setcursor(vi, vi->cursor.row, vi->cursor.column);

      /* Get the next character from the input */

#ifdef CONFIG_SYSTEM_VI_INCLUDE_COMMAND_REPEAT
      /* Test for active cmdrepeat */

      if (vi->cmdrepeat)
        {
          /* Read next command from command buffer */

          ch = vi->cmdbuf[vi->cmdindex++];
        }
      else
#endif
        {
          ch = vi_getch(vi);

#ifdef CONFIG_SYSTEM_VI_INCLUDE_COMMAND_REPEAT
          /* Any arrow, pgup, pgdn, etc. key resets command repeat */

          if (ch == KEY_UP || ch == KEY_DOWN || ch == KEY_LEFT ||
              ch == KEY_RIGHT || ch == KEY_HOME || ch == KEY_END ||
              ch == KEY_PPAGE || ch == KEY_NPAGE)
            {
              vi->cmdcount = 1;
              vi->redrawline = true;
            }
          else
            {
              vi_appendrepeat(vi, ch);
            }
#endif
        }

      /* Test for printable character first since we will get mostly those,
       * and this will give better performance.
       */

      vi->updatereqcol = true;
      if (isprint(ch) || ch == '\t')
        {
          /* Insert the filtered character into the buffer */

          if (vi->mode == MODE_INSERT)
            {
              vi_insertch(vi, ch);
            }
          else
            {
              vi_replacech(vi, ch);
            }

          /* If we don't have to scroll the screen to display the
           * character, then do a simple putch, otherwise request
           * a line redraw.
           */

          if (vi->cursor.column + 1 < vi->display.column && ch != '\t' &&
              (vi->curpos + 1 == vi->textsize ||
               vi->text[vi->curpos + 1] == '\n'))
            {
              vi_putch(vi, ch);
            }
          else
            {
              vi->redrawline = true;
            }

          vi->cursor.column++;

          continue;
        }

      /* Any key press clears the error message */

      vi->error = false;
      vi->redrawline = true;

      /* Handle the newly received character */

      switch (ch)
        {
          case KEY_INSMODE_QUOTE: /* Quoted character follows */
            {
              /* Insert the next character unconditionally */

              vi_insertch(vi, vi_getch(vi));
            }
            break;

          case ASCII_DEL:
            {
              if (vi->curpos < vi->textsize)
                {
                  if (vi->text[vi->curpos] == '\n')
                    {
                      vi->drawtoeos = true;
                    }

                  vi_shrinktext(vi, vi->curpos, 1);
                }
            }
            break;

          case ASCII_BS:
            {
              /* Backspace changes based on mode */

              if (vi->mode == MODE_INSERT)
                {
                  /* In insert mode, we remove characters */

                  if (vi->curpos > 0)
                    {
                      if (vi->text[vi->curpos - 1] == '\n')
                        {
                          vi->drawtoeos = true;
                        }

                      vi_shrinktext(vi, vi->curpos - 1, 1);
                    }
                }
              else
                {
                  /* In replace mode, we simply move the cursor left */

                  if (vi->curpos > start)
                    {
                      vi->curpos = vi_cursorleft(vi, vi->curpos, 1);
                    }
                }
            }
            break;

          case ASCII_ESC: /* Escape exits insert mode */
            {
              vi_setmode(vi, MODE_COMMAND, 0);
              vi->updatereqcol = true;

              /* Move cursor 1 space to the left when exiting insert mode */

              if (vi->curpos > 0 && vi->text[vi->curpos - 1] != '\n')
                {
                  --vi->curpos;
                }
            }
            break;

          /* What do we do with carriage returns? */

          case '\n': /* LF terminates line */
            {
              if (vi->mode == MODE_INSERT)
                {
                  vi_insertch(vi, '\n');
                }
              else
                {
                  vi_replacech(vi, '\n');
                }

              vi->drawtoeos = true;
            }
            break;

          case KEY_UP:         /* Move the cursor up one line */
            {
              vi->updatereqcol = false;
              vi_cusorup(vi, 1);
            }
            break;

          case KEY_DOWN:         /* Move the cursor down one line */
            {
              vi->updatereqcol = false;
              vi_cursordown(vi, 1);
            }
            break;

          case KEY_LEFT:         /* Move the cursor left N characters */
            {
              vi->curpos = vi_cursorleft(vi, vi->curpos, 1);
            }
            break;

          case KEY_RIGHT:         /* Move the cursor right one character */
            {
              vi->curpos = vi_cursorright(vi, vi->curpos, 1);
              if (vi->curpos >= vi->textsize)
                {
                  vi->curpos = vi->textsize;
                }
            }
            break;

          case KEY_HOME:
            {
              vi->curpos = vi_linebegin(vi, vi->curpos);
            }
            break;

          case KEY_END:
            {
              vi->curpos = vi_lineend(vi, vi->curpos);
            }
            break;

          case KEY_PPAGE:
            {
              vi->updatereqcol = false;
              vi_cusorup(vi, vi->display.row);
            }
            break;

          case KEY_NPAGE:
            {
              vi->updatereqcol = false;
              vi_cursordown(vi, vi->display.row);
            }
            break;

          default:
            {
              /* Don't print BEL if char is -1 from termcurses */

              if (ch == -1)
                {
                  continue;
                }
              else
                {
                  VI_BEL(vi);
                }
            }
            break;
        }
    }

  vi_clearbottomline(vi);
}