|
|
1.1 root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.