(IT_set_frame_parameters): Don't initialize Lisp_Object
[bpt/emacs.git] / src / msdos.c
CommitLineData
c6a6499f 1/* MS-DOS specific C utilities. -*- coding: raw-text -*-
68c45bf0 2 Copyright (C) 1993, 94, 95, 96, 97, 1999 Free Software Foundation, Inc.
1b94449f
RS
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
edfc0d45 8the Free Software Foundation; either version 2, or (at your option)
1b94449f
RS
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
1b94449f 20
9da6e765 21/* Contributed by Morten Welinder */
f32d4091 22/* New display, keyboard, and mouse control by Kim F. Storm */
9da6e765 23
1b94449f
RS
24/* Note: some of the stuff here was taken from end of sysdep.c in demacs. */
25
48984716 26#include <config.h>
1b94449f
RS
27
28#ifdef MSDOS
29#include "lisp.h"
30#include <stdio.h>
31#include <stdlib.h>
06b1ea13 32#include <time.h>
1b94449f
RS
33#include <sys/param.h>
34#include <sys/time.h>
35#include <dos.h>
d21e67b5 36#include <errno.h>
a7cf9151 37#include <string.h> /* for bzero and string functions */
d21e67b5 38#include <sys/stat.h> /* for _fixpath */
a7cf9151 39#include <unistd.h> /* for chdir, dup, dup2, etc. */
1bd7b2c7
RS
40#if __DJGPP__ >= 2
41#include <fcntl.h>
a7cf9151 42#include <io.h> /* for setmode */
fc171623
KH
43#include <dpmi.h> /* for __dpmi_xxx stuff */
44#include <sys/farptr.h> /* for _farsetsel, _farnspokeb */
d21e67b5 45#include <libc/dosio.h> /* for _USE_LFN */
a7cf9151 46#include <conio.h> /* for cputs */
1bd7b2c7
RS
47#endif
48
1b94449f
RS
49#include "msdos.h"
50#include "systime.h"
51#include "termhooks.h"
aa9ce936 52#include "termchar.h"
87485d6f 53#include "dispextern.h"
c77f6f1b 54#include "dosfns.h"
87485d6f 55#include "termopts.h"
aa9ce936
EZ
56#include "charset.h"
57#include "coding.h"
58#include "disptab.h"
1b94449f 59#include "frame.h"
87485d6f 60#include "window.h"
fc171623
KH
61#include "buffer.h"
62#include "commands.h"
41ad069b 63#include "blockinput.h"
97dd288b 64#include "keyboard.h"
1b94449f
RS
65#include <go32.h>
66#include <pc.h>
67#include <ctype.h>
68/* #include <process.h> */
69/* Damn that local process.h! Instead we can define P_WAIT ourselves. */
70#define P_WAIT 1
71
d21e67b5
RS
72#ifndef _USE_LFN
73#define _USE_LFN 0
74#endif
75
b36701cc
RS
76#ifndef _dos_ds
77#define _dos_ds _go32_info_block.selector_for_linear_memory
78#endif
79
1bd7b2c7
RS
80#if __DJGPP__ > 1
81
8748735b 82#include <signal.h>
417a04bb 83#include "syssignal.h"
8748735b 84
1bd7b2c7
RS
85#ifndef SYSTEM_MALLOC
86
87#ifdef GNU_MALLOC
88
89/* If other `malloc' than ours is used, force our `sbrk' behave like
90 Unix programs expect (resize memory blocks to keep them contiguous).
91 If `sbrk' from `ralloc.c' is NOT used, also zero-out sbrk'ed memory,
92 because that's what `gmalloc' expects to get. */
93#include <crt0.h>
94
95#ifdef REL_ALLOC
96int _crt0_startup_flags = _CRT0_FLAG_UNIX_SBRK;
97#else /* not REL_ALLOC */
98int _crt0_startup_flags = (_CRT0_FLAG_UNIX_SBRK | _CRT0_FLAG_FILL_SBRK_MEMORY);
99#endif /* not REL_ALLOC */
100#endif /* GNU_MALLOC */
101
102#endif /* not SYSTEM_MALLOC */
103#endif /* __DJGPP__ > 1 */
aee81730
RS
104
105static unsigned long
106event_timestamp ()
107{
108 struct time t;
109 unsigned long s;
f32d4091 110
aee81730
RS
111 gettime (&t);
112 s = t.ti_min;
113 s *= 60;
114 s += t.ti_sec;
115 s *= 1000;
116 s += t.ti_hund * 10;
f32d4091 117
aee81730
RS
118 return s;
119}
120
f32d4091
KS
121\f
122/* ------------------------ Mouse control ---------------------------
123 *
124 * Coordinates are in screen positions and zero based.
125 * Mouse buttons are numbered from left to right and also zero based.
126 */
1b94449f 127
0c3cfc51
EZ
128/* This used to be in termhooks.h, but mainstream Emacs code no longer
129 uses it, and it was removed... */
130#define NUM_MOUSE_BUTTONS (5)
131
f32d4091
KS
132int have_mouse; /* 0: no, 1: enabled, -1: disabled */
133static int mouse_visible;
1b94449f 134
f32d4091
KS
135static int mouse_last_x;
136static int mouse_last_y;
1b94449f 137
f32d4091
KS
138static int mouse_button_translate[NUM_MOUSE_BUTTONS];
139static int mouse_button_count;
1b94449f 140
f32d4091
KS
141void
142mouse_on ()
1b94449f 143{
1b94449f 144 union REGS regs;
1b94449f 145
f32d4091 146 if (have_mouse > 0 && !mouse_visible)
1b94449f 147 {
f32d4091
KS
148 if (termscript)
149 fprintf (termscript, "<M_ON>");
150 regs.x.ax = 0x0001;
151 int86 (0x33, &regs, &regs);
152 mouse_visible = 1;
1b94449f 153 }
1b94449f
RS
154}
155
f32d4091
KS
156void
157mouse_off ()
1b94449f 158{
f32d4091 159 union REGS regs;
1b94449f 160
f32d4091 161 if (have_mouse > 0 && mouse_visible)
1b94449f 162 {
f32d4091
KS
163 if (termscript)
164 fprintf (termscript, "<M_OFF>");
165 regs.x.ax = 0x0002;
166 int86 (0x33, &regs, &regs);
167 mouse_visible = 0;
1b94449f 168 }
1b94449f
RS
169}
170
8f190436
EZ
171static void
172mouse_setup_buttons (int n_buttons)
173{
174 if (n_buttons == 3)
175 {
176 mouse_button_count = 3;
177 mouse_button_translate[0] = 0; /* Left */
178 mouse_button_translate[1] = 2; /* Middle */
179 mouse_button_translate[2] = 1; /* Right */
180 }
181 else /* two, what else? */
182 {
183 mouse_button_count = 2;
184 mouse_button_translate[0] = 0;
185 mouse_button_translate[1] = 1;
186 }
187}
188
189DEFUN ("msdos-set-mouse-buttons", Fmsdos_set_mouse_buttons, Smsdos_set_mouse_buttons,
190 1, 1, "NSet number of mouse buttons to: ",
84968b32
EZ
191 "Set the number of mouse buttons to use by Emacs.\n\
192This is useful with mice that report the number of buttons inconsistently,\n\
193e.g., if the number of buttons is reported as 3, but Emacs only sees 2 of\n\
8f190436
EZ
194them. This happens with wheeled mice on Windows 9X, for example.")
195 (nbuttons)
196 Lisp_Object nbuttons;
197{
198 CHECK_NUMBER (nbuttons, 0);
199 mouse_setup_buttons (XINT (nbuttons));
200 return Qnil;
201}
202
211c7152
EZ
203static void
204mouse_get_xy (int *x, int *y)
205{
206 union REGS regs;
207
208 regs.x.ax = 0x0003;
209 int86 (0x33, &regs, &regs);
210 *x = regs.x.cx / 8;
211 *y = regs.x.dx / 8;
212}
213
f32d4091
KS
214void
215mouse_moveto (x, y)
216 int x, y;
1b94449f 217{
f32d4091 218 union REGS regs;
1b94449f 219
f32d4091
KS
220 if (termscript)
221 fprintf (termscript, "<M_XY=%dx%d>", x, y);
222 regs.x.ax = 0x0004;
223 mouse_last_x = regs.x.cx = x * 8;
224 mouse_last_y = regs.x.dx = y * 8;
225 int86 (0x33, &regs, &regs);
1b94449f
RS
226}
227
f32d4091
KS
228static int
229mouse_pressed (b, xp, yp)
230 int b, *xp, *yp;
1b94449f 231{
f32d4091 232 union REGS regs;
1b94449f 233
f32d4091
KS
234 if (b >= mouse_button_count)
235 return 0;
236 regs.x.ax = 0x0005;
237 regs.x.bx = mouse_button_translate[b];
238 int86 (0x33, &regs, &regs);
239 if (regs.x.bx)
240 *xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
241 return (regs.x.bx != 0);
1b94449f
RS
242}
243
f32d4091
KS
244static int
245mouse_released (b, xp, yp)
246 int b, *xp, *yp;
1b94449f
RS
247{
248 union REGS regs;
249
f32d4091
KS
250 if (b >= mouse_button_count)
251 return 0;
252 regs.x.ax = 0x0006;
253 regs.x.bx = mouse_button_translate[b];
254 int86 (0x33, &regs, &regs);
255 if (regs.x.bx)
256 *xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
257 return (regs.x.bx != 0);
1b94449f
RS
258}
259
0c7bc1aa
EZ
260static int
261mouse_button_depressed (b, xp, yp)
262 int b, *xp, *yp;
263{
264 union REGS regs;
265
266 if (b >= mouse_button_count)
267 return 0;
268 regs.x.ax = 0x0003;
269 int86 (0x33, &regs, &regs);
270 if ((regs.x.bx & (1 << mouse_button_translate[b])) != 0)
271 {
272 *xp = regs.x.cx / 8;
273 *yp = regs.x.dx / 8;
274 return 1;
275 }
276 return 0;
277}
278
f32d4091
KS
279void
280mouse_get_pos (f, insist, bar_window, part, x, y, time)
281 FRAME_PTR *f;
282 int insist;
283 Lisp_Object *bar_window, *x, *y;
284 enum scroll_bar_part *part;
285 unsigned long *time;
286{
287 int ix, iy;
211c7152
EZ
288 Lisp_Object frame, tail;
289
290 /* Clear the mouse-moved flag for every frame on this display. */
291 FOR_EACH_FRAME (tail, frame)
292 XFRAME (frame)->mouse_moved = 0;
f32d4091 293
2d764c78 294 *f = SELECTED_FRAME();
f32d4091
KS
295 *bar_window = Qnil;
296 mouse_get_xy (&ix, &iy);
f32d4091 297 *time = event_timestamp ();
211c7152
EZ
298 *x = make_number (mouse_last_x = ix);
299 *y = make_number (mouse_last_y = iy);
f32d4091 300}
1b94449f 301
f32d4091
KS
302static void
303mouse_check_moved ()
1b94449f 304{
aee81730 305 int x, y;
1b94449f 306
f32d4091 307 mouse_get_xy (&x, &y);
2d764c78 308 SELECTED_FRAME()->mouse_moved |= (x != mouse_last_x || y != mouse_last_y);
f32d4091
KS
309 mouse_last_x = x;
310 mouse_last_y = y;
311}
1b94449f 312
97dd288b
EZ
313/* Force the mouse driver to ``forget'' about any button clicks until
314 now. */
315static void
316mouse_clear_clicks (void)
317{
318 int b;
319
320 for (b = 0; b < mouse_button_count; b++)
321 {
322 int dummy_x, dummy_y;
323
324 (void) mouse_pressed (b, &dummy_x, &dummy_y);
325 (void) mouse_released (b, &dummy_x, &dummy_y);
326 }
327}
328
f32d4091
KS
329void
330mouse_init ()
331{
332 union REGS regs;
647c32eb 333
f32d4091
KS
334 if (termscript)
335 fprintf (termscript, "<M_INIT>");
1b94449f 336
f32d4091
KS
337 regs.x.ax = 0x0021;
338 int86 (0x33, &regs, &regs);
091d0bdf 339
0c7bc1aa
EZ
340 /* Reset the mouse last press/release info. It seems that Windows
341 doesn't do that automatically when function 21h is called, which
342 causes Emacs to ``remember'' the click that switched focus to the
343 window just before Emacs was started from that window. */
97dd288b 344 mouse_clear_clicks ();
0c7bc1aa 345
f32d4091
KS
346 regs.x.ax = 0x0007;
347 regs.x.cx = 0;
348 regs.x.dx = 8 * (ScreenCols () - 1);
349 int86 (0x33, &regs, &regs);
1b94449f 350
f32d4091
KS
351 regs.x.ax = 0x0008;
352 regs.x.cx = 0;
353 regs.x.dx = 8 * (ScreenRows () - 1);
354 int86 (0x33, &regs, &regs);
1b94449f 355
f32d4091
KS
356 mouse_moveto (0, 0);
357 mouse_visible = 0;
358}
3eb1dbb6 359\f
f32d4091
KS
360/* ------------------------- Screen control ----------------------
361 *
362 */
aee81730 363
f32d4091 364static int internal_terminal = 0;
aee81730 365
f32d4091
KS
366#ifndef HAVE_X_WINDOWS
367extern unsigned char ScreenAttrib;
368static int screen_face;
369static int highlight;
aee81730 370
f32d4091
KS
371static int screen_size_X;
372static int screen_size_Y;
373static int screen_size;
1b94449f 374
f32d4091
KS
375static int current_pos_X;
376static int current_pos_Y;
377static int new_pos_X;
378static int new_pos_Y;
1b94449f 379
f32d4091
KS
380static void *startup_screen_buffer;
381static int startup_screen_size_X;
382static int startup_screen_size_Y;
383static int startup_pos_X;
384static int startup_pos_Y;
c9adab25 385static unsigned char startup_screen_attrib;
1b94449f 386
06b1ea13
EZ
387static clock_t startup_time;
388
f32d4091 389static int term_setup_done;
1b94449f 390
8ba01a32
EZ
391static unsigned short outside_cursor;
392
f32d4091 393/* Similar to the_only_frame. */
f6816f88 394struct x_output the_only_x_display;
1b94449f 395
039274cf
EZ
396/* Support for DOS/V (allows Japanese characters to be displayed on
397 standard, non-Japanese, ATs). Only supported for DJGPP v2 and later. */
398
399/* Holds the address of the text-mode screen buffer. */
400static unsigned long screen_old_address = 0;
401/* Segment and offset of the virtual screen. If 0, DOS/V is NOT loaded. */
402static unsigned short screen_virtual_segment = 0;
403static unsigned short screen_virtual_offset = 0;
68026917
AI
404/* A flag to control how to display unibyte 8-bit characters. */
405extern int unibyte_display_via_language_environment;
039274cf 406
8ba01a32
EZ
407Lisp_Object Qbar;
408
039274cf
EZ
409#if __DJGPP__ > 1
410/* Update the screen from a part of relocated DOS/V screen buffer which
411 begins at OFFSET and includes COUNT characters. */
412static void
413dosv_refresh_virtual_screen (int offset, int count)
414{
415 __dpmi_regs regs;
416
9ab8560d 417 if (offset < 0 || count < 0) /* paranoia; invalid values crash DOS/V */
40437cf5
EZ
418 return;
419
039274cf
EZ
420 regs.h.ah = 0xff; /* update relocated screen */
421 regs.x.es = screen_virtual_segment;
422 regs.x.di = screen_virtual_offset + offset;
423 regs.x.cx = count;
424 __dpmi_int (0x10, &regs);
425}
426#endif
427
d1d5dc19 428static void
f32d4091
KS
429dos_direct_output (y, x, buf, len)
430 int y;
431 int x;
432 char *buf;
433 int len;
1b94449f 434{
40437cf5
EZ
435 int t0 = 2 * (x + y * screen_size_X);
436 int t = t0 + (int) ScreenPrimary;
039274cf 437 int l0 = len;
fc171623
KH
438
439#if (__DJGPP__ < 2)
f32d4091
KS
440 while (--len >= 0) {
441 dosmemput (buf++, 1, t);
442 t += 2;
443 }
fc171623
KH
444#else
445 /* This is faster. */
446 for (_farsetsel (_dos_ds); --len >= 0; t += 2, buf++)
447 _farnspokeb (t, *buf);
039274cf
EZ
448
449 if (screen_virtual_segment)
450 dosv_refresh_virtual_screen (t0, l0);
fc171623 451#endif
1b94449f 452}
aee81730 453#endif
1b94449f 454
1b94449f
RS
455/* Flash the screen as a substitute for BEEPs. */
456
f32d4091 457#if (__DJGPP__ < 2)
49a09c76 458static void
fcea9cd4 459do_visible_bell (xorattr)
1b94449f
RS
460 unsigned char xorattr;
461{
49a09c76 462 asm volatile
ca986694 463 (" movb $1,%%dl
1b94449f 464visible_bell_0:
ca986694 465 movl _ScreenPrimary,%%eax
49a09c76 466 call dosmemsetup
ca986694
RS
467 movl %%eax,%%ebx
468 movl %1,%%ecx
469 movb %0,%%al
470 incl %%ebx
1b94449f 471visible_bell_1:
ca986694
RS
472 xorb %%al,%%gs:(%%ebx)
473 addl $2,%%ebx
474 decl %%ecx
49a09c76 475 jne visible_bell_1
ca986694 476 decb %%dl
49a09c76 477 jne visible_bell_3
1b94449f 478visible_bell_2:
ca986694
RS
479 movzwl %%ax,%%eax
480 movzwl %%ax,%%eax
481 movzwl %%ax,%%eax
482 movzwl %%ax,%%eax
483 decw %%cx
49a09c76
RS
484 jne visible_bell_2
485 jmp visible_bell_0
ca986694
RS
486visible_bell_3:"
487 : /* no output */
f32d4091 488 : "m" (xorattr), "g" (screen_size)
ca986694 489 : "%eax", "%ebx", /* "%gs",*/ "%ecx", "%edx");
1b94449f
RS
490}
491
f32d4091
KS
492static void
493ScreenVisualBell (void)
494{
495 /* This creates an xor-mask that will swap the default fore- and
496 background colors. */
497 do_visible_bell (((the_only_x_display.foreground_pixel
498 ^ the_only_x_display.background_pixel)
499 * 0x11) & 0x7f);
500}
501#endif
502
503#ifndef HAVE_X_WINDOWS
504
b36701cc
RS
505static int blink_bit = -1; /* the state of the blink bit at startup */
506
76ac1508
RS
507/* Enable bright background colors. */
508static void
509bright_bg (void)
510{
511 union REGS regs;
512
b36701cc
RS
513 /* Remember the original state of the blink/bright-background bit.
514 It is stored at 0040:0065h in the BIOS data area. */
515 if (blink_bit == -1)
516 blink_bit = (_farpeekb (_dos_ds, 0x465) & 0x20) == 0x20;
517
76ac1508
RS
518 regs.h.bl = 0;
519 regs.x.ax = 0x1003;
520 int86 (0x10, &regs, &regs);
521}
522
b36701cc
RS
523/* Disable bright background colors (and enable blinking) if we found
524 the video system in that state at startup. */
525static void
526maybe_enable_blinking (void)
527{
528 if (blink_bit == 1)
529 {
530 union REGS regs;
531
532 regs.h.bl = 1;
533 regs.x.ax = 0x1003;
534 int86 (0x10, &regs, &regs);
535 }
536}
537
8ba01a32
EZ
538/* Return non-zero if the system has a VGA adapter. */
539static int
540vga_installed (void)
541{
542 union REGS regs;
543
544 regs.x.ax = 0x1a00;
545 int86 (0x10, &regs, &regs);
546 if (regs.h.al == 0x1a && regs.h.bl > 5 && regs.h.bl < 13)
547 return 1;
548 return 0;
549}
550
4a96d4d2
KH
551/* Set the screen dimensions so that it can show no less than
552 ROWS x COLS frame. */
48ffe371 553
4a96d4d2
KH
554void
555dos_set_window_size (rows, cols)
556 int *rows, *cols;
557{
558 char video_name[30];
559 Lisp_Object video_mode;
560 int video_mode_value;
561 int have_vga = 0;
562 union REGS regs;
563 int current_rows = ScreenRows (), current_cols = ScreenCols ();
564
565 if (*rows == current_rows && *cols == current_cols)
566 return;
567
4a96d4d2 568 mouse_off ();
8ba01a32 569 have_vga = vga_installed ();
4a96d4d2 570
48ffe371 571 /* If the user specified a special video mode for these dimensions,
4a96d4d2
KH
572 use that mode. */
573 sprintf (video_name, "screen-dimensions-%dx%d", *rows, *cols);
574 video_mode = XSYMBOL (Fintern_soft (build_string (video_name),
575 Qnil))-> value;
576
577 if (INTEGERP (video_mode)
578 && (video_mode_value = XINT (video_mode)) > 0)
579 {
580 regs.x.ax = video_mode_value;
581 int86 (0x10, &regs, &regs);
48ffe371
RS
582
583 if (have_mouse)
584 {
585 /* Must hardware-reset the mouse, or else it won't update
586 its notion of screen dimensions for some non-standard
587 video modes. This is *painfully* slow... */
588 regs.x.ax = 0;
589 int86 (0x33, &regs, &regs);
590 }
4a96d4d2
KH
591 }
592
593 /* Find one of the dimensions supported by standard EGA/VGA
594 which gives us at least the required dimensions. */
595
596#if __DJGPP__ > 1
597
598 else
599 {
600 static struct {
601 int rows;
602 int need_vga;
603 } std_dimension[] = {
604 {25, 0},
605 {28, 1},
606 {35, 0},
607 {40, 1},
608 {43, 0},
609 {50, 1}
610 };
611 int i = 0;
612
613 while (i < sizeof (std_dimension) / sizeof (std_dimension[0]))
614 {
615 if (std_dimension[i].need_vga <= have_vga
616 && std_dimension[i].rows >= *rows)
617 {
618 if (std_dimension[i].rows != current_rows
619 || *cols != current_cols)
48ffe371 620 _set_screen_lines (std_dimension[i].rows);
4a96d4d2
KH
621 break;
622 }
48ffe371 623 i++;
4a96d4d2
KH
624 }
625 }
626
627#else /* not __DJGPP__ > 1 */
628
629 else if (*rows <= 25)
630 {
631 if (current_rows != 25 || current_cols != 80)
632 {
633 regs.x.ax = 3;
634 int86 (0x10, &regs, &regs);
635 regs.x.ax = 0x1101;
636 regs.h.bl = 0;
637 int86 (0x10, &regs, &regs);
638 regs.x.ax = 0x1200;
639 regs.h.bl = 32;
640 int86 (0x10, &regs, &regs);
641 regs.x.ax = 3;
642 int86 (0x10, &regs, &regs);
643 }
644 }
645 else if (*rows <= 50)
646 if (have_vga && (current_rows != 50 || current_cols != 80)
647 || *rows <= 43 && (current_rows != 43 || current_cols != 80))
648 {
649 regs.x.ax = 3;
650 int86 (0x10, &regs, &regs);
651 regs.x.ax = 0x1112;
652 regs.h.bl = 0;
653 int86 (0x10, &regs, &regs);
654 regs.x.ax = 0x1200;
655 regs.h.bl = 32;
656 int86 (0x10, &regs, &regs);
657 regs.x.ax = 0x0100;
658 regs.x.cx = 7;
659 int86 (0x10, &regs, &regs);
660 }
661#endif /* not __DJGPP__ > 1 */
662
663 if (have_mouse)
664 {
4a96d4d2
KH
665 mouse_init ();
666 mouse_on ();
667 }
668
669 /* Tell the caller what dimensions have been REALLY set. */
670 *rows = ScreenRows ();
671 *cols = ScreenCols ();
76ac1508 672
41ad069b
EZ
673#if __DJGPP__ > 1
674 /* If the dimensions changed, the mouse highlight info is invalid. */
675 if (current_rows != *rows || current_cols != *cols)
676 {
677 struct frame *f = SELECTED_FRAME();
678 struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
679 Lisp_Object window = dpyinfo->mouse_face_window;
680
681 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
682 {
683 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
684 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
685 dpyinfo->mouse_face_window = Qnil;
686 }
687 }
688#endif
689
76ac1508
RS
690 /* Enable bright background colors. */
691 bright_bg ();
039274cf
EZ
692
693 /* FIXME: I'm not sure the above will run at all on DOS/V. But let's
694 be defensive anyway. */
695 if (screen_virtual_segment)
696 dosv_refresh_virtual_screen (0, *cols * *rows);
4a96d4d2
KH
697}
698
48ffe371
RS
699/* If we write a character in the position where the mouse is,
700 the mouse cursor may need to be refreshed. */
09e2ac30
RS
701
702static void
f32d4091 703mouse_off_maybe ()
09e2ac30 704{
f32d4091
KS
705 int x, y;
706
707 if (!mouse_visible)
708 return;
709
710 mouse_get_xy (&x, &y);
711 if (y != new_pos_Y || x < new_pos_X)
712 return;
713
714 mouse_off ();
715}
716
8ba01a32
EZ
717#define DEFAULT_CURSOR_START (-1)
718#define DEFAULT_CURSOR_WIDTH (-1)
719#define BOX_CURSOR_WIDTH (-32)
720
721/* Set cursor to begin at scan line START_LINE in the character cell
722 and extend for WIDTH scan lines. Scan lines are counted from top
723 of the character cell, starting from zero. */
724static void
725msdos_set_cursor_shape (struct frame *f, int start_line, int width)
726{
727#if __DJGPP__ > 1
728 unsigned desired_cursor;
729 __dpmi_regs regs;
730 int max_line, top_line, bot_line;
731
732 /* Avoid the costly BIOS call if F isn't the currently selected
733 frame. Allow for NULL as unconditionally meaning the selected
734 frame. */
735 if (f && f != SELECTED_FRAME())
736 return;
737
738 /* The character cell size in scan lines is stored at 40:85 in the
739 BIOS data area. */
740 max_line = _farpeekw (_dos_ds, 0x485) - 1;
741 switch (max_line)
742 {
743 default: /* this relies on CGA cursor emulation being ON! */
744 case 7:
745 bot_line = 7;
746 break;
747 case 9:
748 bot_line = 9;
749 break;
750 case 13:
751 bot_line = 12;
752 break;
753 case 15:
754 bot_line = 14;
755 break;
756 }
757
758 if (width < 0)
759 {
760 if (width == BOX_CURSOR_WIDTH)
761 {
762 top_line = 0;
763 bot_line = max_line;
764 }
765 else if (start_line != DEFAULT_CURSOR_START)
766 {
767 top_line = start_line;
768 bot_line = top_line - width - 1;
769 }
770 else if (width != DEFAULT_CURSOR_WIDTH)
771 {
772 top_line = 0;
773 bot_line = -1 - width;
774 }
775 else
776 top_line = bot_line + 1;
777 }
778 else if (width == 0)
779 {
780 /* [31, 0] seems to DTRT for all screen sizes. */
781 top_line = 31;
782 bot_line = 0;
783 }
784 else /* WIDTH is positive */
785 {
786 if (start_line != DEFAULT_CURSOR_START)
787 bot_line = start_line;
788 top_line = bot_line - (width - 1);
789 }
790
791 /* If the current cursor shape is already what they want, we are
792 history here. */
793 desired_cursor = ((top_line & 0x1f) << 8) | (bot_line & 0x1f);
794 if (desired_cursor == _farpeekw (_dos_ds, 0x460))
795 return;
796
797 regs.h.ah = 1;
798 regs.x.cx = desired_cursor;
799 __dpmi_int (0x10, &regs);
800#endif /* __DJGPP__ > 1 */
801}
802
803static void
804IT_set_cursor_type (struct frame *f, Lisp_Object cursor_type)
805{
806 if (EQ (cursor_type, Qbar))
807 {
808 /* Just BAR means the normal EGA/VGA cursor. */
809 msdos_set_cursor_shape (f, DEFAULT_CURSOR_START, DEFAULT_CURSOR_WIDTH);
810 }
811 else if (CONSP (cursor_type) && EQ (XCAR (cursor_type), Qbar))
812 {
813 Lisp_Object bar_parms = XCDR (cursor_type);
814 int width;
815
816 if (INTEGERP (bar_parms))
817 {
818 /* Feature: negative WIDTH means cursor at the top
819 of the character cell, zero means invisible cursor. */
820 width = XINT (bar_parms);
821 msdos_set_cursor_shape (f, width >= 0 ? DEFAULT_CURSOR_START : 0,
822 width);
823 }
824 else if (CONSP (bar_parms)
825 && INTEGERP (XCAR (bar_parms))
826 && INTEGERP (XCDR (bar_parms)))
827 {
828 int start_line = XINT (XCDR (bar_parms));
829
830 width = XINT (XCAR (bar_parms));
831 msdos_set_cursor_shape (f, start_line, width);
832 }
833 }
834 else
835 /* Treat anything unknown as "box cursor". This includes nil, so
836 that a frame which doesn't specify a cursor type gets a box,
837 which is the default in Emacs. */
838 msdos_set_cursor_shape (f, 0, BOX_CURSOR_WIDTH);
839}
840
71f65669
EZ
841static void
842IT_ring_bell (void)
f32d4091
KS
843{
844 if (visible_bell)
aee81730 845 {
f32d4091
KS
846 mouse_off ();
847 ScreenVisualBell ();
aee81730 848 }
f32d4091 849 else
3635be47
RS
850 {
851 union REGS inregs, outregs;
852 inregs.h.ah = 2;
853 inregs.h.dl = 7;
854 intdos (&inregs, &outregs);
855 }
09e2ac30
RS
856}
857
c77f6f1b
EZ
858/* Given a face id FACE, extract the face parameters to be used for
859 display until the face changes. The face parameters (actually, its
860 color) are used to construct the video attribute byte for each
861 glyph during the construction of the buffer that is then blitted to
862 the video RAM. */
f32d4091
KS
863static void
864IT_set_face (int face)
865{
2d764c78
EZ
866 struct frame *sf = SELECTED_FRAME();
867 struct face *fp = FACE_FROM_ID (sf, face);
c77f6f1b 868 unsigned long fg, bg;
f32d4091 869
c77f6f1b 870 if (!fp)
e30aee93 871 {
2d764c78 872 fp = FACE_FROM_ID (sf, DEFAULT_FACE_ID);
e30aee93
EZ
873 /* The default face for the frame should always be realized and
874 cached. */
875 if (!fp)
876 abort ();
877 }
f32d4091 878 screen_face = face;
c77f6f1b
EZ
879 fg = fp->foreground;
880 bg = fp->background;
881
3b620731
EZ
882 /* Don't use invalid colors. In particular, FACE_TTY_DEFAULT_*
883 colors mean use the colors of the default face, except that if
884 highlight is on, invert the foreground and the background. Note
885 that we assume all 16 colors to be available for the background,
886 since Emacs switches on this mode (and loses the blinking
887 attribute) at startup. */
f9d2fdc4 888 if (fg == FACE_TTY_DEFAULT_COLOR || fg == FACE_TTY_DEFAULT_FG_COLOR)
3b620731 889 fg = FRAME_FOREGROUND_PIXEL (sf);
f9d2fdc4 890 else if (fg == FACE_TTY_DEFAULT_BG_COLOR)
3b620731
EZ
891 fg = FRAME_BACKGROUND_PIXEL (sf);
892 if (bg == FACE_TTY_DEFAULT_COLOR || bg == FACE_TTY_DEFAULT_BG_COLOR)
893 bg = FRAME_BACKGROUND_PIXEL (sf);
f9d2fdc4 894 else if (bg == FACE_TTY_DEFAULT_FG_COLOR)
3b620731
EZ
895 bg = FRAME_FOREGROUND_PIXEL (sf);
896
897 /* Make sure highlighted lines really stand out, come what may. */
898 if ((highlight || fp->tty_reverse_p)
899 && (fg == FRAME_FOREGROUND_PIXEL (sf)
900 && bg == FRAME_BACKGROUND_PIXEL (sf)))
901 {
902 unsigned long tem = fg;
903
904 fg = bg;
905 bg = tem;
906 }
c77f6f1b 907 if (termscript)
3b620731
EZ
908 fprintf (termscript, "<FACE %d%s: %d/%d[FG:%d/BG:%d]>", face,
909 highlight ? "H" : "", fp->foreground, fp->background, fg, bg);
c77f6f1b
EZ
910 if (fg >= 0 && fg < 16)
911 {
912 ScreenAttrib &= 0xf0;
913 ScreenAttrib |= fg;
914 }
915 if (bg >= 0 && bg < 16)
916 {
917 ScreenAttrib &= 0x0f;
918 ScreenAttrib |= ((bg & 0x0f) << 4);
919 }
f32d4091
KS
920}
921
aa9ce936
EZ
922Lisp_Object Vdos_unsupported_char_glyph;
923
71f65669 924static void
c77f6f1b 925IT_write_glyphs (struct glyph *str, int str_len)
f32d4091 926{
aa9ce936
EZ
927 unsigned char *screen_buf, *screen_bp, *screen_buf_end, *bp;
928 int unsupported_face = FAST_GLYPH_FACE (Vdos_unsupported_char_glyph);
929 unsigned unsupported_char= FAST_GLYPH_CHAR (Vdos_unsupported_char_glyph);
039274cf 930 int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
aa9ce936
EZ
931 register int sl = str_len;
932 register int tlen = GLYPH_TABLE_LENGTH;
933 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
934
e023fb27
EZ
935 /* If terminal_coding does any conversion, use it, otherwise use
936 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
937 because it always returns 1 if terminal_coding.src_multibyte is 1. */
938 struct coding_system *coding =
939 (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
940 ? &terminal_coding
941 : &safe_terminal_coding);
2d764c78 942 struct frame *sf;
87485d6f 943
52d38ab2
EZ
944 /* Do we need to consider conversion of unibyte characters to
945 multibyte? */
946 int convert_unibyte_characters
e16bf494
AI
947 = (NILP (current_buffer->enable_multibyte_characters)
948 && unibyte_display_via_language_environment);
52d38ab2 949
648648a9
KH
950 unsigned char conversion_buffer[256];
951 int conversion_buffer_size = sizeof conversion_buffer;
952
3b620731 953 if (str_len <= 0) return;
aee81730 954
aa9ce936
EZ
955 screen_buf = screen_bp = alloca (str_len * 2);
956 screen_buf_end = screen_buf + str_len * 2;
2d764c78 957 sf = SELECTED_FRAME();
e30aee93
EZ
958
959 /* Since faces get cached and uncached behind our back, we can't
960 rely on their indices in the cache being consistent across
961 invocations. So always reset the screen face to the default
962 face of the frame, before writing glyphs, and let the glyphs
963 set the right face if it's different from the default. */
964 IT_set_face (DEFAULT_FACE_ID);
aee81730 965
aa9ce936
EZ
966 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
967 the tail. */
968 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
969 while (sl)
970 {
c77f6f1b 971 int cf, chlen, enclen;
3b620731 972 unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *buf;
c77f6f1b 973 unsigned ch;
aa9ce936
EZ
974
975 /* Glyphs with GLYPH_MASK_PADDING bit set are actually there
976 only for the redisplay code to know how many columns does
977 this character occupy on the screen. Skip padding glyphs. */
c77f6f1b 978 if (CHAR_GLYPH_PADDING_P (*str))
aa9ce936
EZ
979 {
980 str++;
981 sl--;
982 }
983 else
984 {
04ee4f45
EZ
985 register GLYPH g = GLYPH_FROM_CHAR_GLYPH (*str);
986 int glyph_not_in_table = 0;
987
988 if (g < 0 || g >= tlen)
989 {
990 /* This glyph doesn't have an entry in Vglyph_table. */
991 ch = str->u.ch;
992 glyph_not_in_table = 1;
993 }
994 else
995 {
996 /* This glyph has an entry in Vglyph_table, so process
997 any aliases before testing for simpleness. */
998 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
999 ch = FAST_GLYPH_CHAR (g);
1000 }
1001
aa9ce936 1002 /* Convert the character code to multibyte, if they
04ee4f45
EZ
1003 requested display via language environment. We only want
1004 to convert unibyte characters to multibyte in unibyte
1005 buffers! Otherwise, the 8-bit value in CH came from the
1006 display table set up to display foreign characters. */
52d38ab2 1007 if (SINGLE_BYTE_CHAR_P (ch) && convert_unibyte_characters
f0dd4c35
EZ
1008 && (ch >= 0240
1009 || (ch >= 0200 && !NILP (Vnonascii_translation_table))))
aa9ce936
EZ
1010 ch = unibyte_char_to_multibyte (ch);
1011
1012 /* Invalid characters are displayed with a special glyph. */
04ee4f45 1013 if (! CHAR_VALID_P (ch, 0))
aa9ce936
EZ
1014 {
1015 g = !NILP (Vdos_unsupported_char_glyph)
1016 ? Vdos_unsupported_char_glyph
2d764c78 1017 : MAKE_GLYPH (sf, '\177', GLYPH_FACE (sf, g));
aa9ce936
EZ
1018 ch = FAST_GLYPH_CHAR (g);
1019 }
aa9ce936
EZ
1020
1021 /* If the face of this glyph is different from the current
1022 screen face, update the screen attribute byte. */
1023 cf = FAST_GLYPH_FACE (g);
1024 if (cf != screen_face)
1025 IT_set_face (cf); /* handles invalid faces gracefully */
1026
04ee4f45 1027 if (glyph_not_in_table || GLYPH_SIMPLE_P (tbase, tlen, g))
3b620731
EZ
1028 {
1029 /* We generate the multi-byte form of CH in WORKBUF. */
1030 chlen = CHAR_STRING (ch, workbuf);
1031 buf = workbuf;
1032 }
aa9ce936
EZ
1033 else
1034 {
1035 /* We have a string in Vglyph_table. */
1036 chlen = GLYPH_LENGTH (tbase, g);
1037 buf = GLYPH_STRING (tbase, g);
1038 }
1039
c77f6f1b 1040 /* If the character is not multibyte, don't bother converting it. */
aa9ce936
EZ
1041 if (chlen == 1)
1042 {
1043 *conversion_buffer = (unsigned char)ch;
1044 chlen = 0;
1045 enclen = 1;
1046 }
1047 else
1048 {
55a17202 1049 coding->src_multibyte = 1;
aa9ce936
EZ
1050 encode_coding (coding, buf, conversion_buffer, chlen,
1051 conversion_buffer_size);
1052 chlen -= coding->consumed;
1053 enclen = coding->produced;
1054
1055 /* Replace glyph codes that cannot be converted by
1056 terminal_coding with Vdos_unsupported_char_glyph. */
1057 if (*conversion_buffer == '?')
1058 {
5e30eaa2 1059 unsigned char *cbp = conversion_buffer;
aa9ce936
EZ
1060
1061 while (cbp < conversion_buffer + enclen && *cbp == '?')
1062 *cbp++ = unsupported_char;
1063 if (unsupported_face != screen_face)
1064 IT_set_face (unsupported_face);
1065 }
1066 }
1067
1068 if (enclen + chlen > screen_buf_end - screen_bp)
1069 {
1070 /* The allocated buffer for screen writes is too small.
1071 Flush it and loop again without incrementing STR, so
1072 that the next loop will begin with the same glyph. */
1073 int nbytes = screen_bp - screen_buf;
1074
1075 mouse_off_maybe ();
1076 dosmemput (screen_buf, nbytes, (int)ScreenPrimary + offset);
1077 if (screen_virtual_segment)
1078 dosv_refresh_virtual_screen (offset, nbytes / 2);
1079 new_pos_X += nbytes / 2;
1080 offset += nbytes;
1081
1082 /* Prepare to reuse the same buffer again. */
1083 screen_bp = screen_buf;
1084 }
1085 else
1086 {
1087 /* There's enough place in the allocated buffer to add
1088 the encoding of this glyph. */
1089
1090 /* First, copy the encoded bytes. */
1091 for (bp = conversion_buffer; enclen--; bp++)
1092 {
1093 *screen_bp++ = (unsigned char)*bp;
1094 *screen_bp++ = ScreenAttrib;
1095 if (termscript)
1096 fputc (*bp, termscript);
1097 }
1098
1099 /* Now copy the bytes not consumed by the encoding. */
1100 if (chlen > 0)
1101 {
1102 buf += coding->consumed;
1103 while (chlen--)
1104 {
1105 if (termscript)
1106 fputc (*buf, termscript);
1107 *screen_bp++ = (unsigned char)*buf++;
1108 *screen_bp++ = ScreenAttrib;
1109 }
1110 }
1111
1112 /* Update STR and its remaining length. */
1113 str++;
1114 sl--;
1115 }
1116 }
aee81730
RS
1117 }
1118
aa9ce936 1119 /* Dump whatever is left in the screen buffer. */
f32d4091 1120 mouse_off_maybe ();
aa9ce936 1121 dosmemput (screen_buf, screen_bp - screen_buf, (int)ScreenPrimary + offset);
039274cf 1122 if (screen_virtual_segment)
aa9ce936
EZ
1123 dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2);
1124 new_pos_X += (screen_bp - screen_buf) / 2;
1125
1126 /* We may have to output some codes to terminate the writing. */
1127 if (CODING_REQUIRE_FLUSHING (coding))
1128 {
1129 coding->mode |= CODING_MODE_LAST_BLOCK;
1130 encode_coding (coding, "", conversion_buffer, 0, conversion_buffer_size);
1131 if (coding->produced > 0)
1132 {
241424da 1133 screen_buf = alloca (coding->produced * 2);
aa9ce936
EZ
1134 for (screen_bp = screen_buf, bp = conversion_buffer;
1135 coding->produced--; bp++)
1136 {
1137 *screen_bp++ = (unsigned char)*bp;
1138 *screen_bp++ = ScreenAttrib;
1139 if (termscript)
1140 fputc (*bp, termscript);
1141 }
1142 offset += screen_bp - screen_buf;
1143 mouse_off_maybe ();
1144 dosmemput (screen_buf, screen_bp - screen_buf,
1145 (int)ScreenPrimary + offset);
1146 if (screen_virtual_segment)
1147 dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2);
1148 new_pos_X += (screen_bp - screen_buf) / 2;
1149 }
1150 }
f32d4091 1151}
aee81730 1152
41ad069b
EZ
1153/************************************************************************
1154 Mouse Highlight (and friends..)
1155 ************************************************************************/
1156
1157/* This is used for debugging, to turn off note_mouse_highlight. */
1158int disable_mouse_highlight;
1159
48c14970
EZ
1160/* If non-nil, dos_rawgetc generates an event to display that string.
1161 (The display is done in keyboard.c:read_char, by calling
1162 show_help_echo.) */
41ad069b
EZ
1163static Lisp_Object help_echo;
1164static Lisp_Object previous_help_echo; /* a helper temporary variable */
1165
48c14970
EZ
1166/* These record the window, the object and the position where the help
1167 echo string was generated. */
1168static Lisp_Object help_echo_window;
1169static Lisp_Object help_echo_object;
1170static int help_echo_pos;
1171
41ad069b
EZ
1172static int mouse_preempted = 0; /* non-zero when XMenu gobbles mouse events */
1173
1174/* Set the mouse pointer shape according to whether it is in the
1175 area where the mouse highlight is in effect. */
1176static void
1177IT_set_mouse_pointer (int mode)
1178{
1179 /* A no-op for now. DOS text-mode mouse pointer doesn't offer too
1180 many possibilities to change its shape, and the available
1181 functionality pretty much sucks (e.g., almost every reasonable
1182 shape will conceal the character it is on). Since the color of
1183 the pointer changes in the highlighted area, it is not clear to
1184 me whether anything else is required, anyway. */
1185}
1186
1187/* Display the active region described by mouse_face_*
1188 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1189static void
1190show_mouse_face (struct display_info *dpyinfo, int hl)
1191{
1192 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
1193 struct frame *f = XFRAME (WINDOW_FRAME (w));
1194 int i;
1195 struct face *fp;
1196
1197
1198 /* If window is in the process of being destroyed, don't bother
1199 doing anything. */
1200 if (w->current_matrix == NULL)
1201 goto set_cursor_shape;
1202
1203 /* Recognize when we are called to operate on rows that don't exist
1204 anymore. This can happen when a window is split. */
1205 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
1206 goto set_cursor_shape;
1207
1208 /* There's no sense to do anything if the mouse face isn't realized. */
1209 if (hl > 0)
1210 {
1211 fp = FACE_FROM_ID (SELECTED_FRAME(), dpyinfo->mouse_face_face_id);
1212 if (!fp)
1213 goto set_cursor_shape;
1214 }
1215
1216 /* Note that mouse_face_beg_row etc. are window relative. */
1217 for (i = dpyinfo->mouse_face_beg_row;
1218 i <= dpyinfo->mouse_face_end_row;
1219 i++)
1220 {
1221 int start_hpos, end_hpos;
1222 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
1223
1224 /* Don't do anything if row doesn't have valid contents. */
1225 if (!row->enabled_p)
1226 continue;
1227
1228 /* For all but the first row, the highlight starts at column 0. */
1229 if (i == dpyinfo->mouse_face_beg_row)
1230 start_hpos = dpyinfo->mouse_face_beg_col;
1231 else
1232 start_hpos = 0;
1233
1234 if (i == dpyinfo->mouse_face_end_row)
1235 end_hpos = dpyinfo->mouse_face_end_col;
1236 else
1237 end_hpos = row->used[TEXT_AREA];
1238
1239 if (end_hpos <= start_hpos)
1240 continue;
48c14970
EZ
1241 /* Record that some glyphs of this row are displayed in
1242 mouse-face. */
1243 row->mouse_face_p = hl > 0;
41ad069b
EZ
1244 if (hl > 0)
1245 {
1246 int vpos = row->y + WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
1247 int kstart = start_hpos + WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
1248 int nglyphs = end_hpos - start_hpos;
1249 int offset = ScreenPrimary + 2*(vpos*screen_size_X + kstart) + 1;
1250 int start_offset = offset;
1251
1252 if (termscript)
1253 fprintf (termscript, "\n<MH+ %d-%d:%d>",
1254 kstart, kstart + nglyphs - 1, vpos);
1255
1256 mouse_off ();
1257 IT_set_face (dpyinfo->mouse_face_face_id);
1258 /* Since we are going to change only the _colors_ of the
1259 displayed text, there's no need to go through all the
1260 pain of generating and encoding the text from the glyphs.
1261 Instead, we simply poke the attribute byte of each
1262 affected position in video memory with the colors
1263 computed by IT_set_face! */
1264 _farsetsel (_dos_ds);
1265 while (nglyphs--)
1266 {
1267 _farnspokeb (offset, ScreenAttrib);
1268 offset += 2;
1269 }
1270 if (screen_virtual_segment)
1271 dosv_refresh_virtual_screen (start_offset, end_hpos - start_hpos);
1272 mouse_on ();
1273 }
1274 else
1275 {
1276 /* We are removing a previously-drawn mouse highlight. The
1277 safest way to do so is to redraw the glyphs anew, since
1278 all kinds of faces and display tables could have changed
1279 behind our back. */
1280 int nglyphs = end_hpos - start_hpos;
1281 int save_x = new_pos_X, save_y = new_pos_Y;
1282
1283 if (end_hpos >= row->used[TEXT_AREA])
1284 nglyphs = row->used[TEXT_AREA] - start_hpos;
1285
1286 /* IT_write_glyphs writes at cursor position, so we need to
1287 temporarily move cursor coordinates to the beginning of
1288 the highlight region. */
1289 new_pos_X = start_hpos + WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
1290 new_pos_Y = row->y + WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
1291
1292 if (termscript)
1293 fprintf (termscript, "<MH- %d-%d:%d>",
1294 new_pos_X, new_pos_X + nglyphs - 1, new_pos_Y);
1295 IT_write_glyphs (row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
1296 if (termscript)
1297 fputs ("\n", termscript);
1298 new_pos_X = save_x;
1299 new_pos_Y = save_y;
1300 }
1301 }
1302
1303 set_cursor_shape:
1304
1305 /* Change the mouse pointer shape. */
1306 IT_set_mouse_pointer (hl);
1307}
1308
1309/* Clear out the mouse-highlighted active region.
1310 Redraw it un-highlighted first. */
1311static void
1312clear_mouse_face (struct display_info *dpyinfo)
1313{
1314 if (! NILP (dpyinfo->mouse_face_window))
1315 show_mouse_face (dpyinfo, 0);
1316
1317 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1318 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1319 dpyinfo->mouse_face_window = Qnil;
1320}
1321
1322/* Find the glyph matrix position of buffer position POS in window W.
1323 *HPOS and *VPOS are set to the positions found. W's current glyphs
1324 must be up to date. If POS is above window start return (0, 0).
1325 If POS is after end of W, return end of last line in W. */
1326static int
1327fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
1328{
1329 int i;
1330 int lastcol;
1331 int maybe_next_line_p = 0;
1332 int line_start_position;
1333 int yb = window_text_bottom_y (w);
1334 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
1335 struct glyph_row *best_row = row;
1336
1337 while (row->y < yb)
1338 {
1339 if (row->used[TEXT_AREA])
1340 line_start_position = row->glyphs[TEXT_AREA]->charpos;
1341 else
1342 line_start_position = 0;
1343
1344 if (line_start_position > pos)
1345 break;
1346 /* If the position sought is the end of the buffer,
1347 don't include the blank lines at the bottom of the window. */
1348 else if (line_start_position == pos
1349 && pos == BUF_ZV (XBUFFER (w->buffer)))
1350 {
1351 maybe_next_line_p = 1;
1352 break;
1353 }
1354 else if (line_start_position > 0)
1355 best_row = row;
1356
1357 ++row;
1358 }
1359
1360 /* Find the right column within BEST_ROW. */
1361 lastcol = 0;
1362 row = best_row;
1363 for (i = 0; i < row->used[TEXT_AREA]; i++)
1364 {
1365 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
1366 int charpos;
1367
1368 charpos = glyph->charpos;
1369 if (charpos == pos)
1370 {
1371 *hpos = i;
1372 *vpos = row->y;
1373 return 1;
1374 }
1375 else if (charpos > pos)
1376 break;
1377 else if (charpos > 0)
1378 lastcol = i;
1379 }
1380
1381 /* If we're looking for the end of the buffer,
1382 and we didn't find it in the line we scanned,
1383 use the start of the following line. */
1384 if (maybe_next_line_p)
1385 {
1386 ++row;
1387 lastcol = 0;
1388 }
1389
1390 *vpos = row->y;
1391 *hpos = lastcol + 1;
1392 return 0;
1393}
1394
1395/* Take proper action when mouse has moved to the mode or top line of
1396 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
1397 mode line. X is relative to the start of the text display area of
1398 W, so the width of bitmap areas and scroll bars must be subtracted
1399 to get a position relative to the start of the mode line. */
1400static void
1401IT_note_mode_line_highlight (struct window *w, int x, int mode_line_p)
1402{
1403 struct frame *f = XFRAME (w->frame);
1404 struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1405 struct glyph_row *row;
1406
1407 if (mode_line_p)
1408 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
1409 else
1410 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1411
1412 if (row->enabled_p)
1413 {
1414 extern Lisp_Object Qhelp_echo;
1415 struct glyph *glyph, *end;
1416 Lisp_Object help, map;
1417
1418 /* Find the glyph under X. */
1419 glyph = row->glyphs[TEXT_AREA]
1420 + x - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
1421 end = glyph + row->used[TEXT_AREA];
1422 if (glyph < end
1423 && STRINGP (glyph->object)
1424 && XSTRING (glyph->object)->intervals
1425 && glyph->charpos >= 0
1426 && glyph->charpos < XSTRING (glyph->object)->size)
1427 {
1428 /* If we're on a string with `help-echo' text property,
1429 arrange for the help to be displayed. This is done by
1430 setting the global variable help_echo to the help string. */
1431 help = Fget_text_property (make_number (glyph->charpos),
1432 Qhelp_echo, glyph->object);
b7e80413 1433 if (!NILP (help))
48c14970
EZ
1434 {
1435 help_echo = help;
1436 XSETWINDOW (help_echo_window, w);
1437 help_echo_object = glyph->object;
1438 help_echo_pos = glyph->charpos;
1439 }
41ad069b
EZ
1440 }
1441 }
1442}
1443
1444/* Take proper action when the mouse has moved to position X, Y on
1445 frame F as regards highlighting characters that have mouse-face
1446 properties. Also de-highlighting chars where the mouse was before.
1447 X and Y can be negative or out of range. */
1448static void
1449IT_note_mouse_highlight (struct frame *f, int x, int y)
1450{
1451 struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1452 int portion;
1453 Lisp_Object window;
1454 struct window *w;
1455
1456 /* When a menu is active, don't highlight because this looks odd. */
1457 if (mouse_preempted)
1458 return;
1459
515d0d0e
EZ
1460 if (disable_mouse_highlight
1461 || !f->glyphs_initialized_p)
41ad069b
EZ
1462 return;
1463
1464 dpyinfo->mouse_face_mouse_x = x;
1465 dpyinfo->mouse_face_mouse_y = y;
1466 dpyinfo->mouse_face_mouse_frame = f;
1467
1468 if (dpyinfo->mouse_face_defer)
1469 return;
1470
1471 if (gc_in_progress)
1472 {
1473 dpyinfo->mouse_face_deferred_gc = 1;
1474 return;
1475 }
1476
1477 /* Which window is that in? */
1478 window = window_from_coordinates (f, x, y, &portion, 0);
1479
1480 /* If we were displaying active text in another window, clear that. */
1481 if (! EQ (window, dpyinfo->mouse_face_window))
1482 clear_mouse_face (dpyinfo);
1483
1484 /* Not on a window -> return. */
1485 if (!WINDOWP (window))
1486 return;
1487
1488 /* Convert to window-relative coordinates. */
1489 w = XWINDOW (window);
1490 x -= WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
1491 y -= WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
1492
1493 if (portion == 1 || portion == 3)
1494 {
1495 /* Mouse is on the mode or top line. */
1496 IT_note_mode_line_highlight (w, x, portion == 1);
1497 return;
1498 }
1499 else
1500 IT_set_mouse_pointer (0);
1501
1502 /* Are we in a window whose display is up to date?
1503 And verify the buffer's text has not changed. */
1504 if (/* Within text portion of the window. */
1505 portion == 0
1506 && EQ (w->window_end_valid, w->buffer)
1507 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
1508 && (XFASTINT (w->last_overlay_modified)
1509 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
1510 {
1511 int pos, i, area;
1512 struct glyph_row *row;
1513 struct glyph *glyph;
1514
1515 /* Find the glyph under X/Y. */
1516 glyph = NULL;
1517 if (y < w->current_matrix->nrows)
1518 {
1519 row = MATRIX_ROW (w->current_matrix, y);
1520 if (row->enabled_p
1521 && row->displays_text_p
1522 && x < window_box_width (w, TEXT_AREA))
1523 {
1524 glyph = row->glyphs[TEXT_AREA];
1525 if (x >= row->used[TEXT_AREA])
1526 glyph = NULL;
1527 else
1528 {
1529 glyph += x;
1530 if (!BUFFERP (glyph->object))
1531 glyph = NULL;
1532 }
1533 }
1534 }
1535
1536 /* Clear mouse face if X/Y not over text. */
1537 if (glyph == NULL)
1538 {
1539 clear_mouse_face (dpyinfo);
1540 return;
1541 }
1542
1543 if (!BUFFERP (glyph->object))
1544 abort ();
1545 pos = glyph->charpos;
1546
1547 /* Check for mouse-face and help-echo. */
1548 {
1549 extern Lisp_Object Qmouse_face;
1550 Lisp_Object mouse_face, overlay, position;
1551 Lisp_Object *overlay_vec;
1552 int len, noverlays;
1553 struct buffer *obuf;
1554 int obegv, ozv;
1555
1556 /* If we get an out-of-range value, return now; avoid an error. */
1557 if (pos > BUF_Z (XBUFFER (w->buffer)))
1558 return;
1559
1560 /* Make the window's buffer temporarily current for
1561 overlays_at and compute_char_face. */
1562 obuf = current_buffer;
1563 current_buffer = XBUFFER (w->buffer);
1564 obegv = BEGV;
1565 ozv = ZV;
1566 BEGV = BEG;
1567 ZV = Z;
1568
1569 /* Is this char mouse-active or does it have help-echo? */
1570 XSETINT (position, pos);
1571
1572 /* Put all the overlays we want in a vector in overlay_vec.
1573 Store the length in len. If there are more than 10, make
1574 enough space for all, and try again. */
1575 len = 10;
1576 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
99cd7364 1577 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
41ad069b
EZ
1578 if (noverlays > len)
1579 {
1580 len = noverlays;
1581 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
99cd7364
EZ
1582 noverlays = overlays_at (pos,
1583 0, &overlay_vec, &len, NULL, NULL, 0);
41ad069b
EZ
1584 }
1585
f0a4139c 1586 /* Sort overlays into increasing priority order. */
41ad069b
EZ
1587 noverlays = sort_overlays (overlay_vec, noverlays, w);
1588
1589 /* Check mouse-face highlighting. */
1590 if (! (EQ (window, dpyinfo->mouse_face_window)
1591 && y >= dpyinfo->mouse_face_beg_row
1592 && y <= dpyinfo->mouse_face_end_row
1593 && (y > dpyinfo->mouse_face_beg_row
1594 || x >= dpyinfo->mouse_face_beg_col)
1595 && (y < dpyinfo->mouse_face_end_row
1596 || x < dpyinfo->mouse_face_end_col
1597 || dpyinfo->mouse_face_past_end)))
1598 {
1599 /* Clear the display of the old active region, if any. */
1600 clear_mouse_face (dpyinfo);
1601
1602 /* Find highest priority overlay that has a mouse-face prop. */
1603 overlay = Qnil;
f0a4139c 1604 for (i = noverlays - 1; i >= 0; --i)
41ad069b
EZ
1605 {
1606 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
1607 if (!NILP (mouse_face))
1608 {
1609 overlay = overlay_vec[i];
1610 break;
1611 }
1612 }
1613
1614 /* If no overlay applies, get a text property. */
1615 if (NILP (overlay))
1616 mouse_face = Fget_text_property (position, Qmouse_face,
1617 w->buffer);
1618
1619 /* Handle the overlay case. */
1620 if (! NILP (overlay))
1621 {
1622 /* Find the range of text around this char that
1623 should be active. */
1624 Lisp_Object before, after;
1625 int ignore;
1626
1627 before = Foverlay_start (overlay);
1628 after = Foverlay_end (overlay);
1629 /* Record this as the current active region. */
1630 fast_find_position (w, XFASTINT (before),
1631 &dpyinfo->mouse_face_beg_col,
1632 &dpyinfo->mouse_face_beg_row);
1633 dpyinfo->mouse_face_past_end
1634 = !fast_find_position (w, XFASTINT (after),
1635 &dpyinfo->mouse_face_end_col,
1636 &dpyinfo->mouse_face_end_row);
1637 dpyinfo->mouse_face_window = window;
1638 dpyinfo->mouse_face_face_id
1639 = face_at_buffer_position (w, pos, 0, 0,
1640 &ignore, pos + 1, 1);
1641
1642 /* Display it as active. */
1643 show_mouse_face (dpyinfo, 1);
1644 }
1645 /* Handle the text property case. */
1646 else if (! NILP (mouse_face))
1647 {
1648 /* Find the range of text around this char that
1649 should be active. */
1650 Lisp_Object before, after, beginning, end;
1651 int ignore;
1652
1653 beginning = Fmarker_position (w->start);
1654 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
1655 - XFASTINT (w->window_end_pos)));
1656 before
1657 = Fprevious_single_property_change (make_number (pos + 1),
1658 Qmouse_face,
1659 w->buffer, beginning);
1660 after
1661 = Fnext_single_property_change (position, Qmouse_face,
1662 w->buffer, end);
1663 /* Record this as the current active region. */
1664 fast_find_position (w, XFASTINT (before),
1665 &dpyinfo->mouse_face_beg_col,
1666 &dpyinfo->mouse_face_beg_row);
1667 dpyinfo->mouse_face_past_end
1668 = !fast_find_position (w, XFASTINT (after),
1669 &dpyinfo->mouse_face_end_col,
1670 &dpyinfo->mouse_face_end_row);
1671 dpyinfo->mouse_face_window = window;
1672 dpyinfo->mouse_face_face_id
1673 = face_at_buffer_position (w, pos, 0, 0,
1674 &ignore, pos + 1, 1);
1675
1676 /* Display it as active. */
1677 show_mouse_face (dpyinfo, 1);
1678 }
1679 }
1680
1681 /* Look for a `help-echo' property. */
1682 {
1683 Lisp_Object help;
1684 extern Lisp_Object Qhelp_echo;
1685
1686 /* Check overlays first. */
1687 help = Qnil;
f0a4139c
EZ
1688 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
1689 {
1690 overlay = overlay_vec[i];
1691 help = Foverlay_get (overlay, Qhelp_echo);
1692 }
41ad069b 1693
b7e80413 1694 if (!NILP (help))
48c14970
EZ
1695 {
1696 help_echo = help;
1697 help_echo_window = window;
f0a4139c 1698 help_echo_object = overlay;
48c14970
EZ
1699 help_echo_pos = pos;
1700 }
1701 /* Try text properties. */
1702 else if (NILP (help)
1703 && ((STRINGP (glyph->object)
1704 && glyph->charpos >= 0
1705 && glyph->charpos < XSTRING (glyph->object)->size)
1706 || (BUFFERP (glyph->object)
1707 && glyph->charpos >= BEGV
1708 && glyph->charpos < ZV)))
1709 {
1710 help = Fget_text_property (make_number (glyph->charpos),
1711 Qhelp_echo, glyph->object);
1712 if (!NILP (help))
1713 {
1714 help_echo = help;
1715 help_echo_window = window;
1716 help_echo_object = glyph->object;
1717 help_echo_pos = glyph->charpos;
1718 }
1719 }
41ad069b
EZ
1720 }
1721
1722 BEGV = obegv;
1723 ZV = ozv;
1724 current_buffer = obuf;
1725 }
1726 }
1727}
1728
71f65669
EZ
1729static void
1730IT_clear_end_of_line (int first_unused)
f32d4091
KS
1731{
1732 char *spaces, *sp;
1733 int i, j;
039274cf 1734 int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
aa9ce936
EZ
1735 extern int fatal_error_in_progress;
1736
2d764c78 1737 if (new_pos_X >= first_unused || fatal_error_in_progress)
aa9ce936 1738 return;
f32d4091
KS
1739
1740 IT_set_face (0);
2d764c78 1741 i = (j = first_unused - new_pos_X) * 2;
e25d9653
EZ
1742 if (termscript)
1743 fprintf (termscript, "<CLR:EOL[%d..%d)>", new_pos_X, first_unused);
f32d4091 1744 spaces = sp = alloca (i);
aee81730 1745
f32d4091 1746 while (--j >= 0)
aee81730 1747 {
f32d4091
KS
1748 *sp++ = ' ';
1749 *sp++ = ScreenAttrib;
aee81730
RS
1750 }
1751
f32d4091 1752 mouse_off_maybe ();
039274cf
EZ
1753 dosmemput (spaces, i, (int)ScreenPrimary + offset);
1754 if (screen_virtual_segment)
1755 dosv_refresh_virtual_screen (offset, i / 2);
2d764c78
EZ
1756
1757 /* clear_end_of_line_raw on term.c leaves the cursor at first_unused.
1758 Let's follow their lead, in case someone relies on this. */
1759 new_pos_X = first_unused;
aee81730
RS
1760}
1761
71f65669 1762static void
f32d4091
KS
1763IT_clear_screen (void)
1764{
1765 if (termscript)
1766 fprintf (termscript, "<CLR:SCR>");
1767 IT_set_face (0);
1768 mouse_off ();
1769 ScreenClear ();
039274cf
EZ
1770 if (screen_virtual_segment)
1771 dosv_refresh_virtual_screen (0, screen_size);
f32d4091
KS
1772 new_pos_X = new_pos_Y = 0;
1773}
1774
71f65669 1775static void
f32d4091
KS
1776IT_clear_to_end (void)
1777{
1778 if (termscript)
1779 fprintf (termscript, "<CLR:EOS>");
1780
1781 while (new_pos_Y < screen_size_Y) {
1782 new_pos_X = 0;
e25d9653 1783 IT_clear_end_of_line (screen_size_X);
f32d4091
KS
1784 new_pos_Y++;
1785 }
1786}
1787
71f65669 1788static void
f32d4091
KS
1789IT_cursor_to (int y, int x)
1790{
1791 if (termscript)
1792 fprintf (termscript, "\n<XY=%dx%d>", x, y);
1793 new_pos_X = x;
1794 new_pos_Y = y;
1795}
1796
fc171623
KH
1797static int cursor_cleared;
1798
d1d5dc19 1799static void
fc171623
KH
1800IT_display_cursor (int on)
1801{
1802 if (on && cursor_cleared)
1803 {
1804 ScreenSetCursor (current_pos_Y, current_pos_X);
1805 cursor_cleared = 0;
1806 }
1807 else if (!on && !cursor_cleared)
1808 {
1809 ScreenSetCursor (-1, -1);
1810 cursor_cleared = 1;
1811 }
1812}
1813
1814/* Emacs calls cursor-movement functions a lot when it updates the
1815 display (probably a legacy of old terminals where you cannot
1816 update a screen line without first moving the cursor there).
1817 However, cursor movement is expensive on MSDOS (it calls a slow
1818 BIOS function and requires 2 mode switches), while actual screen
1819 updates access the video memory directly and don't depend on
1820 cursor position. To avoid slowing down the redisplay, we cheat:
1821 all functions that move the cursor only set internal variables
1822 which record the cursor position, whereas the cursor is only
1823 moved to its final position whenever screen update is complete.
1824
1825 `IT_cmgoto' is called from the keyboard reading loop and when the
1826 frame update is complete. This means that we are ready for user
1827 input, so we update the cursor position to show where the point is,
1828 and also make the mouse pointer visible.
1829
1830 Special treatment is required when the cursor is in the echo area,
1831 to put the cursor at the end of the text displayed there. */
1832
71f65669
EZ
1833static void
1834IT_cmgoto (FRAME_PTR f)
fc171623
KH
1835{
1836 /* Only set the cursor to where it should be if the display is
1837 already in sync with the window contents. */
2d764c78
EZ
1838 int update_cursor_pos = 1; /* MODIFF == unchanged_modified; */
1839
1840 /* FIXME: This needs to be rewritten for the new redisplay, or
1841 removed. */
1842#if 0
06da1de1
EZ
1843 static int previous_pos_X = -1;
1844
2d764c78
EZ
1845 update_cursor_pos = 1; /* temporary!!! */
1846
06da1de1
EZ
1847 /* If the display is in sync, forget any previous knowledge about
1848 cursor position. This is primarily for unexpected events like
1849 C-g in the minibuffer. */
1850 if (update_cursor_pos && previous_pos_X >= 0)
1851 previous_pos_X = -1;
1852 /* If we are in the echo area, put the cursor at the
1853 end of the echo area message. */
fc171623
KH
1854 if (!update_cursor_pos
1855 && XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top) <= new_pos_Y)
1856 {
06da1de1
EZ
1857 int tem_X = current_pos_X, dummy;
1858
1859 if (echo_area_glyphs)
1860 {
1861 tem_X = echo_area_glyphs_length;
1862 /* Save current cursor position, to be restored after the
1863 echo area message is erased. Only remember one level
1864 of previous cursor position. */
1865 if (previous_pos_X == -1)
1866 ScreenGetCursor (&dummy, &previous_pos_X);
1867 }
1868 else if (previous_pos_X >= 0)
1869 {
1870 /* We wind up here after the echo area message is erased.
1871 Restore the cursor position we remembered above. */
1872 tem_X = previous_pos_X;
1873 previous_pos_X = -1;
1874 }
9a599a60 1875
06da1de1 1876 if (current_pos_X != tem_X)
9a599a60
EZ
1877 {
1878 new_pos_X = tem_X;
1879 update_cursor_pos = 1;
1880 }
fc171623 1881 }
2d764c78 1882#endif
fc171623
KH
1883
1884 if (update_cursor_pos
1885 && (current_pos_X != new_pos_X || current_pos_Y != new_pos_Y))
1886 {
1887 ScreenSetCursor (current_pos_Y = new_pos_Y, current_pos_X = new_pos_X);
1888 if (termscript)
1889 fprintf (termscript, "\n<CURSOR:%dx%d>", current_pos_X, current_pos_Y);
1890 }
1891
1892 /* Maybe cursor is invisible, so make it visible. */
1893 IT_display_cursor (1);
1894
1895 /* Mouse pointer should be always visible if we are waiting for
1896 keyboard input. */
1897 if (!mouse_visible)
1898 mouse_on ();
1899}
1900
71f65669
EZ
1901static void
1902IT_reassert_line_highlight (int new, int vpos)
f32d4091
KS
1903{
1904 highlight = new;
f32d4091
KS
1905}
1906
71f65669 1907static void
c77f6f1b 1908IT_change_line_highlight (int new_highlight, int y, int vpos, int first_unused_hpos)
1b94449f 1909{
f32d4091 1910 highlight = new_highlight;
f32d4091
KS
1911 IT_cursor_to (vpos, 0);
1912 IT_clear_end_of_line (first_unused_hpos);
1913}
1914
71f65669 1915static void
41ad069b 1916IT_update_begin (struct frame *f)
f32d4091 1917{
41ad069b 1918 struct display_info *display_info = FRAME_X_DISPLAY_INFO (f);
b9f80d41 1919 struct frame *mouse_face_frame = display_info->mouse_face_mouse_frame;
41ad069b 1920
f32d4091 1921 highlight = 0;
41ad069b
EZ
1922
1923 BLOCK_INPUT;
1924
b9f80d41 1925 if (f && f == mouse_face_frame)
41ad069b
EZ
1926 {
1927 /* Don't do highlighting for mouse motion during the update. */
1928 display_info->mouse_face_defer = 1;
1929
1930 /* If F needs to be redrawn, simply forget about any prior mouse
1931 highlighting. */
1932 if (FRAME_GARBAGED_P (f))
1933 display_info->mouse_face_window = Qnil;
1934
1935 /* Can we tell that this update does not affect the window
1936 where the mouse highlight is? If so, no need to turn off.
48c14970
EZ
1937 Likewise, don't do anything if none of the enabled rows
1938 contains glyphs highlighted in mouse face. */
8ccb9a54
EZ
1939 if (!NILP (display_info->mouse_face_window)
1940 && WINDOWP (display_info->mouse_face_window))
41ad069b
EZ
1941 {
1942 struct window *w = XWINDOW (display_info->mouse_face_window);
1943 int i;
1944
8ccb9a54
EZ
1945 /* If the mouse highlight is in the window that was deleted
1946 (e.g., if it was popped by completion), clear highlight
1947 unconditionally. */
1948 if (NILP (w->buffer))
1949 display_info->mouse_face_window = Qnil;
1950 else
1951 {
1952 for (i = 0; i < w->desired_matrix->nrows; ++i)
48c14970
EZ
1953 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i)
1954 && MATRIX_ROW (w->current_matrix, i)->mouse_face_p)
8ccb9a54
EZ
1955 break;
1956 }
41ad069b 1957
8ccb9a54 1958 if (NILP (w->buffer) || i < w->desired_matrix->nrows)
41ad069b
EZ
1959 clear_mouse_face (display_info);
1960 }
1961 }
b9f80d41 1962 else if (mouse_face_frame && !FRAME_LIVE_P (mouse_face_frame))
41ad069b
EZ
1963 {
1964 /* If the frame with mouse highlight was deleted, invalidate the
1965 highlight info. */
1966 display_info->mouse_face_beg_row = display_info->mouse_face_beg_col = -1;
1967 display_info->mouse_face_end_row = display_info->mouse_face_end_col = -1;
1968 display_info->mouse_face_window = Qnil;
1969 display_info->mouse_face_deferred_gc = 0;
1970 display_info->mouse_face_mouse_frame = NULL;
1971 }
1972
1973 UNBLOCK_INPUT;
f32d4091
KS
1974}
1975
71f65669 1976static void
41ad069b 1977IT_update_end (struct frame *f)
f32d4091 1978{
41ad069b
EZ
1979 highlight = 0;
1980 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
1981}
1982
8ba01a32
EZ
1983Lisp_Object Qcursor_type;
1984
41ad069b
EZ
1985static void
1986IT_frame_up_to_date (struct frame *f)
1987{
1988 struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
0c3cfc51
EZ
1989 Lisp_Object new_cursor, frame_desired_cursor;
1990 struct window *sw;
41ad069b
EZ
1991
1992 if (dpyinfo->mouse_face_deferred_gc
b9f80d41 1993 || (f && f == dpyinfo->mouse_face_mouse_frame))
41ad069b
EZ
1994 {
1995 BLOCK_INPUT;
1996 if (dpyinfo->mouse_face_mouse_frame)
1997 IT_note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1998 dpyinfo->mouse_face_mouse_x,
1999 dpyinfo->mouse_face_mouse_y);
2000 dpyinfo->mouse_face_deferred_gc = 0;
2001 UNBLOCK_INPUT;
2002 }
2003
0c3cfc51
EZ
2004 /* Set the cursor type to whatever they wanted. In a minibuffer
2005 window, we want the cursor to appear only if we are reading input
2006 from this window, and we want the cursor to be taken from the
2007 frame parameters. For the selected window, we use either its
2008 buffer-local value or the value from the frame parameters if the
2009 buffer doesn't define its local value for the cursor type. */
2010 sw = XWINDOW (f->selected_window);
2011 frame_desired_cursor = Fcdr (Fassq (Qcursor_type, f->param_alist));
2012 if (cursor_in_echo_area
2013 && FRAME_HAS_MINIBUF_P (f)
2014 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window)
2015 && sw == XWINDOW (echo_area_window))
2016 new_cursor = frame_desired_cursor;
2017 else
2018 {
2019 struct buffer *b = XBUFFER (sw->buffer);
2020
2021 if (EQ (b->cursor_type, Qt))
2022 new_cursor = frame_desired_cursor;
2023 else if (NILP (b->cursor_type)) /* nil means no cursor */
2024 new_cursor = Fcons (Qbar, make_number (0));
2025 else
2026 new_cursor = b->cursor_type;
2027 }
2028
2029 IT_set_cursor_type (f, new_cursor);
8ba01a32 2030
41ad069b 2031 IT_cmgoto (f); /* position cursor when update is done */
f32d4091 2032}
1b94449f 2033
c77f6f1b
EZ
2034/* Copy LEN glyphs displayed on a single line whose vertical position
2035 is YPOS, beginning at horizontal position XFROM to horizontal
2036 position XTO, by moving blocks in the video memory. Used by
2037 functions that insert and delete glyphs. */
2038static void
2039IT_copy_glyphs (int xfrom, int xto, size_t len, int ypos)
2040{
2041 /* The offsets of source and destination relative to the
2042 conventional memorty selector. */
2043 int from = 2 * (xfrom + screen_size_X * ypos) + ScreenPrimary;
2044 int to = 2 * (xto + screen_size_X * ypos) + ScreenPrimary;
2045
2046 if (from == to || len <= 0)
2047 return;
2048
2049 _farsetsel (_dos_ds);
2050
2051 /* The source and destination might overlap, so we need to move
2052 glyphs non-destructively. */
2053 if (from > to)
2054 {
2055 for ( ; len; from += 2, to += 2, len--)
2056 _farnspokew (to, _farnspeekw (from));
2057 }
2058 else
2059 {
2060 from += (len - 1) * 2;
2061 to += (len - 1) * 2;
2062 for ( ; len; from -= 2, to -= 2, len--)
2063 _farnspokew (to, _farnspeekw (from));
2064 }
2065 if (screen_virtual_segment)
2066 dosv_refresh_virtual_screen (ypos * screen_size_X * 2, screen_size_X);
2067}
2068
2069/* Insert and delete glyphs. */
aa9ce936
EZ
2070static void
2071IT_insert_glyphs (start, len)
c77f6f1b 2072 register struct glyph *start;
aa9ce936
EZ
2073 register int len;
2074{
c77f6f1b
EZ
2075 int shift_by_width = screen_size_X - (new_pos_X + len);
2076
2077 /* Shift right the glyphs from the nominal cursor position to the
2078 end of this line. */
2079 IT_copy_glyphs (new_pos_X, new_pos_X + len, shift_by_width, new_pos_Y);
2080
2081 /* Now write the glyphs to be inserted. */
2082 IT_write_glyphs (start, len);
aa9ce936
EZ
2083}
2084
2085static void
2086IT_delete_glyphs (n)
2087 register int n;
2088{
2089 abort ();
2090}
2091
211c7152 2092/* set-window-configuration on window.c needs this. */
3bb1f22f
RS
2093void
2094x_set_menu_bar_lines (f, value, oldval)
2095 struct frame *f;
2096 Lisp_Object value, oldval;
2097{
211c7152
EZ
2098 set_menu_bar_lines (f, value, oldval);
2099}
3bb1f22f 2100
984f5aaa 2101/* This was copied from xfaces.c */
3bb1f22f 2102
984f5aaa
EZ
2103extern Lisp_Object Qbackground_color;
2104extern Lisp_Object Qforeground_color;
8ba01a32 2105Lisp_Object Qreverse;
211c7152 2106extern Lisp_Object Qtitle;
3bb1f22f 2107
48ffe371
RS
2108/* IT_set_terminal_modes is called when emacs is started,
2109 resumed, and whenever the screen is redrawn! */
f32d4091 2110
71f65669 2111static void
f32d4091
KS
2112IT_set_terminal_modes (void)
2113{
aee81730 2114 if (termscript)
f32d4091
KS
2115 fprintf (termscript, "\n<SET_TERM>");
2116 highlight = 0;
2117
2118 screen_size_X = ScreenCols ();
2119 screen_size_Y = ScreenRows ();
2120 screen_size = screen_size_X * screen_size_Y;
aee81730 2121
f32d4091
KS
2122 new_pos_X = new_pos_Y = 0;
2123 current_pos_X = current_pos_Y = -1;
2124
2125 if (term_setup_done)
2126 return;
2127 term_setup_done = 1;
aee81730 2128
f32d4091
KS
2129 startup_screen_size_X = screen_size_X;
2130 startup_screen_size_Y = screen_size_Y;
c9adab25 2131 startup_screen_attrib = ScreenAttrib;
f32d4091 2132
039274cf
EZ
2133#if __DJGPP__ > 1
2134 /* Is DOS/V (or any other RSIS software which relocates
2135 the screen) installed? */
2136 {
2137 unsigned short es_value;
2138 __dpmi_regs regs;
2139
2140 regs.h.ah = 0xfe; /* get relocated screen address */
2141 if (ScreenPrimary == 0xb0000UL || ScreenPrimary == 0xb8000UL)
2142 regs.x.es = (ScreenPrimary >> 4) & 0xffff;
2143 else if (screen_old_address) /* already switched to Japanese mode once */
2144 regs.x.es = (screen_old_address >> 4) & 0xffff;
2145 else
2146 regs.x.es = ScreenMode () == 7 ? 0xb000 : 0xb800;
2147 regs.x.di = 0;
2148 es_value = regs.x.es;
2149 __dpmi_int (0x10, &regs);
2150
d1d5dc19 2151 if (regs.x.es != es_value)
039274cf 2152 {
d1d5dc19
EZ
2153 /* screen_old_address is only set if ScreenPrimary does NOT
2154 already point to the relocated buffer address returned by
2155 the Int 10h/AX=FEh call above. DJGPP v2.02 and later sets
2156 ScreenPrimary to that address at startup under DOS/V. */
2157 if (regs.x.es != (ScreenPrimary >> 4) & 0xffff)
2158 screen_old_address = ScreenPrimary;
039274cf
EZ
2159 screen_virtual_segment = regs.x.es;
2160 screen_virtual_offset = regs.x.di;
2161 ScreenPrimary = (screen_virtual_segment << 4) + screen_virtual_offset;
2162 }
2163 }
2164#endif /* __DJGPP__ > 1 */
2165
f32d4091
KS
2166 ScreenGetCursor (&startup_pos_Y, &startup_pos_X);
2167 ScreenRetrieve (startup_screen_buffer = xmalloc (screen_size * 2));
2168
2169 if (termscript)
c9adab25 2170 fprintf (termscript, "<SCREEN SAVED (dimensions=%dx%d)>\n",
039274cf 2171 screen_size_X, screen_size_Y);
76ac1508
RS
2172
2173 bright_bg ();
f32d4091
KS
2174}
2175
48ffe371
RS
2176/* IT_reset_terminal_modes is called when emacs is
2177 suspended or killed. */
f32d4091 2178
71f65669 2179static void
f32d4091
KS
2180IT_reset_terminal_modes (void)
2181{
c9adab25
KH
2182 int display_row_start = (int) ScreenPrimary;
2183 int saved_row_len = startup_screen_size_X * 2;
2184 int update_row_len = ScreenCols () * 2;
2185 int current_rows = ScreenRows ();
2186 int to_next_row = update_row_len;
2187 unsigned char *saved_row = startup_screen_buffer;
2188 int cursor_pos_X = ScreenCols () - 1;
2189 int cursor_pos_Y = ScreenRows () - 1;
2190
f32d4091 2191 if (termscript)
5063b150 2192 fprintf (termscript, "\n<RESET_TERM>");
f32d4091
KS
2193
2194 highlight = 0;
2195
2196 if (!term_setup_done)
2197 return;
2198
c9adab25 2199 mouse_off ();
b36701cc
RS
2200
2201 /* Leave the video system in the same state as we found it,
2202 as far as the blink/bright-background bit is concerned. */
2203 maybe_enable_blinking ();
06b1ea13 2204
c9adab25
KH
2205 /* We have a situation here.
2206 We cannot just do ScreenUpdate(startup_screen_buffer) because
2207 the luser could have changed screen dimensions inside Emacs
2208 and failed (or didn't want) to restore them before killing
2209 Emacs. ScreenUpdate() uses the *current* screen dimensions and
2210 thus will happily use memory outside what was allocated for
2211 `startup_screen_buffer'.
2212 Thus we only restore as much as the current screen dimensions
2213 can hold, and clear the rest (if the saved screen is smaller than
2214 the current) with the color attribute saved at startup. The cursor
2215 is also restored within the visible dimensions. */
2216
2217 ScreenAttrib = startup_screen_attrib;
c9adab25 2218
06b1ea13
EZ
2219 /* Don't restore the screen if we are exiting less than 2 seconds
2220 after startup: we might be crashing, and the screen might show
2221 some vital clues to what's wrong. */
2222 if (clock () - startup_time >= 2*CLOCKS_PER_SEC)
c9adab25 2223 {
06b1ea13 2224 ScreenClear ();
039274cf 2225 if (screen_virtual_segment)
06b1ea13
EZ
2226 dosv_refresh_virtual_screen (0, screen_size);
2227
2228 if (update_row_len > saved_row_len)
2229 update_row_len = saved_row_len;
2230 if (current_rows > startup_screen_size_Y)
2231 current_rows = startup_screen_size_Y;
2232
2233 if (termscript)
2234 fprintf (termscript, "<SCREEN RESTORED (dimensions=%dx%d)>\n",
2235 update_row_len / 2, current_rows);
2236
2237 while (current_rows--)
2238 {
2239 dosmemput (saved_row, update_row_len, display_row_start);
2240 if (screen_virtual_segment)
2241 dosv_refresh_virtual_screen (display_row_start - ScreenPrimary,
2242 update_row_len / 2);
2243 saved_row += saved_row_len;
2244 display_row_start += to_next_row;
2245 }
c9adab25
KH
2246 }
2247 if (startup_pos_X < cursor_pos_X)
2248 cursor_pos_X = startup_pos_X;
2249 if (startup_pos_Y < cursor_pos_Y)
2250 cursor_pos_Y = startup_pos_Y;
2251
2252 ScreenSetCursor (cursor_pos_Y, cursor_pos_X);
2253 xfree (startup_screen_buffer);
f32d4091
KS
2254
2255 term_setup_done = 0;
2256}
2257
71f65669
EZ
2258static void
2259IT_set_terminal_window (int foo)
f32d4091
KS
2260{
2261}
2262
2d764c78
EZ
2263/* Remember the screen colors of the curent frame, to serve as the
2264 default colors for newly-created frames. */
2265
2266static int initial_screen_colors[2];
2267
2268DEFUN ("msdos-remember-default-colors", Fmsdos_remember_default_colors,
2269 Smsdos_remember_default_colors, 1, 1, 0,
2270 "Remember the screen colors of the current frame.")
2271 (frame)
2272 Lisp_Object frame;
2273{
2274 int reverse;
2275 struct frame *f;
2276
2277 CHECK_FRAME (frame, 0);
2278 f= XFRAME (frame);
2279 reverse = EQ (Fcdr (Fassq (intern ("reverse"), f->param_alist)), Qt);
2280
2281 initial_screen_colors[0]
2282 = reverse ? FRAME_BACKGROUND_PIXEL (f) : FRAME_FOREGROUND_PIXEL (f);
2283 initial_screen_colors[1]
2284 = reverse ? FRAME_FOREGROUND_PIXEL (f) : FRAME_BACKGROUND_PIXEL (f);
2285}
2286
f32d4091 2287void
3bb1f22f 2288IT_set_frame_parameters (f, alist)
c77f6f1b 2289 struct frame *f;
f32d4091
KS
2290 Lisp_Object alist;
2291{
2292 Lisp_Object tail;
db722735 2293 int length = XINT (Flength (alist));
2d764c78 2294 int i, j;
db722735
RS
2295 Lisp_Object *parms
2296 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
2297 Lisp_Object *values
2298 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
2d764c78 2299 /* Do we have to reverse the foreground and background colors? */
8ba01a32 2300 int reverse = EQ (Fcdr (Fassq (Qreverse, f->param_alist)), Qt);
2d764c78
EZ
2301 int was_reverse = reverse;
2302 int redraw = 0, fg_set = 0, bg_set = 0;
2303 unsigned long orig_fg;
2304 unsigned long orig_bg;
2305
2306 /* If we are creating a new frame, begin with the original screen colors
2307 used for the initial frame. */
2308 if (alist == Vdefault_frame_alist
2309 && initial_screen_colors[0] != -1 && initial_screen_colors[1] != -1)
2310 {
2311 FRAME_FOREGROUND_PIXEL (f) = initial_screen_colors[0];
2312 FRAME_BACKGROUND_PIXEL (f) = initial_screen_colors[1];
2313 }
2314 orig_fg = FRAME_FOREGROUND_PIXEL (f);
2315 orig_bg = FRAME_BACKGROUND_PIXEL (f);
db722735
RS
2316
2317 /* Extract parm names and values into those vectors. */
2318 i = 0;
f32d4091
KS
2319 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
2320 {
db722735 2321 Lisp_Object elt;
f32d4091
KS
2322
2323 elt = Fcar (tail);
db722735
RS
2324 parms[i] = Fcar (elt);
2325 CHECK_SYMBOL (parms[i], 1);
2326 values[i] = Fcdr (elt);
2327 i++;
2328 }
2329
2d764c78 2330 j = i;
db722735 2331
2d764c78
EZ
2332 for (i = 0; i < j; i++)
2333 {
1e21fe48
EZ
2334 Lisp_Object prop, val;
2335
2336 prop = parms[i];
2337 val = values[i];
2d764c78 2338
8ba01a32 2339 if (EQ (prop, Qreverse))
2d764c78
EZ
2340 reverse = EQ (val, Qt);
2341 }
2342
2343 if (termscript && reverse && !was_reverse)
2344 fprintf (termscript, "<INVERSE-VIDEO>\n");
2345
2346 /* Now process the alist elements in reverse of specified order. */
db722735
RS
2347 for (i--; i >= 0; i--)
2348 {
1e21fe48
EZ
2349 extern Lisp_Object Qdefault, QCforeground, QCbackground;
2350 Lisp_Object prop, val;
2351 Lisp_Object frame;
2352
2353 prop = parms[i];
2354 val = values[i];
f32d4091 2355
4e825084 2356 if (EQ (prop, Qforeground_color))
f32d4091 2357 {
2d764c78
EZ
2358 unsigned long new_color = load_color (f, NULL, val, reverse
2359 ? LFACE_BACKGROUND_INDEX
2360 : LFACE_FOREGROUND_INDEX);
3b620731
EZ
2361 if (new_color != FACE_TTY_DEFAULT_COLOR
2362 && new_color != FACE_TTY_DEFAULT_FG_COLOR
2363 && new_color != FACE_TTY_DEFAULT_BG_COLOR)
f32d4091 2364 {
1e21fe48
EZ
2365 /* Make sure the foreground of the default face for this
2366 frame is changed as well. */
2367 XSETFRAME (frame, f);
2d764c78 2368 if (reverse)
1e21fe48
EZ
2369 {
2370 FRAME_BACKGROUND_PIXEL (f) = new_color;
2371 Finternal_set_lisp_face_attribute (Qdefault, QCbackground,
2372 val, frame);
2373 }
2d764c78 2374 else
1e21fe48
EZ
2375 {
2376 FRAME_FOREGROUND_PIXEL (f) = new_color;
2377 Finternal_set_lisp_face_attribute (Qdefault, QCforeground,
2378 val, frame);
2379 }
f32d4091 2380 redraw = 1;
2d764c78 2381 fg_set = 1;
76ac1508 2382 if (termscript)
a7cf9151 2383 fprintf (termscript, "<FGCOLOR %lu>\n", new_color);
f32d4091
KS
2384 }
2385 }
4e825084 2386 else if (EQ (prop, Qbackground_color))
f32d4091 2387 {
2d764c78
EZ
2388 unsigned long new_color = load_color (f, NULL, val, reverse
2389 ? LFACE_FOREGROUND_INDEX
2390 : LFACE_BACKGROUND_INDEX);
3b620731
EZ
2391 if (new_color != FACE_TTY_DEFAULT_COLOR
2392 && new_color != FACE_TTY_DEFAULT_FG_COLOR
2393 && new_color != FACE_TTY_DEFAULT_BG_COLOR)
f32d4091 2394 {
1e21fe48
EZ
2395 /* Make sure the background of the default face for this
2396 frame is changed as well. */
2397 XSETFRAME (frame, f);
2d764c78 2398 if (reverse)
1e21fe48
EZ
2399 {
2400 FRAME_FOREGROUND_PIXEL (f) = new_color;
2401 Finternal_set_lisp_face_attribute (Qdefault, QCforeground,
2402 val, frame);
2403 }
2d764c78 2404 else
1e21fe48
EZ
2405 {
2406 FRAME_BACKGROUND_PIXEL (f) = new_color;
2407 Finternal_set_lisp_face_attribute (Qdefault, QCbackground,
2408 val, frame);
2409 }
f32d4091 2410 redraw = 1;
2d764c78 2411 bg_set = 1;
76ac1508 2412 if (termscript)
a7cf9151 2413 fprintf (termscript, "<BGCOLOR %lu>\n", new_color);
f32d4091
KS
2414 }
2415 }
211c7152
EZ
2416 else if (EQ (prop, Qtitle))
2417 {
2418 x_set_title (f, val);
2419 if (termscript)
2420 fprintf (termscript, "<TITLE: %s>\n", XSTRING (val)->data);
2421 }
8ba01a32
EZ
2422 else if (EQ (prop, Qcursor_type))
2423 {
2424 IT_set_cursor_type (f, val);
2425 if (termscript)
2426 fprintf (termscript, "<CTYPE: %s>\n",
2427 EQ (val, Qbar) || CONSP (val) && EQ (XCAR (val), Qbar)
2428 ? "bar" : "box");
2429 }
db722735 2430 store_frame_param (f, prop, val);
2d764c78 2431 }
db722735 2432
2d764c78
EZ
2433 /* If they specified "reverse", but not the colors, we need to swap
2434 the current frame colors. */
2435 if (reverse && !was_reverse)
2436 {
1e21fe48
EZ
2437 Lisp_Object frame;
2438
2d764c78
EZ
2439 if (!fg_set)
2440 {
2441 FRAME_BACKGROUND_PIXEL (f) = orig_fg;
1e21fe48
EZ
2442 XSETFRAME (frame, f);
2443 Finternal_set_lisp_face_attribute (Qdefault, QCbackground,
2444 tty_color_name (orig_fg), frame);
2d764c78
EZ
2445 redraw = 1;
2446 }
2447 if (!bg_set)
2448 {
2449 FRAME_FOREGROUND_PIXEL (f) = orig_bg;
1e21fe48
EZ
2450 XSETFRAME (frame, f);
2451 Finternal_set_lisp_face_attribute (Qdefault, QCforeground,
2452 tty_color_name (orig_bg), frame);
2d764c78
EZ
2453 redraw = 1;
2454 }
f32d4091
KS
2455 }
2456
2457 if (redraw)
2458 {
2d764c78
EZ
2459 face_change_count++; /* forces xdisp.c to recompute basic faces */
2460 if (f == SELECTED_FRAME())
3bb1f22f 2461 redraw_frame (f);
f32d4091
KS
2462 }
2463}
2464
a7cf9151
EZ
2465extern void init_frame_faces (FRAME_PTR);
2466
f32d4091
KS
2467#endif /* !HAVE_X_WINDOWS */
2468
2469
48ffe371
RS
2470/* Do we need the internal terminal? */
2471
f32d4091
KS
2472void
2473internal_terminal_init ()
2474{
2475 char *term = getenv ("TERM");
2476 char *colors;
2d764c78 2477 struct frame *sf = SELECTED_FRAME();
f32d4091
KS
2478
2479#ifdef HAVE_X_WINDOWS
2480 if (!inhibit_window_system)
2481 return;
2482#endif
2483
2484 internal_terminal
2485 = (!noninteractive) && term && !strcmp (term, "internal");
2486
2487 if (getenv ("EMACSTEST"))
5063b150 2488 termscript = fopen (getenv ("EMACSTEST"), "wt");
f32d4091
KS
2489
2490#ifndef HAVE_X_WINDOWS
2491 if (!internal_terminal || inhibit_window_system)
2492 {
2d764c78 2493 sf->output_method = output_termcap;
f32d4091
KS
2494 return;
2495 }
2496
2497 Vwindow_system = intern ("pc");
2498 Vwindow_system_version = make_number (1);
2d764c78 2499 sf->output_method = output_msdos_raw;
039274cf
EZ
2500
2501 /* If Emacs was dumped on DOS/V machine, forget the stale VRAM address. */
2502 screen_old_address = 0;
2503
2d764c78
EZ
2504 /* Forget the stale screen colors as well. */
2505 initial_screen_colors[0] = initial_screen_colors[1] = -1;
2506
f32d4091
KS
2507 bzero (&the_only_x_display, sizeof the_only_x_display);
2508 the_only_x_display.background_pixel = 7; /* White */
2509 the_only_x_display.foreground_pixel = 0; /* Black */
76ac1508 2510 bright_bg ();
5063b150 2511 colors = getenv ("EMACSCOLORS");
f32d4091
KS
2512 if (colors && strlen (colors) >= 2)
2513 {
76ac1508
RS
2514 /* The colors use 4 bits each (we enable bright background). */
2515 if (isdigit (colors[0]))
2516 colors[0] -= '0';
2517 else if (isxdigit (colors[0]))
2518 colors[0] -= (isupper (colors[0]) ? 'A' : 'a') - 10;
1bd7b2c7
RS
2519 if (colors[0] >= 0 && colors[0] < 16)
2520 the_only_x_display.foreground_pixel = colors[0];
76ac1508
RS
2521 if (isdigit (colors[1]))
2522 colors[1] -= '0';
2523 else if (isxdigit (colors[1]))
2524 colors[1] -= (isupper (colors[1]) ? 'A' : 'a') - 10;
2525 if (colors[1] >= 0 && colors[1] < 16)
1bd7b2c7 2526 the_only_x_display.background_pixel = colors[1];
f32d4091
KS
2527 }
2528 the_only_x_display.line_height = 1;
64ec6a02 2529 the_only_x_display.font = (XFontStruct *)1; /* must *not* be zero */
41ad069b
EZ
2530 the_only_x_display.display_info.mouse_face_mouse_frame = NULL;
2531 the_only_x_display.display_info.mouse_face_deferred_gc = 0;
2532 the_only_x_display.display_info.mouse_face_beg_row =
2533 the_only_x_display.display_info.mouse_face_beg_col = -1;
2534 the_only_x_display.display_info.mouse_face_end_row =
2535 the_only_x_display.display_info.mouse_face_end_col = -1;
2536 the_only_x_display.display_info.mouse_face_face_id = DEFAULT_FACE_ID;
2537 the_only_x_display.display_info.mouse_face_window = Qnil;
2538 the_only_x_display.display_info.mouse_face_mouse_x =
2539 the_only_x_display.display_info.mouse_face_mouse_y = 0;
2540 the_only_x_display.display_info.mouse_face_defer = 0;
f32d4091 2541
2d764c78 2542 init_frame_faces (sf);
f32d4091
KS
2543
2544 ring_bell_hook = IT_ring_bell;
aa9ce936
EZ
2545 insert_glyphs_hook = IT_insert_glyphs;
2546 delete_glyphs_hook = IT_delete_glyphs;
f32d4091
KS
2547 write_glyphs_hook = IT_write_glyphs;
2548 cursor_to_hook = raw_cursor_to_hook = IT_cursor_to;
2549 clear_to_end_hook = IT_clear_to_end;
2550 clear_end_of_line_hook = IT_clear_end_of_line;
2551 clear_frame_hook = IT_clear_screen;
2552 change_line_highlight_hook = IT_change_line_highlight;
2553 update_begin_hook = IT_update_begin;
2554 update_end_hook = IT_update_end;
2555 reassert_line_highlight_hook = IT_reassert_line_highlight;
41ad069b 2556 frame_up_to_date_hook = IT_frame_up_to_date;
f32d4091
KS
2557
2558 /* These hooks are called by term.c without being checked. */
2559 set_terminal_modes_hook = IT_set_terminal_modes;
2560 reset_terminal_modes_hook = IT_reset_terminal_modes;
2561 set_terminal_window_hook = IT_set_terminal_window;
c77f6f1b 2562 char_ins_del_ok = 0;
f32d4091
KS
2563#endif
2564}
2565
2566dos_get_saved_screen (screen, rows, cols)
2567 char **screen;
2568 int *rows;
2569 int *cols;
2570{
2571#ifndef HAVE_X_WINDOWS
2572 *screen = startup_screen_buffer;
2573 *cols = startup_screen_size_X;
2574 *rows = startup_screen_size_Y;
039274cf 2575 return *screen != (char *)0;
f32d4091
KS
2576#else
2577 return 0;
2578#endif
2579}
3bb1f22f
RS
2580
2581#ifndef HAVE_X_WINDOWS
2582
2583/* We are not X, but we can emulate it well enough for our needs... */
2584void
2585check_x (void)
2586{
2d764c78
EZ
2587 if (! FRAME_MSDOS_P (SELECTED_FRAME()))
2588 error ("Not running under a window system");
3bb1f22f
RS
2589}
2590
2591#endif
2592
5063b150 2593\f
f32d4091
KS
2594/* ----------------------- Keyboard control ----------------------
2595 *
2596 * Keymaps reflect the following keyboard layout:
2597 *
2598 * 0 1 2 3 4 5 6 7 8 9 10 11 12 BS
2599 * TAB 15 16 17 18 19 20 21 22 23 24 25 26 (41)
2600 * CLOK 30 31 32 33 34 35 36 37 38 39 40 (41) RET
2601 * SH () 45 46 47 48 49 50 51 52 53 54 SHIFT
2602 * SPACE
2603 */
2604
d1d5dc19
EZ
2605#define Ignore 0x0000
2606#define Normal 0x0000 /* normal key - alt changes scan-code */
2607#define FctKey 0x1000 /* func key if c == 0, else c */
2608#define Special 0x2000 /* func key even if c != 0 */
2609#define ModFct 0x3000 /* special if mod-keys, else 'c' */
2610#define Map 0x4000 /* alt scan-code, map to unshift/shift key */
2611#define KeyPad 0x5000 /* map to insert/kp-0 depending on c == 0xe0 */
2612#define Grey 0x6000 /* Grey keypad key */
2613
2614#define Alt 0x0100 /* alt scan-code */
2615#define Ctrl 0x0200 /* ctrl scan-code */
2616#define Shift 0x0400 /* shift scan-code */
2617
f32d4091
KS
2618static int extended_kbd; /* 101 (102) keyboard present. */
2619
d1d5dc19
EZ
2620struct kbd_translate {
2621 unsigned char sc;
2622 unsigned char ch;
2623 unsigned short code;
2624};
2625
f32d4091
KS
2626struct dos_keyboard_map
2627{
2628 char *unshifted;
2629 char *shifted;
2630 char *alt_gr;
d1d5dc19 2631 struct kbd_translate *translate_table;
f32d4091
KS
2632};
2633
2634
2635static struct dos_keyboard_map us_keyboard = {
2636/* 0 1 2 3 4 5 */
2637/* 01234567890123456789012345678901234567890 12345678901234 */
2638 "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ",
2639/* 0123456789012345678901234567890123456789 012345678901234 */
2640 "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ",
d1d5dc19
EZ
2641 0, /* no Alt-Gr key */
2642 0 /* no translate table */
f32d4091
KS
2643};
2644
2645static struct dos_keyboard_map fr_keyboard = {
2646/* 0 1 2 3 4 5 */
2647/* 012 3456789012345678901234567890123456789012345678901234 */
2648