Commit | Line | Data |
---|---|---|
15637ed4 RG |
1 | /* Copyright 1992 by Holger Veit |
2 | * May be freely used with Bill Jolitz's port of | |
3 | * 386bsd and may be included in a 386bsd collection | |
4 | * as long as binary and source are available and reproduce the above | |
5 | * copyright. | |
6 | * | |
7 | * You may freely modify this code and contribute improvements based | |
8 | * on this code as long as you don't claim to be the original author. | |
9 | * Commercial use of this source requires permittance of the copyright | |
10 | * holder. A general license for 386bsd will override this restriction. | |
11 | * | |
12 | * Use at your own risk. The copyright holder or any person who makes | |
13 | * this code available for the public (administrators of public archives | |
14 | * for instance) are not responsible for any harm to hardware or software | |
15 | * that might happen due to wrong application or program faults. | |
16 | * | |
17 | * @(#) $RCSfile: co_pc3.c,v $ $Revision: 1.6 $ (Contributed to 386bsd) $Date: 93/01/23 23:14:46 $ | |
18 | * | |
19 | * History: see CO_HISTORY | |
20 | */ | |
21 | static char *rcsid = "$Header: /usr/src/sys.386bsd/i386/isa/codrv/RCS/co_pc3.c,v 1.6 93/01/23 23:14:46 root Exp Locker: root $"; | |
22 | ||
23 | /* This file provides a plug-in interface for different terminal emulations. | |
24 | * As a reference, the pc3/pc3x/pc3n/pc3nc interface is shown. | |
25 | * | |
26 | * Programmers are invited to provide different emulations, e.g. | |
27 | * vt100/vt220/vt320, adm3a/adm31, hp262x, etc. | |
28 | * | |
29 | * The following conventions have to be met: | |
30 | * | |
31 | * The video subsystem provides a number of support functions to | |
32 | * manipulate screen data, such as writing to a VTY screen, or moving the | |
33 | * cursor, etc. | |
34 | * | |
35 | * All these routines are named "emul_*". See co_hdr.h for a list of available | |
36 | * facilities. You will see that these are defines to either a set of | |
37 | * "vga_*" or "gfx_*" routines (not yet available). To make a migration to | |
38 | * the future graphics console as smooth as possible, avoid using other | |
39 | * routines to access the screen, even if you know tricky code | |
40 | * that runs 10 times as fast. There is time enough to do optimizations | |
41 | * when the graphics subsystem is running. | |
42 | * | |
43 | *************************************************************************** | |
44 | * | |
45 | * This file contains one central routine, 'vtemul_exec', which is called | |
46 | * by the console driver, with the following arguments: | |
47 | * | |
48 | * vp: Pointer to the actual vty | |
49 | * ch: Character to be processed (note that this is not a "u_char"!) | |
50 | * | |
51 | *************************************************************************** | |
52 | * | |
53 | * A second call is used during coattach: 'vtemul_init', which | |
54 | * can be used for local initialisation. vtemul_init also MUST fill an | |
55 | * identifier into the field 'emul_name' of struct consinfo cons_capabilities. | |
56 | * | |
57 | *************************************************************************** | |
58 | * | |
59 | * Only use the PUBLIC fields in struct vty! | |
60 | * Don't rely on the PRIVATE members of the structure, even if you | |
61 | * can access them (PRIVATE and PUBLIC are #defines only). | |
62 | * The reason is, that a future version may run in graphics mode, and | |
63 | * will interpret these fields in a different way you may think they | |
64 | * might be used. This holds in particular for Crtat and Crtat!!!! | |
65 | * | |
66 | * If you need more special variables, use a local structure | |
67 | * use #include "vty.h" to find out the number of vtys available. | |
68 | * But even in the local structure, don't think that there is | |
69 | * direct accessible video memory, even if using this this speeds up | |
70 | * everything extremely! | |
71 | */ | |
72 | ||
73 | /* example code follows: */ | |
74 | ||
75 | /* check my optional symbol to avoid multiple inclusions */ | |
76 | #ifdef PC3 | |
77 | #ifndef MINITERM | |
78 | ||
79 | #include "co_hdr.h" | |
80 | #include "vty.h" | |
81 | ||
82 | #define ESC_NONE 0 /* No esc in progress */ | |
83 | #define ESC_WBRAC 1 /* got esc, wait for '[' or 'c' */ | |
84 | #define ESC_WPARAM 2 /* got esc [, wait for param, ';' or letter */ | |
85 | ||
86 | /* !!! this may look like a Keycap_def, like in co_kbd.c, but isn't ! :-) */ | |
87 | static struct Keycap2 { | |
88 | short key; | |
89 | u_short type; /* type of key */ | |
90 | XCHAR unshift[KBDDEFOVLKEYSIZE+1]; /* default codes */ | |
91 | XCHAR shift[KBDDEFOVLKEYSIZE+1]; | |
92 | XCHAR ctrl[KBDDEFOVLKEYSIZE+1]; | |
93 | } pc3keys[] = { | |
94 | 75, KBD_FUNC, XE3('[','L'), XE3('|','a'), XE3('|','b'), /* INS */ | |
95 | 76, KBD_FUNC, XC1('\177'), XE3('|','c'), XE3('|','d'), /* DEL */ | |
96 | 79, KBD_FUNC, XE3('[','D'), XE3('|','e'), XE3('|','f'), /* CU <- */ | |
97 | 80, KBD_FUNC, XE3('[','H'), XE3('|','g'), XE3('|','h'), /* HOME */ | |
98 | 81, KBD_FUNC, XE3('[','F'), XE3('|','i'), XE3('|','j'), /* END */ | |
99 | 83, KBD_FUNC, XE3('[','A'), XE3('|','k'), XE3('|','l'), /* CU ^ */ | |
100 | 84, KBD_FUNC, XE3('[','B'), XE3('|','m'), XE3('|','n'), /* CU v */ | |
101 | 85, KBD_FUNC, XE3('[','I'), XE3('|','o'), XE3('|','p'), /* PG UP */ | |
102 | 86, KBD_FUNC, XE3('[','G'), XE3('|','q'), XE3('|','r'), /* PG DN */ | |
103 | 89, KBD_FUNC, XE3('[','C'), XE3('|','s'), XE3('|','t'), /* CU -> */ | |
104 | 91, KBD_KP, XC1('7'), XE3('[','H'), XC1('7'), | |
105 | 92, KBD_KP, XC1('4'), XE3('[','D'), XC1('4'), | |
106 | 93, KBD_KP, XC1('1'), XE3('[','F'), XC1('1'), | |
107 | 95, KBD_KP, XC1('/'), XC1('/'), XC1('/'), | |
108 | 96, KBD_KP, XC1('8'), XE3('[','A'), XC1('8'), | |
109 | 97, KBD_KP, XC1('5'), XE3('[','E'), XC1('5'), | |
110 | 98, KBD_KP, XC1('2'), XE3('[','B'), XC1('2'), | |
111 | 99, KBD_KP, XC1('0'), XE3('[','L'), XC1('0'), | |
112 | 100, KBD_KP, XC1('*'), XC1('*'), XC1('*'), | |
113 | 101, KBD_KP, XC1('9'), XE3('[','I'), XC1('9'), | |
114 | 102, KBD_KP, XC1('6'), XE3('[','C'), XC1('6'), | |
115 | 103, KBD_KP, XC1('3'), XE3('[','G'), XC1('3'), | |
116 | 104, KBD_KP, XC1('.'), XC1('\177'), XC1('.'), | |
117 | 105, KBD_KP, XC1('-'), XC1('-'), XC1('-'), | |
118 | 106, KBD_KP, XC1('+'), XC1('+'), XC1('+'), | |
119 | 112, KBD_FUNC, XE3('[','M'), XE3('[','Y'), XE3('[','k'), /* F1 */ | |
120 | 113, KBD_FUNC, XE3('[','N'), XE3('[','Z'), XE3('[','l'), /* F2 */ | |
121 | 114, KBD_FUNC, XE3('[','O'), XE3('[','a'), XE3('[','m'), /* F3 */ | |
122 | 115, KBD_FUNC, XE3('[','P'), XE3('[','b'), XE3('[','n'), /* F4 */ | |
123 | 116, KBD_FUNC, XE3('[','Q'), XE3('[','c'), XE3('[','o'), /* F5 */ | |
124 | 117, KBD_FUNC, XE3('[','R'), XE3('[','d'), XE3('[','p'), /* F6 */ | |
125 | 118, KBD_FUNC, XE3('[','S'), XE3('[','e'), XE3('[','q'), /* F7 */ | |
126 | 119, KBD_FUNC, XE3('[','T'), XE3('[','f'), XE3('[','r'), /* F8 */ | |
127 | 120, KBD_FUNC, XE3('[','U'), XE3('[','g'), XE3('[','s'), /* F9 */ | |
128 | 121, KBD_FUNC, XE3('[','V'), XE3('[','h'), XE3('[','t'), /* F10 */ | |
129 | 122, KBD_FUNC, XE3('[','W'), XE3('[','i'), XE3('[','u'), /* F11 */ | |
130 | 123, KBD_FUNC, XE3('[','X'), XE3('[','j'), XE3('[','v'), /* F12 */ | |
131 | 124, KBD_KP, XE3('[','w'), XE3('[','x'), XE3('[','y'), | |
132 | 0, KBD_NONE, XC0, XC0, XC0 | |
133 | }; | |
134 | ||
135 | /* | |
136 | * Do the local initialisations. Notice that many things are already done | |
137 | * in vty_init | |
138 | */ | |
139 | void vtemul_init() | |
140 | { | |
141 | char *c,*id = "pc3n"; | |
142 | XCHAR *xc; | |
143 | Keycap_def *kp; | |
144 | struct Keycap2 *k2; | |
145 | ||
146 | /* fill the cons_capabilities structure | |
147 | * Don't use strcpy here! | |
148 | */ | |
149 | c = id; | |
150 | xc = cons_capabilities.emul_name; | |
151 | while (*xc++ = xc_char2xc(*c++)) ; | |
152 | ||
153 | #define copydef(src,dst)\ | |
154 | xc_bcopy(src,dst,KBDDEFOVLKEYSIZE) | |
155 | ||
156 | /* set the function keys new */ | |
157 | for (k2 = pc3keys; k2->key; k2++) { | |
158 | kp = &kbd_keytab[k2->key]; | |
159 | kp->type = k2->type; | |
160 | kp->ovlptr = 0; | |
161 | copydef(k2->unshift,kp->unshift); | |
162 | copydef(k2->shift,kp->shift); | |
163 | copydef(k2->ctrl,kp->ctrl); | |
164 | } | |
165 | } | |
166 | ||
167 | /* | |
168 | * this routine does all the ESC and character processing stuff | |
169 | */ | |
170 | void vtemul_exec(struct vty *vp, XCHAR ch) | |
171 | { | |
172 | int inccol, par1, par2; | |
173 | int sc = 1; /* do scroll check */ | |
174 | u_short at,sat; | |
175 | struct outmode *sk = vp->op; | |
176 | ||
177 | /* which attributes do we use? */ | |
178 | at = sk->fg_at|sk->bg_at; | |
179 | sat= vp->so_at; | |
180 | ||
181 | /* translate to proper font */ | |
182 | ch = vga_xlatiso646(vp,&at,&sat,ch); | |
183 | ||
184 | switch(ch) { | |
185 | case 016: /* SO, select font 2 */ | |
186 | emul_selectfont(vp,2); | |
187 | break; | |
188 | case 017: /* SI, select font 1 */ | |
189 | emul_selectfont(vp,1); | |
190 | break; | |
191 | case 0x1B: | |
192 | if(sk->escstate != ESC_NONE) | |
193 | emul_wrtchar(vp,ch,sat); | |
194 | else | |
195 | sk->escstate = ESC_WBRAC; | |
196 | break; | |
197 | ||
198 | case '\t': | |
199 | inccol = (8 - vp->col % 8); /* non-destructive tab */ | |
200 | emul_cursorrelative(vp,inccol,0); | |
201 | break; | |
202 | ||
203 | case '\010': | |
204 | emul_cursorleft(vp, 1); | |
205 | break; | |
206 | ||
207 | case '\r': | |
208 | emul_cursorrelative(vp,-vp->col,0); | |
209 | break; | |
210 | ||
211 | case '\n': | |
212 | emul_cursorrelative(vp,0,1); | |
213 | break; | |
214 | ||
215 | case 0x07: | |
216 | /* different sounds for different vtys possible */ | |
217 | sysbeep (vp->pitch, vp->duration); | |
218 | break; | |
219 | default: | |
220 | /* ESC Processing */ | |
221 | switch (sk->escstate) { | |
222 | ||
223 | default: | |
224 | case ESC_NONE: | |
225 | /* NO ESC, normal processing */ | |
226 | emul_wrtchar(vp,ch,vp->so ? sat : at); | |
227 | if (vp->col >= vp->ncol) vp->col = 0; | |
228 | break; | |
229 | ||
230 | case ESC_WBRAC: | |
231 | /* has seen ESC, wait for [ or 'c' */ | |
232 | if (ch=='[') { | |
233 | sk->escstate = ESC_WPARAM; | |
234 | sk->parcnt = 0; | |
235 | sk->param[0] = 0; | |
236 | sk->param[1] = 0; | |
237 | } | |
238 | else if (ch == 'c') { | |
239 | /* Clear screen & home */ | |
240 | emul_clearcursor(vp, 2); | |
241 | emul_cursormove(vp, 0, 0); | |
242 | sk->escstate = ESC_NONE; | |
243 | } | |
244 | else { | |
245 | /* error */ | |
246 | sk->escstate = ESC_NONE; | |
247 | emul_wrtchar(vp, ch, sat); | |
248 | } | |
249 | break; | |
250 | ||
251 | case ESC_WPARAM: /* has seen ESC [ wait for digit, ';' or letter */ | |
252 | if (ch>='0' && ch<='9') { | |
253 | sk->param[sk->parcnt] *= 10; | |
254 | sk->param[sk->parcnt] += ch-'0'; | |
255 | } | |
256 | else if (ch==';') { | |
257 | if (sk->parcnt>=2) { | |
258 | sk->escstate = ESC_NONE; /* error */ | |
259 | emul_wrtchar(vp,ch,sat); | |
260 | } | |
261 | else { | |
262 | sk->parcnt++; | |
263 | sk->param[sk->parcnt] = 0; | |
264 | } | |
265 | } | |
266 | else if (ch>=' ' && ch<='~') { | |
267 | par1 = sk->param[0]; | |
268 | par2 = sk->param[1]; | |
269 | sk->parcnt++; | |
270 | sk->param[sk->parcnt] = 0; | |
271 | switch (ch) { | |
272 | case 'A': /* back cx rows */ | |
273 | emul_cursorup(vp, par1); | |
274 | sc = 0; | |
275 | break; | |
276 | case 'B': /* down cx rows */ | |
277 | emul_cursordown(vp, par1); | |
278 | sc = 0; | |
279 | break; | |
280 | case 'C': /* right cursor */ | |
281 | emul_cursorright(vp, par1, 1); | |
282 | sc = 0; | |
283 | break; | |
284 | case 'D': /* left cursor */ | |
285 | emul_cursorleft(vp, par1); | |
286 | sc = 0; | |
287 | break; | |
288 | case 'f': /* in system V consoles */ | |
289 | case 'H': /* Cursor move */ | |
290 | emul_cursormove(vp, par1, par2); | |
291 | break; | |
292 | case 'J': /* Clear ... */ | |
293 | emul_clearcursor(vp, par1); | |
294 | break; | |
295 | case 'K': /* Clear line ... */ | |
296 | emul_clearline(vp, par1); | |
297 | break; | |
298 | case 'L': /* Insert Line */ | |
299 | emul_insertline(vp, par1); | |
300 | break; | |
301 | case 'M': /* Delete Line */ | |
302 | emul_deleteline(vp, par1); | |
303 | break; | |
304 | case 'P': /* delete spaces */ | |
305 | emul_deletechars(vp, par1); | |
306 | break; | |
307 | case 'S': /* scroll up cx lines */ | |
308 | emul_scrollup(vp, par1, 0); | |
309 | break; | |
310 | case 'T': /* scroll down cx lines */ | |
311 | emul_scrolldown(vp, par1); | |
312 | break; | |
313 | case 'm': /* standout mode */ | |
314 | if (par1) vp->so = 1; | |
315 | else vp->so = 0; | |
316 | break; | |
317 | case 'r': | |
318 | vp->so_at = (par1 & 0x0f) | ((par2 & 0x0f) << 4); | |
319 | break; | |
320 | case 'x': /* set attributes */ | |
321 | emul_setattributes(vp, par1, par2); | |
322 | break; | |
323 | case '@': /* insert spaces */ | |
324 | emul_insertchars(vp, par1); | |
325 | break; | |
326 | case '!': /* set beep pitch and duration */ | |
327 | kbd_cvtsound(par1, &vp->pitch, | |
328 | par2, &vp->duration); | |
329 | break; | |
330 | default: | |
331 | emul_wrtchar(vp,ch,sat); | |
332 | } | |
333 | sk->escstate = ESC_NONE; | |
334 | } | |
335 | break; | |
336 | } | |
337 | } | |
338 | ||
339 | if (sc && emul_checkcursor(vp) > 0) { | |
340 | if (consoftc.cs_flags&CO_OPEN) | |
341 | do | |
342 | (void)kbd_sgetc(1); | |
343 | while (vp->scroll); | |
344 | ||
345 | emul_scrollup(vp, 1, 1); | |
346 | } | |
347 | } | |
348 | ||
349 | #endif /* !MINITERM */ | |
350 | #endif /* PC3 */ |