1 /* ******************************************** 2 * * 3 * Copyright, (C) Honeywell Bull Inc., 1988 * 4 * * 5 ******************************************** */ 6 7 /* HISTORY COMMENTS: 8 1) change(88-06-13,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel), 9 install(88-10-12,MR12.2-1160): 10 Created. 11 2) change(88-07-25,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel), 12 install(88-10-12,MR12.2-1160): 13 Documentation additions only. Added header comments to all routines. 14 3) change(88-08-09,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel), 15 install(88-10-12,MR12.2-1160): 16 Fix references to include files; "wstdefs.h" was split into 17 "wstdefs.h" and "wsttype.h" to avoid declaration clash; also, 18 various constants defined to descriptive names. 19 4) change(89-01-18,Lee), approve(89-01-02,MCR8043), audit(89-03-14,Flegel), 20 install(89-04-24,MR12.3-1033): 21 phx21233 - Converted display_char() to display_char_prim() for handling 22 primitive display function; new display_char() added which calls the 23 primitive and displays only when keyboard echoing is enabled. Added 24 routine get_echoed_input() for extracting only echoed input from line 25 buffer. 26 END HISTORY COMMENTS */ 27 28 #include <dos.h> 29 #include "wstdefs.h" 30 #include "wstglob.h" 31 32 /*^L 33 *********************************************************************** 34 35 Routine: DISPLAY_CHAR_STR 36 37 Function: 38 This routine returns the display string for a character 39 displayed in line editing. In particular, it determines how 40 non-printable characters are displayed. 41 42 Parameters: 43 (input) ch - specifies the ASCII character being 44 displayed 45 46 Returns: a pointer to a static string containing the 47 displayed form of the ASCII character 48 49 **********************************************************************/ 50 51 char *display_char_str(ch) 52 int ch; /* character to display */ 53 { 54 static char display_string[MAX_DISPLAY_CHAR_SIZE+1]; /* string to pass back result */ 55 int octval; 56 57 /* check for non-printable control character */ 58 if (ch < MIN_PRINTABLE_ASCII) { 59 octval = ch; 60 display_string[0] = '\\'; 61 display_string[3] = (ch & 07) + '0'; 62 ch >>= 3; 63 display_string[2] = (ch & 07) + '0'; 64 ch >>= 3; 65 display_string[1] = (ch & 07) + '0'; 66 display_string[4] = NUL_TERMINATOR; 67 } 68 69 /* check for printable ASCII */ 70 else if (ch < ASCII_DEL) { 71 display_string[0] = ch; 72 display_string[1] = NUL_TERMINATOR; 73 } 74 75 /* check for ASCII DEL character */ 76 else if (ch == ASCII_DEL) { 77 strcpy(display_string,"\\177"); 78 } 79 80 /* extended ASCII character */ 81 else { 82 sprintf(display_string,"<%d>", ch); 83 } 84 85 return(display_string); 86 } 87 88 89 /*^L 90 *********************************************************************** 91 92 Routine: DISPLAY_TAB_STR 93 94 Function: 95 This routine returns a string filled with enough blanks to pad 96 to the next tab column. 97 98 Parameters: 99 (input) cur_col - specifies the current column on the 100 screen to tab from 101 102 Returns: a pointer to a static string containing enough 103 spaces to pad to the next tab position on 104 the screen 105 106 **********************************************************************/ 107 108 char *display_tab_str(cur_col) 109 int cur_col; /* specifies current cursor column coordinate */ 110 { 111 static char display_string[TAB_SIZE+1]; /* result string to pass back */ 112 int n_spaces; /* number of spaces to pad */ 113 register int i; /* working index */ 114 115 /* if column exceeds right screen edge, assume wrap around to 116 leftmost edge on next line 117 */ 118 if (cur_col >= ss.right) 119 n_spaces = TAB_SIZE; 120 121 /* handle current column within screen */ 122 else { 123 /* calculate padding to next tab column */ 124 n_spaces = TAB_SIZE - ((cur_col - ss.left) % TAB_SIZE); 125 126 /* if exceeds right edge, truncate to get to leftmost 127 column on next line; this handles the case where the 128 screen width is not a multiple of the tab size and 129 guarantees wrap around to the leftmost column 130 */ 131 if (cur_col + n_spaces >= ss.right) 132 n_spaces = ss.right - cur_col + 1; 133 } 134 135 /* initialize the string with the correct number of spaces */ 136 for (i = 0; i < n_spaces; i++) 137 display_string[i] = ' '; 138 139 /* null-terminate the string */ 140 display_string[i] = NUL_TERMINATOR; 141 142 return(display_string); 143 } 144 145 146 /*^L 147 *********************************************************************** 148 149 Routine: DISPLAY_CHAR_PRIM 150 151 Function: 152 This routine displays a character entered from the keyboard in 153 an appropriate representation. It keeps track of cursor position, 154 line wrap arounds and scrolling. 155 156 Parameters: 157 (input/output) pos - pointer to a structure which maintains 158 cursor position information; information is 159 updated after the display 160 (input) ch - specifies the ASCII character to display 161 162 Returns: The number of characters displayed to represent 163 the keyboard character 164 165 **********************************************************************/ 166 167 display_char_prim(pos,ch) 168 CURPOS *pos; /* pointer to structure for keeping track of cursor position */ 169 int ch; /* character to display */ 170 { 171 char *display_char_str(); 172 char *ptr; /* pointer to display string */ 173 int display_length; /* holds length of display string */ 174 175 /* character is the TAB character ? */ 176 if (ch == TAB) 177 /* get the string to display for the tab */ 178 ptr = display_tab_str(pos->cur_col); 179 180 /* not tab, get the string to display for the character */ 181 else 182 ptr = display_char_str(ch); 183 184 /* determine the length of the display string */ 185 display_length = strlen(ptr); 186 187 /* display the display string, keeping track of cursor position */ 188 while (TRUE) { 189 190 /* cursor column past right screen edge */ 191 if (pos->cur_col > ss.right) { 192 193 /* wrap around to left edge */ 194 pos->cur_col = ss.left; 195 196 /* at bottom of screen? */ 197 if (pos->cur_row >= ss.bottom) { 198 199 /* scroll and tally the scroll */ 200 pos->scroll_flag++; 201 wst_scroll(); 202 } 203 204 /* not at bottom of screen, at next line */ 205 else 206 pos->cur_row++; 207 208 /* update the physical cursor */ 209 set_cursor(pos->cur_row,pos->cur_col); 210 } 211 212 /* if NUL terminator reached, exit print loop */ 213 if (!*ptr) break; 214 215 /* display the character */ 216 putch(*ptr); 217 218 /* point to next character in display string */ 219 ptr++; 220 221 /* move the cursor forward */ 222 pos->cur_col++; 223 224 } 225 226 return(display_length); 227 } 228 229 230 /*^L 231 *********************************************************************** 232 233 Routine: REDISPLAY 234 235 Function: 236 This routine redisplays the edited line from a particular 237 position in the line until the end or the end of the screen is 238 reached, whichever is reached first. The fields in the line 239 structure passed to this routine are not directly altered. 240 241 Parameters: 242 (input) line - pointer to the structure containing the 243 line and information about the line being 244 edited 245 (input) pos - specifies what position in the line to 246 begin redisplaying 247 (output) max_row - specifies the integer to pass back 248 the ending row coordinate after the 249 redisplay 250 (output) max_col - specifies the integer to pass back 251 the ending column coordinate after the 252 redisplay 253 254 Returns: NONE 255 256 Note 1 - It is assumed that the physical cursor on the screen is at 257 the line position specified by the parameter 'pos'. 258 **********************************************************************/ 259 260 redisplay(line,pos,max_row,max_col) 261 EDIT_LINE *line; 262 int pos; 263 int *max_row; 264 int *max_col; 265 { 266 char *display_char_str(); 267 char *display_tab_str(); 268 char *ptr; 269 int row; 270 int col; 271 int i; 272 int tmp_row; 273 int tmp_col; 274 275 /* get a working copy of current cursor row and column coordinates */ 276 row = line->cur_row; 277 col = line->cur_col; 278 279 /* check that position in line buffer to start redisplay is valid */ 280 if (pos >= 0 && pos < line->length) { 281 282 /* display each character until end of line */ 283 for (i = pos; i < line->length; i++) { 284 285 /* check if character is a tab */ 286 if (line->line[i] == TAB) 287 /* get tab string and update size of tab */ 288 ptr = display_tab_str(col); 289 290 /* otherwise just get character string */ 291 else 292 ptr = display_char_str(line->line[i]); 293 294 /* phx21233 R.L. - size of 0 means character not echoed and */ 295 /* should not be displayed */ 296 if (line->size[i]) 297 line->size[i] = strlen(ptr); 298 299 else 300 continue; 301 302 /* display character string until NUL terminator reached */ 303 while (*ptr) { 304 305 /* check for wrap around past right edge of screen */ 306 if (check_line_wrap(line,&row,&col,max_row,max_col) < 0) 307 return; 308 309 /* display the current character in the string */ 310 putch(*ptr); 311 312 /* point to next character in the string */ 313 ptr++; 314 315 /* increment cursor position */ 316 col++; 317 318 /* check if a text key was hit */ 319 if (stop_display(line)) { 320 321 /* stop redisplay routine because another character 322 has been entered from the keyboard which will 323 call redisplay again to finish updating the screen 324 */ 325 set_cursor(line->cur_row,line->cur_col); 326 return; 327 } 328 } 329 } 330 331 /* check for wrap around past right edge of screen */ 332 if (check_line_wrap(line,&row,&col,max_row,max_col) < 0) 333 return; 334 } 335 336 /* save ending coordinates (coordinates of where line 337 displayed ends) 338 */ 339 tmp_row = row; 340 tmp_col = col; 341 342 /* reached the end of line, but must pad to ending 343 coordinates with blanks to erase leftover characters 344 */ 345 while (row < line->max_row) { 346 if (col > ss.right) { 347 col = ss.left; 348 row++; 349 set_cursor(row,col); 350 } 351 else { 352 putch(' '); 353 col++; 354 } 355 } 356 357 if (row == line->max_row) { 358 while (col <= line->max_col) { 359 putch(' '); 360 col++; 361 } 362 } 363 364 /* update the physical location of the cursor */ 365 set_cursor(line->cur_row,line->cur_col); 366 *max_row = tmp_row; 367 *max_col = tmp_col; 368 } 369 370 371 372 /*^L 373 *********************************************************************** 374 375 Routine: CHECK_LINE_WRAP 376 377 Function: 378 This routine checks to see if the cursor has gone past the 379 defined right edge of the screen and moves the cursor to the left 380 most column of the next line. If the line is wrapped at the bottom 381 most line of the defined screen area, a flag in the line structure 382 is set and the maximum row and col coordinates of the screen are 383 past back to the caller. 384 385 Parameters: 386 (input) line - pointer to the structure containing the 387 line and information about the line being 388 edited 389 (input/output) row - contains the address of the variable containing 390 the current row coordinates of the cursor 391 (input/output) col - contains the address of the variable containing 392 the current column coordinates of the cursor 393 (output) max_row - this variable is initialized to the 394 maximum screen row coordinate if the line 395 wraps on the last row 396 (output) max_col - this variable is initialized to the 397 maximum screen column coordinate if the 398 line wraps on the last row 399 400 Returns: 0 if screen not completely filled 401 -1 if the line extends beyond the end of the 402 screen 403 404 **********************************************************************/ 405 406 check_line_wrap(line,row,col,max_row,max_col) 407 EDIT_LINE *line; 408 int *row; 409 int *col; 410 int *max_row; 411 int *max_col; 412 { 413 /* check for wrap around past right edge of screen */ 414 if (*col > ss.right) { 415 /* wrap around to left side of screen */ 416 *col = ss.left; 417 418 /* reached bottom of screen? */ 419 if (*row >= ss.bottom) { 420 421 /* update max row and col variables */ 422 *max_row = ss.bottom; 423 *max_col = ss.right; 424 425 /* flag not all characters displayed */ 426 line->off_screen = TRUE; 427 428 /* restore physical cursor position */ 429 set_cursor(line->cur_row,line->cur_col); 430 return(-1); 431 } 432 433 /* not bottom of screen, go to next line */ 434 else 435 (*row)++; 436 437 /* update location of physical cursor */ 438 set_cursor(*row,*col); 439 } 440 return(0); 441 } 442 443 444 /*^L 445 *********************************************************************** 446 447 Routine: STOP_DISPLAY 448 449 Function: 450 This routine is used to optimize screen updates by checking to 451 see if updating of the screen may be stopped before it is 452 completed. This is possible if another key is detected that 453 guarantees the redisplay routine will be called again to update the 454 screen. 455 456 Parameters: 457 (input) line - pointer to the structure containing the 458 line and information about the line being 459 edited 460 461 Returns: TRUE if a key was detected that guarantees a 462 subsequent screen update 463 FALSE otherwise 464 465 **********************************************************************/ 466 467 stop_display(line) 468 EDIT_LINE *line; 469 { 470 int ch; 471 472 /* don't stop update if no key hit or key is not ASCII */ 473 if ((ch = checkkey()) < 0 || ch > ASCII_EXTEND_CODE) return(FALSE); 474 475 switch (ch) { 476 /* kill to beginning of line will update if not already at */ 477 /* beginning of line */ 478 case '@': 479 if (line->index > ZERO_INDEX_VALUE) return(TRUE); 480 return(FALSE); 481 482 /* literal escape or escape does not guarantee subsequent */ 483 /* redisplay */ 484 case '\\': 485 case ESC: 486 return(FALSE); 487 488 /* backspace and delete key redisplays if a character is */ 489 /* deleted */ 490 case BACKSPACE: 491 case DEL_KEY: 492 if (line->index > ZERO_INDEX_VALUE) return(TRUE); 493 return(FALSE); 494 495 /* delete character key redisplays if cursor is before end */ 496 /* of line */ 497 case CTRL_D: 498 if (line->index < line->length) return(TRUE); 499 return(FALSE); 500 501 /* kill to end of line redisplays if not already at end of */ 502 /* line */ 503 case CTRL_K: 504 if (line->index < line->length) return(TRUE); 505 return(FALSE); 506 507 default: 508 509 /* if not a tab and not a printable character, may not */ 510 /* force a redraw */ 511 if (ch != TAB && 512 (ch < MIN_PRINTABLE_ASCII || ch > MAX_PRINTABLE_ASCII)) 513 return(FALSE); 514 515 /* a printable character; if in replace mode, redraws */ 516 /* if not at end of line */ 517 if (line->mode) { 518 if (line->length < MAX_LINE_SIZE) return(TRUE); 519 return(FALSE); 520 } 521 522 /* in insert mode, redraws if maximum line size has */ 523 /* not been reached */ 524 else { 525 if (line->index < MAX_LINE_SIZE) return(TRUE); 526 return(FALSE); 527 } 528 } 529 } 530 531 532 /*^L 533 *********************************************************************** 534 535 Routine: GET_ECHOED_INPUT 536 537 Function: 538 This routine is used to extract echoed input from a specified 539 part of the edit-mode input line buffer. Only characters echoed will 540 be extracted. The results are passed back in a static string, along 541 with the length of the extracted input item. 542 543 Parameters: 544 (input) line - pointer to the structure containing the 545 line and information about the line being 546 edited 547 (input) item_pos - index to position in line buffer 548 to begin extracting 549 (input) item_size - number of characters in line buffer 550 from which to extract 551 (output) display_str - pointer to the string extracted 552 (output) display_len - length of string extract 553 554 Returns: None 555 556 **********************************************************************/ 557 558 get_echoed_input(line,item_pos,item_size,display_str,display_len) 559 EDIT_LINE *line; 560 int item_pos; 561 int item_size; 562 char **display_str; 563 int *display_len; 564 { 565 static char echoed_str[MAX_LINE_SIZE+1]; 566 register int i; 567 register int count; 568 569 /* ensure specified position for extraction is valid */ 570 if (item_pos > line->length) item_pos = line->length; 571 else if (item_pos < 0) item_pos = 0; 572 573 /* ensure specified number of chars for extraction is valid */ 574 if (item_pos+item_size > line->length) 575 item_size = line->length - item_pos; 576 577 /* tally and copy over the echoed input characters from input buffer */ 578 count = 0; 579 for (i = item_pos; i < item_size; i++) 580 /* if represented by at least 1 character */ 581 if (line->size[i] > 0) 582 echoed_str[count++] = line->line[i]; 583 echoed_str[count] = 0; 584 585 /* pass back the results */ 586 *display_str = echoed_str; 587 *display_len = count; 588 } 589 590 591 592 /*^L 593 *********************************************************************** 594 595 Routine: DISPLAY_CHAR 596 597 Function: 598 This routine displays a character entered from the keyboard in 599 an appropriate representation by calling display_char_prim() if 600 keyboard echoing is enabled. If echoing is disabled, nothing is 601 displayed and 0 is returned. 602 603 Parameters: 604 (input/output) pos - pointer to a structure which maintains 605 cursor position information; information is 606 updated after the display 607 (input) ch - specifies the ASCII character to display 608 609 Returns: The number of characters displayed to represent 610 the keyboard character if keyboard echoing enabled 611 0 if keyboard character echoing is disabled 612 613 **********************************************************************/ 614 615 display_char(pos,ch) 616 CURPOS *pos; /* pointer to structure for keeping track of cursor position */ 617 int ch; /* character to display */ 618 { 619 if (!kb.echo) 620 return(0); 621 622 return(display_char_prim(pos,ch)); 623 } 624