1: /*
   2:  * curses.c
   3:  *
   4:  * This source herein may be modified and/or distributed by anybody who
   5:  * so desires, with the following restrictions:
   6:  *    1.)  No portion of this notice shall be removed.
   7:  *    2.)  Credit shall not be taken for the creation of this source.
   8:  *    3.)  This code is not to be traded, sold, or used for personal
   9:  *         gain or profit.
  10:  *
  11:  */
  12: 
  13: #ifndef lint
  14: static char sccsid[] = "@(#)curses.c	5.1 (Berkeley) 11/25/87";
  15: #endif /* not lint */
  16: 
  17: #ifdef CURSES
  18: 
  19: /* The following is a curses emulation package suitable for the rogue program
  20:  * in which it is included.  No other suitability is claimed or suspected.
  21:  * Only those routines currently needed by this rogue program are included.
  22:  * This is being provided for those systems that don't have a suitable
  23:  * curses package and want to run this rogue program.
  24:  *
  25:  * Compile the entire program with -DCURSES to incorporate this package.
  26:  *
  27:  * The following is NOT supported:
  28:  *   "%D", "%B", "%n", or "%>" inside a cursor motion (cm) termcap string.
  29:  *   Terminals in which the cursor motion addresses the row differently from
  30:  *       the column, as in ":cm=\E%2,%3" or ":cm=\EY%+x;%+y"
  31:  *   Termcap database stored in the TERMCAP environ variable as returned
  32:  *       from md_getenv().  Only the termcap file name can be stored there.
  33:  *       See the comments for md_getenv() in machdep.c.
  34:  *   Terminals without non-destructive backspace.  Backspace (^H) is used
  35:  *       for cursor motion regardless of any termcap entries.
  36:  *   The ":tc=" termcap entry is ignored.
  37:  *
  38:  * Suggestions:
  39:  *   Use line-feed as your termcap "do" entry: ":do=^J", ":do=\012" or
  40:  *      ":do=\n"  This will help cursor motion optimization.  If line-feed
  41:  *      won't work, then a short escape sequence will do.
  42:  */
  43: 
  44: #include <stdio.h>
  45: #include "rogue.h"
  46: 
  47: boolean tc_tname();
  48: 
  49: #define BS 010
  50: #define LF 012
  51: #define CR 015
  52: #define ESC '\033'
  53: #define TAB '\011'
  54: 
  55: #define ST_MASK 0x80
  56: #define BUFLEN 256
  57: 
  58: char terminal[DROWS][DCOLS];
  59: char buffer[DROWS][DCOLS];
  60: char *tc_file;
  61: 
  62: char cm_esc[16];
  63: char cm_sep[16];
  64: char cm_end[16];
  65: boolean cm_reverse = 0;
  66: boolean cm_two = 0;
  67: boolean cm_three = 0;
  68: boolean cm_char = 0;
  69: short cm_inc = 0;
  70: 
  71: boolean screen_dirty;
  72: boolean lines_dirty[DROWS];
  73: boolean buf_stand_out = 0;
  74: boolean term_stand_out = 0;
  75: 
  76: int LINES = DROWS;
  77: int COLS = DCOLS;
  78: WINDOW scr_buf;
  79: WINDOW *curscr = &scr_buf;
  80: 
  81: char *CL = (char *) 0;
  82: char *CM = (char *) 0;
  83: char *UC = (char *) 0;  /* UP */
  84: char *DO = (char *) 0;
  85: char *VS = "";
  86: char *VE = "";
  87: char *TI = "";
  88: char *TE = "";
  89: char *SO = "";
  90: char *SE = "";
  91: 
  92: short cur_row;
  93: short cur_col;
  94: 
  95: initscr()
  96: {
  97:     clear();
  98:     get_term_info();
  99:     printf("%s%s", TI, VS);
 100: }
 101: 
 102: endwin()
 103: {
 104:     printf("%s%s", TE, VE);
 105:     md_cbreak_no_echo_nonl(0);
 106: }
 107: 
 108: move(row, col)
 109: short row, col;
 110: {
 111:     curscr->_cury = row;
 112:     curscr->_curx = col;
 113:     screen_dirty = 1;
 114: }
 115: 
 116: mvaddstr(row, col, str)
 117: short row, col;
 118: char *str;
 119: {
 120:     move(row, col);
 121:     addstr(str);
 122: }
 123: 
 124: addstr(str)
 125: char *str;
 126: {
 127:     while (*str) {
 128:         addch((int) *str++);
 129:     }
 130: }
 131: 
 132: addch(ch)
 133: register int ch;
 134: {
 135:     short row, col;
 136: 
 137:     row = curscr->_cury;
 138:     col = curscr->_curx++;
 139: 
 140:     if (buf_stand_out) {
 141:         ch |= ST_MASK;
 142:     }
 143:     buffer[row][col] = (char) ch;
 144:     lines_dirty[row] = 1;
 145:     screen_dirty = 1;
 146: }
 147: 
 148: mvaddch(row, col, ch)
 149: short row, col;
 150: int ch;
 151: {
 152:     move(row, col);
 153:     addch(ch);
 154: }
 155: 
 156: refresh()
 157: {
 158:     register i, j, line;
 159:     short old_row, old_col, first_row;
 160: 
 161:     if (screen_dirty) {
 162: 
 163:         old_row = curscr->_cury;
 164:         old_col = curscr->_curx;
 165:         first_row = cur_row;
 166: 
 167:         for (i = 0; i < DROWS; i++) {
 168:             line = (first_row + i) % DROWS;
 169:             if (lines_dirty[line]) {
 170:                 for (j = 0; j < DCOLS; j++) {
 171:                     if (buffer[line][j] != terminal[line][j]) {
 172:                         put_char_at(line, j, buffer[line][j]);
 173:                     }
 174:                 }
 175:                 lines_dirty[line] = 0;
 176:             }
 177:         }
 178:         put_cursor(old_row, old_col);
 179:         screen_dirty = 0;
 180:         fflush(stdout);
 181:     }
 182: }
 183: 
 184: wrefresh(scr)
 185: WINDOW *scr;
 186: {
 187:     short i, col;
 188: 
 189:     printf("%s", CL);
 190:     cur_row = cur_col = 0;
 191: 
 192:     for (i = 0; i < DROWS; i++) {
 193:         col = 0;
 194:         while (col < DCOLS) {
 195:             while ((col < DCOLS) && (buffer[i][col] == ' ')) {
 196:                 col++;
 197:             }
 198:             if (col < DCOLS) {
 199:                 put_cursor(i, col);
 200:             }
 201:             while ((col < DCOLS) && (buffer[i][col] != ' ')) {
 202:                 put_st_char((int) buffer[i][col]);
 203:                 cur_col++;
 204:                 col++;
 205:             }
 206:         }
 207:     }
 208:     put_cursor(curscr->_cury, curscr->_curx);
 209:     fflush(stdout);
 210:     scr = scr;      /* make lint happy */
 211: }
 212: 
 213: mvinch(row, col)
 214: short row, col;
 215: {
 216:     move(row, col);
 217:     return((int) buffer[row][col]);
 218: }
 219: 
 220: clear()
 221: {
 222:     printf("%s", CL);
 223:     fflush(stdout);
 224:     cur_row = cur_col = 0;
 225:     move(0, 0);
 226:     clear_buffers();
 227: }
 228: 
 229: clrtoeol()
 230: {
 231:     short row, col;
 232: 
 233:     row = curscr->_cury;
 234: 
 235:     for (col = curscr->_curx; col < DCOLS; col++) {
 236:         buffer[row][col] = ' ';
 237:     }
 238:     lines_dirty[row] = 1;
 239: }
 240: 
 241: standout()
 242: {
 243:     buf_stand_out = 1;
 244: }
 245: 
 246: standend()
 247: {
 248:     buf_stand_out = 0;
 249: }
 250: 
 251: crmode()
 252: {
 253:     md_cbreak_no_echo_nonl(1);
 254: }
 255: 
 256: noecho()
 257: {
 258:     /* crmode() takes care of this */
 259: }
 260: 
 261: nonl()
 262: {
 263:     /* crmode() takes care of this */
 264: }
 265: 
 266: clear_buffers()
 267: {
 268:     register i, j;
 269: 
 270:     screen_dirty = 0;
 271: 
 272:     for (i = 0; i < DROWS; i++) {
 273:         lines_dirty[i] = 0;
 274:         for (j = 0; j < DCOLS; j++) {
 275:             terminal[i][j] = ' ';
 276:             buffer[i][j] = ' ';
 277:         }
 278:     }
 279: }
 280: 
 281: put_char_at(row, col, ch)
 282: register row, col, ch;
 283: {
 284:     put_cursor(row, col);
 285:     put_st_char(ch);
 286:     terminal[row][col] = (char) ch;
 287:     cur_col++;
 288: }
 289: 
 290: put_cursor(row, col)
 291: register row, col;
 292: {
 293:     register i, rdif, cdif;
 294:     short ch, t;
 295: 
 296:     rdif = (row > cur_row) ? row - cur_row : cur_row - row;
 297:     cdif = (col > cur_col) ? col - cur_col : cur_col - col;
 298: 
 299:     if (((row > cur_row) && DO) || ((cur_row > row) && UC)) {
 300:         if ((rdif < 4) && (cdif < 4)) {
 301:             for (i = 0; i < rdif; i++) {
 302:                 printf("%s", ((row < cur_row) ? UC : DO));
 303:             }
 304:             cur_row = row;
 305:             if (col == cur_col) {
 306:                 return;
 307:             }
 308:         }
 309:     }
 310:     if (row == cur_row) {
 311:         if (cdif <= 6) {
 312:         for (i = 0; i < cdif; i++) {
 313:                 ch = (col < cur_col) ? BS :
 314:                         terminal[row][cur_col + i];
 315:                 put_st_char((int) ch);
 316:             }
 317:             cur_row = row;
 318:             cur_col = col;
 319:             return;
 320:         }
 321:     }
 322:     cur_row = row;
 323:     cur_col = col;
 324: 
 325:     row += cm_inc;
 326:     col += cm_inc;
 327: 
 328:     if (cm_reverse) {
 329:         t = row;
 330:         row = col;
 331:         col = t;
 332:     }
 333:     if (cm_two) {
 334:         printf("%s%02d%s%02d%s", cm_esc, row, cm_sep, col, cm_end);
 335:     } else if (cm_three) {
 336:         printf("%s%03d%s%03d%s", cm_esc, row, cm_sep, col, cm_end);
 337:     } else if (cm_char) {
 338:         printf("%s%c%s%c%s", cm_esc, row, cm_sep, col, cm_end);
 339:     } else {
 340:         printf("%s%d%s%d%s", cm_esc, row, cm_sep, col, cm_end);
 341:     }
 342: }
 343: 
 344: put_st_char(ch)
 345: register ch;
 346: {
 347:     if ((ch & ST_MASK) && (!term_stand_out)) {
 348:         ch &= ~ST_MASK;
 349:         printf("%s%c", SO, ch);
 350:         term_stand_out = 1;
 351:     } else if ((!(ch & ST_MASK)) && term_stand_out) {
 352:         printf("%s%c", SE, ch);
 353:         term_stand_out = 0;
 354:     } else {
 355:         ch &= ~ST_MASK;
 356:         putchar(ch);
 357:     }
 358: }
 359: 
 360: get_term_info()
 361: {
 362:     FILE *fp;
 363:     char *term, *tcf;
 364:     char buf[BUFLEN];
 365: 
 366:     if (tcf = md_getenv("TERMCAP")) {
 367:         if (strlen(tcf) > 40) {
 368:             clean_up("TERMCAP file name too long");
 369:         }
 370:         tc_file = tcf;
 371:     } else {
 372:         if (!(tc_file = md_gdtcf())) {
 373:             clean_up("I need a termcap file");
 374:         }
 375:     }
 376: 
 377:     if (!(term = md_getenv("TERM"))) {
 378:         clean_up("Cannot find TERM variable in environ");
 379:     }
 380:     if ((fp = fopen(tc_file, "r")) == NULL) {
 381:         sprintf(buf, "Cannot open TERMCAP file: %s", tc_file);
 382:         clean_up(buf);
 383:     }
 384: 
 385:     if (!tc_tname(fp, term, buf)) {
 386:         sprintf(buf, "Cannot find TERM type: %s in TERMCAP file: %s", term,
 387:             tc_file);
 388:         clean_up(buf);
 389:     }
 390:     tc_gtdata(fp, buf);
 391:     fclose(fp);
 392: }
 393: 
 394: boolean
 395: tc_tname(fp, term, buf)
 396: FILE *fp;
 397: char *term;
 398: char *buf;
 399: {
 400:     short i, j;
 401:     boolean found = 0;
 402:     char *fg;
 403: 
 404:     while (!found) {
 405:         i = 0;
 406:         fg = fgets(buf, BUFLEN, fp);
 407:         if (fg != NULL) {
 408:             if (    (buf[0] != '#') && (buf[0] != ' ') && (buf[0] != TAB) &&
 409:                     (buf[0] != CR) && (buf[0] != LF)) {
 410:                 while (buf[i] && (!found)) {
 411:                     j = 0;
 412:                     while (buf[i] == term[j]) {
 413:                         i++;
 414:                         j++;
 415:                     }
 416:                     if ((!term[j]) && ((buf[i] == '|') || (buf[i] == ':'))) {
 417:                         found = 1;
 418:                     } else {
 419:                         while (buf[i] && (buf[i] != '|') && (buf[i] != ':')) {
 420:                             i++;
 421:                         }
 422:                         if (buf[i]) {
 423:                             i++;
 424:                         }
 425:                     }
 426:                 }
 427:             }
 428:         } else {
 429:             break;
 430:         }
 431:     }
 432:     return(found);
 433: }
 434: 
 435: tc_gtdata(fp, buf)
 436: FILE *fp;
 437: char *buf;
 438: {
 439:     short i;
 440:     boolean first = 1;
 441: 
 442:     do {
 443:         if (!first) {
 444:             if ((buf[0] != TAB) && (buf[0] != ' ')) {
 445:                 break;
 446:             }
 447:         }
 448:         first = 0;
 449:         i = 0;
 450:         while (buf[i]) {
 451:             while (buf[i] && (buf[i] != ':')) {
 452:                 i++;
 453:             }
 454:             if (buf[i] == ':') {
 455:                 if (!strncmp(buf + i, ":cl=", 4)) {
 456:                     tc_gets(buf + i, &CL);
 457:                 } else if (!strncmp(buf + i, ":cm=", 4)) {
 458:                     tc_gets(buf + i, &CM);
 459:                 } else if (!strncmp(buf + i, ":up=", 4)) {
 460:                     tc_gets(buf + i, &UC);
 461:                 } else if (!strncmp(buf + i, ":do=", 4)) {
 462:                     tc_gets(buf + i, &DO);
 463:                 } else if (!strncmp(buf + i, ":vs=", 4)) {
 464:                     tc_gets(buf + i, &VS);
 465:                 } else if (!strncmp(buf + i, ":ve=", 4)) {
 466:                     tc_gets(buf + i, &VE);
 467:                 } else if (!strncmp(buf + i, ":ti=", 4)) {
 468:                     tc_gets(buf + i, &TI);
 469:                 } else if (!strncmp(buf + i, ":te=", 4)) {
 470:                     tc_gets(buf + i, &TE);
 471:                 } else if (!strncmp(buf + i, ":vs=", 4)) {
 472:                     tc_gets(buf + i, &VS);
 473:                 } else if (!strncmp(buf + i, ":ve=", 4)) {
 474:                     tc_gets(buf + i, &VE);
 475:                 } else if (!strncmp(buf + i, ":so=", 4)) {
 476:                     tc_gets(buf + i, &SO);
 477:                 } else if (!strncmp(buf + i, ":se=", 4)) {
 478:                     tc_gets(buf + i, &SE);
 479:                 } else if (!strncmp(buf + i, ":li#", 4)) {
 480:                     tc_gnum(buf + i, &LINES);
 481:                 } else if (!strncmp(buf + i, ":co#", 4)) {
 482:                     tc_gnum(buf + i, &COLS);
 483:                 }
 484:                 i++;
 485:             }
 486:         }
 487:     } while (fgets(buf, BUFLEN, fp) != NULL);
 488: 
 489:     if ((!CM) || (!CL)) {
 490:         clean_up("Terminal and termcap must have cm and cl");
 491:     }
 492:     tc_cmget();
 493: }
 494: 
 495: tc_gets(ibuf, tcstr)
 496: char *ibuf;
 497: char **tcstr;
 498: {
 499:     short i, j, k, n;
 500:     char obuf[BUFLEN];
 501: 
 502:     i = 4;
 503:     j = 0;
 504: 
 505:     while (ibuf[i] && is_digit(ibuf[i])) {
 506:         i++;
 507:     }
 508: 
 509:     while (ibuf[i] && (ibuf[i] != ':')) {
 510:         if (ibuf[i] == '\\') {
 511:             i++;
 512:             switch(ibuf[i]) {
 513:             case 'E':
 514:                 obuf[j] = ESC;
 515:                 i++;
 516:                 break;
 517:             case 'n':
 518:                 obuf[j] = LF;
 519:                 i++;
 520:                 break;
 521:             case 'r':
 522:                 obuf[j] = CR;
 523:                 i++;
 524:                 break;
 525:             case 'b':
 526:                 obuf[j] = BS;
 527:                 i++;
 528:                 break;
 529:             case 't':
 530:                 obuf[j] = TAB;
 531:                 i++;
 532:                 break;
 533:             case '0':
 534:             case '1':
 535:             case '2':
 536:             case '3':
 537:             case '4':
 538:             case '5':
 539:             case '6':
 540:             case '7':
 541:             case '8':
 542:             case '9':
 543:                 n = 0;
 544:                 k = 0;
 545:                 while (k < 3 && ibuf[i] && is_digit(ibuf[i])) {
 546:                     n = (8 * n) + (ibuf[i] - '0');
 547:                     i++;
 548:                     k++;
 549:                 }
 550:                 obuf[j] = (char) n;
 551:                 break;
 552:             default:
 553:                 obuf[j] = ibuf[i];
 554:                 i++;
 555:             }
 556:         } else if (ibuf[i] == '^') {
 557:             obuf[j] = ibuf[i+1] - 64;
 558:             i += 2;
 559:         } else {
 560:             obuf[j] = ibuf[i++];
 561:         }
 562:         j++;
 563:     }
 564:     obuf[j] = 0;
 565:     if (!(*tcstr = md_malloc(j + 1))) {
 566:         clean_up("cannot alloc() memory");
 567:     }
 568:     (void) strcpy(*tcstr, obuf);
 569: }
 570: 
 571: tc_gnum(ibuf, n)
 572: char *ibuf;
 573: int *n;
 574: {
 575:     short i;
 576:     int r = 0;
 577: 
 578:     i = 4;
 579: 
 580:     while (is_digit(ibuf[i])) {
 581:         r = (r * 10) + (ibuf[i] - '0');
 582:         i++;
 583:     }
 584:     *n = r;
 585: }
 586: 
 587: tstp()
 588: {
 589:     endwin();
 590:     md_tstp();
 591: 
 592:     start_window();
 593:     printf("%s%s", TI, VS);
 594:     wrefresh(curscr);
 595:     md_slurp();
 596: }
 597: 
 598: tc_cmget()
 599: {
 600:     short i = 0, j = 0, rc_spec = 0;
 601: 
 602:     while (CM[i] && (CM[i] != '%') && (j < 15)) {
 603:         cm_esc[j++] = CM[i++];
 604:     }
 605:     cm_esc[j] = 0;
 606: 
 607:     while (CM[i] && (rc_spec < 2)) {
 608:         if (CM[i] == '%') {
 609:             i++;
 610:             switch(CM[i]) {
 611:             case 'd':
 612:                 rc_spec++;
 613:                 break;
 614:             case 'i':
 615:                 cm_inc = 1;
 616:                 break;
 617:             case '2':
 618:                 cm_two = 1;
 619:                 rc_spec++;
 620:                 break;
 621:             case '3':
 622:                 cm_three = 1;
 623:                 rc_spec++;
 624:                 break;
 625:             case '.':
 626:                 cm_char = 1;
 627:                 rc_spec++;
 628:                 break;
 629:             case 'r':
 630:                 cm_reverse = 1;
 631:                 break;
 632:             case '+':
 633:                 i++;
 634:                 cm_inc = CM[i];
 635:                 cm_char = 1;
 636:                 rc_spec++;
 637:                 break;
 638:             }
 639:             i++;
 640:         } else {
 641:             j = 0;
 642:             while (CM[i] && (CM[i] != '%')) {
 643:                 cm_sep[j++] = CM[i++];
 644:             }
 645:             cm_sep[j] = 0;
 646:         }
 647:     }
 648: 
 649:     j = 0;
 650:     if (rc_spec == 2) {
 651:         while (CM[i] && (j < 15)) {
 652:             cm_end[j++] = CM[i++];
 653:         }
 654:     }
 655:     cm_end[j] = 0;
 656: }
 657: 
 658: #endif

Defined functions

addch defined in line 132; never used
addstr defined in line 124; never used
clear defined in line 220; never used
clear_buffers defined in line 266; used 1 times
clrtoeol defined in line 229; never used
crmode defined in line 251; never used
endwin defined in line 102; used 2 times
get_term_info defined in line 360; used 1 times
  • in line 98
initscr defined in line 95; used 1 times
move defined in line 108; never used
mvaddch defined in line 148; never used
mvaddstr defined in line 116; never used
mvinch defined in line 213; never used
noecho defined in line 256; never used
nonl defined in line 261; never used
put_char_at defined in line 281; used 1 times
put_cursor defined in line 290; used 4 times
put_st_char defined in line 344; used 3 times
refresh defined in line 156; never used
standend defined in line 246; never used
standout defined in line 241; never used
tc_cmget defined in line 598; used 1 times
tc_gets defined in line 495; used 12 times
tc_gnum defined in line 571; used 2 times
tc_gtdata defined in line 435; used 1 times
tc_tname defined in line 394; used 2 times
tstp defined in line 587; used 1 times
wrefresh defined in line 184; used 3 times

Defined variables

CL defined in line 81; used 4 times
CM defined in line 82; used 14 times
COLS defined in line 77; used 1 times
DO defined in line 84; used 3 times
LINES defined in line 76; used 1 times
SE defined in line 90; used 2 times
SO defined in line 89; used 2 times
TE defined in line 88; used 2 times
TI defined in line 87; used 3 times
UC defined in line 83; used 3 times
VE defined in line 86; used 3 times
VS defined in line 85; used 4 times
buffer defined in line 59; used 9 times
cm_end defined in line 64; used 6 times
cm_esc defined in line 62; used 6 times
cm_inc defined in line 69; used 4 times
cm_sep defined in line 63; used 6 times
cur_col defined in line 93; used 12 times
cur_row defined in line 92; used 13 times
curscr defined in line 79; used 11 times
sccsid defined in line 14; never used
scr_buf defined in line 78; used 1 times
  • in line 79
tc_file defined in line 60; used 5 times
terminal defined in line 58; used 4 times

Defined macros

BS defined in line 49; used 2 times
BUFLEN defined in line 56; used 4 times
CR defined in line 51; used 2 times
ESC defined in line 52; used 1 times
LF defined in line 50; used 2 times
ST_MASK defined in line 55; used 5 times
TAB defined in line 53; used 3 times
Last modified: 1987-11-26
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5201
Valid CSS Valid XHTML 1.0 Strict