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 EZ |
672 | if (!fp) |
673 | fp = FACE_FROM_ID (selected_frame, DEFAULT_FACE_ID); | |
f32d4091 | 674 | screen_face = face; |
c77f6f1b EZ |
675 | fg = fp->foreground; |
676 | bg = fp->background; | |
677 | ||
678 | /* Don't use invalid colors. In particular, a color of -1 means use | |
679 | the colors of the default face, except that if highlight is on, | |
680 | invert the foreground and the background. Note that we assume | |
681 | all 16 colors to be available for the background, since Emacs | |
682 | switches on this mode (and loses the blinking attribute) at | |
683 | startup. */ | |
684 | if (fg == (unsigned long)-1) | |
685 | fg = highlight ? FRAME_BACKGROUND_PIXEL (selected_frame) | |
686 | : FRAME_FOREGROUND_PIXEL (selected_frame); | |
687 | if (bg == (unsigned long)-1) | |
688 | bg = highlight ? FRAME_FOREGROUND_PIXEL (selected_frame) | |
689 | : FRAME_BACKGROUND_PIXEL (selected_frame); | |
690 | if (termscript) | |
691 | fprintf (termscript, "<FACE %d%s: %d/%d>", | |
692 | face, highlight ? "H" : "", fp->foreground, fp->background); | |
693 | if (fg >= 0 && fg < 16) | |
694 | { | |
695 | ScreenAttrib &= 0xf0; | |
696 | ScreenAttrib |= fg; | |
697 | } | |
698 | if (bg >= 0 && bg < 16) | |
699 | { | |
700 | ScreenAttrib &= 0x0f; | |
701 | ScreenAttrib |= ((bg & 0x0f) << 4); | |
702 | } | |
f32d4091 KS |
703 | } |
704 | ||
aa9ce936 EZ |
705 | Lisp_Object Vdos_unsupported_char_glyph; |
706 | ||
71f65669 | 707 | static void |
c77f6f1b | 708 | IT_write_glyphs (struct glyph *str, int str_len) |
f32d4091 | 709 | { |
aa9ce936 EZ |
710 | unsigned char *screen_buf, *screen_bp, *screen_buf_end, *bp; |
711 | int unsupported_face = FAST_GLYPH_FACE (Vdos_unsupported_char_glyph); | |
712 | unsigned unsupported_char= FAST_GLYPH_CHAR (Vdos_unsupported_char_glyph); | |
039274cf | 713 | int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y); |
aa9ce936 EZ |
714 | register int sl = str_len; |
715 | register int tlen = GLYPH_TABLE_LENGTH; | |
716 | register Lisp_Object *tbase = GLYPH_TABLE_BASE; | |
717 | ||
e16bf494 AI |
718 | struct coding_system *coding = (CODING_REQUIRE_ENCODING (&terminal_coding) |
719 | ? &terminal_coding | |
720 | : &safe_terminal_coding); | |
87485d6f | 721 | |
52d38ab2 EZ |
722 | /* Do we need to consider conversion of unibyte characters to |
723 | multibyte? */ | |
724 | int convert_unibyte_characters | |
e16bf494 AI |
725 | = (NILP (current_buffer->enable_multibyte_characters) |
726 | && unibyte_display_via_language_environment); | |
52d38ab2 | 727 | |
aa9ce936 | 728 | if (str_len == 0) return; |
aee81730 | 729 | |
aa9ce936 EZ |
730 | screen_buf = screen_bp = alloca (str_len * 2); |
731 | screen_buf_end = screen_buf + str_len * 2; | |
aee81730 | 732 | |
aa9ce936 EZ |
733 | /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at |
734 | the tail. */ | |
735 | terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK; | |
736 | while (sl) | |
737 | { | |
c77f6f1b | 738 | int cf, chlen, enclen; |
aa9ce936 | 739 | unsigned char workbuf[4], *buf; |
c77f6f1b EZ |
740 | unsigned ch; |
741 | register GLYPH g = GLYPH_FROM_CHAR_GLYPH (*str); | |
aa9ce936 EZ |
742 | |
743 | /* Find the actual glyph to display by traversing the entire | |
744 | aliases chain for this glyph. */ | |
745 | GLYPH_FOLLOW_ALIASES (tbase, tlen, g); | |
746 | ||
747 | /* Glyphs with GLYPH_MASK_PADDING bit set are actually there | |
748 | only for the redisplay code to know how many columns does | |
749 | this character occupy on the screen. Skip padding glyphs. */ | |
c77f6f1b | 750 | if (CHAR_GLYPH_PADDING_P (*str)) |
aa9ce936 EZ |
751 | { |
752 | str++; | |
753 | sl--; | |
754 | } | |
755 | else | |
756 | { | |
757 | /* Convert the character code to multibyte, if they | |
758 | requested display via language environment. */ | |
759 | ch = FAST_GLYPH_CHAR (g); | |
aff4381d EZ |
760 | /* We only want to convert unibyte characters to multibyte |
761 | in unibyte buffers! Otherwise, the 8-bit code might come | |
762 | from the display table set up to display foreign characters. */ | |
52d38ab2 | 763 | if (SINGLE_BYTE_CHAR_P (ch) && convert_unibyte_characters |
f0dd4c35 EZ |
764 | && (ch >= 0240 |
765 | || (ch >= 0200 && !NILP (Vnonascii_translation_table)))) | |
aa9ce936 EZ |
766 | ch = unibyte_char_to_multibyte (ch); |
767 | ||
768 | /* Invalid characters are displayed with a special glyph. */ | |
c77f6f1b | 769 | if (! GLYPH_CHAR_VALID_P (ch)) |
aa9ce936 EZ |
770 | { |
771 | g = !NILP (Vdos_unsupported_char_glyph) | |
772 | ? Vdos_unsupported_char_glyph | |
773 | : MAKE_GLYPH (selected_frame, '\177', | |
774 | GLYPH_FACE (selected_frame, g)); | |
775 | ch = FAST_GLYPH_CHAR (g); | |
776 | } | |
777 | if (COMPOSITE_CHAR_P (ch)) | |
778 | { | |
779 | /* If CH is a composite character, we can display | |
780 | only the first component. */ | |
781 | g = cmpchar_table[COMPOSITE_CHAR_ID (ch)]->glyph[0], | |
782 | ch = GLYPH_CHAR (selected_frame, g); | |
783 | cf = FAST_GLYPH_FACE (g); | |
784 | } | |
785 | ||
786 | /* If the face of this glyph is different from the current | |
787 | screen face, update the screen attribute byte. */ | |
788 | cf = FAST_GLYPH_FACE (g); | |
789 | if (cf != screen_face) | |
790 | IT_set_face (cf); /* handles invalid faces gracefully */ | |
791 | ||
792 | if (GLYPH_SIMPLE_P (tbase, tlen, g)) | |
793 | /* We generate the multi-byte form of CH in BUF. */ | |
794 | chlen = CHAR_STRING (ch, workbuf, buf); | |
795 | else | |
796 | { | |
797 | /* We have a string in Vglyph_table. */ | |
798 | chlen = GLYPH_LENGTH (tbase, g); | |
799 | buf = GLYPH_STRING (tbase, g); | |
800 | } | |
801 | ||
c77f6f1b | 802 | /* If the character is not multibyte, don't bother converting it. */ |
aa9ce936 EZ |
803 | if (chlen == 1) |
804 | { | |
805 | *conversion_buffer = (unsigned char)ch; | |
806 | chlen = 0; | |
807 | enclen = 1; | |
808 | } | |
809 | else | |
810 | { | |
811 | encode_coding (coding, buf, conversion_buffer, chlen, | |
812 | conversion_buffer_size); | |
813 | chlen -= coding->consumed; | |
814 | enclen = coding->produced; | |
815 | ||
816 | /* Replace glyph codes that cannot be converted by | |
817 | terminal_coding with Vdos_unsupported_char_glyph. */ | |
818 | if (*conversion_buffer == '?') | |
819 | { | |
820 | char *cbp = conversion_buffer; | |
821 | ||
822 | while (cbp < conversion_buffer + enclen && *cbp == '?') | |
823 | *cbp++ = unsupported_char; | |
824 | if (unsupported_face != screen_face) | |
825 | IT_set_face (unsupported_face); | |
826 | } | |
827 | } | |
828 | ||
829 | if (enclen + chlen > screen_buf_end - screen_bp) | |
830 | { | |
831 | /* The allocated buffer for screen writes is too small. | |
832 | Flush it and loop again without incrementing STR, so | |
833 | that the next loop will begin with the same glyph. */ | |
834 | int nbytes = screen_bp - screen_buf; | |
835 | ||
836 | mouse_off_maybe (); | |
837 | dosmemput (screen_buf, nbytes, (int)ScreenPrimary + offset); | |
838 | if (screen_virtual_segment) | |
839 | dosv_refresh_virtual_screen (offset, nbytes / 2); | |
840 | new_pos_X += nbytes / 2; | |
841 | offset += nbytes; | |
842 | ||
843 | /* Prepare to reuse the same buffer again. */ | |
844 | screen_bp = screen_buf; | |
845 | } | |
846 | else | |
847 | { | |
848 | /* There's enough place in the allocated buffer to add | |
849 | the encoding of this glyph. */ | |
850 | ||
851 | /* First, copy the encoded bytes. */ | |
852 | for (bp = conversion_buffer; enclen--; bp++) | |
853 | { | |
854 | *screen_bp++ = (unsigned char)*bp; | |
855 | *screen_bp++ = ScreenAttrib; | |
856 | if (termscript) | |
857 | fputc (*bp, termscript); | |
858 | } | |
859 | ||
860 | /* Now copy the bytes not consumed by the encoding. */ | |
861 | if (chlen > 0) | |
862 | { | |
863 | buf += coding->consumed; | |
864 | while (chlen--) | |
865 | { | |
866 | if (termscript) | |
867 | fputc (*buf, termscript); | |
868 | *screen_bp++ = (unsigned char)*buf++; | |
869 | *screen_bp++ = ScreenAttrib; | |
870 | } | |
871 | } | |
872 | ||
873 | /* Update STR and its remaining length. */ | |
874 | str++; | |
875 | sl--; | |
876 | } | |
877 | } | |
aee81730 RS |
878 | } |
879 | ||
aa9ce936 | 880 | /* Dump whatever is left in the screen buffer. */ |
f32d4091 | 881 | mouse_off_maybe (); |
aa9ce936 | 882 | dosmemput (screen_buf, screen_bp - screen_buf, (int)ScreenPrimary + offset); |
039274cf | 883 | if (screen_virtual_segment) |
aa9ce936 EZ |
884 | dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2); |
885 | new_pos_X += (screen_bp - screen_buf) / 2; | |
886 | ||
887 | /* We may have to output some codes to terminate the writing. */ | |
888 | if (CODING_REQUIRE_FLUSHING (coding)) | |
889 | { | |
890 | coding->mode |= CODING_MODE_LAST_BLOCK; | |
891 | encode_coding (coding, "", conversion_buffer, 0, conversion_buffer_size); | |
892 | if (coding->produced > 0) | |
893 | { | |
894 | for (screen_bp = screen_buf, bp = conversion_buffer; | |
895 | coding->produced--; bp++) | |
896 | { | |
897 | *screen_bp++ = (unsigned char)*bp; | |
898 | *screen_bp++ = ScreenAttrib; | |
899 | if (termscript) | |
900 | fputc (*bp, termscript); | |
901 | } | |
902 | offset += screen_bp - screen_buf; | |
903 | mouse_off_maybe (); | |
904 | dosmemput (screen_buf, screen_bp - screen_buf, | |
905 | (int)ScreenPrimary + offset); | |
906 | if (screen_virtual_segment) | |
907 | dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2); | |
908 | new_pos_X += (screen_bp - screen_buf) / 2; | |
909 | } | |
910 | } | |
f32d4091 | 911 | } |
aee81730 | 912 | |
71f65669 EZ |
913 | static void |
914 | IT_clear_end_of_line (int first_unused) | |
f32d4091 KS |
915 | { |
916 | char *spaces, *sp; | |
917 | int i, j; | |
039274cf | 918 | int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y); |
aa9ce936 EZ |
919 | extern int fatal_error_in_progress; |
920 | ||
921 | if (fatal_error_in_progress) | |
922 | return; | |
f32d4091 KS |
923 | |
924 | IT_set_face (0); | |
925 | if (termscript) | |
926 | fprintf (termscript, "<CLR:EOL>"); | |
927 | i = (j = screen_size_X - new_pos_X) * 2; | |
928 | spaces = sp = alloca (i); | |
aee81730 | 929 | |
f32d4091 | 930 | while (--j >= 0) |
aee81730 | 931 | { |
f32d4091 KS |
932 | *sp++ = ' '; |
933 | *sp++ = ScreenAttrib; | |
aee81730 RS |
934 | } |
935 | ||
f32d4091 | 936 | mouse_off_maybe (); |
039274cf EZ |
937 | dosmemput (spaces, i, (int)ScreenPrimary + offset); |
938 | if (screen_virtual_segment) | |
939 | dosv_refresh_virtual_screen (offset, i / 2); | |
aee81730 RS |
940 | } |
941 | ||
71f65669 | 942 | static void |
f32d4091 KS |
943 | IT_clear_screen (void) |
944 | { | |
945 | if (termscript) | |
946 | fprintf (termscript, "<CLR:SCR>"); | |
947 | IT_set_face (0); | |
948 | mouse_off (); | |
949 | ScreenClear (); | |
039274cf EZ |
950 | if (screen_virtual_segment) |
951 | dosv_refresh_virtual_screen (0, screen_size); | |
f32d4091 KS |
952 | new_pos_X = new_pos_Y = 0; |
953 | } | |
954 | ||
71f65669 | 955 | static void |
f32d4091 KS |
956 | IT_clear_to_end (void) |
957 | { | |
958 | if (termscript) | |
959 | fprintf (termscript, "<CLR:EOS>"); | |
960 | ||
961 | while (new_pos_Y < screen_size_Y) { | |
962 | new_pos_X = 0; | |
963 | IT_clear_end_of_line (0); | |
964 | new_pos_Y++; | |
965 | } | |
966 | } | |
967 | ||
71f65669 | 968 | static void |
f32d4091 KS |
969 | IT_cursor_to (int y, int x) |
970 | { | |
971 | if (termscript) | |
972 | fprintf (termscript, "\n<XY=%dx%d>", x, y); | |
973 | new_pos_X = x; | |
974 | new_pos_Y = y; | |
975 | } | |
976 | ||
fc171623 KH |
977 | static int cursor_cleared; |
978 | ||
d1d5dc19 | 979 | static void |
fc171623 KH |
980 | IT_display_cursor (int on) |
981 | { | |
982 | if (on && cursor_cleared) | |
983 | { | |
984 | ScreenSetCursor (current_pos_Y, current_pos_X); | |
985 | cursor_cleared = 0; | |
986 | } | |
987 | else if (!on && !cursor_cleared) | |
988 | { | |
989 | ScreenSetCursor (-1, -1); | |
990 | cursor_cleared = 1; | |
991 | } | |
992 | } | |
993 | ||
994 | /* Emacs calls cursor-movement functions a lot when it updates the | |
995 | display (probably a legacy of old terminals where you cannot | |
996 | update a screen line without first moving the cursor there). | |
997 | However, cursor movement is expensive on MSDOS (it calls a slow | |
998 | BIOS function and requires 2 mode switches), while actual screen | |
999 | updates access the video memory directly and don't depend on | |
1000 | cursor position. To avoid slowing down the redisplay, we cheat: | |
1001 | all functions that move the cursor only set internal variables | |
1002 | which record the cursor position, whereas the cursor is only | |
1003 | moved to its final position whenever screen update is complete. | |
1004 | ||
1005 | `IT_cmgoto' is called from the keyboard reading loop and when the | |
1006 | frame update is complete. This means that we are ready for user | |
1007 | input, so we update the cursor position to show where the point is, | |
1008 | and also make the mouse pointer visible. | |
1009 | ||
1010 | Special treatment is required when the cursor is in the echo area, | |
1011 | to put the cursor at the end of the text displayed there. */ | |
1012 | ||
71f65669 EZ |
1013 | static void |
1014 | IT_cmgoto (FRAME_PTR f) | |
fc171623 KH |
1015 | { |
1016 | /* Only set the cursor to where it should be if the display is | |
1017 | already in sync with the window contents. */ | |
1018 | int update_cursor_pos = MODIFF == unchanged_modified; | |
06da1de1 EZ |
1019 | static int previous_pos_X = -1; |
1020 | ||
1021 | /* If the display is in sync, forget any previous knowledge about | |
1022 | cursor position. This is primarily for unexpected events like | |
1023 | C-g in the minibuffer. */ | |
1024 | if (update_cursor_pos && previous_pos_X >= 0) | |
1025 | previous_pos_X = -1; | |
1026 | /* If we are in the echo area, put the cursor at the | |
1027 | end of the echo area message. */ | |
fc171623 KH |
1028 | if (!update_cursor_pos |
1029 | && XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top) <= new_pos_Y) | |
1030 | { | |
06da1de1 EZ |
1031 | int tem_X = current_pos_X, dummy; |
1032 | ||
1033 | if (echo_area_glyphs) | |
1034 | { | |
1035 | tem_X = echo_area_glyphs_length; | |
1036 | /* Save current cursor position, to be restored after the | |
1037 | echo area message is erased. Only remember one level | |
1038 | of previous cursor position. */ | |
1039 | if (previous_pos_X == -1) | |
1040 | ScreenGetCursor (&dummy, &previous_pos_X); | |
1041 | } | |
1042 | else if (previous_pos_X >= 0) | |
1043 | { | |
1044 | /* We wind up here after the echo area message is erased. | |
1045 | Restore the cursor position we remembered above. */ | |
1046 | tem_X = previous_pos_X; | |
1047 | previous_pos_X = -1; | |
1048 | } | |
9a599a60 | 1049 | |
06da1de1 | 1050 | if (current_pos_X != tem_X) |
9a599a60 EZ |
1051 | { |
1052 | new_pos_X = tem_X; | |
1053 | update_cursor_pos = 1; | |
1054 | } | |
fc171623 KH |
1055 | } |
1056 | ||
1057 | if (update_cursor_pos | |
1058 | && (current_pos_X != new_pos_X || current_pos_Y != new_pos_Y)) | |
1059 | { | |
1060 | ScreenSetCursor (current_pos_Y = new_pos_Y, current_pos_X = new_pos_X); | |
1061 | if (termscript) | |
1062 | fprintf (termscript, "\n<CURSOR:%dx%d>", current_pos_X, current_pos_Y); | |
1063 | } | |
1064 | ||
1065 | /* Maybe cursor is invisible, so make it visible. */ | |
1066 | IT_display_cursor (1); | |
1067 | ||
1068 | /* Mouse pointer should be always visible if we are waiting for | |
1069 | keyboard input. */ | |
1070 | if (!mouse_visible) | |
1071 | mouse_on (); | |
1072 | } | |
1073 | ||
71f65669 EZ |
1074 | static void |
1075 | IT_reassert_line_highlight (int new, int vpos) | |
f32d4091 KS |
1076 | { |
1077 | highlight = new; | |
1078 | IT_set_face (0); /* To possibly clear the highlighting. */ | |
1079 | } | |
1080 | ||
71f65669 | 1081 | static void |
c77f6f1b | 1082 | IT_change_line_highlight (int new_highlight, int y, int vpos, int first_unused_hpos) |
1b94449f | 1083 | { |
f32d4091 KS |
1084 | highlight = new_highlight; |
1085 | IT_set_face (0); /* To possibly clear the highlighting. */ | |
1086 | IT_cursor_to (vpos, 0); | |
1087 | IT_clear_end_of_line (first_unused_hpos); | |
1088 | } | |
1089 | ||
71f65669 EZ |
1090 | static void |
1091 | IT_update_begin (struct frame *foo) | |
f32d4091 KS |
1092 | { |
1093 | highlight = 0; | |
1094 | IT_set_face (0); /* To possibly clear the highlighting. */ | |
1095 | screen_face = -1; | |
1096 | } | |
1097 | ||
71f65669 EZ |
1098 | static void |
1099 | IT_update_end (struct frame *foo) | |
f32d4091 KS |
1100 | { |
1101 | } | |
1b94449f | 1102 | |
c77f6f1b EZ |
1103 | /* Copy LEN glyphs displayed on a single line whose vertical position |
1104 | is YPOS, beginning at horizontal position XFROM to horizontal | |
1105 | position XTO, by moving blocks in the video memory. Used by | |
1106 | functions that insert and delete glyphs. */ | |
1107 | static void | |
1108 | IT_copy_glyphs (int xfrom, int xto, size_t len, int ypos) | |
1109 | { | |
1110 | /* The offsets of source and destination relative to the | |
1111 | conventional memorty selector. */ | |
1112 | int from = 2 * (xfrom + screen_size_X * ypos) + ScreenPrimary; | |
1113 | int to = 2 * (xto + screen_size_X * ypos) + ScreenPrimary; | |
1114 | ||
1115 | if (from == to || len <= 0) | |
1116 | return; | |
1117 | ||
1118 | _farsetsel (_dos_ds); | |
1119 | ||
1120 | /* The source and destination might overlap, so we need to move | |
1121 | glyphs non-destructively. */ | |
1122 | if (from > to) | |
1123 | { | |
1124 | for ( ; len; from += 2, to += 2, len--) | |
1125 | _farnspokew (to, _farnspeekw (from)); | |
1126 | } | |
1127 | else | |
1128 | { | |
1129 | from += (len - 1) * 2; | |
1130 | to += (len - 1) * 2; | |
1131 | for ( ; len; from -= 2, to -= 2, len--) | |
1132 | _farnspokew (to, _farnspeekw (from)); | |
1133 | } | |
1134 | if (screen_virtual_segment) | |
1135 | dosv_refresh_virtual_screen (ypos * screen_size_X * 2, screen_size_X); | |
1136 | } | |
1137 | ||
1138 | /* Insert and delete glyphs. */ | |
aa9ce936 EZ |
1139 | static void |
1140 | IT_insert_glyphs (start, len) | |
c77f6f1b | 1141 | register struct glyph *start; |
aa9ce936 EZ |
1142 | register int len; |
1143 | { | |
c77f6f1b EZ |
1144 | int shift_by_width = screen_size_X - (new_pos_X + len); |
1145 | ||
1146 | /* Shift right the glyphs from the nominal cursor position to the | |
1147 | end of this line. */ | |
1148 | IT_copy_glyphs (new_pos_X, new_pos_X + len, shift_by_width, new_pos_Y); | |
1149 | ||
1150 | /* Now write the glyphs to be inserted. */ | |
1151 | IT_write_glyphs (start, len); | |
aa9ce936 EZ |
1152 | } |
1153 | ||
1154 | static void | |
1155 | IT_delete_glyphs (n) | |
1156 | register int n; | |
1157 | { | |
1158 | abort (); | |
1159 | } | |
1160 | ||
211c7152 | 1161 | /* set-window-configuration on window.c needs this. */ |
3bb1f22f RS |
1162 | void |
1163 | x_set_menu_bar_lines (f, value, oldval) | |
1164 | struct frame *f; | |
1165 | Lisp_Object value, oldval; | |
1166 | { | |
211c7152 EZ |
1167 | set_menu_bar_lines (f, value, oldval); |
1168 | } | |
3bb1f22f | 1169 | |
211c7152 | 1170 | /* This was copied from xfns.c */ |
3bb1f22f | 1171 | |
211c7152 EZ |
1172 | Lisp_Object Qbackground_color; |
1173 | Lisp_Object Qforeground_color; | |
1174 | extern Lisp_Object Qtitle; | |
3bb1f22f | 1175 | |
48ffe371 RS |
1176 | /* IT_set_terminal_modes is called when emacs is started, |
1177 | resumed, and whenever the screen is redrawn! */ | |
f32d4091 | 1178 | |
71f65669 | 1179 | static void |
f32d4091 KS |
1180 | IT_set_terminal_modes (void) |
1181 | { | |
aee81730 | 1182 | if (termscript) |
f32d4091 KS |
1183 | fprintf (termscript, "\n<SET_TERM>"); |
1184 | highlight = 0; | |
1185 | ||
1186 | screen_size_X = ScreenCols (); | |
1187 | screen_size_Y = ScreenRows (); | |
1188 | screen_size = screen_size_X * screen_size_Y; | |
aee81730 | 1189 | |
f32d4091 KS |
1190 | new_pos_X = new_pos_Y = 0; |
1191 | current_pos_X = current_pos_Y = -1; | |
1192 | ||
1193 | if (term_setup_done) | |
1194 | return; | |
1195 | term_setup_done = 1; | |
aee81730 | 1196 | |
f32d4091 KS |
1197 | startup_screen_size_X = screen_size_X; |
1198 | startup_screen_size_Y = screen_size_Y; | |
c9adab25 | 1199 | startup_screen_attrib = ScreenAttrib; |
f32d4091 | 1200 | |
039274cf EZ |
1201 | #if __DJGPP__ > 1 |
1202 | /* Is DOS/V (or any other RSIS software which relocates | |
1203 | the screen) installed? */ | |
1204 | { | |
1205 | unsigned short es_value; | |
1206 | __dpmi_regs regs; | |
1207 | ||
1208 | regs.h.ah = 0xfe; /* get relocated screen address */ | |
1209 | if (ScreenPrimary == 0xb0000UL || ScreenPrimary == 0xb8000UL) | |
1210 | regs.x.es = (ScreenPrimary >> 4) & 0xffff; | |
1211 | else if (screen_old_address) /* already switched to Japanese mode once */ | |
1212 | regs.x.es = (screen_old_address >> 4) & 0xffff; | |
1213 | else | |
1214 | regs.x.es = ScreenMode () == 7 ? 0xb000 : 0xb800; | |
1215 | regs.x.di = 0; | |
1216 | es_value = regs.x.es; | |
1217 | __dpmi_int (0x10, ®s); | |
1218 | ||
d1d5dc19 | 1219 | if (regs.x.es != es_value) |
039274cf | 1220 | { |
d1d5dc19 EZ |
1221 | /* screen_old_address is only set if ScreenPrimary does NOT |
1222 | already point to the relocated buffer address returned by | |
1223 | the Int 10h/AX=FEh call above. DJGPP v2.02 and later sets | |
1224 | ScreenPrimary to that address at startup under DOS/V. */ | |
1225 | if (regs.x.es != (ScreenPrimary >> 4) & 0xffff) | |
1226 | screen_old_address = ScreenPrimary; | |
039274cf EZ |
1227 | screen_virtual_segment = regs.x.es; |
1228 | screen_virtual_offset = regs.x.di; | |
1229 | ScreenPrimary = (screen_virtual_segment << 4) + screen_virtual_offset; | |
1230 | } | |
1231 | } | |
1232 | #endif /* __DJGPP__ > 1 */ | |
1233 | ||
f32d4091 KS |
1234 | ScreenGetCursor (&startup_pos_Y, &startup_pos_X); |
1235 | ScreenRetrieve (startup_screen_buffer = xmalloc (screen_size * 2)); | |
1236 | ||
1237 | if (termscript) | |
c9adab25 | 1238 | fprintf (termscript, "<SCREEN SAVED (dimensions=%dx%d)>\n", |
039274cf | 1239 | screen_size_X, screen_size_Y); |
76ac1508 RS |
1240 | |
1241 | bright_bg (); | |
f32d4091 KS |
1242 | } |
1243 | ||
48ffe371 RS |
1244 | /* IT_reset_terminal_modes is called when emacs is |
1245 | suspended or killed. */ | |
f32d4091 | 1246 | |
71f65669 | 1247 | static void |
f32d4091 KS |
1248 | IT_reset_terminal_modes (void) |
1249 | { | |
c9adab25 KH |
1250 | int display_row_start = (int) ScreenPrimary; |
1251 | int saved_row_len = startup_screen_size_X * 2; | |
1252 | int update_row_len = ScreenCols () * 2; | |
1253 | int current_rows = ScreenRows (); | |
1254 | int to_next_row = update_row_len; | |
1255 | unsigned char *saved_row = startup_screen_buffer; | |
1256 | int cursor_pos_X = ScreenCols () - 1; | |
1257 | int cursor_pos_Y = ScreenRows () - 1; | |
1258 | ||
f32d4091 | 1259 | if (termscript) |
5063b150 | 1260 | fprintf (termscript, "\n<RESET_TERM>"); |
f32d4091 KS |
1261 | |
1262 | highlight = 0; | |
1263 | ||
1264 | if (!term_setup_done) | |
1265 | return; | |
1266 | ||
c9adab25 | 1267 | mouse_off (); |
b36701cc RS |
1268 | |
1269 | /* Leave the video system in the same state as we found it, | |
1270 | as far as the blink/bright-background bit is concerned. */ | |
1271 | maybe_enable_blinking (); | |
06b1ea13 | 1272 | |
c9adab25 KH |
1273 | /* We have a situation here. |
1274 | We cannot just do ScreenUpdate(startup_screen_buffer) because | |
1275 | the luser could have changed screen dimensions inside Emacs | |
1276 | and failed (or didn't want) to restore them before killing | |
1277 | Emacs. ScreenUpdate() uses the *current* screen dimensions and | |
1278 | thus will happily use memory outside what was allocated for | |
1279 | `startup_screen_buffer'. | |
1280 | Thus we only restore as much as the current screen dimensions | |
1281 | can hold, and clear the rest (if the saved screen is smaller than | |
1282 | the current) with the color attribute saved at startup. The cursor | |
1283 | is also restored within the visible dimensions. */ | |
1284 | ||
1285 | ScreenAttrib = startup_screen_attrib; | |
c9adab25 | 1286 | |
06b1ea13 EZ |
1287 | /* Don't restore the screen if we are exiting less than 2 seconds |
1288 | after startup: we might be crashing, and the screen might show | |
1289 | some vital clues to what's wrong. */ | |
1290 | if (clock () - startup_time >= 2*CLOCKS_PER_SEC) | |
c9adab25 | 1291 | { |
06b1ea13 | 1292 | ScreenClear (); |
039274cf | 1293 | if (screen_virtual_segment) |
06b1ea13 EZ |
1294 | dosv_refresh_virtual_screen (0, screen_size); |
1295 | ||
1296 | if (update_row_len > saved_row_len) | |
1297 | update_row_len = saved_row_len; | |
1298 | if (current_rows > startup_screen_size_Y) | |
1299 | current_rows = startup_screen_size_Y; | |
1300 | ||
1301 | if (termscript) | |
1302 | fprintf (termscript, "<SCREEN RESTORED (dimensions=%dx%d)>\n", | |
1303 | update_row_len / 2, current_rows); | |
1304 | ||
1305 | while (current_rows--) | |
1306 | { | |
1307 | dosmemput (saved_row, update_row_len, display_row_start); | |
1308 | if (screen_virtual_segment) | |
1309 | dosv_refresh_virtual_screen (display_row_start - ScreenPrimary, | |
1310 | update_row_len / 2); | |
1311 | saved_row += saved_row_len; | |
1312 | display_row_start += to_next_row; | |
1313 | } | |
c9adab25 KH |
1314 | } |
1315 | if (startup_pos_X < cursor_pos_X) | |
1316 | cursor_pos_X = startup_pos_X; | |
1317 | if (startup_pos_Y < cursor_pos_Y) | |
1318 | cursor_pos_Y = startup_pos_Y; | |
1319 | ||
1320 | ScreenSetCursor (cursor_pos_Y, cursor_pos_X); | |
1321 | xfree (startup_screen_buffer); | |
f32d4091 KS |
1322 | |
1323 | term_setup_done = 0; | |
1324 | } | |
1325 | ||
71f65669 EZ |
1326 | static void |
1327 | IT_set_terminal_window (int foo) | |
f32d4091 KS |
1328 | { |
1329 | } | |
1330 | ||
1331 | void | |
3bb1f22f | 1332 | IT_set_frame_parameters (f, alist) |
c77f6f1b | 1333 | struct frame *f; |
f32d4091 KS |
1334 | Lisp_Object alist; |
1335 | { | |
1336 | Lisp_Object tail; | |
db722735 RS |
1337 | int length = XINT (Flength (alist)); |
1338 | int i; | |
1339 | Lisp_Object *parms | |
1340 | = (Lisp_Object *) alloca (length * sizeof (Lisp_Object)); | |
1341 | Lisp_Object *values | |
1342 | = (Lisp_Object *) alloca (length * sizeof (Lisp_Object)); | |
f32d4091 | 1343 | int redraw; |
c77f6f1b EZ |
1344 | struct face *dflt = NULL; |
1345 | ||
1346 | if (FRAME_FACE_CACHE (f)) | |
1347 | dflt = FACE_FROM_ID (f, DEFAULT_FACE_ID); | |
f32d4091 KS |
1348 | |
1349 | redraw = 0; | |
db722735 RS |
1350 | |
1351 | /* Extract parm names and values into those vectors. */ | |
1352 | i = 0; | |
f32d4091 KS |
1353 | for (tail = alist; CONSP (tail); tail = Fcdr (tail)) |
1354 | { | |
db722735 | 1355 | Lisp_Object elt; |
f32d4091 KS |
1356 | |
1357 | elt = Fcar (tail); | |
db722735 RS |
1358 | parms[i] = Fcar (elt); |
1359 | CHECK_SYMBOL (parms[i], 1); | |
1360 | values[i] = Fcdr (elt); | |
1361 | i++; | |
1362 | } | |
1363 | ||
1364 | ||
1365 | /* Now process them in reverse of specified order. */ | |
1366 | for (i--; i >= 0; i--) | |
1367 | { | |
1368 | Lisp_Object prop = parms[i]; | |
1369 | Lisp_Object val = values[i]; | |
f32d4091 | 1370 | |
4e825084 | 1371 | if (EQ (prop, Qforeground_color)) |
f32d4091 | 1372 | { |
c77f6f1b EZ |
1373 | unsigned long new_color = load_color (f, NULL, val, |
1374 | LFACE_FOREGROUND_INDEX); | |
f32d4091 KS |
1375 | if (new_color != ~0) |
1376 | { | |
c77f6f1b EZ |
1377 | if (!dflt) |
1378 | abort (); | |
f32d4091 | 1379 | FRAME_FOREGROUND_PIXEL (f) = new_color; |
c77f6f1b | 1380 | dflt->foreground = new_color; |
f32d4091 | 1381 | redraw = 1; |
76ac1508 | 1382 | if (termscript) |
a7cf9151 | 1383 | fprintf (termscript, "<FGCOLOR %lu>\n", new_color); |
f32d4091 KS |
1384 | } |
1385 | } | |
4e825084 | 1386 | else if (EQ (prop, Qbackground_color)) |
f32d4091 | 1387 | { |
c77f6f1b EZ |
1388 | unsigned long new_color = load_color (f, NULL, val, |
1389 | LFACE_BACKGROUND_INDEX); | |
f32d4091 KS |
1390 | if (new_color != ~0) |
1391 | { | |
c77f6f1b EZ |
1392 | if (!dflt) |
1393 | abort (); | |
76ac1508 | 1394 | FRAME_BACKGROUND_PIXEL (f) = new_color; |
c77f6f1b | 1395 | dflt->background = new_color; |
f32d4091 | 1396 | redraw = 1; |
76ac1508 | 1397 | if (termscript) |
a7cf9151 | 1398 | fprintf (termscript, "<BGCOLOR %lu>\n", new_color); |
f32d4091 KS |
1399 | } |
1400 | } | |
211c7152 EZ |
1401 | else if (EQ (prop, Qtitle)) |
1402 | { | |
1403 | x_set_title (f, val); | |
1404 | if (termscript) | |
1405 | fprintf (termscript, "<TITLE: %s>\n", XSTRING (val)->data); | |
1406 | } | |
1407 | else if (EQ (prop, intern ("reverse")) && EQ (val, Qt)) | |
1408 | { | |
1409 | unsigned long fg = FRAME_FOREGROUND_PIXEL (f); | |
db722735 | 1410 | |
c77f6f1b EZ |
1411 | if (!dflt) |
1412 | abort (); | |
1413 | FRAME_FOREGROUND_PIXEL (f) = FRAME_BACKGROUND_PIXEL (f); /* FIXME! */ | |
211c7152 | 1414 | FRAME_BACKGROUND_PIXEL (f) = fg; |
c77f6f1b EZ |
1415 | dflt->foreground = FRAME_FOREGROUND_PIXEL (f); |
1416 | dflt->foreground = fg; | |
211c7152 EZ |
1417 | if (termscript) |
1418 | fprintf (termscript, "<INVERSE-VIDEO>\n"); | |
1419 | } | |
db722735 RS |
1420 | store_frame_param (f, prop, val); |
1421 | ||
f32d4091 KS |
1422 | } |
1423 | ||
1424 | if (redraw) | |
1425 | { | |
1426 | recompute_basic_faces (f); | |
3bb1f22f RS |
1427 | if (f == selected_frame) |
1428 | redraw_frame (f); | |
f32d4091 KS |
1429 | } |
1430 | } | |
1431 | ||
a7cf9151 EZ |
1432 | extern void init_frame_faces (FRAME_PTR); |
1433 | ||
f32d4091 KS |
1434 | #endif /* !HAVE_X_WINDOWS */ |
1435 | ||
1436 | ||
48ffe371 RS |
1437 | /* Do we need the internal terminal? */ |
1438 | ||
f32d4091 KS |
1439 | void |
1440 | internal_terminal_init () | |
1441 | { | |
1442 | char *term = getenv ("TERM"); | |
1443 | char *colors; | |
1444 | ||
1445 | #ifdef HAVE_X_WINDOWS | |
1446 | if (!inhibit_window_system) | |
1447 | return; | |
1448 | #endif | |
1449 | ||
1450 | internal_terminal | |
1451 | = (!noninteractive) && term && !strcmp (term, "internal"); | |
1452 | ||
1453 | if (getenv ("EMACSTEST")) | |
5063b150 | 1454 | termscript = fopen (getenv ("EMACSTEST"), "wt"); |
f32d4091 KS |
1455 | |
1456 | #ifndef HAVE_X_WINDOWS | |
1457 | if (!internal_terminal || inhibit_window_system) | |
1458 | { | |
3bb1f22f | 1459 | selected_frame->output_method = output_termcap; |
f32d4091 KS |
1460 | return; |
1461 | } | |
1462 | ||
1463 | Vwindow_system = intern ("pc"); | |
1464 | Vwindow_system_version = make_number (1); | |
039274cf EZ |
1465 | |
1466 | /* If Emacs was dumped on DOS/V machine, forget the stale VRAM address. */ | |
1467 | screen_old_address = 0; | |
1468 | ||
f32d4091 KS |
1469 | bzero (&the_only_x_display, sizeof the_only_x_display); |
1470 | the_only_x_display.background_pixel = 7; /* White */ | |
1471 | the_only_x_display.foreground_pixel = 0; /* Black */ | |
76ac1508 | 1472 | bright_bg (); |
5063b150 | 1473 | colors = getenv ("EMACSCOLORS"); |
f32d4091 KS |
1474 | if (colors && strlen (colors) >= 2) |
1475 | { | |
76ac1508 RS |
1476 | /* The colors use 4 bits each (we enable bright background). */ |
1477 | if (isdigit (colors[0])) | |
1478 | colors[0] -= '0'; | |
1479 | else if (isxdigit (colors[0])) | |
1480 | colors[0] -= (isupper (colors[0]) ? 'A' : 'a') - 10; | |
1bd7b2c7 RS |
1481 | if (colors[0] >= 0 && colors[0] < 16) |
1482 | the_only_x_display.foreground_pixel = colors[0]; | |
76ac1508 RS |
1483 | if (isdigit (colors[1])) |
1484 | colors[1] -= '0'; | |
1485 | else if (isxdigit (colors[1])) | |
1486 | colors[1] -= (isupper (colors[1]) ? 'A' : 'a') - 10; | |
1487 | if (colors[1] >= 0 && colors[1] < 16) | |
1bd7b2c7 | 1488 | the_only_x_display.background_pixel = colors[1]; |
f32d4091 KS |
1489 | } |
1490 | the_only_x_display.line_height = 1; | |
64ec6a02 | 1491 | the_only_x_display.font = (XFontStruct *)1; /* must *not* be zero */ |
f32d4091 | 1492 | |
3bb1f22f | 1493 | init_frame_faces (selected_frame); |
f32d4091 KS |
1494 | |
1495 | ring_bell_hook = IT_ring_bell; | |
aa9ce936 EZ |
1496 | insert_glyphs_hook = IT_insert_glyphs; |
1497 | delete_glyphs_hook = IT_delete_glyphs; | |
f32d4091 KS |
1498 | write_glyphs_hook = IT_write_glyphs; |
1499 | cursor_to_hook = raw_cursor_to_hook = IT_cursor_to; | |
1500 | clear_to_end_hook = IT_clear_to_end; | |
1501 | clear_end_of_line_hook = IT_clear_end_of_line; | |
1502 | clear_frame_hook = IT_clear_screen; | |
1503 | change_line_highlight_hook = IT_change_line_highlight; | |
1504 | update_begin_hook = IT_update_begin; | |
1505 | update_end_hook = IT_update_end; | |
1506 | reassert_line_highlight_hook = IT_reassert_line_highlight; | |
fc171623 | 1507 | frame_up_to_date_hook = IT_cmgoto; /* position cursor when update is done */ |
f32d4091 KS |
1508 | |
1509 | /* These hooks are called by term.c without being checked. */ | |
1510 | set_terminal_modes_hook = IT_set_terminal_modes; | |
1511 | reset_terminal_modes_hook = IT_reset_terminal_modes; | |
1512 | set_terminal_window_hook = IT_set_terminal_window; | |
c77f6f1b | 1513 | char_ins_del_ok = 0; |
f32d4091 KS |
1514 | #endif |
1515 | } | |
1516 | ||
1517 | dos_get_saved_screen (screen, rows, cols) | |
1518 | char **screen; | |
1519 | int *rows; | |
1520 | int *cols; | |
1521 | { | |
1522 | #ifndef HAVE_X_WINDOWS | |
1523 | *screen = startup_screen_buffer; | |
1524 | *cols = startup_screen_size_X; | |
1525 | *rows = startup_screen_size_Y; | |
039274cf | 1526 | return *screen != (char *)0; |
f32d4091 KS |
1527 | #else |
1528 | return 0; | |
1529 | #endif | |
1530 | } | |
3bb1f22f RS |
1531 | |
1532 | #ifndef HAVE_X_WINDOWS | |
1533 | ||
1534 | /* We are not X, but we can emulate it well enough for our needs... */ | |
1535 | void | |
1536 | check_x (void) | |
1537 | { | |
1538 | if (! FRAME_MSDOS_P (selected_frame)) | |
1539 | error ("Not running under a windows system"); | |
1540 | } | |
1541 | ||
1542 | #endif | |
1543 | ||
5063b150 | 1544 | \f |
f32d4091 KS |
1545 | /* ----------------------- Keyboard control ---------------------- |
1546 | * | |
1547 | * Keymaps reflect the following keyboard layout: | |
1548 | * | |
1549 | * 0 1 2 3 4 5 6 7 8 9 10 11 12 BS | |
1550 | * TAB 15 16 17 18 19 20 21 22 23 24 25 26 (41) | |
1551 | * CLOK 30 31 32 33 34 35 36 37 38 39 40 (41) RET | |
1552 | * SH () 45 46 47 48 49 50 51 52 53 54 SHIFT | |
1553 | * SPACE | |
1554 | */ | |
1555 | ||
d1d5dc19 EZ |
1556 | #define Ignore 0x0000 |
1557 | #define Normal 0x0000 /* normal key - alt changes scan-code */ | |
1558 | #define FctKey 0x1000 /* func key if c == 0, else c */ | |
1559 | #define Special 0x2000 /* func key even if c != 0 */ | |
1560 | #define ModFct 0x3000 /* special if mod-keys, else 'c' */ | |
1561 | #define Map 0x4000 /* alt scan-code, map to unshift/shift key */ | |
1562 | #define KeyPad 0x5000 /* map to insert/kp-0 depending on c == 0xe0 */ | |
1563 | #define Grey 0x6000 /* Grey keypad key */ | |
1564 | ||
1565 | #define Alt 0x0100 /* alt scan-code */ | |
1566 | #define Ctrl 0x0200 /* ctrl scan-code */ | |
1567 | #define Shift 0x0400 /* shift scan-code */ | |
1568 | ||
f32d4091 KS |
1569 | static int extended_kbd; /* 101 (102) keyboard present. */ |
1570 | ||
d1d5dc19 EZ |
1571 | struct kbd_translate { |
1572 | unsigned char sc; | |
1573 | unsigned char ch; | |
1574 | unsigned short code; | |
1575 | }; | |
1576 | ||
f32d4091 KS |
1577 | struct dos_keyboard_map |
1578 | { | |
1579 | char *unshifted; | |
1580 | char *shifted; | |
1581 | char *alt_gr; | |
d1d5dc19 | 1582 | struct kbd_translate *translate_table; |
f32d4091 KS |
1583 | }; |
1584 | ||
1585 | ||
1586 | static struct dos_keyboard_map us_keyboard = { | |
1587 | /* 0 1 2 3 4 5 */ | |
1588 | /* 01234567890123456789012345678901234567890 12345678901234 */ | |
1589 | "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ", | |
1590 | /* 0123456789012345678901234567890123456789 012345678901234 */ | |
1591 | "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ", | |
d1d5dc19 EZ |
1592 | 0, /* no Alt-Gr key */ |
1593 | 0 /* no translate table */ | |
f32d4091 KS |
1594 | }; |
1595 | ||
1596 | static struct dos_keyboard_map fr_keyboard = { | |
1597 | /* 0 1 2 3 4 5 */ | |
1598 | /* 012 3456789012345678901234567890123456789012345678901234 */ | |
1599 |