(realize_default_face) [MSDOS]: Don't take default
[bpt/emacs.git] / src / msdos.c
CommitLineData
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
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
edfc0d45 8the Free Software Foundation; either version 2, or (at your option)
1b94449f
RS
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, 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
94int _crt0_startup_flags = _CRT0_FLAG_UNIX_SBRK;
95#else /* not REL_ALLOC */
96int _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
103static unsigned long
104event_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
126int have_mouse; /* 0: no, 1: enabled, -1: disabled */
127static int mouse_visible;
1b94449f 128
f32d4091
KS
129static int mouse_last_x;
130static int mouse_last_y;
1b94449f 131
f32d4091
KS
132static int mouse_button_translate[NUM_MOUSE_BUTTONS];
133static int mouse_button_count;
1b94449f 134
f32d4091
KS
135void
136mouse_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, &regs, &regs);
146 mouse_visible = 1;
1b94449f 147 }
1b94449f
RS
148}
149
f32d4091
KS
150void
151mouse_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, &regs, &regs);
161 mouse_visible = 0;
1b94449f 162 }
1b94449f
RS
163}
164
211c7152
EZ
165static void
166mouse_get_xy (int *x, int *y)
167{
168 union REGS regs;
169
170 regs.x.ax = 0x0003;
171 int86 (0x33, &regs, &regs);
172 *x = regs.x.cx / 8;
173 *y = regs.x.dx / 8;
174}
175
f32d4091
KS
176void
177mouse_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, &regs, &regs);
1b94449f
RS
188}
189
f32d4091
KS
190static int
191mouse_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, &regs, &regs);
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
206static int
207mouse_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, &regs, &regs);
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
222static int
223mouse_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, &regs, &regs);
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
241void
242mouse_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
264static void
265mouse_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
275void
276mouse_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, &regs, &regs);
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, &regs, &regs);
1b94449f 303
f32d4091
KS
304 regs.x.ax = 0x0008;
305 regs.x.cx = 0;
306 regs.x.dx = 8 * (ScreenRows () - 1);
307 int86 (0x33, &regs, &regs);
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 317static int internal_terminal = 0;
aee81730 318
f32d4091
KS
319#ifndef HAVE_X_WINDOWS
320extern unsigned char ScreenAttrib;
321static int screen_face;
322static int highlight;
aee81730 323
f32d4091
KS
324static int screen_size_X;
325static int screen_size_Y;
326static int screen_size;
1b94449f 327
f32d4091
KS
328static int current_pos_X;
329static int current_pos_Y;
330static int new_pos_X;
331static int new_pos_Y;
1b94449f 332
f32d4091
KS
333static void *startup_screen_buffer;
334static int startup_screen_size_X;
335static int startup_screen_size_Y;
336static int startup_pos_X;
337static int startup_pos_Y;
c9adab25 338static unsigned char startup_screen_attrib;
1b94449f 339
06b1ea13
EZ
340static clock_t startup_time;
341
f32d4091 342static int term_setup_done;
1b94449f 343
f32d4091 344/* Similar to the_only_frame. */
f6816f88 345struct x_output the_only_x_display;
1b94449f 346
f32d4091
KS
347/* This is never dereferenced. */
348Display *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. */
354static unsigned long screen_old_address = 0;
355/* Segment and offset of the virtual screen. If 0, DOS/V is NOT loaded. */
356static unsigned short screen_virtual_segment = 0;
357static unsigned short screen_virtual_offset = 0;
68026917
AI
358/* A flag to control how to display unibyte 8-bit characters. */
359extern 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. */
364static void
365dosv_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, &regs);
377}
378#endif
379
d1d5dc19 380static void
f32d4091
KS
381dos_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 410static void
fcea9cd4 411do_visible_bell (xorattr)
1b94449f
RS
412 unsigned char xorattr;
413{
49a09c76 414 asm volatile
ca986694 415 (" movb $1,%%dl
1b94449f 416visible_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 423visible_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 430visible_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
438visible_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
444static void
445ScreenVisualBell (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
457static int blink_bit = -1; /* the state of the blink bit at startup */
458
76ac1508
RS
459/* Enable bright background colors. */
460static void
461bright_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, &regs, &regs);
473}
474
b36701cc
RS
475/* Disable bright background colors (and enable blinking) if we found
476 the video system in that state at startup. */
477static void
478maybe_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, &regs, &regs);
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
493void
494dos_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, &regs, &regs);
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, &regs, &regs);
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, &regs, &regs);
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, &regs, &regs);
579 regs.x.ax = 0x1101;
580 regs.h.bl = 0;
581 int86 (0x10, &regs, &regs);
582 regs.x.ax = 0x1200;
583 regs.h.bl = 32;
584 int86 (0x10, &regs, &regs);
585 regs.x.ax = 3;
586 int86 (0x10, &regs, &regs);
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, &regs, &regs);
595 regs.x.ax = 0x1112;
596 regs.h.bl = 0;
597 int86 (0x10, &regs, &regs);
598 regs.x.ax = 0x1200;
599 regs.h.bl = 32;
600 int86 (0x10, &regs, &regs);
601 regs.x.ax = 0x0100;
602 regs.x.cx = 7;
603 int86 (0x10, &regs, &regs);
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
629static void
f32d4091 630mouse_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
644static void
645IT_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
666static void
667IT_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
705Lisp_Object Vdos_unsupported_char_glyph;
706
71f65669 707static void
c77f6f1b 708IT_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
913static void
914IT_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 942static void
f32d4091
KS
943IT_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 955static void
f32d4091
KS
956IT_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 968static void
f32d4091
KS
969IT_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
977static int cursor_cleared;
978
d1d5dc19 979static void
fc171623
KH
980IT_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
1013static void
1014IT_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
1074static void
1075IT_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 1081static void
c77f6f1b 1082IT_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
1090static void
1091IT_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
1098static void
1099IT_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. */
1107static void
1108IT_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
1139static void
1140IT_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
1154static void
1155IT_delete_glyphs (n)
1156 register int n;
1157{
1158 abort ();
1159}
1160
211c7152 1161/* set-window-configuration on window.c needs this. */
3bb1f22f
RS
1162void
1163x_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
1172Lisp_Object Qbackground_color;
1173Lisp_Object Qforeground_color;
1174extern 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 1179static void
f32d4091
KS
1180IT_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, &regs);
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 1247static void
f32d4091
KS
1248IT_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
1326static void
1327IT_set_terminal_window (int foo)
f32d4091
KS
1328{
1329}
1330
1331void
3bb1f22f 1332IT_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
1432extern 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
1439void
1440internal_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
1517dos_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... */
1535void
1536check_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
1569static int extended_kbd; /* 101 (102) keyboard present. */
1570
d1d5dc19
EZ
1571struct kbd_translate {
1572 unsigned char sc;
1573 unsigned char ch;
1574 unsigned short code;
1575};
1576
f32d4091
KS
1577struct 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
1586static 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
1596static struct dos_keyboard_map fr_keyboard = {
1597/* 0 1 2 3 4 5 */
1598/* 012 3456789012345678901234567890123456789012345678901234 */
1599