1 /* ibmpc/ms_ansi.c: a set of routines to provide either PCcurses or ANSI output
2
3 Copyright (c) 1989-94 James E. Wilson, Don Kneller
4
5 This software may be copied and distributed for educational, research, and
6 not for profit purposes provided that this copyright and statement are
7 included in all such copies. */
8
9 #include <curses.h>
10 #include <stdio.h>
11
12 #if defined(MSDOS) && defined(ANSI)
13
14 #ifdef LINT_ARGS
15 static int curses_move(int, int);
16 static char *getent(char *,char * *,int );
17 static void initansistr(void);
18 static int ansi_initscr(void);
19 static int ansi_endwin(void);
20 static int ansi_addch(int );
21 static int ansi_mvaddstr(int ,int ,char *);
22 static int ansi_mvprintw(int ,int ,char *,int ,int ,int ,int );
23 static int ansi_move(int ,int );
24 static int ansi_move_tgoto(int ,int );
25 static int ansi_clrtobot(void);
26 static int ansi_clrtoeol(void);
27 static int ansi_mvaddch(int ,int ,char );
28 static int ansi_clear(void);
29 static int ansi_refresh(void);
30 static int ansi_noop(void);
31 int ansi_prep(int ,int, int);
32 #else
33 static int ansi_addch(), ansi_mvaddstr(), ansi_mvprintw(), ansi_move(),
34 ansi_move_tgoto(),
35 ansi_clrtobot(), ansi_clrtoeol(), ansi_mvaddch(), ansi_endwin(),
36 ansi_refresh(), ansi_clear(), ansi_noop(), ansi_initscr();
37 int ansi_prep();
38 #endif
39
40 extern char *tgetstr();
41 extern char *getenv();
42 extern char *tgoto();
43
44 /* Must supply a functional form of the PCcurses "move" routine */
45 static int
curses_move(y,x)46 curses_move(y, x)
47 int y, x;
48 {
49 return wmove(stdscr, y, x);
50 }
51
52 /* Default is for curses to be used */
53 int (*output_addch)() = addch;
54 int (*output_mvaddstr)() = mvaddstr;
55 int (*output_mvprintw)() = mvprintw;
56 int (*output_move)() = curses_move;
57 int (*output_endwin)() = endwin;
58 int (*output_clrtobot)() = clrtobot;
59 int (*output_clrtoeol)() = clrtoeol;
60 int (*output_mvaddch)() = mvaddch;
61 int (*output_initscr)() = initscr;
62 int (*output_refresh)() = refresh;
63 int (*output_clear)() = clear;
64
65 int (*output_nocrmode)() = nocrmode;
66 int (*output_crmode)() = crmode;
67 int (*output_nonl)() = nonl;
68 int (*output_nl)() = nl;
69 int (*output_noecho)() = noecho;
70 int (*output_echo)() = echo;
71 int ansi;
72 int LI;
73
74 #define LEFTFIELD -10;
75 #define NEED 1
76
77 static int moveopt = 1;
78 static char *CE, *CL, *CM, *DO, *LE, *ND, *TE, *TI, *UP;
79 static int currow = 0;
80 static int curcol = LEFTFIELD;
81
82 static char *
getent(str,tbufp,need)83 getent(str, tbufp, need)
84 char *str, **tbufp;
85 int need;
86 {
87 char *value;
88
89 if ((value = tgetstr(str, tbufp)) == NULL && need == NEED)
90 error("termcap: Moria needs %s\n", str);
91 return value;
92 }
93
94 static void
initansistr()95 initansistr()
96 {
97 static char tbuf[512];
98 char temp[1024], *tbufp, *term;
99
100 if ((term = getenv("TERM")) == NULL)
101 term = "ibmpc-mono";
102 if (tgetent(temp, term) < 1)
103 error("Unknown terminal type: %s.", term);
104 tbufp = tbuf;
105 LE = getent("le", &tbufp, NEED);
106 CE = getent("ce", &tbufp, NEED);
107 CL = getent("cl", &tbufp, NEED);
108 CM = getent("cm", &tbufp, NEED);
109 ND = getent("nd", &tbufp, NEED);
110 TE = getent("te", &tbufp, !NEED);
111 TI = getent("ti", &tbufp, !NEED);
112 UP = getent("up", &tbufp, NEED);
113 DO = getent("do", &tbufp, NEED);
114 LI = tgetnum("li");
115 if (LI <= 0)
116 LI = 24;
117 }
118
ansi_prep(check_ansi,domoveopt,truetgoto)119 ansi_prep(check_ansi, domoveopt, truetgoto)
120 int check_ansi;
121 int domoveopt;
122 int truetgoto;
123 {
124 moveopt = domoveopt;
125
126 /* Check for ANSI.SYS */
127 if (check_ansi) {
128 /* Clear the input queue */
129 while (kbhit())
130 (void) getch();
131
132 /* Send out the DSR string */
133 fputs("\033[6n", stdout);
134 fflush(stdout);
135
136 /* Is there anything in the input? If so ANSI responded. */
137 if (kbhit()) {
138 while (kbhit())
139 (void) getch();
140 }
141 else {
142 putchar('\n');
143 error("ANSI.SYS not installed! See MORIA.DOC for details!\n");
144 }
145 }
146
147 /* get the ANSI strings */
148 initansistr();
149
150 /* change function pointers to ANSI versions */
151 output_addch = ansi_addch;
152 output_mvaddstr = ansi_mvaddstr;
153 output_mvprintw = ansi_mvprintw;
154 if (truetgoto)
155 output_move = ansi_move_tgoto;
156 else
157 output_move = ansi_move;
158 output_clrtobot = ansi_clrtobot;
159 output_clrtoeol = ansi_clrtoeol;
160 output_mvaddch = ansi_mvaddch;
161 output_refresh = ansi_refresh;
162 output_clear = ansi_clear;
163 output_initscr = ansi_initscr;
164 output_endwin = ansi_endwin;
165
166 output_nocrmode =
167 output_crmode =
168 output_nonl =
169 output_nl =
170 output_noecho =
171 output_echo = ansi_noop;
172
173 ansi = 1;
174 }
175
176 static int
ansi_initscr()177 ansi_initscr()
178 {
179 if (TI != NULL)
180 fputs(TI, stdout);
181 return OK;
182 }
183
184 static int
ansi_endwin()185 ansi_endwin()
186 {
187 if (TI != NULL)
188 fputs(TE, stdout);
189 return OK;
190 }
191
192 static int
ansi_addch(ch)193 ansi_addch(ch)
194 int ch;
195 {
196 putc(ch, stdout);
197 curcol++;
198 return OK;
199 }
200
201 static int
ansi_mvaddstr(row,col,str)202 ansi_mvaddstr(row, col, str)
203 int row, col;
204 char *str;
205 {
206 (void) ansi_move(row, col);
207 fputs(str, stdout);
208 curcol = LEFTFIELD;
209 return OK;
210 }
211
212 static int
ansi_mvprintw(row,col,fmt,a1,a2,a3,a4)213 ansi_mvprintw(row, col, fmt, a1, a2, a3, a4)
214 int row, col;
215 char *fmt;
216 int a1, a2, a3, a4; /* large enough for %c%s%c of files.c ! */
217 {
218 (void) ansi_move(row, col);
219 fprintf(stdout, fmt, a1, a2, a3, a4);
220 curcol = LEFTFIELD;
221 return OK;
222 }
223
224 #define abs(x) ((x) < 0 ? -(x) : (x))
225
226 /* For a bit more speed, don't use tgoto() from termcap */
227 static int
ansi_move(row,col)228 ansi_move(row, col)
229 int row, col;
230 {
231 if (moveopt && abs(currow - row) < 3 && abs(curcol - col) < 3) {
232 while (row > currow)
233 fputs(DO, stdout), currow++;
234 while (row < currow)
235 fputs(UP, stdout), currow--;
236 while (col > curcol)
237 fputs(ND, stdout), curcol++;
238 while (col < curcol)
239 fputs(LE, stdout), curcol--;
240 }
241 else
242 fprintf(stdout, "\033[%d;%dH\0__cursor motion__", row+1,col+1);
243 currow = row;
244 curcol = col;
245 return OK;
246 }
247
248 /* Use tgoto (which is rather slow) */
249 static int
ansi_move_tgoto(row,col)250 ansi_move_tgoto(row, col)
251 int row, col;
252 {
253 if (moveopt && abs(currow - row) < 3 && abs(curcol - col) < 3) {
254 while (row > currow)
255 fputs(DO, stdout), currow++;
256 while (row < currow)
257 fputs(UP, stdout), currow--;
258 while (col > curcol)
259 fputs(ND, stdout), curcol++;
260 while (col < curcol)
261 fputs(LE, stdout), curcol--;
262 }
263 else {
264 fputs(tgoto(CM, col, row), stdout);
265 }
266 currow = row;
267 curcol = col;
268 return OK;
269 }
270
271 static int
ansi_clrtobot()272 ansi_clrtobot()
273 {
274 ansi_clrtoeol();
275 ansi_move(++currow, 0);
276 ansi_clrtoeol();
277 for (; currow <= LI; currow++) {
278 fputs(DO, stdout);
279 ansi_clrtoeol();
280 }
281 curcol = LEFTFIELD;
282 return OK;
283 }
284
285 static int
ansi_clrtoeol()286 ansi_clrtoeol()
287 {
288 fputs(CE, stdout);
289 return OK;
290 }
291
292 static int
ansi_mvaddch(row,col,ch)293 ansi_mvaddch(row, col, ch)
294 int row, col;
295 char ch;
296 {
297 ansi_move(row, col);
298 putchar(ch);
299 curcol++;
300 return OK;
301 }
302
303 static int
ansi_clear()304 ansi_clear()
305 {
306 fputs(CL, stdout);
307 return OK;
308 }
309
310 static int
ansi_refresh()311 ansi_refresh()
312 {
313 fflush(stdout);
314 return OK;
315 }
316
317 static int
ansi_noop()318 ansi_noop()
319 {
320 return OK;
321 }
322 #endif
323