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