www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2001/07/26/16:20:20

From: "Mark E." <snowball3 AT bigfoot DOT com>
To: djgpp-workers AT delorie DOT com
Date: Thu, 26 Jul 2001 16:19:49 -0400
MIME-Version: 1.0
Subject: termios cursor motion support
Message-ID: <3B604325.14771.32CE14@localhost>
X-mailer: Pegasus Mail for Win32 (v3.12c)
Reply-To: djgpp-workers AT delorie DOT com

This patch adds support for acting on ecma-48 commands and support for cursor 

motion commands.  Other commands can be supported using the current output 
method. But I think color support would require the direct video method ala 
conio. Comments?

*** tminit.bak	Thu Jul 26 09:52:38 2001
--- tminit.c	Thu Jul 26 16:12:26 2001
***************
*** 34,39 ****
--- 34,41 ----
  #define SENSE_REG_KEY	1
  #define SENSE_EXT_KEY	2
  
+ #define NARGS 16
+ 
  /* tty buffers */
  unsigned char __libc_tty_queue_buffer[_TTY_QUEUE_SIZE];
  struct tty __libc_tty_internal = TTYDEFAULT;
*************** static unsigned ah_ctrl_sense;
*** 50,55 ****
--- 52,65 ----
  
  static const unsigned char *ext_key_string;
  
+ /* Console command parser */
+ 
+ enum cmd_parser_states { need_esc = 0, have_esc, have_lbracket,
+                          have_arg, have_cmd};
+ 
+ static enum cmd_parser_states cmd_state;
+ 
+ 
  /* static functions */
  static void __libc_termios_fflushall (void);
  static ssize_t __libc_termios_read (int handle, void *buffer, size_t count, ssize_t *rv);
*************** static void __libc_termios_clear_queue (
*** 69,74 ****
--- 79,86 ----
  static int __libc_termios_get_queue (void);
  static int __libc_termios_put_queue (unsigned char ch);
  static void __libc_termios_fill_queue (void);
+ static size_t parse_console_command(const unsigned char *buf, size_t count);
+ static void execute_console_command(const unsigned char cmd, unsigned char argc, unsigned int args[NARGS]);
  
  /* direct I/O functions */
  static inline int __direct_keysense (void);
*************** __libc_termios_write_cooked_tty (int han
*** 420,429 ****
  
        rp = buffer;
        n = count;
!       while (--n >= 0)
  	{
  	  /* get character */
! 	  ch = *rp++;
  
  	  /* NOTE: multibyte character don't contain control character */
  	  /* map NL to CRNL */
--- 432,456 ----
  
        rp = buffer;
        n = count;
!       while (n > 0)
  	{
  	  /* get character */
!           ch = *rp;
! 
!           /* Handle console commands */
! 	  if (ch == '\e' || cmd_state != need_esc)
!           {
!             size_t delta;
!             delta = parse_console_command(rp, n);
! 
!             /* Skip past what was parsed.  */
!             n -= delta;
!             rp += delta;
!             continue;
!           }
! 
! 	  ++rp;
!           --n;
  
  	  /* NOTE: multibyte character don't contain control character */
  	  /* map NL to CRNL */
*************** proc_skip:
*** 963,965 ****
--- 990,1208 ----
  
  /******************************************************************************/
  
+ static size_t
+ parse_console_command(const unsigned char *buf, size_t count)
+ {
+   static unsigned int args[NARGS];
+   static unsigned char arg_count;
+ 
+   const unsigned char *ptr = buf;
+   const unsigned char *ptr_end = buf + count;
+ 
+   while (ptr < ptr_end)
+   {
+     switch (cmd_state)
+     {
+       case need_esc:
+         /* Find an escape or bail out.  */
+         if (*ptr != '\e')
+           return (ptr - buf);
+         ++ptr;
+         cmd_state = have_esc;
+         if (ptr >= ptr_end)
+           break;
+ 
+       case have_esc:
+         /* Find a left bracket or bail out.  */
+         if (*ptr != '[')
+           return (ptr - buf);
+ 
+         cmd_state = have_lbracket;
+         ++ptr;
+         if (ptr == ptr_end)
+           break;
+ 
+       case have_lbracket:
+         /* After the left bracket, either an argument
+            or the command follows.  */
+         arg_count = NARGS;
+         arg_count = 0;
+         args[0] = 0;
+         if (isdigit(*ptr))
+         {
+           cmd_state = have_arg;
+         }
+         else
+         {
+           cmd_state = have_cmd;
+           break;
+         }
+ 
+       case have_arg:
+       {
+         /* Parse the argument.  Quit when there are no more digits.  */
+         if (isdigit(*ptr))
+         {
+           do
+           {
+             args[arg_count] *= 10;
+             args[arg_count] += *ptr - '0';
+             ++ptr;
+           } while (ptr < ptr_end && isdigit(*ptr));
+           break;
+         }
+         else if (*ptr == ';')
+         {
+           /* Argument separator.  */
+           ++arg_count;
+           if (arg_count < NARGS)
+             args[arg_count] = 0;
+           ++ptr;
+           break;
+         }
+         else
+         {
+           /* End of the current argument.
+              Assume the command has been reached.  */
+           cmd_state = have_cmd;
+           ++arg_count;
+         }
+       }
+       case have_cmd:
+       {
+         /* Execute the command.  */
+         execute_console_command(*ptr, arg_count, args);
+         /* Reset the parse state.  */
+         cmd_state = need_esc;
+         ++ptr;
+         return ptr - buf;
+       }
+     }
+   }
+   return ptr - buf;
+ }
+ 
+ static inline void
+ get_cursor(unsigned char *col, unsigned char *row)
+ {
+   unsigned char cur_page;
+   unsigned short rowcol;
+ 
+   cur_page = _farnspeekb(0x462);
+ 
+   rowcol = _farnspeekw(0x450 + cur_page);
+   *row = rowcol >> 8;
+   *col = rowcol & 0xff;
+ }
+ 
+ 
+ static void
+ move_cursor(int x_delta, int y_delta)
+ {
+   unsigned char row, col;
+   unsigned char max_row, max_col;
+   unsigned char cur_page;
+   unsigned short rowcol;
+   __dpmi_regs r;
+ 
+   _farsetsel(_dos_ds);
+   cur_page = _farnspeekb(0x462);
+ 
+   rowcol = _farnspeekw(0x450 + cur_page);
+   row = rowcol >> 8;
+   col = rowcol & 0xff;
+ 
+   max_row = _farnspeekb(0x484) + 1;
+   max_col = _farnspeekb(0x44a);
+ 
+   if ((int)row + y_delta < 0)
+     row = 0;
+   else if (row + y_delta > max_row)
+     row = max_row;
+ 
+   if ((int)col + x_delta < 0)
+     col = 0;
+   else if (col + x_delta > max_row)
+     col = max_col;
+ 
+   r.h.ah = 2;
+   r.h.bh = cur_page;
+   r.h.dh = row + y_delta;
+   r.h.dl = col + x_delta;
+   __dpmi_int(0x10, &r);
+ }
+ 
+ static void
+ set_cursor(unsigned char col, unsigned char row)
+ {
+   unsigned char max_row, max_col;
+   unsigned char cur_page;
+   unsigned short rowcol;
+   __dpmi_regs r;
+ 
+   _farsetsel(_dos_ds);
+   cur_page = _farnspeekb(0x462);
+ 
+   max_row = _farnspeekb(0x484) + 1;
+   max_col = _farnspeekb(0x44a);
+ 
+   if (row + y_delta > max_row)
+     row = max_row;
+ 
+   if (col + x_delta > max_row)
+     col = max_col;
+ 
+   r.h.ah = 2;
+   r.h.bh = cur_page;
+   r.h.dh = row;
+   r.h.dl = col;
+   __dpmi_int(0x10, &r);
+ }
+ 
+ #define GET_ARG(I, DEFVAL) ((argc > I) ? (args[I] : (DEFVAL)))
+ 
+ static void
+ execute_console_command(const unsigned char cmd, unsigned char argc,
+                         unsigned int args[NARGS])
+ {
+   unsigned char row, col;
+ 
+   switch (cmd)
+   {
+     /* Move up.  */
+     case 'A':
+       move_cursor(0, -GET_ARG(0, 1));
+       break;
+ 
+     /* Move down.  */
+     case 'B':
+       move_cursor(0, -GET_ARG(0, 1);
+       break;
+ 
+     /* Move left.  */
+     case 'C':
+       move_cursor(-GET_ARG(0, 1), 0);
+       break;
+ 
+     /* Move right.  */
+     case 'D':
+       move_cursor(GET_ARG(0, 1), 0);
+       break;
+ 
+     /* Move to column.  */
+     case 'G':
+       get_cursor(&row, &col);
+       set_cursor(GET_ARG(0, 1) - 1, row);
+       break;
+ 
+     /* Move to row and column.  */
+     case 'H':
+       set_cursor(GET_ARG(0, 1) - 1, GET_ARG(1, 1) - 1);
+       break;
+ 
+     /* Move to row.  */
+     case 'd':
+       get_cursor(&row, &col);
+       set_cursor(row, GET_ARG(0, 1) - 1);
+   }
+ }

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019