openblt

a hobby OS from the late 90s
git clone http://frotz.net/git/openblt.git
Log | Files | Refs | LICENSE

vt100.c (13317B)


      1 /* $Id: //depot/blt/srv/console2/vt100.c#1 $ */
      2 /* VT100 Engine Copyright 1997 Daniel Marks <dmarks@uiuc.edu> */
      3 
      4 #include "vt100.h"
      5 #include <stdlib.h>
      6 
      7 #define STRICT_VT100
      8 
      9 /* struct virtscreen newscr; */
     10 
     11 void std_interpret_char(struct virtscreen *cur, unsigned char ch);
     12 void std_interpret_ansi(struct virtscreen *cur, unsigned char ch);
     13 void special_reading_ansi(struct virtscreen *cur, unsigned char ch);
     14 void special_ansi_charset_0(struct virtscreen *cur, unsigned char ch);
     15 void special_ansi_charset_1(struct virtscreen *cur, unsigned char ch);
     16 
     17 void clear_region(struct virtscreen *cur, int y1, int x1, int y2, int x2, int atrb);
     18 
     19 int init_virtscreen(struct virtscreen *cur, int rows, int columns)
     20 {
     21 
     22   cur->num_bytes = ((sizeof(unsigned short) * rows * columns));
     23 
     24   if (!(cur->data=malloc(cur->num_bytes)))
     25     return (-1);
     26 
     27   cur->data_off_scr = cur->data;
     28 
     29   cur->bottom_scroll = cur->rows = rows;
     30   cur->columns = columns;
     31   cur->cur_ansi_number = cur->top_scroll = 0;
     32   cur->ansi_elements = cur->ansi_reading_number = 0;
     33   cur->next_char_send = std_interpret_char;
     34   cur->old_attrib = cur->attrib = 0x07;
     35   cur->next_char_send = std_interpret_char;
     36   clear_region(cur,0,0,rows-1,columns-1,cur->attrib);
     37   cur->old_xpos = cur->old_ypos = 0;
     38 
     39   return (0);
     40 }
     41 
     42 void clear_region(struct virtscreen *cur, int y1, int x1, int y2, int x2, int atrb)
     43 {
     44   ushort *ch = loc_in_virtscreen(cur,y1,x1);
     45   ushort *tr = loc_in_virtscreen(cur,y2,x2);
     46   int dt = 0x20 | (atrb << 8);
     47 
     48   while (ch<=tr)
     49     *ch++ = dt;
     50 }
     51 
     52 void clear_virtscreen(struct virtscreen *cur, int mode)
     53 {
     54   switch (mode)
     55   {
     56     case 0: clear_region(cur,cur->ypos,cur->xpos,
     57 			 cur->rows-1,cur->columns-1,cur->attrib);
     58             break;
     59     case 1: clear_region(cur,0,0,cur->ypos,cur->xpos,cur->attrib);
     60             break;
     61     default: clear_region(cur,0,0,cur->rows-1,cur->columns-1,cur->attrib);
     62              cur->xpos = cur->ypos = 0;
     63              break;
     64   }
     65 }
     66 
     67 void clear_to_eol(struct virtscreen *cur, int mode)
     68 {
     69   switch(mode)
     70     {
     71       case 0: 
     72           clear_region(cur,cur->ypos,cur->xpos,cur->ypos,
     73                        cur->columns-1,cur->attrib);
     74           break;
     75       case 1:
     76 	  clear_region(cur,cur->ypos,0,cur->ypos,cur->xpos,
     77                        cur->attrib);
     78           break;
     79       default:
     80           clear_region(cur,cur->ypos,0,cur->ypos,cur->columns-1,
     81                        cur->attrib);
     82 	}
     83 }
     84 
     85 
     86 void move_cursor(struct virtscreen *cur);
     87 /*
     88 {
     89 }
     90 */
     91 
     92 void position_console(struct virtscreen *cur, int ypos, int xpos, int rel)
     93 {
     94   if (rel)
     95     {
     96       cur->xpos += xpos;
     97       cur->ypos += ypos;
     98   } else
     99     {
    100       cur->xpos = xpos;
    101       cur->ypos = ypos;
    102     }
    103   if (cur->xpos < 0) cur->xpos = 0;
    104   if (cur->xpos >= cur->columns) cur->xpos = cur->columns-1;
    105   if (cur->ypos < 0) cur->ypos = 0;
    106   if (cur->ypos >= cur->rows) cur->ypos = cur->rows-1;
    107   move_cursor(cur);
    108 }
    109 
    110 void delete_chars_in_line(struct virtscreen *cur, int char_move)
    111 {
    112    ushort *next_move;
    113    ushort *end_move;
    114    ushort *start_move;
    115    ushort clr_with;
    116 
    117    clr_with = (cur->attrib << 8) | 0x20; 
    118    start_move = loc_in_virtscreen(cur,cur->ypos,cur->xpos);
    119    end_move = loc_in_virtscreen(cur,cur->ypos,cur->columns);
    120    if ((cur->xpos + char_move) < cur->columns)
    121    {
    122      next_move = loc_in_virtscreen(cur,cur->ypos,cur->xpos+char_move);
    123      while (next_move<end_move)
    124        *start_move++ = *next_move++;
    125    }
    126    while (start_move<end_move) *start_move++ = clr_with;
    127 }
    128 
    129 void scroll_virt_up_at_cursor(struct virtscreen *cur, int dir)
    130 {
    131    ushort clr_with;
    132    ushort *beginScr;
    133    ushort *endofScr;
    134    ushort *lastLine;
    135    ushort *nextLine;
    136    unsigned int real_scroll_length;
    137 
    138    if ((cur->ypos >= cur->top_scroll) &&
    139        (cur->ypos < cur->bottom_scroll))
    140    {
    141      clr_with = (cur->attrib << 8) | 0x20;
    142      beginScr = loc_in_virtscreen(cur,cur->ypos,0);
    143      endofScr = loc_in_virtscreen(cur,cur->bottom_scroll,0);
    144      lastLine = endofScr - cur->columns;
    145      nextLine = beginScr + cur->columns;
    146      real_scroll_length = ((unsigned int) lastLine) -
    147                           ((unsigned int) beginScr);
    148 
    149      if (dir)
    150        {
    151 	 memmove(beginScr,nextLine,real_scroll_length);
    152          while (lastLine < endofScr)
    153 	   *lastLine++ = clr_with;
    154        } else
    155 	 {
    156 	   memmove(nextLine,beginScr,real_scroll_length);
    157            while (beginScr < nextLine)
    158 	     *beginScr++ = clr_with;
    159 	 }
    160    }
    161 }
    162 
    163 void scroll_virtscreen(struct virtscreen *cur)
    164  {
    165    int clr_with = (cur->attrib << 8) | 0x20;
    166    ushort *beginScr = loc_in_virtscreen(cur,cur->top_scroll,0);
    167    ushort *endofScr = loc_in_virtscreen(cur,cur->bottom_scroll,0);
    168    ushort *lastLine = endofScr - cur->columns;
    169    ushort *nextLine = beginScr + cur->columns;
    170    unsigned int real_scroll_length = ((unsigned int) lastLine) -
    171                           ((unsigned int) beginScr);
    172 
    173    memmove(beginScr,nextLine,real_scroll_length);
    174    while (lastLine < endofScr)
    175      *lastLine++ = clr_with;
    176  };
    177 
    178 void set_scroll_region(struct virtscreen *cur, int low, int high)
    179 {
    180    low--;
    181    high = (high >= cur->rows) ? cur->rows : high;
    182    low = (low < 0) ? 0 : low;
    183 
    184    cur->top_scroll = low;
    185    cur->bottom_scroll = high;
    186 }
    187 
    188 void change_attribute(struct virtscreen *cur, int attrib)
    189 {
    190   cur->attrib = attrib;
    191 }
    192 
    193 void change_character(struct virtscreen *cur, int ch)
    194 {
    195   *(loc_in_virtscreen(cur,cur->ypos,cur->xpos)) =
    196     ch | (cur->attrib << 8);
    197 }
    198 
    199 void special_ansi_charset_0(struct virtscreen *cur, unsigned char ch)
    200 {
    201   cur->next_char_send = std_interpret_char;
    202 }
    203 
    204 void special_ansi_charset_1(struct virtscreen *cur, unsigned char ch)
    205 {
    206   cur->next_char_send = std_interpret_char;
    207 }
    208 
    209 void std_interpret_ansi(struct virtscreen *cur, unsigned char ch)
    210 {
    211   switch (ch)
    212   {
    213     case '(':  cur->next_char_send = special_ansi_charset_0;
    214                return;
    215     case ')':  cur->next_char_send = special_ansi_charset_1;
    216                return;
    217     case '[':  cur->cur_ansi_number = 0;
    218                cur->ansi_elements = 0;
    219                cur->ansi_reading_number = 0;
    220                cur->next_char_send = special_reading_ansi;
    221                return;
    222     case '7':  cur->old_attrib = cur->attrib;
    223                cur->old_xpos = cur->xpos;
    224                cur->old_ypos = cur->ypos;
    225                break;
    226     case '8':  change_attribute(cur,cur->old_attrib);
    227                position_console(cur,cur->ypos,cur->xpos,0);
    228                break;
    229     case 'E':  cur->xpos = 0;
    230     case 'D':  cur->ypos++;
    231                if (cur->ypos >= cur->bottom_scroll)
    232                {
    233                  scroll_virtscreen(cur);
    234                  cur->ypos--;
    235                }
    236                move_cursor(cur);
    237                break; 
    238     case 'M':  cur->ypos--;
    239                if (cur->ypos < cur->top_scroll)
    240                {
    241                  cur->ypos++;
    242                  scroll_virt_up_at_cursor(cur,0);
    243                }
    244                move_cursor(cur);
    245                break;    /* recalculate screen pos */
    246   }
    247   if (ch != 27)
    248     cur->next_char_send = std_interpret_char;
    249 }
    250 
    251 void std_interpret_char(struct virtscreen *cur, unsigned char ch)
    252 {
    253   switch (ch)
    254   {
    255     case 27: cur->next_char_send = std_interpret_ansi;
    256              return;
    257     case 12: clear_virtscreen(cur,2);
    258              break;
    259     case 13: cur->xpos = 0;        /* return = back to begin */
    260              break;
    261     case 10: cur->ypos++;
    262              if (cur->ypos >= cur->bottom_scroll)
    263                      /* if we're at bottom */
    264              {
    265                if (cur->ypos == cur->bottom_scroll)
    266 		 scroll_virtscreen(cur);        /* and scroll it! */
    267                cur->ypos--;            /* go back up a line */
    268              }
    269              cur->xpos=0;
    270              break;  
    271     case 9:  position_console(cur,cur->ypos,cur->xpos+(8-(cur->xpos % 8)),0);
    272              break;
    273     case 8:  cur->xpos--;               /* backspace on screen */
    274              if (cur->xpos<0)
    275              {
    276                cur->xpos = cur->columns - 1;
    277                cur->ypos;
    278                if (cur->ypos<0)
    279 		 cur->ypos=0;
    280              }
    281              break;
    282     default: if (!ch)
    283                 break;
    284              change_character(cur,ch);
    285              cur->xpos++;
    286              if (cur->xpos >= cur->columns)
    287 	       {
    288 #ifdef STRICT_VT100
    289 		 cur->xpos = cur->columns-1;
    290 #else
    291 		 cur->xpos = 0;
    292                  cur->ypos++;
    293                  if (cur->ypos == cur->bottom_scroll)
    294 		   {
    295 		     cur->ypos--;
    296 		     scroll_virtscreen(cur);
    297 		   }
    298 #endif
    299 	       }
    300              break;
    301     }
    302   move_cursor(cur);
    303 }
    304 
    305 void special_reading_ansi(struct virtscreen *cur, unsigned char ch)
    306 {
    307   if ((ch>='0') && (ch<='9'))
    308   {
    309     cur->cur_ansi_number = (cur->cur_ansi_number * 10) + (ch - '0');
    310     cur->ansi_reading_number = 1;
    311     return;
    312   }
    313 
    314   if ((cur->ansi_reading_number) || (ch == ';'))
    315   {
    316      if (cur->ansi_elements<MAX_ANSI_ELEMENTS)
    317       cur->ansi_element[cur->ansi_elements++] = cur->cur_ansi_number;
    318      cur->ansi_reading_number = 0;
    319   }
    320   cur->cur_ansi_number = 0;
    321   switch (ch)
    322   {
    323     case '?':
    324     case ';':   return;
    325     case 'D':   position_console(cur,0,(cur->ansi_elements) ?
    326 			 -cur->ansi_element[0] : -1,1);
    327                 break;
    328     case 'a':
    329     case 'C':   position_console(cur,0,(cur->ansi_elements) ?
    330 			 cur->ansi_element[0] : 1,1);
    331                 break;
    332     case 'A':   position_console(cur,(cur->ansi_elements) ? 
    333 		         -cur->ansi_element[0] : -1,0,1);
    334                 break;
    335     case 'e':
    336     case 'B':   position_console(cur,(cur->ansi_elements) ?
    337 			 cur->ansi_element[0] : 1,0,1);
    338                 break;
    339     case '`':
    340     case 'G':   
    341                 {
    342                   int temp = cur->ansi_elements ? cur->ansi_element[0] : 1;
    343 		  if (temp)
    344 		    temp--;
    345                   position_console(cur,cur->ypos,temp,0);
    346 		}
    347                 break;
    348     case 'E':   position_console(cur,cur->ypos + 
    349 		         ((cur->ansi_elements) ? cur->ansi_element[0] : 1),
    350 			 0,0);
    351                 break;
    352     case 'F':   position_console(cur,cur->ypos - 
    353 		         ((cur->ansi_elements) ? cur->ansi_element[0] : 1),
    354 			 0,0);
    355                 break;
    356     case 'd':   
    357                 {
    358                   int temp = cur->ansi_elements ? cur->ansi_element[0] : 1;
    359 		  if (temp)
    360 		    temp--;
    361                   position_console(cur,temp,cur->xpos,0);
    362 		}
    363                 break;
    364     case 'f':
    365     case 'H':
    366       {
    367         int row = (cur->ansi_elements > 0) ? cur->ansi_element[0] : 1;
    368         int col = (cur->ansi_elements > 1) ? cur->ansi_element[1] : 1;
    369 	if (row)
    370 	  row--;
    371 	if (col)
    372 	  col--;
    373         position_console(cur,row,col,0);
    374       }
    375       break;
    376     case 'J':   clear_virtscreen(cur,(cur->ansi_elements) ?
    377 		       cur->ansi_element[0]: 0);
    378                 break;
    379     case 'L':   {
    380                   int lines = (cur->ansi_elements) ? 
    381 		     cur->ansi_element[0] : 1;
    382                   while (lines>0)
    383                   {
    384                     scroll_virt_up_at_cursor(cur,0);
    385                     lines--;
    386                   }
    387                 }
    388                 break;
    389     case 'M':   {
    390                   int lines = (cur->ansi_elements) ? 
    391 		     cur->ansi_element[0] : 1;
    392                   while (lines>0)
    393                   {
    394                     scroll_virt_up_at_cursor(cur,1);
    395                     lines--;
    396                   }
    397                 }
    398                 break;
    399     case 'P':   delete_chars_in_line(cur,(cur->ansi_elements) ? 
    400 			 cur->ansi_element[0] : 1);
    401                 break;
    402     case 'K':   clear_to_eol(cur,cur->ansi_elements ? 
    403 		    cur->ansi_element[0] : 0);
    404                 break;
    405     case 's':   cur->old_xpos = cur->xpos;
    406                 cur->old_ypos = cur->ypos;
    407                 break;
    408     case 'u':   position_console(cur,cur->old_ypos,cur->old_xpos,0);
    409                 break;
    410     case 'r':   {
    411                   int low = (cur->ansi_elements > 0) ?
    412 		      cur->ansi_element[0] : 1;
    413                   int high = (cur->ansi_elements > 1) ?
    414 		      cur->ansi_element[1] : cur->rows;
    415                   if (low<=high)
    416                     set_scroll_region(cur,low,high);
    417                 }
    418                 break;
    419     case 'm':
    420        {
    421           int count = 0;
    422           int cthing;
    423           if (!cur->ansi_elements)
    424             change_attribute(cur,0x07);
    425           while (count < cur->ansi_elements)
    426           {
    427             cthing = cur->ansi_element[count];
    428             switch (cthing)
    429             {
    430               case 0:
    431               case 27: change_attribute(cur,0x07);
    432                        break;
    433               case 1:  change_attribute(cur,cur->attrib | 0x08);
    434                        break;
    435               case 5:  change_attribute(cur,cur->attrib | 0x80);
    436                        break;
    437               case 7:  change_attribute(cur,0x70);
    438                        break;
    439               case 21:
    440               case 22: change_attribute(cur,cur->attrib & 0xF7);
    441                        break;
    442               case 25: change_attribute(cur,cur->attrib & 0x7F);
    443                        break;
    444               default:
    445                 if ((cthing>=30) && (cthing<=37))
    446 		  {
    447 		    change_attribute(cur,(cur->attrib & 0xF8) | (cthing-30));
    448 		  }
    449                 if ((cthing>=40) && (cthing<=47))
    450 		  {
    451 		    change_attribute(cur,(cur->attrib & 0x8F) | 
    452 				     ((cthing-40) << 4));
    453 		  }
    454                 break;
    455 	      }
    456             count++;
    457 	  }
    458 	}
    459       break;
    460       
    461   }
    462   cur->next_char_send = std_interpret_char;
    463 }
    464