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