Commit | Line | Data |
---|---|---|
15637ed4 RG |
1 | /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ |
2 | /* hack.termcap.c - version 1.0.3 */ | |
3 | ||
4 | #include <stdio.h> | |
5 | #include "config.h" /* for ROWNO and COLNO */ | |
6 | #include "def.flag.h" /* for flags.nonull */ | |
7 | extern char *tgetstr(), *tgoto(), *getenv(); | |
8 | extern long *alloc(); | |
9 | ||
10 | #ifndef lint | |
11 | extern /* it is defined in libtermlib (libtermcap) */ | |
12 | #endif lint | |
13 | short ospeed; /* terminal baudrate; used by tputs */ | |
14 | static char tbuf[512]; | |
15 | static char *HO, *CL, *CE, *UP, *CM, *ND, *XD, *BC, *SO, *SE, *TI, *TE; | |
16 | static char *VS, *VE; | |
17 | static int SG; | |
18 | static char PC = '\0'; | |
19 | char *CD; /* tested in pri.c: docorner() */ | |
20 | int CO, LI; /* used in pri.c and whatis.c */ | |
21 | ||
22 | startup() | |
23 | { | |
24 | register char *term; | |
25 | register char *tptr; | |
26 | char *tbufptr, *pc; | |
27 | ||
28 | tptr = (char *) alloc(1024); | |
29 | ||
30 | tbufptr = tbuf; | |
31 | if(!(term = getenv("TERM"))) | |
32 | error("Can't get TERM."); | |
33 | if(!strncmp(term, "5620", 4)) | |
34 | flags.nonull = 1; /* this should be a termcap flag */ | |
35 | if(tgetent(tptr, term) < 1) | |
36 | error("Unknown terminal type: %s.", term); | |
37 | if(pc = tgetstr("pc", &tbufptr)) | |
38 | PC = *pc; | |
39 | if(!(BC = tgetstr("bc", &tbufptr))) { | |
40 | if(!tgetflag("bs")) | |
41 | error("Terminal must backspace."); | |
42 | BC = tbufptr; | |
43 | tbufptr += 2; | |
44 | *BC = '\b'; | |
45 | } | |
46 | HO = tgetstr("ho", &tbufptr); | |
47 | CO = tgetnum("co"); | |
48 | LI = tgetnum("li"); | |
49 | if(CO < COLNO || LI < ROWNO+2) | |
50 | setclipped(); | |
51 | if(!(CL = tgetstr("cl", &tbufptr))) | |
52 | error("Hack needs CL."); | |
53 | ND = tgetstr("nd", &tbufptr); | |
54 | if(tgetflag("os")) | |
55 | error("Hack can't have OS."); | |
56 | CE = tgetstr("ce", &tbufptr); | |
57 | UP = tgetstr("up", &tbufptr); | |
58 | /* It seems that xd is no longer supported, and we should use | |
59 | a linefeed instead; unfortunately this requires resetting | |
60 | CRMOD, and many output routines will have to be modified | |
61 | slightly. Let's leave that till the next release. */ | |
62 | XD = tgetstr("xd", &tbufptr); | |
63 | /* not: XD = tgetstr("do", &tbufptr); */ | |
64 | if(!(CM = tgetstr("cm", &tbufptr))) { | |
65 | if(!UP && !HO) | |
66 | error("Hack needs CM or UP or HO."); | |
67 | printf("Playing hack on terminals without cm is suspect...\n"); | |
68 | getret(); | |
69 | } | |
70 | SO = tgetstr("so", &tbufptr); | |
71 | SE = tgetstr("se", &tbufptr); | |
72 | SG = tgetnum("sg"); /* -1: not fnd; else # of spaces left by so */ | |
73 | if(!SO || !SE || (SG > 0)) SO = SE = 0; | |
74 | CD = tgetstr("cd", &tbufptr); | |
75 | set_whole_screen(); /* uses LI and CD */ | |
76 | if(tbufptr-tbuf > sizeof(tbuf)) error("TERMCAP entry too big...\n"); | |
77 | free(tptr); | |
78 | } | |
79 | ||
80 | start_screen() | |
81 | { | |
82 | xputs(TI); | |
83 | xputs(VS); | |
84 | } | |
85 | ||
86 | end_screen() | |
87 | { | |
88 | xputs(VE); | |
89 | xputs(TE); | |
90 | } | |
91 | ||
92 | /* Cursor movements */ | |
93 | extern xchar curx, cury; | |
94 | ||
95 | curs(x, y) | |
96 | register int x, y; /* not xchar: perhaps xchar is unsigned and | |
97 | curx-x would be unsigned as well */ | |
98 | { | |
99 | ||
100 | if (y == cury && x == curx) | |
101 | return; | |
102 | if(!ND && (curx != x || x <= 3)) { /* Extremely primitive */ | |
103 | cmov(x, y); /* bunker!wtm */ | |
104 | return; | |
105 | } | |
106 | if(abs(cury-y) <= 3 && abs(curx-x) <= 3) | |
107 | nocmov(x, y); | |
108 | else if((x <= 3 && abs(cury-y)<= 3) || (!CM && x<abs(curx-x))) { | |
109 | (void) putchar('\r'); | |
110 | curx = 1; | |
111 | nocmov(x, y); | |
112 | } else if(!CM) { | |
113 | nocmov(x, y); | |
114 | } else | |
115 | cmov(x, y); | |
116 | } | |
117 | ||
118 | nocmov(x, y) | |
119 | { | |
120 | if (cury > y) { | |
121 | if(UP) { | |
122 | while (cury > y) { /* Go up. */ | |
123 | xputs(UP); | |
124 | cury--; | |
125 | } | |
126 | } else if(CM) { | |
127 | cmov(x, y); | |
128 | } else if(HO) { | |
129 | home(); | |
130 | curs(x, y); | |
131 | } /* else impossible("..."); */ | |
132 | } else if (cury < y) { | |
133 | if(XD) { | |
134 | while(cury < y) { | |
135 | xputs(XD); | |
136 | cury++; | |
137 | } | |
138 | } else if(CM) { | |
139 | cmov(x, y); | |
140 | } else { | |
141 | while(cury < y) { | |
142 | xputc('\n'); | |
143 | curx = 1; | |
144 | cury++; | |
145 | } | |
146 | } | |
147 | } | |
148 | if (curx < x) { /* Go to the right. */ | |
149 | if(!ND) cmov(x, y); else /* bah */ | |
150 | /* should instead print what is there already */ | |
151 | while (curx < x) { | |
152 | xputs(ND); | |
153 | curx++; | |
154 | } | |
155 | } else if (curx > x) { | |
156 | while (curx > x) { /* Go to the left. */ | |
157 | xputs(BC); | |
158 | curx--; | |
159 | } | |
160 | } | |
161 | } | |
162 | ||
163 | cmov(x, y) | |
164 | register x, y; | |
165 | { | |
166 | xputs(tgoto(CM, x-1, y-1)); | |
167 | cury = y; | |
168 | curx = x; | |
169 | } | |
170 | ||
171 | xputc(c) char c; { | |
172 | (void) fputc(c, stdout); | |
173 | } | |
174 | ||
175 | xputs(s) char *s; { | |
176 | tputs(s, 1, xputc); | |
177 | } | |
178 | ||
179 | cl_end() { | |
180 | if(CE) | |
181 | xputs(CE); | |
182 | else { /* no-CE fix - free after Harold Rynes */ | |
183 | /* this looks terrible, especially on a slow terminal | |
184 | but is better than nothing */ | |
185 | register cx = curx, cy = cury; | |
186 | ||
187 | while(curx < COLNO) { | |
188 | xputc(' '); | |
189 | curx++; | |
190 | } | |
191 | curs(cx, cy); | |
192 | } | |
193 | } | |
194 | ||
195 | clear_screen() { | |
196 | xputs(CL); | |
197 | curx = cury = 1; | |
198 | } | |
199 | ||
200 | home() | |
201 | { | |
202 | if(HO) | |
203 | xputs(HO); | |
204 | else if(CM) | |
205 | xputs(tgoto(CM, 0, 0)); | |
206 | else | |
207 | curs(1, 1); /* using UP ... */ | |
208 | curx = cury = 1; | |
209 | } | |
210 | ||
211 | standoutbeg() | |
212 | { | |
213 | if(SO) xputs(SO); | |
214 | } | |
215 | ||
216 | standoutend() | |
217 | { | |
218 | if(SE) xputs(SE); | |
219 | } | |
220 | ||
221 | backsp() | |
222 | { | |
223 | xputs(BC); | |
224 | curx--; | |
225 | } | |
226 | ||
227 | bell() | |
228 | { | |
229 | (void) putchar('\007'); /* curx does not change */ | |
230 | (void) fflush(stdout); | |
231 | } | |
232 | ||
233 | static short tmspc10[] = { /* from termcap */ | |
234 | 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5 | |
235 | }; | |
236 | ||
237 | delay_output() { | |
238 | /* delay 50 ms - could also use a 'nap'-system call */ | |
239 | /* BUG: if the padding character is visible, as it is on the 5620 | |
240 | then this looks terrible. */ | |
241 | if(!flags.nonull) | |
242 | tputs("50", 1, xputc); | |
243 | ||
244 | /* cbosgd!cbcephus!pds for SYS V R2 */ | |
245 | /* is this terminfo, or what? */ | |
246 | /* tputs("$<50>", 1, xputc); */ | |
247 | ||
248 | else if(ospeed > 0 || ospeed < SIZE(tmspc10)) if(CM) { | |
249 | /* delay by sending cm(here) an appropriate number of times */ | |
250 | register int cmlen = strlen(tgoto(CM, curx-1, cury-1)); | |
251 | register int i = 500 + tmspc10[ospeed]/2; | |
252 | ||
253 | while(i > 0) { | |
254 | cmov(curx, cury); | |
255 | i -= cmlen*tmspc10[ospeed]; | |
256 | } | |
257 | } | |
258 | } | |
259 | ||
260 | cl_eos() /* free after Robert Viduya */ | |
261 | { /* must only be called with curx = 1 */ | |
262 | ||
263 | if(CD) | |
264 | xputs(CD); | |
265 | else { | |
266 | register int cx = curx, cy = cury; | |
267 | while(cury <= LI-2) { | |
268 | cl_end(); | |
269 | xputc('\n'); | |
270 | curx = 1; | |
271 | cury++; | |
272 | } | |
273 | cl_end(); | |
274 | curs(cx, cy); | |
275 | } | |
276 | } |