00001 /*@A (C) 1992 Allen I. Holub */ 00002 #include <stdio.h> 00003 #include "cur.h" 00004 00005 00006 /*-------------------------------------------------------- 00007 * WINIO.C Lowest level I/O routines: 00008 * waddch(win,c) wgetch(win) 00009 * echo() noecho() 00010 * nl() nonl() 00011 * crmode() nocrmode() 00012 *-------------------------------------------------------- 00013 */ 00014 00015 /* and map both to \n\r on output */ 00016 void echo (WINDOW *w) { w->Echo = 1; } 00017 void noecho (WINDOW *w) { w->Echo = 0; } 00018 void nl (WINDOW *w) { w->Nl = 1; } 00019 void nonl (WINDOW *w) { w->Nl = 0; } 00020 00021 void crmode(WINDOW *w) 00022 { 00023 /* setvbuf(stdin, NULL, _IONBF, 0); */ /* Turn off buffering */ 00024 w->Crmode = 1; 00025 } 00026 00027 void nocrmode(WINDOW *w) 00028 { 00029 /* freopen( "/dev/con", "r", stdin ); */ 00030 w->Crmode = 0; 00031 } 00032 00033 /*--------------------------------------------------------*/ 00034 00035 unsigned char *getbuf(WINDOW *win,unsigned char * buf) 00036 { 00037 /* Get a buffer interactively. ^H is a destructive backspace. This routine 00038 * is mildly recursive (it's called from wgetch() when Crmode is false. 00039 * The newline is put into the buffer. Returns it's second argument. 00040 */ 00041 00042 int c; 00043 unsigned char *sbuf = buf; 00044 00045 win->Crmode = 1; 00046 while( (c = wgetch(win)) != '\n' && c != '\r' ) 00047 { 00048 switch( c ) 00049 { 00050 case '\b': if( buf > sbuf ) 00051 { 00052 --buf; 00053 wprintw( win, " \b" ); 00054 } 00055 else 00056 { 00057 wprintw( win, " " ); 00058 putchar('\007'); 00059 } 00060 break; 00061 00062 default: *buf++ = c; 00063 break; 00064 } 00065 } 00066 *buf++ = c ; /* Add line terminator (\n or \r) */ 00067 *buf = '\0'; 00068 win->Crmode = 0 ; 00069 return sbuf ; 00070 } 00071 00072 /*--------------------------------------------------------*/ 00073 00074 int wgetch( WINDOW *win ) 00075 { 00076 /* Get a character from DOS without echoing. We need to do this in order 00077 * to support (echo/noecho). We'll also do noncrmode input buffering here. 00078 * Maximum input line length is 132 columns. 00079 * 00080 * In nocrmode(), DOS functions are used to get a line and all the normal 00081 * command-line editing functions are available. Since there's no way to 00082 * turn off echo in this case, characters are echoed to the screen 00083 * regardless of the status of echo(). In order to retain control of the 00084 * window, input fetched for wgetch() is always done in crmode, even if 00085 * Crmode isn't set. If nl() mode is enabled, carriage return (Enter, ^M) 00086 * and linefeed (^J) are both mapped to '\n', otherwise they are not mapped. 00087 * 00088 * Characters are returned in an int. The high byte is 0 for normal 00089 * characters. Extended characters (like the function keys) are returned 00090 * with the high byte set to 0xff and the character code in the low byte. 00091 * Extended characters are not echoed. 00092 */ 00093 00094 static unsigned char buf[ 133 ]; /* Assuming initialization to 0's */ 00095 static unsigned char *p = buf; 00096 register int c; 00097 00098 if( !win->Crmode ) 00099 { 00100 if( !*p ) p = getbuf( win, buf ); 00101 return( win->Nl && *p == '\r' ) ? '\n' : *p++ ; 00102 } 00103 else 00104 { 00105 if(win->IO) 00106 { 00107 if( (c = fgetc((FILE *)win->IO) & 0xff) == ('Z'-'@') ) /* Ctrl-Z */ 00108 return EOF ; 00109 else 00110 { 00111 if( c == '\r' && win->Nl ) c = '\n' ; 00112 if( win->Echo ) waddch( win, c ); 00113 } 00114 } 00115 else 00116 { 00117 c = EOF; 00118 } 00119 return c; 00120 } 00121 } 00122 00123 /*--------------------------------------------------------*/ 00124 00125 int waddch(WINDOW *win,int c ) 00126 { 00127 /* Print a character to an active (not hidden) window: 00128 * The following are handled specially: 00129 * 00130 * \n Clear the line from the current cursor position to the right edge 00131 * of the window. Then: 00132 * if nl() is active: 00133 * go to the left edge of the next line 00134 * else 00135 * go to the current column on the next line 00136 * In addition, if scrolling is enabled, the window scrolls if you're 00137 * on the bottom line. 00138 * \t is expanded into an 8-space field. If the tab goes past the right 00139 * edge of the window, the cursor wraps to the next line. 00140 * \r gets you to the beginning of the current line. 00141 * \b backs up one space but may not back up past the left edge of the 00142 * window. Nondestructive. The curses documentation doesn't say that 00143 * \b is handled explicitly but it does indeed work. 00144 * ESC This is not standard curses but is useful. It is valid only if 00145 * DOESC was true during the compile. All characters between an ASCII 00146 * ESC and an alphabetic character are sent to the output but are other 00147 * wise ignored. This let's you send escape sequences directly to the 00148 * terminal if you like. I'm assuming here that you won't change 00149 * windows in the middle of an escape sequence. 00150 * 00151 * Return ERR if the character would have caused the window to scroll 00152 * illegally, or if you attempt to write to a hidden window. 00153 */ 00154 00155 int rval = OK; 00156 00157 if( win->hidden ) 00158 return ERR; 00159 00160 cmove(win, win->y_org + win->row, win->x_org + win->col); 00161 00162 { 00163 switch( c ) 00164 { 00165 case '\b': if( win->col > 0 ) 00166 { 00167 outc(win, '\b', win->attrib ); 00168 --( win->col ); 00169 } 00170 break; 00171 00172 case '\t': do { 00173 waddch( win, ' ' ); 00174 } while( win->col % 8 ); 00175 break; 00176 00177 case '\r': win->col = 0; 00178 cmove(win, win->y_org + win->row, win->x_org); 00179 break; 00180 00181 default: 00182 if( (win->col + 1) < win->x_size ) 00183 { 00184 /* If you're not at the right edge of the window, */ 00185 /* print the character and advance. */ 00186 00187 ++win->col; 00188 // LockScreen(); 00189 outc(win, c, win->attrib ); 00190 // UnlockScreen(); 00191 break; 00192 } 00193 replace(win, c); /* At right edge, don't advance */ 00194 if( !win->wrap_ok ) 00195 { 00196 // UnlockScreen(); 00197 break; 00198 } 00199 // UnlockScreen(); 00200 00201 /* otherwise wrap around by falling through to newline */ 00202 00203 case '\n': 00204 // LockScreen(); 00205 if( c == '\n' ) /* Don't erase character at far */ 00206 { 00207 wclrtoeol( win ); /* right of the screen. */ 00208 } 00209 00210 if( win->Nl ) 00211 win->col = 0; 00212 if( ++(win->row) >= win->y_size ) 00213 { 00214 rval = wscroll( win, 1 ); 00215 --( win->row ); 00216 } 00217 cmove(win, win->y_org + win->row, win->x_org + win->col); 00218 // UnlockScreen(); 00219 break; 00220 } 00221 } 00222 return rval; 00223 }