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