(with-temp-message): Don't display MESSAGE if nil.
[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 "dosfns.h"
50#include "msdos.h"
51#include "systime.h"
52#include "termhooks.h"
aa9ce936 53#include "termchar.h"
87485d6f
MW
54#include "dispextern.h"
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;
358
aa9ce936
EZ
359/* A flag to control how to display unibyte 8-bit character. */
360int unibyte_display_via_language_environment;
361
039274cf
EZ
362#if __DJGPP__ > 1
363/* Update the screen from a part of relocated DOS/V screen buffer which
364 begins at OFFSET and includes COUNT characters. */
365static void
366dosv_refresh_virtual_screen (int offset, int count)
367{
368 __dpmi_regs regs;
369
40437cf5
EZ
370 if (offset < 0 || count < 0) /* paranoia; illegal values crash DOS/V */
371 return;
372
039274cf
EZ
373 regs.h.ah = 0xff; /* update relocated screen */
374 regs.x.es = screen_virtual_segment;
375 regs.x.di = screen_virtual_offset + offset;
376 regs.x.cx = count;
377 __dpmi_int (0x10, &regs);
378}
379#endif
380
f32d4091
KS
381static
382dos_direct_output (y, x, buf, len)
383 int y;
384 int x;
385 char *buf;
386 int len;
1b94449f 387{
40437cf5
EZ
388 int t0 = 2 * (x + y * screen_size_X);
389 int t = t0 + (int) ScreenPrimary;
039274cf 390 int l0 = len;
fc171623
KH
391
392#if (__DJGPP__ < 2)
f32d4091
KS
393 while (--len >= 0) {
394 dosmemput (buf++, 1, t);
395 t += 2;
396 }
fc171623
KH
397#else
398 /* This is faster. */
399 for (_farsetsel (_dos_ds); --len >= 0; t += 2, buf++)
400 _farnspokeb (t, *buf);
039274cf
EZ
401
402 if (screen_virtual_segment)
403 dosv_refresh_virtual_screen (t0, l0);
fc171623 404#endif
1b94449f 405}
aee81730 406#endif
1b94449f 407
1b94449f
RS
408/* Flash the screen as a substitute for BEEPs. */
409
f32d4091 410#if (__DJGPP__ < 2)
49a09c76 411static void
fcea9cd4 412do_visible_bell (xorattr)
1b94449f
RS
413 unsigned char xorattr;
414{
49a09c76 415 asm volatile
ca986694 416 (" movb $1,%%dl
1b94449f 417visible_bell_0:
ca986694 418 movl _ScreenPrimary,%%eax
49a09c76 419 call dosmemsetup
ca986694
RS
420 movl %%eax,%%ebx
421 movl %1,%%ecx
422 movb %0,%%al
423 incl %%ebx
1b94449f 424visible_bell_1:
ca986694
RS
425 xorb %%al,%%gs:(%%ebx)
426 addl $2,%%ebx
427 decl %%ecx
49a09c76 428 jne visible_bell_1
ca986694 429 decb %%dl
49a09c76 430 jne visible_bell_3
1b94449f 431visible_bell_2:
ca986694
RS
432 movzwl %%ax,%%eax
433 movzwl %%ax,%%eax
434 movzwl %%ax,%%eax
435 movzwl %%ax,%%eax
436 decw %%cx
49a09c76
RS
437 jne visible_bell_2
438 jmp visible_bell_0
ca986694
RS
439visible_bell_3:"
440 : /* no output */
f32d4091 441 : "m" (xorattr), "g" (screen_size)
ca986694 442 : "%eax", "%ebx", /* "%gs",*/ "%ecx", "%edx");
1b94449f
RS
443}
444
f32d4091
KS
445static void
446ScreenVisualBell (void)
447{
448 /* This creates an xor-mask that will swap the default fore- and
449 background colors. */
450 do_visible_bell (((the_only_x_display.foreground_pixel
451 ^ the_only_x_display.background_pixel)
452 * 0x11) & 0x7f);
453}
454#endif
455
456#ifndef HAVE_X_WINDOWS
457
b36701cc
RS
458static int blink_bit = -1; /* the state of the blink bit at startup */
459
76ac1508
RS
460/* Enable bright background colors. */
461static void
462bright_bg (void)
463{
464 union REGS regs;
465
b36701cc
RS
466 /* Remember the original state of the blink/bright-background bit.
467 It is stored at 0040:0065h in the BIOS data area. */
468 if (blink_bit == -1)
469 blink_bit = (_farpeekb (_dos_ds, 0x465) & 0x20) == 0x20;
470
76ac1508
RS
471 regs.h.bl = 0;
472 regs.x.ax = 0x1003;
473 int86 (0x10, &regs, &regs);
474}
475
b36701cc
RS
476/* Disable bright background colors (and enable blinking) if we found
477 the video system in that state at startup. */
478static void
479maybe_enable_blinking (void)
480{
481 if (blink_bit == 1)
482 {
483 union REGS regs;
484
485 regs.h.bl = 1;
486 regs.x.ax = 0x1003;
487 int86 (0x10, &regs, &regs);
488 }
489}
490
4a96d4d2
KH
491/* Set the screen dimensions so that it can show no less than
492 ROWS x COLS frame. */
48ffe371 493
4a96d4d2
KH
494void
495dos_set_window_size (rows, cols)
496 int *rows, *cols;
497{
498 char video_name[30];
499 Lisp_Object video_mode;
500 int video_mode_value;
501 int have_vga = 0;
502 union REGS regs;
503 int current_rows = ScreenRows (), current_cols = ScreenCols ();
504
505 if (*rows == current_rows && *cols == current_cols)
506 return;
507
508 /* Do we have a VGA? */
509 regs.x.ax = 0x1a00;
510 int86 (0x10, &regs, &regs);
511 if (regs.h.al == 0x1a && regs.h.bl > 5 && regs.h.bl < 13)
512 have_vga = 1;
513
514 mouse_off ();
515
48ffe371 516 /* If the user specified a special video mode for these dimensions,
4a96d4d2
KH
517 use that mode. */
518 sprintf (video_name, "screen-dimensions-%dx%d", *rows, *cols);
519 video_mode = XSYMBOL (Fintern_soft (build_string (video_name),
520 Qnil))-> value;
521
522 if (INTEGERP (video_mode)
523 && (video_mode_value = XINT (video_mode)) > 0)
524 {
525 regs.x.ax = video_mode_value;
526 int86 (0x10, &regs, &regs);
48ffe371
RS
527
528 if (have_mouse)
529 {
530 /* Must hardware-reset the mouse, or else it won't update
531 its notion of screen dimensions for some non-standard
532 video modes. This is *painfully* slow... */
533 regs.x.ax = 0;
534 int86 (0x33, &regs, &regs);
535 }
4a96d4d2
KH
536 }
537
538 /* Find one of the dimensions supported by standard EGA/VGA
539 which gives us at least the required dimensions. */
540
541#if __DJGPP__ > 1
542
543 else
544 {
545 static struct {
546 int rows;
547 int need_vga;
548 } std_dimension[] = {
549 {25, 0},
550 {28, 1},
551 {35, 0},
552 {40, 1},
553 {43, 0},
554 {50, 1}
555 };
556 int i = 0;
557
558 while (i < sizeof (std_dimension) / sizeof (std_dimension[0]))
559 {
560 if (std_dimension[i].need_vga <= have_vga
561 && std_dimension[i].rows >= *rows)
562 {
563 if (std_dimension[i].rows != current_rows
564 || *cols != current_cols)
48ffe371 565 _set_screen_lines (std_dimension[i].rows);
4a96d4d2
KH
566 break;
567 }
48ffe371 568 i++;
4a96d4d2
KH
569 }
570 }
571
572#else /* not __DJGPP__ > 1 */
573
574 else if (*rows <= 25)
575 {
576 if (current_rows != 25 || current_cols != 80)
577 {
578 regs.x.ax = 3;
579 int86 (0x10, &regs, &regs);
580 regs.x.ax = 0x1101;
581 regs.h.bl = 0;
582 int86 (0x10, &regs, &regs);
583 regs.x.ax = 0x1200;
584 regs.h.bl = 32;
585 int86 (0x10, &regs, &regs);
586 regs.x.ax = 3;
587 int86 (0x10, &regs, &regs);
588 }
589 }
590 else if (*rows <= 50)
591 if (have_vga && (current_rows != 50 || current_cols != 80)
592 || *rows <= 43 && (current_rows != 43 || current_cols != 80))
593 {
594 regs.x.ax = 3;
595 int86 (0x10, &regs, &regs);
596 regs.x.ax = 0x1112;
597 regs.h.bl = 0;
598 int86 (0x10, &regs, &regs);
599 regs.x.ax = 0x1200;
600 regs.h.bl = 32;
601 int86 (0x10, &regs, &regs);
602 regs.x.ax = 0x0100;
603 regs.x.cx = 7;
604 int86 (0x10, &regs, &regs);
605 }
606#endif /* not __DJGPP__ > 1 */
607
608 if (have_mouse)
609 {
4a96d4d2
KH
610 mouse_init ();
611 mouse_on ();
612 }
613
614 /* Tell the caller what dimensions have been REALLY set. */
615 *rows = ScreenRows ();
616 *cols = ScreenCols ();
76ac1508
RS
617
618 /* Enable bright background colors. */
619 bright_bg ();
039274cf
EZ
620
621 /* FIXME: I'm not sure the above will run at all on DOS/V. But let's
622 be defensive anyway. */
623 if (screen_virtual_segment)
624 dosv_refresh_virtual_screen (0, *cols * *rows);
4a96d4d2
KH
625}
626
48ffe371
RS
627/* If we write a character in the position where the mouse is,
628 the mouse cursor may need to be refreshed. */
09e2ac30
RS
629
630static void
f32d4091 631mouse_off_maybe ()
09e2ac30 632{
f32d4091
KS
633 int x, y;
634
635 if (!mouse_visible)
636 return;
637
638 mouse_get_xy (&x, &y);
639 if (y != new_pos_Y || x < new_pos_X)
640 return;
641
642 mouse_off ();
643}
644
71f65669
EZ
645static void
646IT_ring_bell (void)
f32d4091
KS
647{
648 if (visible_bell)
aee81730 649 {
f32d4091
KS
650 mouse_off ();
651 ScreenVisualBell ();
aee81730 652 }
f32d4091 653 else
3635be47
RS
654 {
655 union REGS inregs, outregs;
656 inregs.h.ah = 2;
657 inregs.h.dl = 7;
658 intdos (&inregs, &outregs);
659 }
09e2ac30
RS
660}
661
f32d4091
KS
662static void
663IT_set_face (int face)
664{
665 struct face *fp;
666 extern struct face *intern_face (/* FRAME_PTR, struct face * */);
667
668 if (face == 1 || (face == 0 && highlight))
669 fp = FRAME_MODE_LINE_FACE (foo);
670 else if (face <= 0 || face >= FRAME_N_COMPUTED_FACES (foo))
671 fp = FRAME_DEFAULT_FACE (foo);
672 else
673 fp = intern_face (selected_frame, FRAME_COMPUTED_FACES (foo)[face]);
674 if (termscript)
5d7e8345
RS
675 fprintf (termscript, "<FACE %d: %d/%d>",
676 face, FACE_FOREGROUND (fp), FACE_BACKGROUND (fp));
f32d4091
KS
677 screen_face = face;
678 ScreenAttrib = (FACE_BACKGROUND (fp) << 4) | FACE_FOREGROUND (fp);
679}
680
aa9ce936
EZ
681Lisp_Object Vdos_unsupported_char_glyph;
682
71f65669 683static void
aa9ce936 684IT_write_glyphs (GLYPH *str, int str_len)
f32d4091 685{
aa9ce936
EZ
686 unsigned char *screen_buf, *screen_bp, *screen_buf_end, *bp;
687 int unsupported_face = FAST_GLYPH_FACE (Vdos_unsupported_char_glyph);
688 unsigned unsupported_char= FAST_GLYPH_CHAR (Vdos_unsupported_char_glyph);
039274cf 689 int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
aa9ce936
EZ
690 register int sl = str_len;
691 register int tlen = GLYPH_TABLE_LENGTH;
692 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
693
694 struct coding_system *coding = CODING_REQUIRE_ENCODING (&terminal_coding)
695 ? &terminal_coding
696 : &safe_terminal_coding;
87485d6f 697
aa9ce936 698 if (str_len == 0) return;
aee81730 699
aa9ce936
EZ
700 screen_buf = screen_bp = alloca (str_len * 2);
701 screen_buf_end = screen_buf + str_len * 2;
aee81730 702
aa9ce936
EZ
703 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
704 the tail. */
705 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
706 while (sl)
707 {
708 int cf, ch, chlen, enclen;
709 unsigned char workbuf[4], *buf;
710 register GLYPH g = *str;
711
712 /* Find the actual glyph to display by traversing the entire
713 aliases chain for this glyph. */
714 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
715
716 /* Glyphs with GLYPH_MASK_PADDING bit set are actually there
717 only for the redisplay code to know how many columns does
718 this character occupy on the screen. Skip padding glyphs. */
719 if ((g & GLYPH_MASK_PADDING))
720 {
721 str++;
722 sl--;
723 }
724 else
725 {
726 /* Convert the character code to multibyte, if they
727 requested display via language environment. */
728 ch = FAST_GLYPH_CHAR (g);
aff4381d
EZ
729 /* We only want to convert unibyte characters to multibyte
730 in unibyte buffers! Otherwise, the 8-bit code might come
731 from the display table set up to display foreign characters. */
732 if (NILP (current_buffer->enable_multibyte_characters)
733 && unibyte_display_via_language_environment
aa9ce936 734 && SINGLE_BYTE_CHAR_P (ch)
f0dd4c35
EZ
735 && (ch >= 0240
736 || (ch >= 0200 && !NILP (Vnonascii_translation_table))))
aa9ce936
EZ
737 ch = unibyte_char_to_multibyte (ch);
738
739 /* Invalid characters are displayed with a special glyph. */
740 if (ch > MAX_CHAR)
741 {
742 g = !NILP (Vdos_unsupported_char_glyph)
743 ? Vdos_unsupported_char_glyph
744 : MAKE_GLYPH (selected_frame, '\177',
745 GLYPH_FACE (selected_frame, g));
746 ch = FAST_GLYPH_CHAR (g);
747 }
748 if (COMPOSITE_CHAR_P (ch))
749 {
750 /* If CH is a composite character, we can display
751 only the first component. */
752 g = cmpchar_table[COMPOSITE_CHAR_ID (ch)]->glyph[0],
753 ch = GLYPH_CHAR (selected_frame, g);
754 cf = FAST_GLYPH_FACE (g);
755 }
756
757 /* If the face of this glyph is different from the current
758 screen face, update the screen attribute byte. */
759 cf = FAST_GLYPH_FACE (g);
760 if (cf != screen_face)
761 IT_set_face (cf); /* handles invalid faces gracefully */
762
763 if (GLYPH_SIMPLE_P (tbase, tlen, g))
764 /* We generate the multi-byte form of CH in BUF. */
765 chlen = CHAR_STRING (ch, workbuf, buf);
766 else
767 {
768 /* We have a string in Vglyph_table. */
769 chlen = GLYPH_LENGTH (tbase, g);
770 buf = GLYPH_STRING (tbase, g);
771 }
772
773 /* If the character is not multibyte, don't bother converting it.
774 FIXME: what about "emacs --unibyte" */
775 if (chlen == 1)
776 {
777 *conversion_buffer = (unsigned char)ch;
778 chlen = 0;
779 enclen = 1;
780 }
781 else
782 {
783 encode_coding (coding, buf, conversion_buffer, chlen,
784 conversion_buffer_size);
785 chlen -= coding->consumed;
786 enclen = coding->produced;
787
788 /* Replace glyph codes that cannot be converted by
789 terminal_coding with Vdos_unsupported_char_glyph. */
790 if (*conversion_buffer == '?')
791 {
792 char *cbp = conversion_buffer;
793
794 while (cbp < conversion_buffer + enclen && *cbp == '?')
795 *cbp++ = unsupported_char;
796 if (unsupported_face != screen_face)
797 IT_set_face (unsupported_face);
798 }
799 }
800
801 if (enclen + chlen > screen_buf_end - screen_bp)
802 {
803 /* The allocated buffer for screen writes is too small.
804 Flush it and loop again without incrementing STR, so
805 that the next loop will begin with the same glyph. */
806 int nbytes = screen_bp - screen_buf;
807
808 mouse_off_maybe ();
809 dosmemput (screen_buf, nbytes, (int)ScreenPrimary + offset);
810 if (screen_virtual_segment)
811 dosv_refresh_virtual_screen (offset, nbytes / 2);
812 new_pos_X += nbytes / 2;
813 offset += nbytes;
814
815 /* Prepare to reuse the same buffer again. */
816 screen_bp = screen_buf;
817 }
818 else
819 {
820 /* There's enough place in the allocated buffer to add
821 the encoding of this glyph. */
822
823 /* First, copy the encoded bytes. */
824 for (bp = conversion_buffer; enclen--; bp++)
825 {
826 *screen_bp++ = (unsigned char)*bp;
827 *screen_bp++ = ScreenAttrib;
828 if (termscript)
829 fputc (*bp, termscript);
830 }
831
832 /* Now copy the bytes not consumed by the encoding. */
833 if (chlen > 0)
834 {
835 buf += coding->consumed;
836 while (chlen--)
837 {
838 if (termscript)
839 fputc (*buf, termscript);
840 *screen_bp++ = (unsigned char)*buf++;
841 *screen_bp++ = ScreenAttrib;
842 }
843 }
844
845 /* Update STR and its remaining length. */
846 str++;
847 sl--;
848 }
849 }
aee81730
RS
850 }
851
aa9ce936 852 /* Dump whatever is left in the screen buffer. */
f32d4091 853 mouse_off_maybe ();
aa9ce936 854 dosmemput (screen_buf, screen_bp - screen_buf, (int)ScreenPrimary + offset);
039274cf 855 if (screen_virtual_segment)
aa9ce936
EZ
856 dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2);
857 new_pos_X += (screen_bp - screen_buf) / 2;
858
859 /* We may have to output some codes to terminate the writing. */
860 if (CODING_REQUIRE_FLUSHING (coding))
861 {
862 coding->mode |= CODING_MODE_LAST_BLOCK;
863 encode_coding (coding, "", conversion_buffer, 0, conversion_buffer_size);
864 if (coding->produced > 0)
865 {
866 for (screen_bp = screen_buf, bp = conversion_buffer;
867 coding->produced--; bp++)
868 {
869 *screen_bp++ = (unsigned char)*bp;
870 *screen_bp++ = ScreenAttrib;
871 if (termscript)
872 fputc (*bp, termscript);
873 }
874 offset += screen_bp - screen_buf;
875 mouse_off_maybe ();
876 dosmemput (screen_buf, screen_bp - screen_buf,
877 (int)ScreenPrimary + offset);
878 if (screen_virtual_segment)
879 dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2);
880 new_pos_X += (screen_bp - screen_buf) / 2;
881 }
882 }
f32d4091 883}
aee81730 884
71f65669
EZ
885static void
886IT_clear_end_of_line (int first_unused)
f32d4091
KS
887{
888 char *spaces, *sp;
889 int i, j;
039274cf 890 int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
aa9ce936
EZ
891 extern int fatal_error_in_progress;
892
893 if (fatal_error_in_progress)
894 return;
f32d4091
KS
895
896 IT_set_face (0);
897 if (termscript)
898 fprintf (termscript, "<CLR:EOL>");
899 i = (j = screen_size_X - new_pos_X) * 2;
900 spaces = sp = alloca (i);
aee81730 901
f32d4091 902 while (--j >= 0)
aee81730 903 {
f32d4091
KS
904 *sp++ = ' ';
905 *sp++ = ScreenAttrib;
aee81730
RS
906 }
907
f32d4091 908 mouse_off_maybe ();
039274cf
EZ
909 dosmemput (spaces, i, (int)ScreenPrimary + offset);
910 if (screen_virtual_segment)
911 dosv_refresh_virtual_screen (offset, i / 2);
aee81730
RS
912}
913
71f65669 914static void
f32d4091
KS
915IT_clear_screen (void)
916{
917 if (termscript)
918 fprintf (termscript, "<CLR:SCR>");
919 IT_set_face (0);
920 mouse_off ();
921 ScreenClear ();
039274cf
EZ
922 if (screen_virtual_segment)
923 dosv_refresh_virtual_screen (0, screen_size);
f32d4091
KS
924 new_pos_X = new_pos_Y = 0;
925}
926
71f65669 927static void
f32d4091
KS
928IT_clear_to_end (void)
929{
930 if (termscript)
931 fprintf (termscript, "<CLR:EOS>");
932
933 while (new_pos_Y < screen_size_Y) {
934 new_pos_X = 0;
935 IT_clear_end_of_line (0);
936 new_pos_Y++;
937 }
938}
939
71f65669 940static void
f32d4091
KS
941IT_cursor_to (int y, int x)
942{
943 if (termscript)
944 fprintf (termscript, "\n<XY=%dx%d>", x, y);
945 new_pos_X = x;
946 new_pos_Y = y;
947}
948
fc171623
KH
949static int cursor_cleared;
950
951static
952IT_display_cursor (int on)
953{
954 if (on && cursor_cleared)
955 {
956 ScreenSetCursor (current_pos_Y, current_pos_X);
957 cursor_cleared = 0;
958 }
959 else if (!on && !cursor_cleared)
960 {
961 ScreenSetCursor (-1, -1);
962 cursor_cleared = 1;
963 }
964}
965
966/* Emacs calls cursor-movement functions a lot when it updates the
967 display (probably a legacy of old terminals where you cannot
968 update a screen line without first moving the cursor there).
969 However, cursor movement is expensive on MSDOS (it calls a slow
970 BIOS function and requires 2 mode switches), while actual screen
971 updates access the video memory directly and don't depend on
972 cursor position. To avoid slowing down the redisplay, we cheat:
973 all functions that move the cursor only set internal variables
974 which record the cursor position, whereas the cursor is only
975 moved to its final position whenever screen update is complete.
976
977 `IT_cmgoto' is called from the keyboard reading loop and when the
978 frame update is complete. This means that we are ready for user
979 input, so we update the cursor position to show where the point is,
980 and also make the mouse pointer visible.
981
982 Special treatment is required when the cursor is in the echo area,
983 to put the cursor at the end of the text displayed there. */
984
71f65669
EZ
985static void
986IT_cmgoto (FRAME_PTR f)
fc171623
KH
987{
988 /* Only set the cursor to where it should be if the display is
989 already in sync with the window contents. */
990 int update_cursor_pos = MODIFF == unchanged_modified;
06da1de1
EZ
991 static int previous_pos_X = -1;
992
993 /* If the display is in sync, forget any previous knowledge about
994 cursor position. This is primarily for unexpected events like
995 C-g in the minibuffer. */
996 if (update_cursor_pos && previous_pos_X >= 0)
997 previous_pos_X = -1;
998 /* If we are in the echo area, put the cursor at the
999 end of the echo area message. */
fc171623
KH
1000 if (!update_cursor_pos
1001 && XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top) <= new_pos_Y)
1002 {
06da1de1
EZ
1003 int tem_X = current_pos_X, dummy;
1004
1005 if (echo_area_glyphs)
1006 {
1007 tem_X = echo_area_glyphs_length;
1008 /* Save current cursor position, to be restored after the
1009 echo area message is erased. Only remember one level
1010 of previous cursor position. */
1011 if (previous_pos_X == -1)
1012 ScreenGetCursor (&dummy, &previous_pos_X);
1013 }
1014 else if (previous_pos_X >= 0)
1015 {
1016 /* We wind up here after the echo area message is erased.
1017 Restore the cursor position we remembered above. */
1018 tem_X = previous_pos_X;
1019 previous_pos_X = -1;
1020 }
9a599a60 1021
06da1de1 1022 if (current_pos_X != tem_X)
9a599a60
EZ
1023 {
1024 new_pos_X = tem_X;
1025 update_cursor_pos = 1;
1026 }
fc171623
KH
1027 }
1028
1029 if (update_cursor_pos
1030 && (current_pos_X != new_pos_X || current_pos_Y != new_pos_Y))
1031 {
1032 ScreenSetCursor (current_pos_Y = new_pos_Y, current_pos_X = new_pos_X);
1033 if (termscript)
1034 fprintf (termscript, "\n<CURSOR:%dx%d>", current_pos_X, current_pos_Y);
1035 }
1036
1037 /* Maybe cursor is invisible, so make it visible. */
1038 IT_display_cursor (1);
1039
1040 /* Mouse pointer should be always visible if we are waiting for
1041 keyboard input. */
1042 if (!mouse_visible)
1043 mouse_on ();
1044}
1045
71f65669
EZ
1046static void
1047IT_reassert_line_highlight (int new, int vpos)
f32d4091
KS
1048{
1049 highlight = new;
1050 IT_set_face (0); /* To possibly clear the highlighting. */
1051}
1052
71f65669
EZ
1053static void
1054IT_change_line_highlight (int new_highlight, int vpos, int first_unused_hpos)
1b94449f 1055{
f32d4091
KS
1056 highlight = new_highlight;
1057 IT_set_face (0); /* To possibly clear the highlighting. */
1058 IT_cursor_to (vpos, 0);
1059 IT_clear_end_of_line (first_unused_hpos);
1060}
1061
71f65669
EZ
1062static void
1063IT_update_begin (struct frame *foo)
f32d4091
KS
1064{
1065 highlight = 0;
1066 IT_set_face (0); /* To possibly clear the highlighting. */
1067 screen_face = -1;
1068}
1069
71f65669
EZ
1070static void
1071IT_update_end (struct frame *foo)
f32d4091
KS
1072{
1073}
1b94449f 1074
aa9ce936
EZ
1075/* Insert and delete characters. These are not supposed to be used
1076 because we are supposed to turn off the feature of using them by
1077 setting char_ins_del_ok to zero (see internal_terminal_init). */
1078static void
1079IT_insert_glyphs (start, len)
1080 register char *start;
1081 register int len;
1082{
1083 abort ();
1084}
1085
1086static void
1087IT_delete_glyphs (n)
1088 register int n;
1089{
1090 abort ();
1091}
1092
211c7152 1093/* set-window-configuration on window.c needs this. */
3bb1f22f
RS
1094void
1095x_set_menu_bar_lines (f, value, oldval)
1096 struct frame *f;
1097 Lisp_Object value, oldval;
1098{
211c7152
EZ
1099 set_menu_bar_lines (f, value, oldval);
1100}
3bb1f22f 1101
211c7152 1102/* This was copied from xfns.c */
3bb1f22f 1103
211c7152
EZ
1104Lisp_Object Qbackground_color;
1105Lisp_Object Qforeground_color;
1106extern Lisp_Object Qtitle;
3bb1f22f 1107
48ffe371
RS
1108/* IT_set_terminal_modes is called when emacs is started,
1109 resumed, and whenever the screen is redrawn! */
f32d4091 1110
71f65669 1111static void
f32d4091
KS
1112IT_set_terminal_modes (void)
1113{
aee81730 1114 if (termscript)
f32d4091
KS
1115 fprintf (termscript, "\n<SET_TERM>");
1116 highlight = 0;
1117
1118 screen_size_X = ScreenCols ();
1119 screen_size_Y = ScreenRows ();
1120 screen_size = screen_size_X * screen_size_Y;
aee81730 1121
f32d4091
KS
1122 new_pos_X = new_pos_Y = 0;
1123 current_pos_X = current_pos_Y = -1;
1124
1125 if (term_setup_done)
1126 return;
1127 term_setup_done = 1;
aee81730 1128
f32d4091
KS
1129 startup_screen_size_X = screen_size_X;
1130 startup_screen_size_Y = screen_size_Y;
c9adab25 1131 startup_screen_attrib = ScreenAttrib;
f32d4091 1132
039274cf
EZ
1133#if __DJGPP__ > 1
1134 /* Is DOS/V (or any other RSIS software which relocates
1135 the screen) installed? */
1136 {
1137 unsigned short es_value;
1138 __dpmi_regs regs;
1139
1140 regs.h.ah = 0xfe; /* get relocated screen address */
1141 if (ScreenPrimary == 0xb0000UL || ScreenPrimary == 0xb8000UL)
1142 regs.x.es = (ScreenPrimary >> 4) & 0xffff;
1143 else if (screen_old_address) /* already switched to Japanese mode once */
1144 regs.x.es = (screen_old_address >> 4) & 0xffff;
1145 else
1146 regs.x.es = ScreenMode () == 7 ? 0xb000 : 0xb800;
1147 regs.x.di = 0;
1148 es_value = regs.x.es;
1149 __dpmi_int (0x10, &regs);
1150
1151 if (regs.x.es != es_value && regs.x.es != (ScreenPrimary >> 4) & 0xffff)
1152 {
1153 screen_old_address = ScreenPrimary;
1154 screen_virtual_segment = regs.x.es;
1155 screen_virtual_offset = regs.x.di;
1156 ScreenPrimary = (screen_virtual_segment << 4) + screen_virtual_offset;
1157 }
1158 }
1159#endif /* __DJGPP__ > 1 */
1160
f32d4091
KS
1161 ScreenGetCursor (&startup_pos_Y, &startup_pos_X);
1162 ScreenRetrieve (startup_screen_buffer = xmalloc (screen_size * 2));
1163
1164 if (termscript)
c9adab25 1165 fprintf (termscript, "<SCREEN SAVED (dimensions=%dx%d)>\n",
039274cf 1166 screen_size_X, screen_size_Y);
76ac1508
RS
1167
1168 bright_bg ();
f32d4091
KS
1169}
1170
48ffe371
RS
1171/* IT_reset_terminal_modes is called when emacs is
1172 suspended or killed. */
f32d4091 1173
71f65669 1174static void
f32d4091
KS
1175IT_reset_terminal_modes (void)
1176{
c9adab25
KH
1177 int display_row_start = (int) ScreenPrimary;
1178 int saved_row_len = startup_screen_size_X * 2;
1179 int update_row_len = ScreenCols () * 2;
1180 int current_rows = ScreenRows ();
1181 int to_next_row = update_row_len;
1182 unsigned char *saved_row = startup_screen_buffer;
1183 int cursor_pos_X = ScreenCols () - 1;
1184 int cursor_pos_Y = ScreenRows () - 1;
1185
f32d4091 1186 if (termscript)
5063b150 1187 fprintf (termscript, "\n<RESET_TERM>");
f32d4091
KS
1188
1189 highlight = 0;
1190
1191 if (!term_setup_done)
1192 return;
1193
c9adab25 1194 mouse_off ();
b36701cc
RS
1195
1196 /* Leave the video system in the same state as we found it,
1197 as far as the blink/bright-background bit is concerned. */
1198 maybe_enable_blinking ();
06b1ea13 1199
c9adab25
KH
1200 /* We have a situation here.
1201 We cannot just do ScreenUpdate(startup_screen_buffer) because
1202 the luser could have changed screen dimensions inside Emacs
1203 and failed (or didn't want) to restore them before killing
1204 Emacs. ScreenUpdate() uses the *current* screen dimensions and
1205 thus will happily use memory outside what was allocated for
1206 `startup_screen_buffer'.
1207 Thus we only restore as much as the current screen dimensions
1208 can hold, and clear the rest (if the saved screen is smaller than
1209 the current) with the color attribute saved at startup. The cursor
1210 is also restored within the visible dimensions. */
1211
1212 ScreenAttrib = startup_screen_attrib;
c9adab25 1213
06b1ea13
EZ
1214 /* Don't restore the screen if we are exiting less than 2 seconds
1215 after startup: we might be crashing, and the screen might show
1216 some vital clues to what's wrong. */
1217 if (clock () - startup_time >= 2*CLOCKS_PER_SEC)
c9adab25 1218 {
06b1ea13 1219 ScreenClear ();
039274cf 1220 if (screen_virtual_segment)
06b1ea13
EZ
1221 dosv_refresh_virtual_screen (0, screen_size);
1222
1223 if (update_row_len > saved_row_len)
1224 update_row_len = saved_row_len;
1225 if (current_rows > startup_screen_size_Y)
1226 current_rows = startup_screen_size_Y;
1227
1228 if (termscript)
1229 fprintf (termscript, "<SCREEN RESTORED (dimensions=%dx%d)>\n",
1230 update_row_len / 2, current_rows);
1231
1232 while (current_rows--)
1233 {
1234 dosmemput (saved_row, update_row_len, display_row_start);
1235 if (screen_virtual_segment)
1236 dosv_refresh_virtual_screen (display_row_start - ScreenPrimary,
1237 update_row_len / 2);
1238 saved_row += saved_row_len;
1239 display_row_start += to_next_row;
1240 }
c9adab25
KH
1241 }
1242 if (startup_pos_X < cursor_pos_X)
1243 cursor_pos_X = startup_pos_X;
1244 if (startup_pos_Y < cursor_pos_Y)
1245 cursor_pos_Y = startup_pos_Y;
1246
1247 ScreenSetCursor (cursor_pos_Y, cursor_pos_X);
1248 xfree (startup_screen_buffer);
f32d4091
KS
1249
1250 term_setup_done = 0;
1251}
1252
71f65669
EZ
1253static void
1254IT_set_terminal_window (int foo)
f32d4091
KS
1255{
1256}
1257
1258void
3bb1f22f
RS
1259IT_set_frame_parameters (f, alist)
1260 FRAME_PTR f;
f32d4091
KS
1261 Lisp_Object alist;
1262{
1263 Lisp_Object tail;
db722735
RS
1264 int length = XINT (Flength (alist));
1265 int i;
1266 Lisp_Object *parms
1267 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
1268 Lisp_Object *values
1269 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
f32d4091
KS
1270 int redraw;
1271 extern unsigned long load_color ();
f32d4091
KS
1272
1273 redraw = 0;
db722735
RS
1274
1275 /* Extract parm names and values into those vectors. */
1276 i = 0;
f32d4091
KS
1277 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
1278 {
db722735 1279 Lisp_Object elt;
f32d4091
KS
1280
1281 elt = Fcar (tail);
db722735
RS
1282 parms[i] = Fcar (elt);
1283 CHECK_SYMBOL (parms[i], 1);
1284 values[i] = Fcdr (elt);
1285 i++;
1286 }
1287
1288
1289 /* Now process them in reverse of specified order. */
1290 for (i--; i >= 0; i--)
1291 {
1292 Lisp_Object prop = parms[i];
1293 Lisp_Object val = values[i];
f32d4091 1294
4e825084 1295 if (EQ (prop, Qforeground_color))
f32d4091
KS
1296 {
1297 unsigned long new_color = load_color (f, val);
1298 if (new_color != ~0)
1299 {
1300 FRAME_FOREGROUND_PIXEL (f) = new_color;
1301 redraw = 1;
76ac1508 1302 if (termscript)
a7cf9151 1303 fprintf (termscript, "<FGCOLOR %lu>\n", new_color);
f32d4091
KS
1304 }
1305 }
4e825084 1306 else if (EQ (prop, Qbackground_color))
f32d4091
KS
1307 {
1308 unsigned long new_color = load_color (f, val);
1309 if (new_color != ~0)
1310 {
76ac1508 1311 FRAME_BACKGROUND_PIXEL (f) = new_color;
f32d4091 1312 redraw = 1;
76ac1508 1313 if (termscript)
a7cf9151 1314 fprintf (termscript, "<BGCOLOR %lu>\n", new_color);
f32d4091
KS
1315 }
1316 }
211c7152
EZ
1317 else if (EQ (prop, Qtitle))
1318 {
1319 x_set_title (f, val);
1320 if (termscript)
1321 fprintf (termscript, "<TITLE: %s>\n", XSTRING (val)->data);
1322 }
1323 else if (EQ (prop, intern ("reverse")) && EQ (val, Qt))
1324 {
1325 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
db722735 1326
211c7152
EZ
1327 FRAME_FOREGROUND_PIXEL (f) = FRAME_BACKGROUND_PIXEL (f);
1328 FRAME_BACKGROUND_PIXEL (f) = fg;
1329 if (termscript)
1330 fprintf (termscript, "<INVERSE-VIDEO>\n");
1331 }
db722735
RS
1332 store_frame_param (f, prop, val);
1333
f32d4091
KS
1334 }
1335
1336 if (redraw)
1337 {
a7cf9151
EZ
1338 extern void recompute_basic_faces (FRAME_PTR);
1339 extern void redraw_frame (FRAME_PTR);
1340
f32d4091 1341 recompute_basic_faces (f);
3bb1f22f
RS
1342 if (f == selected_frame)
1343 redraw_frame (f);
f32d4091
KS
1344 }
1345}
1346
a7cf9151
EZ
1347extern void init_frame_faces (FRAME_PTR);
1348
f32d4091
KS
1349#endif /* !HAVE_X_WINDOWS */
1350
1351
48ffe371
RS
1352/* Do we need the internal terminal? */
1353
f32d4091
KS
1354void
1355internal_terminal_init ()
1356{
1357 char *term = getenv ("TERM");
1358 char *colors;
1359
1360#ifdef HAVE_X_WINDOWS
1361 if (!inhibit_window_system)
1362 return;
1363#endif
1364
1365 internal_terminal
1366 = (!noninteractive) && term && !strcmp (term, "internal");
1367
1368 if (getenv ("EMACSTEST"))
5063b150 1369 termscript = fopen (getenv ("EMACSTEST"), "wt");
f32d4091
KS
1370
1371#ifndef HAVE_X_WINDOWS
1372 if (!internal_terminal || inhibit_window_system)
1373 {
3bb1f22f 1374 selected_frame->output_method = output_termcap;
f32d4091
KS
1375 return;
1376 }
1377
1378 Vwindow_system = intern ("pc");
1379 Vwindow_system_version = make_number (1);
039274cf
EZ
1380
1381 /* If Emacs was dumped on DOS/V machine, forget the stale VRAM address. */
1382 screen_old_address = 0;
1383
f32d4091
KS
1384 bzero (&the_only_x_display, sizeof the_only_x_display);
1385 the_only_x_display.background_pixel = 7; /* White */
1386 the_only_x_display.foreground_pixel = 0; /* Black */
76ac1508 1387 bright_bg ();
5063b150 1388 colors = getenv ("EMACSCOLORS");
f32d4091
KS
1389 if (colors && strlen (colors) >= 2)
1390 {
76ac1508
RS
1391 /* The colors use 4 bits each (we enable bright background). */
1392 if (isdigit (colors[0]))
1393 colors[0] -= '0';
1394 else if (isxdigit (colors[0]))
1395 colors[0] -= (isupper (colors[0]) ? 'A' : 'a') - 10;
1bd7b2c7
RS
1396 if (colors[0] >= 0 && colors[0] < 16)
1397 the_only_x_display.foreground_pixel = colors[0];
76ac1508
RS
1398 if (isdigit (colors[1]))
1399 colors[1] -= '0';
1400 else if (isxdigit (colors[1]))
1401 colors[1] -= (isupper (colors[1]) ? 'A' : 'a') - 10;
1402 if (colors[1] >= 0 && colors[1] < 16)
1bd7b2c7 1403 the_only_x_display.background_pixel = colors[1];
f32d4091
KS
1404 }
1405 the_only_x_display.line_height = 1;
64ec6a02 1406 the_only_x_display.font = (XFontStruct *)1; /* must *not* be zero */
f32d4091 1407
3bb1f22f 1408 init_frame_faces (selected_frame);
f32d4091
KS
1409
1410 ring_bell_hook = IT_ring_bell;
aa9ce936
EZ
1411 insert_glyphs_hook = IT_insert_glyphs;
1412 delete_glyphs_hook = IT_delete_glyphs;
f32d4091
KS
1413 write_glyphs_hook = IT_write_glyphs;
1414 cursor_to_hook = raw_cursor_to_hook = IT_cursor_to;
1415 clear_to_end_hook = IT_clear_to_end;
1416 clear_end_of_line_hook = IT_clear_end_of_line;
1417 clear_frame_hook = IT_clear_screen;
1418 change_line_highlight_hook = IT_change_line_highlight;
1419 update_begin_hook = IT_update_begin;
1420 update_end_hook = IT_update_end;
1421 reassert_line_highlight_hook = IT_reassert_line_highlight;
fc171623 1422 frame_up_to_date_hook = IT_cmgoto; /* position cursor when update is done */
f32d4091
KS
1423
1424 /* These hooks are called by term.c without being checked. */
1425 set_terminal_modes_hook = IT_set_terminal_modes;
1426 reset_terminal_modes_hook = IT_reset_terminal_modes;
1427 set_terminal_window_hook = IT_set_terminal_window;
aa9ce936
EZ
1428
1429 char_ins_del_ok = 0; /* just as fast to write the line */
f32d4091
KS
1430#endif
1431}
1432
1433dos_get_saved_screen (screen, rows, cols)
1434 char **screen;
1435 int *rows;
1436 int *cols;
1437{
1438#ifndef HAVE_X_WINDOWS
1439 *screen = startup_screen_buffer;
1440 *cols = startup_screen_size_X;
1441 *rows = startup_screen_size_Y;
039274cf 1442 return *screen != (char *)0;
f32d4091
KS
1443#else
1444 return 0;
1445#endif
1446}
3bb1f22f
RS
1447
1448#ifndef HAVE_X_WINDOWS
1449
1450/* We are not X, but we can emulate it well enough for our needs... */
1451void
1452check_x (void)
1453{
1454 if (! FRAME_MSDOS_P (selected_frame))
1455 error ("Not running under a windows system");
1456}
1457
1458#endif
1459
5063b150 1460\f
f32d4091
KS
1461/* ----------------------- Keyboard control ----------------------
1462 *
1463 * Keymaps reflect the following keyboard layout:
1464 *
1465 * 0 1 2 3 4 5 6 7 8 9 10 11 12 BS
1466 * TAB 15 16 17 18 19 20 21 22 23 24 25 26 (41)
1467 * CLOK 30 31 32 33 34 35 36 37 38 39 40 (41) RET
1468 * SH () 45 46 47 48 49 50 51 52 53 54 SHIFT
1469 * SPACE
1470 */
1471
1472static int extended_kbd; /* 101 (102) keyboard present. */
1473
1474struct dos_keyboard_map
1475{
1476 char *unshifted;
1477 char *shifted;
1478 char *alt_gr;
1479};
1480
1481
1482static struct dos_keyboard_map us_keyboard = {
1483/* 0 1 2 3 4 5 */
1484/* 01234567890123456789012345678901234567890 12345678901234 */
1485 "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ",
1486/* 0123456789012345678901234567890123456789 012345678901234 */
1487 "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ",
1488 0 /* no Alt-Gr key */
1489};
1490
1491static struct dos_keyboard_map fr_keyboard = {
1492/* 0 1 2 3 4 5 */
1493/* 012 3456789012345678901234567890123456789012345678901234 */
1494