Commit | Line | Data |
---|---|---|
c6a6499f | 1 | /* MS-DOS specific C utilities. -*- coding: raw-text -*- |
db722735 | 2 | Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. |
1b94449f RS |
3 | |
4 | This file is part of GNU Emacs. | |
5 | ||
6 | GNU Emacs is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
edfc0d45 | 8 | the Free Software Foundation; either version 2, or (at your option) |
1b94449f RS |
9 | any later version. |
10 | ||
11 | GNU Emacs is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GNU Emacs; see the file COPYING. If not, write to | |
3b7ad313 EN |
18 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
19 | Boston, MA 02111-1307, USA. */ | |
1b94449f | 20 | |
9da6e765 | 21 | /* Contributed by Morten Welinder */ |
f32d4091 | 22 | /* New display, keyboard, and mouse control by Kim F. Storm */ |
9da6e765 | 23 | |
1b94449f RS |
24 | /* Note: some of the stuff here was taken from end of sysdep.c in demacs. */ |
25 | ||
48984716 | 26 | #include <config.h> |
1b94449f RS |
27 | |
28 | #ifdef MSDOS | |
29 | #include "lisp.h" | |
30 | #include <stdio.h> | |
31 | #include <stdlib.h> | |
06b1ea13 | 32 | #include <time.h> |
1b94449f RS |
33 | #include <sys/param.h> |
34 | #include <sys/time.h> | |
35 | #include <dos.h> | |
d21e67b5 | 36 | #include <errno.h> |
a7cf9151 | 37 | #include <string.h> /* for bzero and string functions */ |
d21e67b5 | 38 | #include <sys/stat.h> /* for _fixpath */ |
a7cf9151 | 39 | #include <unistd.h> /* for chdir, dup, dup2, etc. */ |
1bd7b2c7 RS |
40 | #if __DJGPP__ >= 2 |
41 | #include <fcntl.h> | |
a7cf9151 | 42 | #include <io.h> /* for setmode */ |
fc171623 KH |
43 | #include <dpmi.h> /* for __dpmi_xxx stuff */ |
44 | #include <sys/farptr.h> /* for _farsetsel, _farnspokeb */ | |
d21e67b5 | 45 | #include <libc/dosio.h> /* for _USE_LFN */ |
a7cf9151 | 46 | #include <conio.h> /* for cputs */ |
1bd7b2c7 RS |
47 | #endif |
48 | ||
1b94449f RS |
49 | #include "msdos.h" |
50 | #include "systime.h" | |
51 | #include "termhooks.h" | |
aa9ce936 | 52 | #include "termchar.h" |
87485d6f | 53 | #include "dispextern.h" |
c77f6f1b | 54 | #include "dosfns.h" |
87485d6f | 55 | #include "termopts.h" |
aa9ce936 EZ |
56 | #include "charset.h" |
57 | #include "coding.h" | |
58 | #include "disptab.h" | |
1b94449f | 59 | #include "frame.h" |
87485d6f | 60 | #include "window.h" |
fc171623 KH |
61 | #include "buffer.h" |
62 | #include "commands.h" | |
1b94449f RS |
63 | #include <go32.h> |
64 | #include <pc.h> | |
65 | #include <ctype.h> | |
66 | /* #include <process.h> */ | |
67 | /* Damn that local process.h! Instead we can define P_WAIT ourselves. */ | |
68 | #define P_WAIT 1 | |
69 | ||
d21e67b5 RS |
70 | #ifndef _USE_LFN |
71 | #define _USE_LFN 0 | |
72 | #endif | |
73 | ||
b36701cc RS |
74 | #ifndef _dos_ds |
75 | #define _dos_ds _go32_info_block.selector_for_linear_memory | |
76 | #endif | |
77 | ||
1bd7b2c7 RS |
78 | #if __DJGPP__ > 1 |
79 | ||
8748735b | 80 | #include <signal.h> |
417a04bb | 81 | #include "syssignal.h" |
8748735b | 82 | |
1bd7b2c7 RS |
83 | #ifndef SYSTEM_MALLOC |
84 | ||
85 | #ifdef GNU_MALLOC | |
86 | ||
87 | /* If other `malloc' than ours is used, force our `sbrk' behave like | |
88 | Unix programs expect (resize memory blocks to keep them contiguous). | |
89 | If `sbrk' from `ralloc.c' is NOT used, also zero-out sbrk'ed memory, | |
90 | because that's what `gmalloc' expects to get. */ | |
91 | #include <crt0.h> | |
92 | ||
93 | #ifdef REL_ALLOC | |
94 | int _crt0_startup_flags = _CRT0_FLAG_UNIX_SBRK; | |
95 | #else /* not REL_ALLOC */ | |
96 | int _crt0_startup_flags = (_CRT0_FLAG_UNIX_SBRK | _CRT0_FLAG_FILL_SBRK_MEMORY); | |
97 | #endif /* not REL_ALLOC */ | |
98 | #endif /* GNU_MALLOC */ | |
99 | ||
100 | #endif /* not SYSTEM_MALLOC */ | |
101 | #endif /* __DJGPP__ > 1 */ | |
aee81730 RS |
102 | |
103 | static unsigned long | |
104 | event_timestamp () | |
105 | { | |
106 | struct time t; | |
107 | unsigned long s; | |
f32d4091 | 108 | |
aee81730 RS |
109 | gettime (&t); |
110 | s = t.ti_min; | |
111 | s *= 60; | |
112 | s += t.ti_sec; | |
113 | s *= 1000; | |
114 | s += t.ti_hund * 10; | |
f32d4091 | 115 | |
aee81730 RS |
116 | return s; |
117 | } | |
118 | ||
f32d4091 KS |
119 | \f |
120 | /* ------------------------ Mouse control --------------------------- | |
121 | * | |
122 | * Coordinates are in screen positions and zero based. | |
123 | * Mouse buttons are numbered from left to right and also zero based. | |
124 | */ | |
1b94449f | 125 | |
f32d4091 KS |
126 | int have_mouse; /* 0: no, 1: enabled, -1: disabled */ |
127 | static int mouse_visible; | |
1b94449f | 128 | |
f32d4091 KS |
129 | static int mouse_last_x; |
130 | static int mouse_last_y; | |
1b94449f | 131 | |
f32d4091 KS |
132 | static int mouse_button_translate[NUM_MOUSE_BUTTONS]; |
133 | static int mouse_button_count; | |
1b94449f | 134 | |
f32d4091 KS |
135 | void |
136 | mouse_on () | |
1b94449f | 137 | { |
1b94449f | 138 | union REGS regs; |
1b94449f | 139 | |
f32d4091 | 140 | if (have_mouse > 0 && !mouse_visible) |
1b94449f | 141 | { |
f32d4091 KS |
142 | if (termscript) |
143 | fprintf (termscript, "<M_ON>"); | |
144 | regs.x.ax = 0x0001; | |
145 | int86 (0x33, ®s, ®s); | |
146 | mouse_visible = 1; | |
1b94449f | 147 | } |
1b94449f RS |
148 | } |
149 | ||
f32d4091 KS |
150 | void |
151 | mouse_off () | |
1b94449f | 152 | { |
f32d4091 | 153 | union REGS regs; |
1b94449f | 154 | |
f32d4091 | 155 | if (have_mouse > 0 && mouse_visible) |
1b94449f | 156 | { |
f32d4091 KS |
157 | if (termscript) |
158 | fprintf (termscript, "<M_OFF>"); | |
159 | regs.x.ax = 0x0002; | |
160 | int86 (0x33, ®s, ®s); | |
161 | mouse_visible = 0; | |
1b94449f | 162 | } |
1b94449f RS |
163 | } |
164 | ||
211c7152 EZ |
165 | static void |
166 | mouse_get_xy (int *x, int *y) | |
167 | { | |
168 | union REGS regs; | |
169 | ||
170 | regs.x.ax = 0x0003; | |
171 | int86 (0x33, ®s, ®s); | |
172 | *x = regs.x.cx / 8; | |
173 | *y = regs.x.dx / 8; | |
174 | } | |
175 | ||
f32d4091 KS |
176 | void |
177 | mouse_moveto (x, y) | |
178 | int x, y; | |
1b94449f | 179 | { |
f32d4091 | 180 | union REGS regs; |
1b94449f | 181 | |
f32d4091 KS |
182 | if (termscript) |
183 | fprintf (termscript, "<M_XY=%dx%d>", x, y); | |
184 | regs.x.ax = 0x0004; | |
185 | mouse_last_x = regs.x.cx = x * 8; | |
186 | mouse_last_y = regs.x.dx = y * 8; | |
187 | int86 (0x33, ®s, ®s); | |
1b94449f RS |
188 | } |
189 | ||
f32d4091 KS |
190 | static int |
191 | mouse_pressed (b, xp, yp) | |
192 | int b, *xp, *yp; | |
1b94449f | 193 | { |
f32d4091 | 194 | union REGS regs; |
1b94449f | 195 | |
f32d4091 KS |
196 | if (b >= mouse_button_count) |
197 | return 0; | |
198 | regs.x.ax = 0x0005; | |
199 | regs.x.bx = mouse_button_translate[b]; | |
200 | int86 (0x33, ®s, ®s); | |
201 | if (regs.x.bx) | |
202 | *xp = regs.x.cx / 8, *yp = regs.x.dx / 8; | |
203 | return (regs.x.bx != 0); | |
1b94449f RS |
204 | } |
205 | ||
f32d4091 KS |
206 | static int |
207 | mouse_released (b, xp, yp) | |
208 | int b, *xp, *yp; | |
1b94449f RS |
209 | { |
210 | union REGS regs; | |
211 | ||
f32d4091 KS |
212 | if (b >= mouse_button_count) |
213 | return 0; | |
214 | regs.x.ax = 0x0006; | |
215 | regs.x.bx = mouse_button_translate[b]; | |
216 | int86 (0x33, ®s, ®s); | |
217 | if (regs.x.bx) | |
218 | *xp = regs.x.cx / 8, *yp = regs.x.dx / 8; | |
219 | return (regs.x.bx != 0); | |
1b94449f RS |
220 | } |
221 | ||
0c7bc1aa EZ |
222 | static int |
223 | mouse_button_depressed (b, xp, yp) | |
224 | int b, *xp, *yp; | |
225 | { | |
226 | union REGS regs; | |
227 | ||
228 | if (b >= mouse_button_count) | |
229 | return 0; | |
230 | regs.x.ax = 0x0003; | |
231 | int86 (0x33, ®s, ®s); | |
232 | if ((regs.x.bx & (1 << mouse_button_translate[b])) != 0) | |
233 | { | |
234 | *xp = regs.x.cx / 8; | |
235 | *yp = regs.x.dx / 8; | |
236 | return 1; | |
237 | } | |
238 | return 0; | |
239 | } | |
240 | ||
f32d4091 KS |
241 | void |
242 | mouse_get_pos (f, insist, bar_window, part, x, y, time) | |
243 | FRAME_PTR *f; | |
244 | int insist; | |
245 | Lisp_Object *bar_window, *x, *y; | |
246 | enum scroll_bar_part *part; | |
247 | unsigned long *time; | |
248 | { | |
249 | int ix, iy; | |
211c7152 EZ |
250 | Lisp_Object frame, tail; |
251 | ||
252 | /* Clear the mouse-moved flag for every frame on this display. */ | |
253 | FOR_EACH_FRAME (tail, frame) | |
254 | XFRAME (frame)->mouse_moved = 0; | |
f32d4091 | 255 | |
f32d4091 KS |
256 | *f = selected_frame; |
257 | *bar_window = Qnil; | |
258 | mouse_get_xy (&ix, &iy); | |
f32d4091 | 259 | *time = event_timestamp (); |
211c7152 EZ |
260 | *x = make_number (mouse_last_x = ix); |
261 | *y = make_number (mouse_last_y = iy); | |
f32d4091 | 262 | } |
1b94449f | 263 | |
f32d4091 KS |
264 | static void |
265 | mouse_check_moved () | |
1b94449f | 266 | { |
aee81730 | 267 | int x, y; |
1b94449f | 268 | |
f32d4091 KS |
269 | mouse_get_xy (&x, &y); |
270 | selected_frame->mouse_moved |= (x != mouse_last_x || y != mouse_last_y); | |
271 | mouse_last_x = x; | |
272 | mouse_last_y = y; | |
273 | } | |
1b94449f | 274 | |
f32d4091 KS |
275 | void |
276 | mouse_init () | |
277 | { | |
278 | union REGS regs; | |
0c7bc1aa | 279 | int b; |
647c32eb | 280 | |
f32d4091 KS |
281 | if (termscript) |
282 | fprintf (termscript, "<M_INIT>"); | |
1b94449f | 283 | |
f32d4091 KS |
284 | regs.x.ax = 0x0021; |
285 | int86 (0x33, ®s, ®s); | |
091d0bdf | 286 | |
0c7bc1aa EZ |
287 | /* Reset the mouse last press/release info. It seems that Windows |
288 | doesn't do that automatically when function 21h is called, which | |
289 | causes Emacs to ``remember'' the click that switched focus to the | |
290 | window just before Emacs was started from that window. */ | |
291 | for (b = 0; b < mouse_button_count; b++) | |
292 | { | |
293 | int dummy_x, dummy_y; | |
294 | ||
295 | (void) mouse_pressed (b, &dummy_x, &dummy_y); | |
296 | (void) mouse_released (b, &dummy_x, &dummy_y); | |
297 | } | |
298 | ||
f32d4091 KS |
299 | regs.x.ax = 0x0007; |
300 | regs.x.cx = 0; | |
301 | regs.x.dx = 8 * (ScreenCols () - 1); | |
302 | int86 (0x33, ®s, ®s); | |
1b94449f | 303 | |
f32d4091 KS |
304 | regs.x.ax = 0x0008; |
305 | regs.x.cx = 0; | |
306 | regs.x.dx = 8 * (ScreenRows () - 1); | |
307 | int86 (0x33, ®s, ®s); | |
1b94449f | 308 | |
f32d4091 KS |
309 | mouse_moveto (0, 0); |
310 | mouse_visible = 0; | |
311 | } | |
3eb1dbb6 | 312 | \f |
f32d4091 KS |
313 | /* ------------------------- Screen control ---------------------- |
314 | * | |
315 | */ | |
aee81730 | 316 | |
f32d4091 | 317 | static int internal_terminal = 0; |
aee81730 | 318 | |
f32d4091 KS |
319 | #ifndef HAVE_X_WINDOWS |
320 | extern unsigned char ScreenAttrib; | |
321 | static int screen_face; | |
322 | static int highlight; | |
aee81730 | 323 | |
f32d4091 KS |
324 | static int screen_size_X; |
325 | static int screen_size_Y; | |
326 | static int screen_size; | |
1b94449f | 327 | |
f32d4091 KS |
328 | static int current_pos_X; |
329 | static int current_pos_Y; | |
330 | static int new_pos_X; | |
331 | static int new_pos_Y; | |
1b94449f | 332 | |
f32d4091 KS |
333 | static void *startup_screen_buffer; |
334 | static int startup_screen_size_X; | |
335 | static int startup_screen_size_Y; | |
336 | static int startup_pos_X; | |
337 | static int startup_pos_Y; | |
c9adab25 | 338 | static unsigned char startup_screen_attrib; |
1b94449f | 339 | |
06b1ea13 EZ |
340 | static clock_t startup_time; |
341 | ||
f32d4091 | 342 | static int term_setup_done; |
1b94449f | 343 | |
f32d4091 | 344 | /* Similar to the_only_frame. */ |
f6816f88 | 345 | struct x_output the_only_x_display; |
1b94449f | 346 | |
f32d4091 KS |
347 | /* This is never dereferenced. */ |
348 | Display *x_current_display; | |
1b94449f | 349 | |
039274cf EZ |
350 | /* Support for DOS/V (allows Japanese characters to be displayed on |
351 | standard, non-Japanese, ATs). Only supported for DJGPP v2 and later. */ | |
352 | ||
353 | /* Holds the address of the text-mode screen buffer. */ | |
354 | static unsigned long screen_old_address = 0; | |
355 | /* Segment and offset of the virtual screen. If 0, DOS/V is NOT loaded. */ | |
356 | static unsigned short screen_virtual_segment = 0; | |
357 | static unsigned short screen_virtual_offset = 0; | |
68026917 AI |
358 | /* A flag to control how to display unibyte 8-bit characters. */ |
359 | extern int unibyte_display_via_language_environment; | |
039274cf EZ |
360 | |
361 | #if __DJGPP__ > 1 | |
362 | /* Update the screen from a part of relocated DOS/V screen buffer which | |
363 | begins at OFFSET and includes COUNT characters. */ | |
364 | static void | |
365 | dosv_refresh_virtual_screen (int offset, int count) | |
366 | { | |
367 | __dpmi_regs regs; | |
368 | ||
40437cf5 EZ |
369 | if (offset < 0 || count < 0) /* paranoia; illegal values crash DOS/V */ |
370 | return; | |
371 | ||
039274cf EZ |
372 | regs.h.ah = 0xff; /* update relocated screen */ |
373 | regs.x.es = screen_virtual_segment; | |
374 | regs.x.di = screen_virtual_offset + offset; | |
375 | regs.x.cx = count; | |
376 | __dpmi_int (0x10, ®s); | |
377 | } | |
378 | #endif | |
379 | ||
d1d5dc19 | 380 | static void |
f32d4091 KS |
381 | dos_direct_output (y, x, buf, len) |
382 | int y; | |
383 | int x; | |
384 | char *buf; | |
385 | int len; | |
1b94449f | 386 | { |
40437cf5 EZ |
387 | int t0 = 2 * (x + y * screen_size_X); |
388 | int t = t0 + (int) ScreenPrimary; | |
039274cf | 389 | int l0 = len; |
fc171623 KH |
390 | |
391 | #if (__DJGPP__ < 2) | |
f32d4091 KS |
392 | while (--len >= 0) { |
393 | dosmemput (buf++, 1, t); | |
394 | t += 2; | |
395 | } | |
fc171623 KH |
396 | #else |
397 | /* This is faster. */ | |
398 | for (_farsetsel (_dos_ds); --len >= 0; t += 2, buf++) | |
399 | _farnspokeb (t, *buf); | |
039274cf EZ |
400 | |
401 | if (screen_virtual_segment) | |
402 | dosv_refresh_virtual_screen (t0, l0); | |
fc171623 | 403 | #endif |
1b94449f | 404 | } |
aee81730 | 405 | #endif |
1b94449f | 406 | |
1b94449f RS |
407 | /* Flash the screen as a substitute for BEEPs. */ |
408 | ||
f32d4091 | 409 | #if (__DJGPP__ < 2) |
49a09c76 | 410 | static void |
fcea9cd4 | 411 | do_visible_bell (xorattr) |
1b94449f RS |
412 | unsigned char xorattr; |
413 | { | |
49a09c76 | 414 | asm volatile |
ca986694 | 415 | (" movb $1,%%dl |
1b94449f | 416 | visible_bell_0: |
ca986694 | 417 | movl _ScreenPrimary,%%eax |
49a09c76 | 418 | call dosmemsetup |
ca986694 RS |
419 | movl %%eax,%%ebx |
420 | movl %1,%%ecx | |
421 | movb %0,%%al | |
422 | incl %%ebx | |
1b94449f | 423 | visible_bell_1: |
ca986694 RS |
424 | xorb %%al,%%gs:(%%ebx) |
425 | addl $2,%%ebx | |
426 | decl %%ecx | |
49a09c76 | 427 | jne visible_bell_1 |
ca986694 | 428 | decb %%dl |
49a09c76 | 429 | jne visible_bell_3 |
1b94449f | 430 | visible_bell_2: |
ca986694 RS |
431 | movzwl %%ax,%%eax |
432 | movzwl %%ax,%%eax | |
433 | movzwl %%ax,%%eax | |
434 | movzwl %%ax,%%eax | |
435 | decw %%cx | |
49a09c76 RS |
436 | jne visible_bell_2 |
437 | jmp visible_bell_0 | |
ca986694 RS |
438 | visible_bell_3:" |
439 | : /* no output */ | |
f32d4091 | 440 | : "m" (xorattr), "g" (screen_size) |
ca986694 | 441 | : "%eax", "%ebx", /* "%gs",*/ "%ecx", "%edx"); |
1b94449f RS |
442 | } |
443 | ||
f32d4091 KS |
444 | static void |
445 | ScreenVisualBell (void) | |
446 | { | |
447 | /* This creates an xor-mask that will swap the default fore- and | |
448 | background colors. */ | |
449 | do_visible_bell (((the_only_x_display.foreground_pixel | |
450 | ^ the_only_x_display.background_pixel) | |
451 | * 0x11) & 0x7f); | |
452 | } | |
453 | #endif | |
454 | ||
455 | #ifndef HAVE_X_WINDOWS | |
456 | ||
b36701cc RS |
457 | static int blink_bit = -1; /* the state of the blink bit at startup */ |
458 | ||
76ac1508 RS |
459 | /* Enable bright background colors. */ |
460 | static void | |
461 | bright_bg (void) | |
462 | { | |
463 | union REGS regs; | |
464 | ||
b36701cc RS |
465 | /* Remember the original state of the blink/bright-background bit. |
466 | It is stored at 0040:0065h in the BIOS data area. */ | |
467 | if (blink_bit == -1) | |
468 | blink_bit = (_farpeekb (_dos_ds, 0x465) & 0x20) == 0x20; | |
469 | ||
76ac1508 RS |
470 | regs.h.bl = 0; |
471 | regs.x.ax = 0x1003; | |
472 | int86 (0x10, ®s, ®s); | |
473 | } | |
474 | ||
b36701cc RS |
475 | /* Disable bright background colors (and enable blinking) if we found |
476 | the video system in that state at startup. */ | |
477 | static void | |
478 | maybe_enable_blinking (void) | |
479 | { | |
480 | if (blink_bit == 1) | |
481 | { | |
482 | union REGS regs; | |
483 | ||
484 | regs.h.bl = 1; | |
485 | regs.x.ax = 0x1003; | |
486 | int86 (0x10, ®s, ®s); | |
487 | } | |
488 | } | |
489 | ||
4a96d4d2 KH |
490 | /* Set the screen dimensions so that it can show no less than |
491 | ROWS x COLS frame. */ | |
48ffe371 | 492 | |
4a96d4d2 KH |
493 | void |
494 | dos_set_window_size (rows, cols) | |
495 | int *rows, *cols; | |
496 | { | |
497 | char video_name[30]; | |
498 | Lisp_Object video_mode; | |
499 | int video_mode_value; | |
500 | int have_vga = 0; | |
501 | union REGS regs; | |
502 | int current_rows = ScreenRows (), current_cols = ScreenCols (); | |
503 | ||
504 | if (*rows == current_rows && *cols == current_cols) | |
505 | return; | |
506 | ||
507 | /* Do we have a VGA? */ | |
508 | regs.x.ax = 0x1a00; | |
509 | int86 (0x10, ®s, ®s); | |
510 | if (regs.h.al == 0x1a && regs.h.bl > 5 && regs.h.bl < 13) | |
511 | have_vga = 1; | |
512 | ||
513 | mouse_off (); | |
514 | ||
48ffe371 | 515 | /* If the user specified a special video mode for these dimensions, |
4a96d4d2 KH |
516 | use that mode. */ |
517 | sprintf (video_name, "screen-dimensions-%dx%d", *rows, *cols); | |
518 | video_mode = XSYMBOL (Fintern_soft (build_string (video_name), | |
519 | Qnil))-> value; | |
520 | ||
521 | if (INTEGERP (video_mode) | |
522 | && (video_mode_value = XINT (video_mode)) > 0) | |
523 | { | |
524 | regs.x.ax = video_mode_value; | |
525 | int86 (0x10, ®s, ®s); | |
48ffe371 RS |
526 | |
527 | if (have_mouse) | |
528 | { | |
529 | /* Must hardware-reset the mouse, or else it won't update | |
530 | its notion of screen dimensions for some non-standard | |
531 | video modes. This is *painfully* slow... */ | |
532 | regs.x.ax = 0; | |
533 | int86 (0x33, ®s, ®s); | |
534 | } | |
4a96d4d2 KH |
535 | } |
536 | ||
537 | /* Find one of the dimensions supported by standard EGA/VGA | |
538 | which gives us at least the required dimensions. */ | |
539 | ||
540 | #if __DJGPP__ > 1 | |
541 | ||
542 | else | |
543 | { | |
544 | static struct { | |
545 | int rows; | |
546 | int need_vga; | |
547 | } std_dimension[] = { | |
548 | {25, 0}, | |
549 | {28, 1}, | |
550 | {35, 0}, | |
551 | {40, 1}, | |
552 | {43, 0}, | |
553 | {50, 1} | |
554 | }; | |
555 | int i = 0; | |
556 | ||
557 | while (i < sizeof (std_dimension) / sizeof (std_dimension[0])) | |
558 | { | |
559 | if (std_dimension[i].need_vga <= have_vga | |
560 | && std_dimension[i].rows >= *rows) | |
561 | { | |
562 | if (std_dimension[i].rows != current_rows | |
563 | || *cols != current_cols) | |
48ffe371 | 564 | _set_screen_lines (std_dimension[i].rows); |
4a96d4d2 KH |
565 | break; |
566 | } | |
48ffe371 | 567 | i++; |
4a96d4d2 KH |
568 | } |
569 | } | |
570 | ||
571 | #else /* not __DJGPP__ > 1 */ | |
572 | ||
573 | else if (*rows <= 25) | |
574 | { | |
575 | if (current_rows != 25 || current_cols != 80) | |
576 | { | |
577 | regs.x.ax = 3; | |
578 | int86 (0x10, ®s, ®s); | |
579 | regs.x.ax = 0x1101; | |
580 | regs.h.bl = 0; | |
581 | int86 (0x10, ®s, ®s); | |
582 | regs.x.ax = 0x1200; | |
583 | regs.h.bl = 32; | |
584 | int86 (0x10, ®s, ®s); | |
585 | regs.x.ax = 3; | |
586 | int86 (0x10, ®s, ®s); | |
587 | } | |
588 | } | |
589 | else if (*rows <= 50) | |
590 | if (have_vga && (current_rows != 50 || current_cols != 80) | |
591 | || *rows <= 43 && (current_rows != 43 || current_cols != 80)) | |
592 | { | |
593 | regs.x.ax = 3; | |
594 | int86 (0x10, ®s, ®s); | |
595 | regs.x.ax = 0x1112; | |
596 | regs.h.bl = 0; | |
597 | int86 (0x10, ®s, ®s); | |
598 | regs.x.ax = 0x1200; | |
599 | regs.h.bl = 32; | |
600 | int86 (0x10, ®s, ®s); | |
601 | regs.x.ax = 0x0100; | |
602 | regs.x.cx = 7; | |
603 | int86 (0x10, ®s, ®s); | |
604 | } | |
605 | #endif /* not __DJGPP__ > 1 */ | |
606 | ||
607 | if (have_mouse) | |
608 | { | |
4a96d4d2 KH |
609 | mouse_init (); |
610 | mouse_on (); | |
611 | } | |
612 | ||
613 | /* Tell the caller what dimensions have been REALLY set. */ | |
614 | *rows = ScreenRows (); | |
615 | *cols = ScreenCols (); | |
76ac1508 RS |
616 | |
617 | /* Enable bright background colors. */ | |
618 | bright_bg (); | |
039274cf EZ |
619 | |
620 | /* FIXME: I'm not sure the above will run at all on DOS/V. But let's | |
621 | be defensive anyway. */ | |
622 | if (screen_virtual_segment) | |
623 | dosv_refresh_virtual_screen (0, *cols * *rows); | |
4a96d4d2 KH |
624 | } |
625 | ||
48ffe371 RS |
626 | /* If we write a character in the position where the mouse is, |
627 | the mouse cursor may need to be refreshed. */ | |
09e2ac30 RS |
628 | |
629 | static void | |
f32d4091 | 630 | mouse_off_maybe () |
09e2ac30 | 631 | { |
f32d4091 KS |
632 | int x, y; |
633 | ||
634 | if (!mouse_visible) | |
635 | return; | |
636 | ||
637 | mouse_get_xy (&x, &y); | |
638 | if (y != new_pos_Y || x < new_pos_X) | |
639 | return; | |
640 | ||
641 | mouse_off (); | |
642 | } | |
643 | ||
71f65669 EZ |
644 | static void |
645 | IT_ring_bell (void) | |
f32d4091 KS |
646 | { |
647 | if (visible_bell) | |
aee81730 | 648 | { |
f32d4091 KS |
649 | mouse_off (); |
650 | ScreenVisualBell (); | |
aee81730 | 651 | } |
f32d4091 | 652 | else |
3635be47 RS |
653 | { |
654 | union REGS inregs, outregs; | |
655 | inregs.h.ah = 2; | |
656 | inregs.h.dl = 7; | |
657 | intdos (&inregs, &outregs); | |
658 | } | |
09e2ac30 RS |
659 | } |
660 | ||
c77f6f1b EZ |
661 | /* Given a face id FACE, extract the face parameters to be used for |
662 | display until the face changes. The face parameters (actually, its | |
663 | color) are used to construct the video attribute byte for each | |
664 | glyph during the construction of the buffer that is then blitted to | |
665 | the video RAM. */ | |
f32d4091 KS |
666 | static void |
667 | IT_set_face (int face) | |
668 | { | |
c77f6f1b EZ |
669 | struct face *fp = FACE_FROM_ID (selected_frame, face); |
670 | unsigned long fg, bg; | |
f32d4091 | 671 | |
c77f6f1b | 672 | if (!fp) |
e30aee93 EZ |
673 | { |
674 | fp = FACE_FROM_ID (selected_frame, DEFAULT_FACE_ID); | |
675 | /* The default face for the frame should always be realized and | |
676 | cached. */ | |
677 | if (!fp) | |
678 | abort (); | |
679 | } | |
f32d4091 | 680 | screen_face = face; |
c77f6f1b EZ |
681 | fg = fp->foreground; |
682 | bg = fp->background; | |
683 | ||
684 | /* Don't use invalid colors. In particular, a color of -1 means use | |
685 | the colors of the default face, except that if highlight is on, | |
686 | invert the foreground and the background. Note that we assume | |
687 | all 16 colors to be available for the background, since Emacs | |
688 | switches on this mode (and loses the blinking attribute) at | |
689 | startup. */ | |
690 | if (fg == (unsigned long)-1) | |
691 | fg = highlight ? FRAME_BACKGROUND_PIXEL (selected_frame) | |
692 | : FRAME_FOREGROUND_PIXEL (selected_frame); | |
693 | if (bg == (unsigned long)-1) | |
694 | bg = highlight ? FRAME_FOREGROUND_PIXEL (selected_frame) | |
695 | : FRAME_BACKGROUND_PIXEL (selected_frame); | |
696 | if (termscript) | |
697 | fprintf (termscript, "<FACE %d%s: %d/%d>", | |
698 | face, highlight ? "H" : "", fp->foreground, fp->background); | |
699 | if (fg >= 0 && fg < 16) | |
700 | { | |
701 | ScreenAttrib &= 0xf0; | |
702 | ScreenAttrib |= fg; | |
703 | } | |
704 | if (bg >= 0 && bg < 16) | |
705 | { | |
706 | ScreenAttrib &= 0x0f; | |
707 | ScreenAttrib |= ((bg & 0x0f) << 4); | |
708 | } | |
f32d4091 KS |
709 | } |
710 | ||
aa9ce936 EZ |
711 | Lisp_Object Vdos_unsupported_char_glyph; |
712 | ||
71f65669 | 713 | static void |
c77f6f1b | 714 | IT_write_glyphs (struct glyph *str, int str_len) |
f32d4091 | 715 | { |
aa9ce936 EZ |
716 | unsigned char *screen_buf, *screen_bp, *screen_buf_end, *bp; |
717 | int unsupported_face = FAST_GLYPH_FACE (Vdos_unsupported_char_glyph); | |
718 | unsigned unsupported_char= FAST_GLYPH_CHAR (Vdos_unsupported_char_glyph); | |
039274cf | 719 | int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y); |
aa9ce936 EZ |
720 | register int sl = str_len; |
721 | register int tlen = GLYPH_TABLE_LENGTH; | |
722 | register Lisp_Object *tbase = GLYPH_TABLE_BASE; | |
723 | ||
e16bf494 AI |
724 | struct coding_system *coding = (CODING_REQUIRE_ENCODING (&terminal_coding) |
725 | ? &terminal_coding | |
726 | : &safe_terminal_coding); | |
87485d6f | 727 | |
52d38ab2 EZ |
728 | /* Do we need to consider conversion of unibyte characters to |
729 | multibyte? */ | |
730 | int convert_unibyte_characters | |
e16bf494 AI |
731 | = (NILP (current_buffer->enable_multibyte_characters) |
732 | && unibyte_display_via_language_environment); | |
52d38ab2 | 733 | |
aa9ce936 | 734 | if (str_len == 0) return; |
aee81730 | 735 | |
aa9ce936 EZ |
736 | screen_buf = screen_bp = alloca (str_len * 2); |
737 | screen_buf_end = screen_buf + str_len * 2; | |
e30aee93 EZ |
738 | |
739 | /* Since faces get cached and uncached behind our back, we can't | |
740 | rely on their indices in the cache being consistent across | |
741 | invocations. So always reset the screen face to the default | |
742 | face of the frame, before writing glyphs, and let the glyphs | |
743 | set the right face if it's different from the default. */ | |
744 | IT_set_face (DEFAULT_FACE_ID); | |
aee81730 | 745 | |
aa9ce936 EZ |
746 | /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at |
747 | the tail. */ | |
748 | terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK; | |
749 | while (sl) | |
750 | { | |
c77f6f1b | 751 | int cf, chlen, enclen; |
aa9ce936 | 752 | unsigned char workbuf[4], *buf; |
c77f6f1b EZ |
753 | unsigned ch; |
754 | register GLYPH g = GLYPH_FROM_CHAR_GLYPH (*str); | |
aa9ce936 EZ |
755 | |
756 | /* Find the actual glyph to display by traversing the entire | |
757 | aliases chain for this glyph. */ | |
758 | GLYPH_FOLLOW_ALIASES (tbase, tlen, g); | |
759 | ||
760 | /* Glyphs with GLYPH_MASK_PADDING bit set are actually there | |
761 | only for the redisplay code to know how many columns does | |
762 | this character occupy on the screen. Skip padding glyphs. */ | |
c77f6f1b | 763 | if (CHAR_GLYPH_PADDING_P (*str)) |
aa9ce936 EZ |
764 | { |
765 | str++; | |
766 | sl--; | |
767 | } | |
768 | else | |
769 | { | |
770 | /* Convert the character code to multibyte, if they | |
771 | requested display via language environment. */ | |
772 | ch = FAST_GLYPH_CHAR (g); | |
aff4381d EZ |
773 | /* We only want to convert unibyte characters to multibyte |
774 | in unibyte buffers! Otherwise, the 8-bit code might come | |
775 | from the display table set up to display foreign characters. */ | |
52d38ab2 | 776 | if (SINGLE_BYTE_CHAR_P (ch) && convert_unibyte_characters |
f0dd4c35 EZ |
777 | && (ch >= 0240 |
778 | || (ch >= 0200 && !NILP (Vnonascii_translation_table)))) | |
aa9ce936 EZ |
779 | ch = unibyte_char_to_multibyte (ch); |
780 | ||
781 | /* Invalid characters are displayed with a special glyph. */ | |
c77f6f1b | 782 | if (! GLYPH_CHAR_VALID_P (ch)) |
aa9ce936 EZ |
783 | { |
784 | g = !NILP (Vdos_unsupported_char_glyph) | |
785 | ? Vdos_unsupported_char_glyph | |
786 | : MAKE_GLYPH (selected_frame, '\177', | |
787 | GLYPH_FACE (selected_frame, g)); | |
788 | ch = FAST_GLYPH_CHAR (g); | |
789 | } | |
790 | if (COMPOSITE_CHAR_P (ch)) | |
791 | { | |
792 | /* If CH is a composite character, we can display | |
793 | only the first component. */ | |
794 | g = cmpchar_table[COMPOSITE_CHAR_ID (ch)]->glyph[0], | |
795 | ch = GLYPH_CHAR (selected_frame, g); | |
796 | cf = FAST_GLYPH_FACE (g); | |
797 | } | |
798 | ||
799 | /* If the face of this glyph is different from the current | |
800 | screen face, update the screen attribute byte. */ | |
801 | cf = FAST_GLYPH_FACE (g); | |
802 | if (cf != screen_face) | |
803 | IT_set_face (cf); /* handles invalid faces gracefully */ | |
804 | ||
805 | if (GLYPH_SIMPLE_P (tbase, tlen, g)) | |
806 | /* We generate the multi-byte form of CH in BUF. */ | |
807 | chlen = CHAR_STRING (ch, workbuf, buf); | |
808 | else | |
809 | { | |
810 | /* We have a string in Vglyph_table. */ | |
811 | chlen = GLYPH_LENGTH (tbase, g); | |
812 | buf = GLYPH_STRING (tbase, g); | |
813 | } | |
814 | ||
c77f6f1b | 815 | /* If the character is not multibyte, don't bother converting it. */ |
aa9ce936 EZ |
816 | if (chlen == 1) |
817 | { | |
818 | *conversion_buffer = (unsigned char)ch; | |
819 | chlen = 0; | |
820 | enclen = 1; | |
821 | } | |
822 | else | |
823 | { | |
824 | encode_coding (coding, buf, conversion_buffer, chlen, | |
825 | conversion_buffer_size); | |
826 | chlen -= coding->consumed; | |
827 | enclen = coding->produced; | |
828 | ||
829 | /* Replace glyph codes that cannot be converted by | |
830 | terminal_coding with Vdos_unsupported_char_glyph. */ | |
831 | if (*conversion_buffer == '?') | |
832 | { | |
833 | char *cbp = conversion_buffer; | |
834 | ||
835 | while (cbp < conversion_buffer + enclen && *cbp == '?') | |
836 | *cbp++ = unsupported_char; | |
837 | if (unsupported_face != screen_face) | |
838 | IT_set_face (unsupported_face); | |
839 | } | |
840 | } | |
841 | ||
842 | if (enclen + chlen > screen_buf_end - screen_bp) | |
843 | { | |
844 | /* The allocated buffer for screen writes is too small. | |
845 | Flush it and loop again without incrementing STR, so | |
846 | that the next loop will begin with the same glyph. */ | |
847 | int nbytes = screen_bp - screen_buf; | |
848 | ||
849 | mouse_off_maybe (); | |
850 | dosmemput (screen_buf, nbytes, (int)ScreenPrimary + offset); | |
851 | if (screen_virtual_segment) | |
852 | dosv_refresh_virtual_screen (offset, nbytes / 2); | |
853 | new_pos_X += nbytes / 2; | |
854 | offset += nbytes; | |
855 | ||
856 | /* Prepare to reuse the same buffer again. */ | |
857 | screen_bp = screen_buf; | |
858 | } | |
859 | else | |
860 | { | |
861 | /* There's enough place in the allocated buffer to add | |
862 | the encoding of this glyph. */ | |
863 | ||
864 | /* First, copy the encoded bytes. */ | |
865 | for (bp = conversion_buffer; enclen--; bp++) | |
866 | { | |
867 | *screen_bp++ = (unsigned char)*bp; | |
868 | *screen_bp++ = ScreenAttrib; | |
869 | if (termscript) | |
870 | fputc (*bp, termscript); | |
871 | } | |
872 | ||
873 | /* Now copy the bytes not consumed by the encoding. */ | |
874 | if (chlen > 0) | |
875 | { | |
876 | buf += coding->consumed; | |
877 | while (chlen--) | |
878 | { | |
879 | if (termscript) | |
880 | fputc (*buf, termscript); | |
881 | *screen_bp++ = (unsigned char)*buf++; | |
882 | *screen_bp++ = ScreenAttrib; | |
883 | } | |
884 | } | |
885 | ||
886 | /* Update STR and its remaining length. */ | |
887 | str++; | |
888 | sl--; | |
889 | } | |
890 | } | |
aee81730 RS |
891 | } |
892 | ||
aa9ce936 | 893 | /* Dump whatever is left in the screen buffer. */ |
f32d4091 | 894 | mouse_off_maybe (); |
aa9ce936 | 895 | dosmemput (screen_buf, screen_bp - screen_buf, (int)ScreenPrimary + offset); |
039274cf | 896 | if (screen_virtual_segment) |
aa9ce936 EZ |
897 | dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2); |
898 | new_pos_X += (screen_bp - screen_buf) / 2; | |
899 | ||
900 | /* We may have to output some codes to terminate the writing. */ | |
901 | if (CODING_REQUIRE_FLUSHING (coding)) | |
902 | { | |
903 | coding->mode |= CODING_MODE_LAST_BLOCK; | |
904 | encode_coding (coding, "", conversion_buffer, 0, conversion_buffer_size); | |
905 | if (coding->produced > 0) | |
906 | { | |
907 | for (screen_bp = screen_buf, bp = conversion_buffer; | |
908 | coding->produced--; bp++) | |
909 | { | |
910 | *screen_bp++ = (unsigned char)*bp; | |
911 | *screen_bp++ = ScreenAttrib; | |
912 | if (termscript) | |
913 | fputc (*bp, termscript); | |
914 | } | |
915 | offset += screen_bp - screen_buf; | |
916 | mouse_off_maybe (); | |
917 | dosmemput (screen_buf, screen_bp - screen_buf, | |
918 | (int)ScreenPrimary + offset); | |
919 | if (screen_virtual_segment) | |
920 | dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2); | |
921 | new_pos_X += (screen_bp - screen_buf) / 2; | |
922 | } | |
923 | } | |
f32d4091 | 924 | } |
aee81730 | 925 | |
71f65669 EZ |
926 | static void |
927 | IT_clear_end_of_line (int first_unused) | |
f32d4091 KS |
928 | { |
929 | char *spaces, *sp; | |
930 | int i, j; | |
039274cf | 931 | int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y); |
aa9ce936 EZ |
932 | extern int fatal_error_in_progress; |
933 | ||
934 | if (fatal_error_in_progress) | |
935 | return; | |
f32d4091 KS |
936 | |
937 | IT_set_face (0); | |
938 | if (termscript) | |
939 | fprintf (termscript, "<CLR:EOL>"); | |
940 | i = (j = screen_size_X - new_pos_X) * 2; | |
941 | spaces = sp = alloca (i); | |
aee81730 | 942 | |
f32d4091 | 943 | while (--j >= 0) |
aee81730 | 944 | { |
f32d4091 KS |
945 | *sp++ = ' '; |
946 | *sp++ = ScreenAttrib; | |
aee81730 RS |
947 | } |
948 | ||
f32d4091 | 949 | mouse_off_maybe (); |
039274cf EZ |
950 | dosmemput (spaces, i, (int)ScreenPrimary + offset); |
951 | if (screen_virtual_segment) | |
952 | dosv_refresh_virtual_screen (offset, i / 2); | |
aee81730 RS |
953 | } |
954 | ||
71f65669 | 955 | static void |
f32d4091 KS |
956 | IT_clear_screen (void) |
957 | { | |
958 | if (termscript) | |
959 | fprintf (termscript, "<CLR:SCR>"); | |
960 | IT_set_face (0); | |
961 | mouse_off (); | |
962 | ScreenClear (); | |
039274cf EZ |
963 | if (screen_virtual_segment) |
964 | dosv_refresh_virtual_screen (0, screen_size); | |
f32d4091 KS |
965 | new_pos_X = new_pos_Y = 0; |
966 | } | |
967 | ||
71f65669 | 968 | static void |
f32d4091 KS |
969 | IT_clear_to_end (void) |
970 | { | |
971 | if (termscript) | |
972 | fprintf (termscript, "<CLR:EOS>"); | |
973 | ||
974 | while (new_pos_Y < screen_size_Y) { | |
975 | new_pos_X = 0; | |
976 | IT_clear_end_of_line (0); | |
977 | new_pos_Y++; | |
978 | } | |
979 | } | |
980 | ||
71f65669 | 981 | static void |
f32d4091 KS |
982 | IT_cursor_to (int y, int x) |
983 | { | |
984 | if (termscript) | |
985 | fprintf (termscript, "\n<XY=%dx%d>", x, y); | |
986 | new_pos_X = x; | |
987 | new_pos_Y = y; | |
988 | } | |
989 | ||
fc171623 KH |
990 | static int cursor_cleared; |
991 | ||
d1d5dc19 | 992 | static void |
fc171623 KH |
993 | IT_display_cursor (int on) |
994 | { | |
995 | if (on && cursor_cleared) | |
996 | { | |
997 | ScreenSetCursor (current_pos_Y, current_pos_X); | |
998 | cursor_cleared = 0; | |
999 | } | |
1000 | else if (!on && !cursor_cleared) | |
1001 | { | |
1002 | ScreenSetCursor (-1, -1); | |
1003 | cursor_cleared = 1; | |
1004 | } | |
1005 | } | |
1006 | ||
1007 | /* Emacs calls cursor-movement functions a lot when it updates the | |
1008 | display (probably a legacy of old terminals where you cannot | |
1009 | update a screen line without first moving the cursor there). | |
1010 | However, cursor movement is expensive on MSDOS (it calls a slow | |
1011 | BIOS function and requires 2 mode switches), while actual screen | |
1012 | updates access the video memory directly and don't depend on | |
1013 | cursor position. To avoid slowing down the redisplay, we cheat: | |
1014 | all functions that move the cursor only set internal variables | |
1015 | which record the cursor position, whereas the cursor is only | |
1016 | moved to its final position whenever screen update is complete. | |
1017 | ||
1018 | `IT_cmgoto' is called from the keyboard reading loop and when the | |
1019 | frame update is complete. This means that we are ready for user | |
1020 | input, so we update the cursor position to show where the point is, | |
1021 | and also make the mouse pointer visible. | |
1022 | ||
1023 | Special treatment is required when the cursor is in the echo area, | |
1024 | to put the cursor at the end of the text displayed there. */ | |
1025 | ||
71f65669 EZ |
1026 | static void |
1027 | IT_cmgoto (FRAME_PTR f) | |
fc171623 KH |
1028 | { |
1029 | /* Only set the cursor to where it should be if the display is | |
1030 | already in sync with the window contents. */ | |
1031 | int update_cursor_pos = MODIFF == unchanged_modified; | |
06da1de1 EZ |
1032 | static int previous_pos_X = -1; |
1033 | ||
1034 | /* If the display is in sync, forget any previous knowledge about | |
1035 | cursor position. This is primarily for unexpected events like | |
1036 | C-g in the minibuffer. */ | |
1037 | if (update_cursor_pos && previous_pos_X >= 0) | |
1038 | previous_pos_X = -1; | |
1039 | /* If we are in the echo area, put the cursor at the | |
1040 | end of the echo area message. */ | |
fc171623 KH |
1041 | if (!update_cursor_pos |
1042 | && XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top) <= new_pos_Y) | |
1043 | { | |
06da1de1 EZ |
1044 | int tem_X = current_pos_X, dummy; |
1045 | ||
1046 | if (echo_area_glyphs) | |
1047 | { | |
1048 | tem_X = echo_area_glyphs_length; | |
1049 | /* Save current cursor position, to be restored after the | |
1050 | echo area message is erased. Only remember one level | |
1051 | of previous cursor position. */ | |
1052 | if (previous_pos_X == -1) | |
1053 | ScreenGetCursor (&dummy, &previous_pos_X); | |
1054 | } | |
1055 | else if (previous_pos_X >= 0) | |
1056 | { | |
1057 | /* We wind up here after the echo area message is erased. | |
1058 | Restore the cursor position we remembered above. */ | |
1059 | tem_X = previous_pos_X; | |
1060 | previous_pos_X = -1; | |
1061 | } | |
9a599a60 | 1062 | |
06da1de1 | 1063 | if (current_pos_X != tem_X) |
9a599a60 EZ |
1064 | { |
1065 | new_pos_X = tem_X; | |
1066 | update_cursor_pos = 1; | |
1067 | } | |
fc171623 KH |
1068 | } |
1069 | ||
1070 | if (update_cursor_pos | |
1071 | && (current_pos_X != new_pos_X || current_pos_Y != new_pos_Y)) | |
1072 | { | |
1073 | ScreenSetCursor (current_pos_Y = new_pos_Y, current_pos_X = new_pos_X); | |
1074 | if (termscript) | |
1075 | fprintf (termscript, "\n<CURSOR:%dx%d>", current_pos_X, current_pos_Y); | |
1076 | } | |
1077 | ||
1078 | /* Maybe cursor is invisible, so make it visible. */ | |
1079 | IT_display_cursor (1); | |
1080 | ||
1081 | /* Mouse pointer should be always visible if we are waiting for | |
1082 | keyboard input. */ | |
1083 | if (!mouse_visible) | |
1084 | mouse_on (); | |
1085 | } | |
1086 | ||
71f65669 EZ |
1087 | static void |
1088 | IT_reassert_line_highlight (int new, int vpos) | |
f32d4091 KS |
1089 | { |
1090 | highlight = new; | |
1091 | IT_set_face (0); /* To possibly clear the highlighting. */ | |
1092 | } | |
1093 | ||
71f65669 | 1094 | static void |
c77f6f1b | 1095 | IT_change_line_highlight (int new_highlight, int y, int vpos, int first_unused_hpos) |
1b94449f | 1096 | { |
f32d4091 KS |
1097 | highlight = new_highlight; |
1098 | IT_set_face (0); /* To possibly clear the highlighting. */ | |
1099 | IT_cursor_to (vpos, 0); | |
1100 | IT_clear_end_of_line (first_unused_hpos); | |
1101 | } | |
1102 | ||
71f65669 EZ |
1103 | static void |
1104 | IT_update_begin (struct frame *foo) | |
f32d4091 KS |
1105 | { |
1106 | highlight = 0; | |
1107 | IT_set_face (0); /* To possibly clear the highlighting. */ | |
1108 | screen_face = -1; | |
1109 | } | |
1110 | ||
71f65669 EZ |
1111 | static void |
1112 | IT_update_end (struct frame *foo) | |
f32d4091 KS |
1113 | { |
1114 | } | |
1b94449f | 1115 | |
c77f6f1b EZ |
1116 | /* Copy LEN glyphs displayed on a single line whose vertical position |
1117 | is YPOS, beginning at horizontal position XFROM to horizontal | |
1118 | position XTO, by moving blocks in the video memory. Used by | |
1119 | functions that insert and delete glyphs. */ | |
1120 | static void | |
1121 | IT_copy_glyphs (int xfrom, int xto, size_t len, int ypos) | |
1122 | { | |
1123 | /* The offsets of source and destination relative to the | |
1124 | conventional memorty selector. */ | |
1125 | int from = 2 * (xfrom + screen_size_X * ypos) + ScreenPrimary; | |
1126 | int to = 2 * (xto + screen_size_X * ypos) + ScreenPrimary; | |
1127 | ||
1128 | if (from == to || len <= 0) | |
1129 | return; | |
1130 | ||
1131 | _farsetsel (_dos_ds); | |
1132 | ||
1133 | /* The source and destination might overlap, so we need to move | |
1134 | glyphs non-destructively. */ | |
1135 | if (from > to) | |
1136 | { | |
1137 | for ( ; len; from += 2, to += 2, len--) | |
1138 | _farnspokew (to, _farnspeekw (from)); | |
1139 | } | |
1140 | else | |
1141 | { | |
1142 | from += (len - 1) * 2; | |
1143 | to += (len - 1) * 2; | |
1144 | for ( ; len; from -= 2, to -= 2, len--) | |
1145 | _farnspokew (to, _farnspeekw (from)); | |
1146 | } | |
1147 | if (screen_virtual_segment) | |
1148 | dosv_refresh_virtual_screen (ypos * screen_size_X * 2, screen_size_X); | |
1149 | } | |
1150 | ||
1151 | /* Insert and delete glyphs. */ | |
aa9ce936 EZ |
1152 | static void |
1153 | IT_insert_glyphs (start, len) | |
c77f6f1b | 1154 | register struct glyph *start; |
aa9ce936 EZ |
1155 | register int len; |
1156 | { | |
c77f6f1b EZ |
1157 | int shift_by_width = screen_size_X - (new_pos_X + len); |
1158 | ||
1159 | /* Shift right the glyphs from the nominal cursor position to the | |
1160 | end of this line. */ | |
1161 | IT_copy_glyphs (new_pos_X, new_pos_X + len, shift_by_width, new_pos_Y); | |
1162 | ||
1163 | /* Now write the glyphs to be inserted. */ | |
1164 | IT_write_glyphs (start, len); | |
aa9ce936 EZ |
1165 | } |
1166 | ||
1167 | static void | |
1168 | IT_delete_glyphs (n) | |
1169 | register int n; | |
1170 | { | |
1171 | abort (); | |
1172 | } | |
1173 | ||
211c7152 | 1174 | /* set-window-configuration on window.c needs this. */ |
3bb1f22f RS |
1175 | void |
1176 | x_set_menu_bar_lines (f, value, oldval) | |
1177 | struct frame *f; | |
1178 | Lisp_Object value, oldval; | |
1179 | { | |
211c7152 EZ |
1180 | set_menu_bar_lines (f, value, oldval); |
1181 | } | |
3bb1f22f | 1182 | |
211c7152 | 1183 | /* This was copied from xfns.c */ |
3bb1f22f | 1184 | |
211c7152 EZ |
1185 | Lisp_Object Qbackground_color; |
1186 | Lisp_Object Qforeground_color; | |
1187 | extern Lisp_Object Qtitle; | |
3bb1f22f | 1188 | |
48ffe371 RS |
1189 | /* IT_set_terminal_modes is called when emacs is started, |
1190 | resumed, and whenever the screen is redrawn! */ | |
f32d4091 | 1191 | |
71f65669 | 1192 | static void |
f32d4091 KS |
1193 | IT_set_terminal_modes (void) |
1194 | { | |
aee81730 | 1195 | if (termscript) |
f32d4091 KS |
1196 | fprintf (termscript, "\n<SET_TERM>"); |
1197 | highlight = 0; | |
1198 | ||
1199 | screen_size_X = ScreenCols (); | |
1200 | screen_size_Y = ScreenRows (); | |
1201 | screen_size = screen_size_X * screen_size_Y; | |
aee81730 | 1202 | |
f32d4091 KS |
1203 | new_pos_X = new_pos_Y = 0; |
1204 | current_pos_X = current_pos_Y = -1; | |
1205 | ||
1206 | if (term_setup_done) | |
1207 | return; | |
1208 | term_setup_done = 1; | |
aee81730 | 1209 | |
f32d4091 KS |
1210 | startup_screen_size_X = screen_size_X; |
1211 | startup_screen_size_Y = screen_size_Y; | |
c9adab25 | 1212 | startup_screen_attrib = ScreenAttrib; |
f32d4091 | 1213 | |
039274cf EZ |
1214 | #if __DJGPP__ > 1 |
1215 | /* Is DOS/V (or any other RSIS software which relocates | |
1216 | the screen) installed? */ | |
1217 | { | |
1218 | unsigned short es_value; | |
1219 | __dpmi_regs regs; | |
1220 | ||
1221 | regs.h.ah = 0xfe; /* get relocated screen address */ | |
1222 | if (ScreenPrimary == 0xb0000UL || ScreenPrimary == 0xb8000UL) | |
1223 | regs.x.es = (ScreenPrimary >> 4) & 0xffff; | |
1224 | else if (screen_old_address) /* already switched to Japanese mode once */ | |
1225 | regs.x.es = (screen_old_address >> 4) & 0xffff; | |
1226 | else | |
1227 | regs.x.es = ScreenMode () == 7 ? 0xb000 : 0xb800; | |
1228 | regs.x.di = 0; | |
1229 | es_value = regs.x.es; | |
1230 | __dpmi_int (0x10, ®s); | |
1231 | ||
d1d5dc19 | 1232 | if (regs.x.es != es_value) |
039274cf | 1233 | { |
d1d5dc19 EZ |
1234 | /* screen_old_address is only set if ScreenPrimary does NOT |
1235 | already point to the relocated buffer address returned by | |
1236 | the Int 10h/AX=FEh call above. DJGPP v2.02 and later sets | |
1237 | ScreenPrimary to that address at startup under DOS/V. */ | |
1238 | if (regs.x.es != (ScreenPrimary >> 4) & 0xffff) | |
1239 | screen_old_address = ScreenPrimary; | |
039274cf EZ |
1240 | screen_virtual_segment = regs.x.es; |
1241 | screen_virtual_offset = regs.x.di; | |
1242 | ScreenPrimary = (screen_virtual_segment << 4) + screen_virtual_offset; | |
1243 | } | |
1244 | } | |
1245 | #endif /* __DJGPP__ > 1 */ | |
1246 | ||
f32d4091 KS |
1247 | ScreenGetCursor (&startup_pos_Y, &startup_pos_X); |
1248 | ScreenRetrieve (startup_screen_buffer = xmalloc (screen_size * 2)); | |
1249 | ||
1250 | if (termscript) | |
c9adab25 | 1251 | fprintf (termscript, "<SCREEN SAVED (dimensions=%dx%d)>\n", |
039274cf | 1252 | screen_size_X, screen_size_Y); |
76ac1508 RS |
1253 | |
1254 | bright_bg (); | |
f32d4091 KS |
1255 | } |
1256 | ||
48ffe371 RS |
1257 | /* IT_reset_terminal_modes is called when emacs is |
1258 | suspended or killed. */ | |
f32d4091 | 1259 | |
71f65669 | 1260 | static void |
f32d4091 KS |
1261 | IT_reset_terminal_modes (void) |
1262 | { | |
c9adab25 KH |
1263 | int display_row_start = (int) ScreenPrimary; |
1264 | int saved_row_len = startup_screen_size_X * 2; | |
1265 | int update_row_len = ScreenCols () * 2; | |
1266 | int current_rows = ScreenRows (); | |
1267 | int to_next_row = update_row_len; | |
1268 | unsigned char *saved_row = startup_screen_buffer; | |
1269 | int cursor_pos_X = ScreenCols () - 1; | |
1270 | int cursor_pos_Y = ScreenRows () - 1; | |
1271 | ||
f32d4091 | 1272 | if (termscript) |
5063b150 | 1273 | fprintf (termscript, "\n<RESET_TERM>"); |
f32d4091 KS |
1274 | |
1275 | highlight = 0; | |
1276 | ||
1277 | if (!term_setup_done) | |
1278 | return; | |
1279 | ||
c9adab25 | 1280 | mouse_off (); |
b36701cc RS |
1281 | |
1282 | /* Leave the video system in the same state as we found it, | |
1283 | as far as the blink/bright-background bit is concerned. */ | |
1284 | maybe_enable_blinking (); | |
06b1ea13 | 1285 | |
c9adab25 KH |
1286 | /* We have a situation here. |
1287 | We cannot just do ScreenUpdate(startup_screen_buffer) because | |
1288 | the luser could have changed screen dimensions inside Emacs | |
1289 | and failed (or didn't want) to restore them before killing | |
1290 | Emacs. ScreenUpdate() uses the *current* screen dimensions and | |
1291 | thus will happily use memory outside what was allocated for | |
1292 | `startup_screen_buffer'. | |
1293 | Thus we only restore as much as the current screen dimensions | |
1294 | can hold, and clear the rest (if the saved screen is smaller than | |
1295 | the current) with the color attribute saved at startup. The cursor | |
1296 | is also restored within the visible dimensions. */ | |
1297 | ||
1298 | ScreenAttrib = startup_screen_attrib; | |
c9adab25 | 1299 | |
06b1ea13 EZ |
1300 | /* Don't restore the screen if we are exiting less than 2 seconds |
1301 | after startup: we might be crashing, and the screen might show | |
1302 | some vital clues to what's wrong. */ | |
1303 | if (clock () - startup_time >= 2*CLOCKS_PER_SEC) | |
c9adab25 | 1304 | { |
06b1ea13 | 1305 | ScreenClear (); |
039274cf | 1306 | if (screen_virtual_segment) |
06b1ea13 EZ |
1307 | dosv_refresh_virtual_screen (0, screen_size); |
1308 | ||
1309 | if (update_row_len > saved_row_len) | |
1310 | update_row_len = saved_row_len; | |
1311 | if (current_rows > startup_screen_size_Y) | |
1312 | current_rows = startup_screen_size_Y; | |
1313 | ||
1314 | if (termscript) | |
1315 | fprintf (termscript, "<SCREEN RESTORED (dimensions=%dx%d)>\n", | |
1316 | update_row_len / 2, current_rows); | |
1317 | ||
1318 | while (current_rows--) | |
1319 | { | |
1320 | dosmemput (saved_row, update_row_len, display_row_start); | |
1321 | if (screen_virtual_segment) | |
1322 | dosv_refresh_virtual_screen (display_row_start - ScreenPrimary, | |
1323 | update_row_len / 2); | |
1324 | saved_row += saved_row_len; | |
1325 | display_row_start += to_next_row; | |
1326 | } | |
c9adab25 KH |
1327 | } |
1328 | if (startup_pos_X < cursor_pos_X) | |
1329 | cursor_pos_X = startup_pos_X; | |
1330 | if (startup_pos_Y < cursor_pos_Y) | |
1331 | cursor_pos_Y = startup_pos_Y; | |
1332 | ||
1333 | ScreenSetCursor (cursor_pos_Y, cursor_pos_X); | |
1334 | xfree (startup_screen_buffer); | |
f32d4091 KS |
1335 | |
1336 | term_setup_done = 0; | |
1337 | } | |
1338 | ||
71f65669 EZ |
1339 | static void |
1340 | IT_set_terminal_window (int foo) | |
f32d4091 KS |
1341 | { |
1342 | } | |
1343 | ||
1344 | void | |
3bb1f22f | 1345 | IT_set_frame_parameters (f, alist) |
c77f6f1b | 1346 | struct frame *f; |
f32d4091 KS |
1347 | Lisp_Object alist; |
1348 | { | |
1349 | Lisp_Object tail; | |
db722735 RS |
1350 | int length = XINT (Flength (alist)); |
1351 | int i; | |
1352 | Lisp_Object *parms | |
1353 | = (Lisp_Object *) alloca (length * sizeof (Lisp_Object)); | |
1354 | Lisp_Object *values | |
1355 | = (Lisp_Object *) alloca (length * sizeof (Lisp_Object)); | |
f32d4091 | 1356 | int redraw; |
c77f6f1b EZ |
1357 | struct face *dflt = NULL; |
1358 | ||
1359 | if (FRAME_FACE_CACHE (f)) | |
1360 | dflt = FACE_FROM_ID (f, DEFAULT_FACE_ID); | |
f32d4091 KS |
1361 | |
1362 | redraw = 0; | |
db722735 RS |
1363 | |
1364 | /* Extract parm names and values into those vectors. */ | |
1365 | i = 0; | |
f32d4091 KS |
1366 | for (tail = alist; CONSP (tail); tail = Fcdr (tail)) |
1367 | { | |
db722735 | 1368 | Lisp_Object elt; |
f32d4091 KS |
1369 | |
1370 | elt = Fcar (tail); | |
db722735 RS |
1371 | parms[i] = Fcar (elt); |
1372 | CHECK_SYMBOL (parms[i], 1); | |
1373 | values[i] = Fcdr (elt); | |
1374 | i++; | |
1375 | } | |
1376 | ||
1377 | ||
1378 | /* Now process them in reverse of specified order. */ | |
1379 | for (i--; i >= 0; i--) | |
1380 | { | |
1381 | Lisp_Object prop = parms[i]; | |
1382 | Lisp_Object val = values[i]; | |
f32d4091 | 1383 | |
4e825084 | 1384 | if (EQ (prop, Qforeground_color)) |
f32d4091 | 1385 | { |
c77f6f1b EZ |
1386 | unsigned long new_color = load_color (f, NULL, val, |
1387 | LFACE_FOREGROUND_INDEX); | |
f32d4091 KS |
1388 | if (new_color != ~0) |
1389 | { | |
c77f6f1b EZ |
1390 | if (!dflt) |
1391 | abort (); | |
f32d4091 | 1392 | FRAME_FOREGROUND_PIXEL (f) = new_color; |
c77f6f1b | 1393 | dflt->foreground = new_color; |
f32d4091 | 1394 | redraw = 1; |
76ac1508 | 1395 | if (termscript) |
a7cf9151 | 1396 | fprintf (termscript, "<FGCOLOR %lu>\n", new_color); |
f32d4091 KS |
1397 | } |
1398 | } | |
4e825084 | 1399 | else if (EQ (prop, Qbackground_color)) |
f32d4091 | 1400 | { |
c77f6f1b EZ |
1401 | unsigned long new_color = load_color (f, NULL, val, |
1402 | LFACE_BACKGROUND_INDEX); | |
f32d4091 KS |
1403 | if (new_color != ~0) |
1404 | { | |
c77f6f1b EZ |
1405 | if (!dflt) |
1406 | abort (); | |
76ac1508 | 1407 | FRAME_BACKGROUND_PIXEL (f) = new_color; |
c77f6f1b | 1408 | dflt->background = new_color; |
f32d4091 | 1409 | redraw = 1; |
76ac1508 | 1410 | if (termscript) |
a7cf9151 | 1411 | fprintf (termscript, "<BGCOLOR %lu>\n", new_color); |
f32d4091 KS |
1412 | } |
1413 | } | |
211c7152 EZ |
1414 | else if (EQ (prop, Qtitle)) |
1415 | { | |
1416 | x_set_title (f, val); | |
1417 | if (termscript) | |
1418 | fprintf (termscript, "<TITLE: %s>\n", XSTRING (val)->data); | |
1419 | } | |
1420 | else if (EQ (prop, intern ("reverse")) && EQ (val, Qt)) | |
1421 | { | |
1422 | unsigned long fg = FRAME_FOREGROUND_PIXEL (f); | |
db722735 | 1423 | |
c77f6f1b EZ |
1424 | if (!dflt) |
1425 | abort (); | |
1426 | FRAME_FOREGROUND_PIXEL (f) = FRAME_BACKGROUND_PIXEL (f); /* FIXME! */ | |
211c7152 | 1427 | FRAME_BACKGROUND_PIXEL (f) = fg; |
c77f6f1b EZ |
1428 | dflt->foreground = FRAME_FOREGROUND_PIXEL (f); |
1429 | dflt->foreground = fg; | |
211c7152 EZ |
1430 | if (termscript) |
1431 | fprintf (termscript, "<INVERSE-VIDEO>\n"); | |
1432 | } | |
db722735 RS |
1433 | store_frame_param (f, prop, val); |
1434 | ||
f32d4091 KS |
1435 | } |
1436 | ||
1437 | if (redraw) | |
1438 | { | |
1439 | recompute_basic_faces (f); | |
3bb1f22f RS |
1440 | if (f == selected_frame) |
1441 | redraw_frame (f); | |
f32d4091 KS |
1442 | } |
1443 | } | |
1444 | ||
a7cf9151 EZ |
1445 | extern void init_frame_faces (FRAME_PTR); |
1446 | ||
f32d4091 KS |
1447 | #endif /* !HAVE_X_WINDOWS */ |
1448 | ||
1449 | ||
48ffe371 RS |
1450 | /* Do we need the internal terminal? */ |
1451 | ||
f32d4091 KS |
1452 | void |
1453 | internal_terminal_init () | |
1454 | { | |
1455 | char *term = getenv ("TERM"); | |
1456 | char *colors; | |
1457 | ||
1458 | #ifdef HAVE_X_WINDOWS | |
1459 | if (!inhibit_window_system) | |
1460 | return; | |
1461 | #endif | |
1462 | ||
1463 | internal_terminal | |
1464 | = (!noninteractive) && term && !strcmp (term, "internal"); | |
1465 | ||
1466 | if (getenv ("EMACSTEST")) | |
5063b150 | 1467 | termscript = fopen (getenv ("EMACSTEST"), "wt"); |
f32d4091 KS |
1468 | |
1469 | #ifndef HAVE_X_WINDOWS | |
1470 | if (!internal_terminal || inhibit_window_system) | |
1471 | { | |
3bb1f22f | 1472 | selected_frame->output_method = output_termcap; |
f32d4091 KS |
1473 | return; |
1474 | } | |
1475 | ||
1476 | Vwindow_system = intern ("pc"); | |
1477 | Vwindow_system_version = make_number (1); | |
039274cf EZ |
1478 | |
1479 | /* If Emacs was dumped on DOS/V machine, forget the stale VRAM address. */ | |
1480 | screen_old_address = 0; | |
1481 | ||
f32d4091 KS |
1482 | bzero (&the_only_x_display, sizeof the_only_x_display); |
1483 | the_only_x_display.background_pixel = 7; /* White */ | |
1484 | the_only_x_display.foreground_pixel = 0; /* Black */ | |
76ac1508 | 1485 | bright_bg (); |
5063b150 | 1486 | colors = getenv ("EMACSCOLORS"); |
f32d4091 KS |
1487 | if (colors && strlen (colors) >= 2) |
1488 | { | |
76ac1508 RS |
1489 | /* The colors use 4 bits each (we enable bright background). */ |
1490 | if (isdigit (colors[0])) | |
1491 | colors[0] -= '0'; | |
1492 | else if (isxdigit (colors[0])) | |
1493 | colors[0] -= (isupper (colors[0]) ? 'A' : 'a') - 10; | |
1bd7b2c7 RS |
1494 | if (colors[0] >= 0 && colors[0] < 16) |
1495 | the_only_x_display.foreground_pixel = colors[0]; | |
76ac1508 RS |
1496 | if (isdigit (colors[1])) |
1497 | colors[1] -= '0'; | |
1498 | else if (isxdigit (colors[1])) | |
1499 | colors[1] -= (isupper (colors[1]) ? 'A' : 'a') - 10; | |
1500 | if (colors[1] >= 0 && colors[1] < 16) | |
1bd7b2c7 | 1501 | the_only_x_display.background_pixel = colors[1]; |
f32d4091 KS |
1502 | } |
1503 | the_only_x_display.line_height = 1; | |
64ec6a02 | 1504 | the_only_x_display.font = (XFontStruct *)1; /* must *not* be zero */ |
f32d4091 | 1505 | |
3bb1f22f | 1506 | init_frame_faces (selected_frame); |
f32d4091 KS |
1507 | |
1508 | ring_bell_hook = IT_ring_bell; | |
aa9ce936 EZ |
1509 | insert_glyphs_hook = IT_insert_glyphs; |
1510 | delete_glyphs_hook = IT_delete_glyphs; | |
f32d4091 KS |
1511 | write_glyphs_hook = IT_write_glyphs; |
1512 | cursor_to_hook = raw_cursor_to_hook = IT_cursor_to; | |
1513 | clear_to_end_hook = IT_clear_to_end; | |
1514 | clear_end_of_line_hook = IT_clear_end_of_line; | |
1515 | clear_frame_hook = IT_clear_screen; | |
1516 | change_line_highlight_hook = IT_change_line_highlight; | |
1517 | update_begin_hook = IT_update_begin; | |
1518 | update_end_hook = IT_update_end; | |
1519 | reassert_line_highlight_hook = IT_reassert_line_highlight; | |
fc171623 | 1520 | frame_up_to_date_hook = IT_cmgoto; /* position cursor when update is done */ |
f32d4091 KS |
1521 | |
1522 | /* These hooks are called by term.c without being checked. */ | |
1523 | set_terminal_modes_hook = IT_set_terminal_modes; | |
1524 | reset_terminal_modes_hook = IT_reset_terminal_modes; | |
1525 | set_terminal_window_hook = IT_set_terminal_window; | |
c77f6f1b | 1526 | char_ins_del_ok = 0; |
f32d4091 KS |
1527 | #endif |
1528 | } | |
1529 | ||
1530 | dos_get_saved_screen (screen, rows, cols) | |
1531 | char **screen; | |
1532 | int *rows; | |
1533 | int *cols; | |
1534 | { | |
1535 | #ifndef HAVE_X_WINDOWS | |
1536 | *screen = startup_screen_buffer; | |
1537 | *cols = startup_screen_size_X; | |
1538 | *rows = startup_screen_size_Y; | |
039274cf | 1539 | return *screen != (char *)0; |
f32d4091 KS |
1540 | #else |
1541 | return 0; | |
1542 | #endif | |
1543 | } | |
3bb1f22f RS |
1544 | |
1545 | #ifndef HAVE_X_WINDOWS | |
1546 | ||
1547 | /* We are not X, but we can emulate it well enough for our needs... */ | |
1548 | void | |
1549 | check_x (void) | |
1550 | { | |
1551 | if (! FRAME_MSDOS_P (selected_frame)) | |
1552 | error ("Not running under a windows system"); | |
1553 | } | |
1554 | ||
1555 | #endif | |
1556 | ||
5063b150 | 1557 | \f |
f32d4091 KS |
1558 | /* ----------------------- Keyboard control ---------------------- |
1559 | * | |
1560 | * Keymaps reflect the following keyboard layout: | |
1561 | * | |
1562 | * 0 1 2 3 4 5 6 7 8 9 10 11 12 BS | |
1563 | * TAB 15 16 17 18 19 20 21 22 23 24 25 26 (41) | |
1564 | * CLOK 30 31 32 33 34 35 36 37 38 39 40 (41) RET | |
1565 | * SH () 45 46 47 48 49 50 51 52 53 54 SHIFT | |
1566 | * SPACE | |
1567 | */ | |
1568 | ||
d1d5dc19 EZ |
1569 | #define Ignore 0x0000 |
1570 | #define Normal 0x0000 /* normal key - alt changes scan-code */ | |
1571 | #define FctKey 0x1000 /* func key if c == 0, else c */ | |
1572 | #define Special 0x2000 /* func key even if c != 0 */ | |
1573 | #define ModFct 0x3000 /* special if mod-keys, else 'c' */ | |
1574 | #define Map 0x4000 /* alt scan-code, map to unshift/shift key */ | |
1575 | #define KeyPad 0x5000 /* map to insert/kp-0 depending on c == 0xe0 */ | |
1576 | #define Grey 0x6000 /* Grey keypad key */ | |
1577 | ||
1578 | #define Alt 0x0100 /* alt scan-code */ | |
1579 | #define Ctrl 0x0200 /* ctrl scan-code */ | |
1580 | #define Shift 0x0400 /* shift scan-code */ | |
1581 | ||
f32d4091 KS |
1582 | static int extended_kbd; /* 101 (102) keyboard present. */ |
1583 | ||
d1d5dc19 EZ |
1584 | struct kbd_translate { |
1585 | unsigned char sc; | |
1586 | unsigned char ch; | |
1587 | unsigned short code; | |
1588 | }; | |
1589 | ||
f32d4091 KS |
1590 | struct dos_keyboard_map |
1591 | { | |
1592 | char *unshifted; | |
1593 | char *shifted; | |
1594 | char *alt_gr; | |
d1d5dc19 | 1595 | struct kbd_translate *translate_table; |
f32d4091 KS |
1596 | }; |
1597 | ||
1598 | ||
1599 | static struct dos_keyboard_map us_keyboard = { | |
1600 | /* 0 1 2 3 4 5 */ | |
1601 | /* 01234567890123456789012345678901234567890 12345678901234 */ | |
1602 | "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ", | |
1603 | /* 0123456789012345678901234567890123456789 012345678901234 */ | |
1604 | "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ", | |
d1d5dc19 EZ |
1605 | 0, /* no Alt-Gr key */ |
1606 | 0 /* no translate table */ | |
f32d4091 KS |
1607 | }; |
1608 | ||
1609 | static struct dos_keyboard_map fr_keyboard = { | |
1610 | /* 0 1 2 3 4 5 */ | |
1611 | /* 012 3456789012345678901234567890123456789012345678901234 */ | |
1612 |