static int cle_editloop()

in system/cle/cle.c [675:1030]


static int cle_editloop(FAR struct cle_s *priv)
{
  /* Loop while we are in command mode */

  for (; ; )
    {
#if  1 /* Perhaps here should be a config switch */
      char state = 0;
#endif
      int ch;

      /* Make sure that the display reflects the current state */

      cle_showtext(priv);
      cle_setcursor(priv, priv->curpos);

      /* Get the next character from the input */

#if  1 /* Perhaps here should be a config switch */
      /* Simple decode of some VT100/xterm codes: left/right, up/dn,
       * home/end, del
       */

      /* loop till we have a ch */

      for (; ; )
        {
          ch = cle_getch(priv);
          if (ch < 0)
            {
              return -EIO;
            }
          else if (state != 0)
            {
              if (state == (char)1)  /* Got ESC */
                {
                  if (ch == '[' || ch == 'O')
                    {
                      state = ch;
                    }
                  else
                    {
                      break;  /* break the for loop */
                    }
                }
              else if (state == '[')
                {
                  /* Got ESC[ */

                  switch (ch)
                    {
                      case '3':    /* ESC[3~  = DEL */
                        {
                          state = ch;
                          continue;
                        }

                      case 'A':
                        {
                          ch = KEY_UP;
                        }
                        break;

                      case 'B':
                        {
                          ch = KEY_DN;
                        }
                        break;

                      case 'C':
                        {
                          ch = KEY_RIGHT;
                        }
                        break;

                      case 'D':
                        {
                          ch = KEY_LEFT;
                        }
                        break;

                      case 'F':
                        {
                          ch = KEY_ENDLINE;
                        }
                        break;

                      case 'H':
                        {
                          ch = KEY_BEGINLINE;
                        }
                        break;

                      default:
                        break;
                    }
                  break;  /* Break the 'for' loop */
                }
              else if (state == 'O')
                {
                  /* got ESCO */

                  if (ch == 'F')
                    {
                      ch = KEY_ENDLINE;
                    }

                  break; /* Break the 'for' loop */
               }
              else if (state == '3')
                {
                  if (ch == '~')
                    {
                      ch = KEY_DEL;
                    }

                  break; /* Break the 'for' loop */
                }
              else
                {
                  break; /* Break the 'for' loop */
                }
            }
          else if (ch == ASCII_ESC)
            {
              ++state;
            }
          else
            {
              break; /* Break the 'for' loop, use the char */
            }
        }

#else
      ch = cle_getch(priv);
      if (ch < 0)
        {
          return -EIO;
        }

#endif

      /* Then handle the character. */

#ifdef CONFIG_SYSTEM_CLE_CMD_HISTORY
      if (g_cmd_history_len > 0)
        {
          int i = 1;

          switch (ch)
            {
              case KEY_UP:

                /* Go to the past command in history */

                g_cmd_history_steps_from_head--;

                if (-g_cmd_history_steps_from_head >= g_cmd_history_len)
                  {
                    g_cmd_history_steps_from_head = -(g_cmd_history_len - 1);
                  }

                break;

              case KEY_DN:

                /* Go to the recent command in history */

                g_cmd_history_steps_from_head++;

                if (g_cmd_history_steps_from_head > 1)
                  {
                    g_cmd_history_steps_from_head = 1;
                  }

                break;

              default:
                i = 0;
                break;
            }

          if (i != 0)
            {
              priv->nchars = 0;
              priv->curpos = 0;

              if (g_cmd_history_steps_from_head != 1)
                {
                  int idx = g_cmd_history_head +
                            g_cmd_history_steps_from_head;

                  /* Circular buffer wrap around */

                  if (idx < 0)
                    {
                      idx = idx + CONFIG_SYSTEM_CLE_CMD_HISTORY_LEN;
                    }
                  else if (idx >= CONFIG_SYSTEM_CLE_CMD_HISTORY_LEN)
                    {
                      idx = idx - CONFIG_SYSTEM_CLE_CMD_HISTORY_LEN;
                    }

                  for (i = 0; g_cmd_history[idx][i] != '\0'; i++)
                    {
                      cle_insertch(priv, g_cmd_history[idx][i]);
                    }

                  priv->curpos = priv->nchars;
                }

              continue;
            }
        }
#endif /* CONFIG_SYSTEM_CLE_CMD_HISTORY */

      switch (ch)
        {
        case KEY_BEGINLINE: /* Move cursor to start of current line */
          {
            priv->curpos = 0;
          }
          break;

        case KEY_LEFT: /* Move the cursor left 1 character */
          {
            if (priv->curpos > 0)
              {
                priv->curpos--;
              }
            else
              {
                CLE_BEL(priv);
              }
          }
          break;

        case KEY_DEL: /* Delete 1 character at the cursor */
          {
            if (priv->curpos < priv->nchars)
              {
                cle_closetext(priv, priv->curpos, 1);
              }
            else
              {
                CLE_BEL(priv);
              }
          }
          break;

        case KEY_ENDLINE: /* Move cursor to end of current line */
          {
            priv->curpos = priv->nchars;
          }
          break;

        case KEY_RIGHT: /* Move the cursor right one character */
          {
            if (priv->curpos < priv->nchars)
              {
                priv->curpos++;
              }
            else
              {
                CLE_BEL(priv);
              }
          }
          break;

        case ASCII_DEL:
        case KEY_DELLEFT:  /* Delete 1 character before the cursor */
          {
            if (priv->curpos > 0)
              {
                cle_closetext(priv, --priv->curpos, 1);
              }
            else
              {
                CLE_BEL(priv);
              }
          }
          break;

        case KEY_DELEOL:  /* Delete to the end of the line */
          {
            priv->nchars = (priv->nchars > 0 ? priv->curpos : 0);
          }
          break;

        case KEY_DELLINE:  /* Delete to the end of the line */
          {
            priv->nchars = 0;
            priv->curpos = 0;
          }
          break;

        case KEY_CLRSCR: /* Clear the screen & return cursor to top */
          cle_clrscr(priv);
          break;

        case KEY_QUOTE: /* Quoted character follows */
          {
            ch = cle_getch(priv);
            if (ch < 0)
              {
                return -EIO;
              }

            /* Insert the next character unconditionally */

            cle_insertch(priv, ch);
          }
          break;

        /* Newline terminates editing.  But what is a newline? */

        case '\n': /* LF terminates line */
          {
            /* Add the newline to the buffer at the end of the line */

            priv->curpos = priv->nchars;
            cle_insertch(priv, '\n');
            return OK;
          }
          break;

        /* Text to insert or unimplemented/invalid keypresses */

        default:
          {
            /* Ignore all control characters except for tab and newline */

            if (!iscntrl(ch) || ch == '\t')
              {
                /* Insert the filtered character into the buffer */

                cle_insertch(priv, ch);

                /* Printable character will change the cursor position in */

                if (ch != '\t')
                  {
                    priv->realpos++;
                  }
              }
            else
              {
                CLE_BEL(priv);
              }
          }
          break;
        }
    }

  return OK;
}