00001
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <string.h>
00005 #include <ctype.h>
00006 #include <signal.h>
00007 #include <errno.h>
00008 #include <fcntl.h>
00009 #ifndef WIN32
00010 #include <unistd.h>
00011 #include <sys/time.h>
00012 #else
00013 #include "win32.h"
00014 #include <conio.h>
00015 #endif
00016 #include <sys/types.h>
00017 #include <sys/stat.h>
00018
00019 #include "sic_command_line.h"
00020 #include "kbdtermio.h"
00021
00022 #include "kbdterm.h"
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #define BACKSPACE 0x08
00044 #define SPACE ' '
00045
00046 static char cur_line[MAXBUF];
00047 static char sav_line[MAXBUF];
00048 static int cur_pos = 0;
00049 static int max_pos = 0;
00050
00051 static void fix_line( );
00052 static void redraw_line( );
00053 static void clear_line( );
00054 static void clear_eoline( );
00055 static void copy_line( );
00056
00062 void reset_kbd_line( char *prompt, char *line, int *code)
00063 {
00064
00065 if (*code >= 0)
00066 fputs( prompt, stderr);
00067
00068
00069 if (*code == 0) {
00070 cur_line[0] = '\0';
00071 cur_pos = 0;
00072 max_pos = 0;
00073 } else {
00074 clear_line( prompt);
00075 copy_line( line);
00076 }
00077 }
00078
00096 int CFC_API kbd_line( char *prompt, char *line, int *code)
00097 {
00098 int cur_char;
00099
00100
00101 set_termio( );
00102
00103 reset_kbd_line( prompt, line, code);
00104
00105
00106 if (!isatty( STDIN_FILENO)) {
00107 if ((fgets( line, MAXBUF, stdin)) == NULL)
00108 strcpy( line, "sic\\exit");
00109 *code = 0;
00110 reset_termio( );
00111 return (int)strlen( line);
00112 }
00113
00114
00115 for (;;) {
00116 do {
00117 #ifndef WIN32
00118 cur_char = getc( stdin);
00119 #else
00120 cur_char = _getch( );
00121 #endif
00122 } while (cur_char == EOF);
00123
00124 if (cur_char == 011)
00125 cur_char = 040;
00126
00127
00128 #ifndef WIN32
00129
00130 if (cur_char == 033) {
00131
00132 cur_char = getc( stdin);
00133 if (cur_char == 0133) {
00134 cur_char = getc( stdin);
00135 switch (cur_char) {
00136 case 0104:
00137 cur_char = 002;
00138 break;
00139 case 0103:
00140 cur_char = 006;
00141 break;
00142 case 0101:
00143 cur_char = 020;
00144 break;
00145 case 0102:
00146 cur_char = 016;
00147 break;
00148 default:
00149 cur_char = 0;
00150 break;
00151 }
00152 } else if (cur_char == 0117) {
00153 cur_char = getc( stdin);
00154 switch (cur_char) {
00155 case 0104:
00156 cur_char = 002;
00157 break;
00158 case 0103:
00159 cur_char = 006;
00160 break;
00161 case 0101:
00162 cur_char = 020;
00163 break;
00164 case 0102:
00165 cur_char = 016;
00166 break;
00167 case 0162:
00168 cur_char = 005;
00169 break;
00170 case 0123:
00171 cur_char = 025;
00172 break;
00173 case 0154:
00174 cur_char = 004;
00175 break;
00176 case 0115:
00177 cur_char = 010;
00178 break;
00179 case 0163:
00180 cur_char = 006;
00181 break;
00182 default:
00183 cur_char = 005;
00184 break;
00185 }
00186 } else {
00187 cur_char = 005;
00188 }
00189 }
00190 #else
00191 if ((cur_char == 0xe0) || (cur_char == 0)) {
00192 cur_char = _getch();
00193
00194 switch(cur_char) {
00195 case 0107:
00196 cur_char = 001;
00197 break;
00198 case 0110:
00199 cur_char = 020;
00200 break;
00201 case 0111:
00202 cur_char = 0;
00203 break;
00204 case 0113:
00205 cur_char = 002;
00206 break;
00207 case 0115:
00208 cur_char = 006;
00209 break;
00210 case 0117:
00211 cur_char = 005;
00212 break;
00213 case 0120:
00214 cur_char = 016;
00215 break;
00216 case 0121:
00217 cur_char = 0;
00218 break;
00219 case 0122:
00220 cur_char = 0;
00221 break;
00222 case 0123:
00223 cur_char = 004;
00224 break;
00225 default:
00226 break;
00227 }
00228 }
00229 #endif
00230
00231 if (isprint( cur_char)) {
00232 int i;
00233
00234 for (i = max_pos; i > cur_pos; i--) {
00235 cur_line[i] = cur_line[i - 1];
00236 }
00237 putc( cur_char, stderr);
00238 cur_line[cur_pos] = cur_char;
00239 cur_pos += 1;
00240 max_pos += 1;
00241 if (cur_pos < max_pos)
00242 fix_line( );
00243 cur_line[max_pos] = '\0';
00244
00245
00246 #ifdef VERASE
00247 } else if (cur_char == orig_termio.c_cc[VERASE]) {
00248
00249
00250 if (cur_pos > 0) {
00251 int i;
00252
00253 cur_pos -= 1;
00254 putc( BACKSPACE, stderr);
00255 for (i = cur_pos; i < max_pos; i++)
00256 cur_line[i] = cur_line[i + 1];
00257 max_pos -= 1;
00258 fix_line( );
00259 }
00260 #endif
00261 #ifdef VEOF
00262 } else if (cur_char == orig_termio.c_cc[VEOF]) {
00263
00264
00265 if (max_pos == 0) {
00266 reset_termio( );
00267 *code = 0;
00268 return 0;
00269 }
00270 if ((cur_pos < max_pos) && (cur_char == 004)) {
00271
00272
00273 int i;
00274
00275 for (i = cur_pos; i < max_pos; i++)
00276 cur_line[i] = cur_line[i + 1];
00277 max_pos -= 1;
00278 fix_line( );
00279 }
00280 #endif
00281 #ifdef VKILL
00282 } else if (cur_char == orig_termio.c_cc[VKILL]) {
00283
00284
00285 clear_line( prompt);
00286 #endif
00287 #ifdef VWERASE
00288 } else if (cur_char == orig_termio.c_cc[VWERASE]) {
00289
00290
00291 while ((cur_pos > 0) && (cur_line[cur_pos - 1] == SPACE)) {
00292 cur_pos -= 1;
00293 putc( BACKSPACE, stderr);
00294 }
00295 while ((cur_pos > 0) && (cur_line[cur_pos - 1] != SPACE)) {
00296 cur_pos -= 1;
00297 putc( BACKSPACE, stderr);
00298 }
00299 clear_eoline( );
00300 max_pos = cur_pos;
00301 #endif
00302 #ifdef VREPRINT
00303 } else if (cur_char == orig_termio.c_cc[VREPRINT]) {
00304
00305
00306 putc( '\n', stderr);
00307 redraw_line( prompt);
00308 #else
00309 #ifdef VRPRNT
00310 } else if (cur_char == orig_termio.c_cc[VRPRNT]) {
00311
00312
00313 putc( '\n', stderr);
00314 redraw_line( prompt);
00315 #endif
00316 #endif
00317 #ifdef VSUSP
00318 } else if (cur_char == orig_termio.c_cc[VSUSP]) {
00319 reset_termio( );
00320 kill( 0, SIGTSTP);
00321
00322
00323 set_termio( );
00324
00325
00326 redraw_line( prompt);
00327 #endif
00328 } else {
00329
00330
00331
00332
00333 int i;
00334
00335 switch (cur_char) {
00336 case EOF:
00337 case 004:
00338 if (cur_char == EOF || max_pos == 0) {
00339 reset_termio( );
00340 *code = 0;
00341 copy_line( "sic\\exit");
00342 fix_line( );
00343 putc( '\n', stderr);
00344 strcpy( line, cur_line);
00345 return (int)strlen( line);
00346 }
00347 if (cur_pos < max_pos) {
00348 for (i = cur_pos; i < max_pos; i++)
00349 cur_line[i] = cur_line[i + 1];
00350 max_pos -= 1;
00351 fix_line( );
00352 }
00353 break;
00354 case 001:
00355 while (cur_pos > 0) {
00356 cur_pos -= 1;
00357 putc( BACKSPACE, stderr);
00358 }
00359 break;
00360 case 002:
00361 if (cur_pos > 0) {
00362 cur_pos -= 1;
00363 putc( BACKSPACE, stderr);
00364 }
00365 break;
00366 case 005:
00367 while (cur_pos < max_pos) {
00368 putc( cur_line[cur_pos], stderr);
00369 cur_pos += 1;
00370 }
00371 break;
00372 case 006:
00373 if (cur_pos < max_pos) {
00374 putc( cur_line[cur_pos], stderr);
00375 cur_pos += 1;
00376 }
00377 break;
00378 case 013:
00379 clear_eoline( );
00380 max_pos = cur_pos;
00381 break;
00382
00383
00384 case 020:
00385 if (*code < 2) {
00386 *code = -1;
00387 reset_termio( );
00388 return 0;
00389 }
00390 break;
00391 case 016:
00392 if (*code < 2) {
00393 *code = 1;
00394 reset_termio( );
00395 return 0;
00396 }
00397 break;
00398
00399
00400 case 014:
00401 case 022:
00402 putc( '\n', stderr);
00403 redraw_line( prompt);
00404 break;
00405 case 0177:
00406 case 010:
00407 if (cur_pos > 0) {
00408 cur_pos -= 1;
00409 putc( BACKSPACE, stderr);
00410 for (i = cur_pos; i < max_pos; i++)
00411 cur_line[i] = cur_line[i + 1];
00412 max_pos -= 1;
00413 fix_line( );
00414 }
00415 break;
00416 case 025:
00417 clear_line( prompt);
00418 break;
00419 case 027:
00420 while ((cur_pos > 0) && (cur_line[cur_pos - 1] == SPACE)) {
00421 cur_pos -= 1;
00422 putc( BACKSPACE, stderr);
00423 }
00424 while ((cur_pos > 0) && (cur_line[cur_pos - 1] != SPACE)) {
00425 cur_pos -= 1;
00426 putc( BACKSPACE, stderr);
00427 }
00428 clear_eoline( );
00429 max_pos = cur_pos;
00430 break;
00431 break;
00432
00433
00434 case '\n':
00435 case '\r':
00436 cur_line[max_pos + 1] = '\0';
00437 putc( '\n', stderr);
00438 reset_termio( );
00439 *code = 0;
00440 strcpy( line, cur_line);
00441 return (int)strlen( cur_line);
00442 default:
00443 break;
00444 }
00445 }
00446 }
00447 }
00448
00449
00450
00451
00452
00453
00454 static void fix_line( )
00455 {
00456 int i;
00457
00458
00459 for (i = cur_pos; i < max_pos; i++)
00460 putc( cur_line[i], stderr);
00461
00462
00463 putc( SPACE, stderr);
00464
00465
00466 for (i = max_pos + 1; i > cur_pos; i--)
00467 putc( BACKSPACE, stderr);
00468 }
00469
00470
00471
00472 static void redraw_line( prompt)
00473 char *prompt;
00474 {
00475 int i;
00476
00477 fputs( prompt, stderr);
00478 fputs( cur_line, stderr);
00479
00480
00481 for (i = max_pos; i > cur_pos; i--)
00482 putc( BACKSPACE, stderr);
00483 }
00484
00485
00486
00487 static void clear_line( prompt)
00488 char *prompt;
00489 {
00490 int i;
00491
00492 for (i = 0; i < max_pos; i++)
00493 sav_line[i] = cur_line[i];
00494 sav_line[i] = '\0';
00495 for (i = 0; i < max_pos; i++)
00496 cur_line[i] = '\0';
00497 for (i = cur_pos; i > 0; i--)
00498 putc( BACKSPACE, stderr);
00499 for (i = 0; i < max_pos; i++)
00500 putc( SPACE, stderr);
00501 putc( '\r', stderr);
00502 fputs( prompt, stderr);
00503 cur_pos = 0;
00504 max_pos = 0;
00505 }
00506
00507
00508 static void clear_eoline( prompt)
00509 char *prompt;
00510 {
00511 int i;
00512
00513 for (i = 0; i < max_pos - cur_pos; i++)
00514 sav_line[i] = cur_line[i + cur_pos];
00515 sav_line[i] = '\0';
00516 for (i = cur_pos; i < max_pos; i++)
00517 cur_line[i] = '\0';
00518 for (i = cur_pos; i < max_pos; i++)
00519 putc( SPACE, stderr);
00520 for (i = cur_pos; i < max_pos; i++)
00521 putc( BACKSPACE, stderr);
00522 }
00523
00524
00525
00526 static void copy_line( line)
00527 char *line;
00528 {
00529 strcpy( cur_line, line);
00530 fputs( cur_line, stderr);
00531 cur_pos = max_pos = (int)strlen( cur_line);
00532 }
00533
00534
00535