Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:41

0001 /*
0002  * outch.c  - This file contains code for displaying characters
0003  *        on the console uisng information that should be
0004  *        maintained by the BIOS in its data Area.
0005  *
0006  * Copyright (C) 1998  Eric Valette (valette@crf.canon.fr)
0007  *                     Canon Centre Recherche France.
0008  *
0009  *  The license and distribution terms for this file may be
0010  *  found in the file LICENSE in this distribution or at
0011  *  http://www.rtems.org/license/LICENSE.
0012  *
0013  * Till Straumann <strauman@slac.stanford.edu>, 2003/9:
0014  *  - added handling of basic escape sequences (cursor movement
0015  *    and erasing; just enough for the line editor 'libtecla' to
0016  *    work...)
0017  */
0018 
0019 #include <bsp.h>
0020 
0021 #include <stdlib.h>
0022 #include <string.h>
0023 
0024 #include <crt.h>
0025 
0026 extern void wr_cursor(int, unsigned short);
0027 
0028 #define TAB_SPACE 4
0029 static unsigned short *bitMapBaseAddr;
0030 static unsigned short ioCrtBaseAddr;
0031 static unsigned short maxCol;
0032 static unsigned short maxRow;
0033 static unsigned char  row;
0034 static unsigned char  column;
0035 static unsigned short attribute;
0036 static unsigned int   nLines;
0037 
0038 static void
0039 scroll(void)
0040 {
0041     int i, j;                   /* Counters */
0042     unsigned short *pt_scroll, *pt_bitmap;  /* Pointers on the bit-map  */
0043 
0044     pt_bitmap = bitMapBaseAddr;
0045     j = 0;
0046     pt_bitmap = pt_bitmap + j;
0047     pt_scroll = pt_bitmap + maxCol;
0048     for (i = j; i < (maxRow - 1) * maxCol; i++) {
0049     *pt_bitmap++ = *pt_scroll++;
0050     }
0051 
0052     /*
0053      * Blank characters are displayed on the last line.
0054      */
0055     for (i = 0; i < maxCol; i++) {
0056     *pt_bitmap++ = (short) (' ' | attribute);
0057     }
0058 }
0059 
0060 static void
0061 doCRNL(int cr, int nl)
0062 {
0063     if (nl) {
0064     if (++row == maxRow) {
0065     scroll();   /* Scroll the screen now */
0066     row = maxRow - 1;
0067     }
0068     nLines++;
0069     }
0070     if (cr)
0071         column = 0;
0072     /* Move cursor on the next location  */
0073     if (cr || nl)
0074         wr_cursor(row * maxCol + column, ioCrtBaseAddr);
0075 }
0076 
0077 int (*videoHook)(char, int *)=0;
0078 
0079 static void
0080 advanceCursor(void)
0081 {
0082   if (++column == maxCol)
0083     doCRNL(1,1);
0084   else
0085     wr_cursor(row * maxCol + column, ioCrtBaseAddr);
0086 }
0087 
0088 static void
0089 gotorc(int r, int c)
0090 {
0091     column = c;
0092     row    = r;
0093 
0094     wr_cursor(row * maxCol + column, ioCrtBaseAddr);
0095 }
0096 
0097 #define ESC     ((char)27)
0098 /* erase current location without moving the cursor */
0099 #define BLANK   ((char)0x7f)
0100 
0101 static void
0102 videoPutChar(char car)
0103 {
0104     unsigned short *pt_bitmap = bitMapBaseAddr + row * maxCol + column;
0105 
0106     switch (car) {
0107     case '\b': {
0108         if (column) column--;
0109         /* Move cursor on the previous location  */
0110         wr_cursor(row * maxCol + column, ioCrtBaseAddr);
0111         return;
0112     }
0113     case '\t': {
0114         int i;
0115 
0116         i = TAB_SPACE - (column & (TAB_SPACE - 1));
0117         column += i;
0118         if (column >= maxCol) {
0119         doCRNL(1,1);
0120         return;
0121         }
0122         while (i--) *pt_bitmap++ = ' ' | attribute;
0123         wr_cursor(row * maxCol + column, ioCrtBaseAddr);
0124         return;
0125     }
0126     case '\n': {
0127         doCRNL(0,1);
0128         return;
0129     }
0130     case 7:     {   /* Bell code must be inserted here */
0131         return;
0132     }
0133     case '\r' : {
0134         doCRNL(1,0);
0135         return;
0136     }
0137     case BLANK: {
0138         *pt_bitmap = ' ' | attribute;
0139         /* DONT move the cursor... */
0140         return;
0141     }
0142     default: {
0143         *pt_bitmap = (unsigned char)car | attribute;
0144         advanceCursor();
0145         return;
0146     }
0147     }
0148 }
0149 
0150 /* trivial state machine to handle escape sequences:
0151  *
0152  *                    ---------------------------------
0153  *                   |                                 |
0154  *                   |                                 |
0155  * KEY:        esc   V    [          DCABHKJ       esc |
0156  * STATE:   0 -----> 27 -----> '[' ----------> -1 -----
0157  *          ^\        \          \               \
0158  * KEY:     | \other   \ other    \ other         \ other
0159  *           <-------------------------------------
0160  *
0161  * in state '-1', the DCABHKJ cases are handled
0162  *
0163  * (cursor motion and screen clearing)
0164  */
0165 
0166 #define DONE  (-1)
0167 
0168 static int
0169 handleEscape(int oldState, char car)
0170 {
0171 int rval = 0;
0172 int ro,co;
0173 
0174     switch ( oldState ) {
0175         case DONE:  /*  means the previous char terminated an ESC sequence... */
0176         case 0:
0177             if ( 27 == car ) {
0178                 rval = 27;   /* START of an ESC sequence */
0179             }
0180         break;
0181 
0182         case 27:
0183             if ( '[' == car ) {
0184                 rval = car;  /* received ESC '[', so far */
0185             } else {
0186                 /* dump suppressed 'ESC'; outch will append the char */
0187                 videoPutChar(ESC);
0188             }
0189         break;
0190 
0191         case '[':
0192             /* handle 'ESC' '[' sequences here */
0193             ro = row; co = column;
0194             rval = DONE; /* done */
0195 
0196             switch (car) {
0197                 case 'D': /* left */
0198                     if ( co > 0 )      co--;
0199                 break;
0200                 case 'C': /* right */
0201                     if ( co < maxCol ) co++;
0202                 break;
0203                 case 'A': /* up    */
0204                     if ( ro > 0 )      ro--;
0205                 break;
0206                 case 'B': /* down */
0207                     if ( ro < maxRow ) ro++;
0208                 break;
0209                 case 'H': /* home */
0210                     ro = co = 0;
0211                 break;
0212                 case 'K': /* clear to end of line */
0213                     while ( column < maxCol - 1 )
0214                         videoPutChar(' ');
0215                     videoPutChar(BLANK);
0216                 break;
0217                 case 'J': /* clear to end of screen */
0218                     while (  ((row < maxRow-1) || (column < maxCol-1)) )
0219                         videoPutChar(' ');
0220                     videoPutChar(BLANK);
0221                 break;
0222                 default:
0223                     videoPutChar(ESC);
0224                     videoPutChar('[');
0225                     /* DONT move the cursor */
0226                     ro   = -1;
0227                     rval = 0;
0228                 break;
0229             }
0230             /* reset cursor */
0231             if ( ro >= 0)
0232                 gotorc(ro,co);
0233 
0234         default:
0235         break;
0236 
0237     }
0238 
0239     return rval;
0240 }
0241 
0242 static void
0243 clear_screen(void)
0244 {
0245     int i,j;
0246 
0247     for (j = 0; j <= maxRow; j++) {
0248       for (i = 0; i <= maxCol; i++) {
0249     videoPutChar(' ');
0250       }
0251     }
0252     column  = 0;
0253     row     = 0;
0254 }
0255 
0256 /*-------------------------------------------------------------------------+
0257 |         Function: _IBMPC_outch
0258 |      Description: Higher level (console) interface to consPutc.
0259 | Global Variables: None.
0260 |        Arguments: c - character to write to console.
0261 |          Returns: Nothing.
0262 +--------------------------------------------------------------------------*/
0263 void
0264 _IBMPC_outch(char c)
0265 {
0266 static int escaped = 0;
0267 
0268   if ( ! (escaped = handleEscape(escaped, c)) ) {
0269     if ( '\n' == c )
0270       videoPutChar('\r');
0271     videoPutChar(c);
0272   }
0273 } /* _IBMPC_outch */
0274 
0275 /*-------------------------------------------------------------------------+
0276 |         Function: _IBMPC_initVideo
0277 |      Description: Video system initialization. Hook for any early setup.
0278 | Global Variables: bitMapBaseAddr, ioCrtBaseAddr, maxCol, maxRow, row
0279 |           column, attribute, nLines;
0280 |        Arguments: None.
0281 |          Returns: Nothing.
0282 +--------------------------------------------------------------------------*/
0283 void
0284 _IBMPC_initVideo(void)
0285 {
0286     /*
0287      * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578#c16
0288      */
0289     unsigned char* volatile pt = (unsigned char*) (VIDEO_MODE_ADDR);
0290     unsigned short* volatile crt_base = (unsigned short*) DISPLAY_CRT_BASE_IO_ADDR;
0291     uint8_t* volatile nb_max_row = (uint8_t*) NB_MAX_ROW_ADDR;
0292     uint16_t* volatile nb_max_col = (uint16_t*) NB_MAX_COL_ADDR;
0293 
0294     if (*pt == VGAMODE7) {
0295       bitMapBaseAddr = (unsigned short*) V_MONO;
0296     }
0297     else {
0298       bitMapBaseAddr = (unsigned short*) V_COLOR;
0299     }
0300     ioCrtBaseAddr = *crt_base;
0301     maxCol  = *nb_max_col;
0302     maxRow  = *nb_max_row;
0303     column  = 0;
0304     row     = 0;
0305     attribute = ((BLACK << 4) | WHITE)<<8;
0306     nLines = 0;
0307     clear_screen();
0308 #ifdef DEBUG_EARLY_STAGE
0309     printk("bitMapBaseAddr = %X, display controller base IO = %X\n",
0310        (unsigned) bitMapBaseAddr,
0311        (unsigned) ioCrtBaseAddr);
0312     videoPrintf("maxCol = %d, maxRow = %d\n", (unsigned) maxCol, (unsigned) maxRow);
0313 #endif
0314 } /* _IBMPC_initVideo */
0315 
0316 /* for old DOS compatibility n-curses type of applications */
0317 void gotoxy( int x, int y );
0318 int whereX( void );
0319 int whereY( void );
0320 
0321 void gotoxy( int x, int y )
0322 {
0323   gotorc(y,x);
0324 }
0325 
0326 int whereX( void )
0327 {
0328   return row;
0329 }
0330 
0331 int whereY( void )
0332 {
0333   return column;
0334 }