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