(Qhbar): New variable.
[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
a0738471 415Lisp_Object Qbar, Qhbar;
8ba01a32 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{
a0738471 823 if (EQ (cursor_type, Qbar) || EQ (cursor_type, Qhbar))
8ba01a32
EZ
824 {
825 /* Just BAR means the normal EGA/VGA cursor. */
826 msdos_set_cursor_shape (f, DEFAULT_CURSOR_START, DEFAULT_CURSOR_WIDTH);
827 }
a0738471
EZ
828 else if (CONSP (cursor_type)
829 && (EQ (XCAR (cursor_type), Qbar)
830 || EQ (XCAR (cursor_type), Qhbar)))
8ba01a32
EZ
831 {
832 Lisp_Object bar_parms = XCDR (cursor_type);
833 int width;
834
835 if (INTEGERP (bar_parms))
836 {
837 /* Feature: negative WIDTH means cursor at the top
838 of the character cell, zero means invisible cursor. */
839 width = XINT (bar_parms);
840 msdos_set_cursor_shape (f, width >= 0 ? DEFAULT_CURSOR_START : 0,
841 width);
842 }
843 else if (CONSP (bar_parms)
844 && INTEGERP (XCAR (bar_parms))
845 && INTEGERP (XCDR (bar_parms)))
846 {
847 int start_line = XINT (XCDR (bar_parms));
848
849 width = XINT (XCAR (bar_parms));
850 msdos_set_cursor_shape (f, start_line, width);
851 }
852 }
853 else
854 /* Treat anything unknown as "box cursor". This includes nil, so
855 that a frame which doesn't specify a cursor type gets a box,
856 which is the default in Emacs. */
857 msdos_set_cursor_shape (f, 0, BOX_CURSOR_WIDTH);
858}
859
71f65669
EZ
860static void
861IT_ring_bell (void)
f32d4091
KS
862{
863 if (visible_bell)
aee81730 864 {
f32d4091
KS
865 mouse_off ();
866 ScreenVisualBell ();
aee81730 867 }
f32d4091 868 else
3635be47
RS
869 {
870 union REGS inregs, outregs;
871 inregs.h.ah = 2;
872 inregs.h.dl = 7;
873 intdos (&inregs, &outregs);
874 }
09e2ac30
RS
875}
876
c77f6f1b
EZ
877/* Given a face id FACE, extract the face parameters to be used for
878 display until the face changes. The face parameters (actually, its
879 color) are used to construct the video attribute byte for each
880 glyph during the construction of the buffer that is then blitted to
881 the video RAM. */
f32d4091
KS
882static void
883IT_set_face (int face)
884{
2d764c78 885 struct frame *sf = SELECTED_FRAME();
546701f5
EZ
886 struct face *fp = FACE_FROM_ID (sf, face);
887 struct face *dfp = FACE_FROM_ID (sf, DEFAULT_FACE_ID);
888 unsigned long fg, bg, dflt_fg, dflt_bg;
f32d4091 889
c77f6f1b 890 if (!fp)
e30aee93 891 {
546701f5 892 fp = dfp;
e30aee93
EZ
893 /* The default face for the frame should always be realized and
894 cached. */
895 if (!fp)
896 abort ();
897 }
f32d4091 898 screen_face = face;
c77f6f1b
EZ
899 fg = fp->foreground;
900 bg = fp->background;
546701f5
EZ
901 dflt_fg = dfp->foreground;
902 dflt_bg = dfp->background;
c77f6f1b 903
abcce93a
MB
904 /* Don't use invalid colors. In particular, FACE_TTY_DEFAULT_* colors
905 mean use the colors of the default face. Note that we assume all
906 16 colors to be available for the background, since Emacs switches
907 on this mode (and loses the blinking attribute) at startup. */
f9d2fdc4 908 if (fg == FACE_TTY_DEFAULT_COLOR || fg == FACE_TTY_DEFAULT_FG_COLOR)
3b620731 909 fg = FRAME_FOREGROUND_PIXEL (sf);
f9d2fdc4 910 else if (fg == FACE_TTY_DEFAULT_BG_COLOR)
3b620731
EZ
911 fg = FRAME_BACKGROUND_PIXEL (sf);
912 if (bg == FACE_TTY_DEFAULT_COLOR || bg == FACE_TTY_DEFAULT_BG_COLOR)
913 bg = FRAME_BACKGROUND_PIXEL (sf);
f9d2fdc4 914 else if (bg == FACE_TTY_DEFAULT_FG_COLOR)
3b620731
EZ
915 bg = FRAME_FOREGROUND_PIXEL (sf);
916
917 /* Make sure highlighted lines really stand out, come what may. */
abcce93a 918 if (fp->tty_reverse_p && (fg == dflt_fg && bg == dflt_bg))
3b620731
EZ
919 {
920 unsigned long tem = fg;
921
922 fg = bg;
923 bg = tem;
924 }
76648534
EZ
925 /* If the user requested inverse video, obey. */
926 if (inverse_video)
927 {
928 unsigned long tem2 = fg;
929
930 fg = bg;
931 bg = tem2;
932 }
c77f6f1b 933 if (termscript)
abcce93a
MB
934 fprintf (termscript, "<FACE %d: %d/%d[FG:%d/BG:%d]>", face,
935 fp->foreground, fp->background, fg, bg);
c77f6f1b
EZ
936 if (fg >= 0 && fg < 16)
937 {
938 ScreenAttrib &= 0xf0;
939 ScreenAttrib |= fg;
940 }
941 if (bg >= 0 && bg < 16)
942 {
943 ScreenAttrib &= 0x0f;
944 ScreenAttrib |= ((bg & 0x0f) << 4);
945 }
f32d4091
KS
946}
947
aa9ce936
EZ
948Lisp_Object Vdos_unsupported_char_glyph;
949
71f65669 950static void
c77f6f1b 951IT_write_glyphs (struct glyph *str, int str_len)
f32d4091 952{
aa9ce936
EZ
953 unsigned char *screen_buf, *screen_bp, *screen_buf_end, *bp;
954 int unsupported_face = FAST_GLYPH_FACE (Vdos_unsupported_char_glyph);
955 unsigned unsupported_char= FAST_GLYPH_CHAR (Vdos_unsupported_char_glyph);
039274cf 956 int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
aa9ce936
EZ
957 register int sl = str_len;
958 register int tlen = GLYPH_TABLE_LENGTH;
959 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
960
e023fb27
EZ
961 /* If terminal_coding does any conversion, use it, otherwise use
962 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
963 because it always returns 1 if terminal_coding.src_multibyte is 1. */
964 struct coding_system *coding =
965 (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
966 ? &terminal_coding
967 : &safe_terminal_coding);
2d764c78 968 struct frame *sf;
87485d6f 969
52d38ab2
EZ
970 /* Do we need to consider conversion of unibyte characters to
971 multibyte? */
972 int convert_unibyte_characters
e16bf494
AI
973 = (NILP (current_buffer->enable_multibyte_characters)
974 && unibyte_display_via_language_environment);
52d38ab2 975
648648a9
KH
976 unsigned char conversion_buffer[256];
977 int conversion_buffer_size = sizeof conversion_buffer;
978
3b620731 979 if (str_len <= 0) return;
aee81730 980
aa9ce936
EZ
981 screen_buf = screen_bp = alloca (str_len * 2);
982 screen_buf_end = screen_buf + str_len * 2;
2d764c78 983 sf = SELECTED_FRAME();
e30aee93
EZ
984
985 /* Since faces get cached and uncached behind our back, we can't
986 rely on their indices in the cache being consistent across
987 invocations. So always reset the screen face to the default
988 face of the frame, before writing glyphs, and let the glyphs
989 set the right face if it's different from the default. */
990 IT_set_face (DEFAULT_FACE_ID);
aee81730 991
aa9ce936
EZ
992 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
993 the tail. */
994 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
995 while (sl)
996 {
c77f6f1b 997 int cf, chlen, enclen;
3b620731 998 unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *buf;
c77f6f1b 999 unsigned ch;
aa9ce936
EZ
1000
1001 /* Glyphs with GLYPH_MASK_PADDING bit set are actually there
1002 only for the redisplay code to know how many columns does
1003 this character occupy on the screen. Skip padding glyphs. */
c77f6f1b 1004 if (CHAR_GLYPH_PADDING_P (*str))
aa9ce936
EZ
1005 {
1006 str++;
1007 sl--;
1008 }
1009 else
1010 {
04ee4f45
EZ
1011 register GLYPH g = GLYPH_FROM_CHAR_GLYPH (*str);
1012 int glyph_not_in_table = 0;
1013
78555fbe
EZ
1014 /* If g is negative, it means we have a multibyte character
1015 in *str. That's what GLYPH_FROM_CHAR_GLYPH returns for
1016 multibyte characters. */
04ee4f45
EZ
1017 if (g < 0 || g >= tlen)
1018 {
1019 /* This glyph doesn't have an entry in Vglyph_table. */
1020 ch = str->u.ch;
1021 glyph_not_in_table = 1;
1022 }
1023 else
1024 {
1025 /* This glyph has an entry in Vglyph_table, so process
1026 any aliases before testing for simpleness. */
1027 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
1028 ch = FAST_GLYPH_CHAR (g);
1029 }
1030
aa9ce936 1031 /* Convert the character code to multibyte, if they
04ee4f45
EZ
1032 requested display via language environment. We only want
1033 to convert unibyte characters to multibyte in unibyte
1034 buffers! Otherwise, the 8-bit value in CH came from the
1035 display table set up to display foreign characters. */
52d38ab2 1036 if (SINGLE_BYTE_CHAR_P (ch) && convert_unibyte_characters
f0dd4c35
EZ
1037 && (ch >= 0240
1038 || (ch >= 0200 && !NILP (Vnonascii_translation_table))))
aa9ce936
EZ
1039 ch = unibyte_char_to_multibyte (ch);
1040
1041 /* Invalid characters are displayed with a special glyph. */
04ee4f45 1042 if (! CHAR_VALID_P (ch, 0))
aa9ce936
EZ
1043 {
1044 g = !NILP (Vdos_unsupported_char_glyph)
1045 ? Vdos_unsupported_char_glyph
2d764c78 1046 : MAKE_GLYPH (sf, '\177', GLYPH_FACE (sf, g));
aa9ce936
EZ
1047 ch = FAST_GLYPH_CHAR (g);
1048 }
aa9ce936
EZ
1049
1050 /* If the face of this glyph is different from the current
1051 screen face, update the screen attribute byte. */
78555fbe 1052 cf = str->face_id;
aa9ce936
EZ
1053 if (cf != screen_face)
1054 IT_set_face (cf); /* handles invalid faces gracefully */
1055
04ee4f45 1056 if (glyph_not_in_table || GLYPH_SIMPLE_P (tbase, tlen, g))
3b620731
EZ
1057 {
1058 /* We generate the multi-byte form of CH in WORKBUF. */
1059 chlen = CHAR_STRING (ch, workbuf);
1060 buf = workbuf;
1061 }
aa9ce936
EZ
1062 else
1063 {
1064 /* We have a string in Vglyph_table. */
1065 chlen = GLYPH_LENGTH (tbase, g);
1066 buf = GLYPH_STRING (tbase, g);
1067 }
1068
c77f6f1b 1069 /* If the character is not multibyte, don't bother converting it. */
aa9ce936
EZ
1070 if (chlen == 1)
1071 {
1072 *conversion_buffer = (unsigned char)ch;
1073 chlen = 0;
1074 enclen = 1;
1075 }
1076 else
1077 {
55a17202 1078 coding->src_multibyte = 1;
aa9ce936
EZ
1079 encode_coding (coding, buf, conversion_buffer, chlen,
1080 conversion_buffer_size);
1081 chlen -= coding->consumed;
1082 enclen = coding->produced;
1083
1084 /* Replace glyph codes that cannot be converted by
1085 terminal_coding with Vdos_unsupported_char_glyph. */
1086 if (*conversion_buffer == '?')
1087 {
5e30eaa2 1088 unsigned char *cbp = conversion_buffer;
aa9ce936
EZ
1089
1090 while (cbp < conversion_buffer + enclen && *cbp == '?')
1091 *cbp++ = unsupported_char;
1092 if (unsupported_face != screen_face)
1093 IT_set_face (unsupported_face);
1094 }
1095 }
1096
1097 if (enclen + chlen > screen_buf_end - screen_bp)
1098 {
1099 /* The allocated buffer for screen writes is too small.
1100 Flush it and loop again without incrementing STR, so
1101 that the next loop will begin with the same glyph. */
1102 int nbytes = screen_bp - screen_buf;
1103
1104 mouse_off_maybe ();
1105 dosmemput (screen_buf, nbytes, (int)ScreenPrimary + offset);
1106 if (screen_virtual_segment)
1107 dosv_refresh_virtual_screen (offset, nbytes / 2);
1108 new_pos_X += nbytes / 2;
1109 offset += nbytes;
1110
1111 /* Prepare to reuse the same buffer again. */
1112 screen_bp = screen_buf;
1113 }
1114 else
1115 {
1116 /* There's enough place in the allocated buffer to add
1117 the encoding of this glyph. */
1118
1119 /* First, copy the encoded bytes. */
1120 for (bp = conversion_buffer; enclen--; bp++)
1121 {
1122 *screen_bp++ = (unsigned char)*bp;
1123 *screen_bp++ = ScreenAttrib;
1124 if (termscript)
1125 fputc (*bp, termscript);
1126 }
1127
1128 /* Now copy the bytes not consumed by the encoding. */
1129 if (chlen > 0)
1130 {
1131 buf += coding->consumed;
1132 while (chlen--)
1133 {
1134 if (termscript)
1135 fputc (*buf, termscript);
1136 *screen_bp++ = (unsigned char)*buf++;
1137 *screen_bp++ = ScreenAttrib;
1138 }
1139 }
1140
1141 /* Update STR and its remaining length. */
1142 str++;
1143 sl--;
1144 }
1145 }
aee81730
RS
1146 }
1147
aa9ce936 1148 /* Dump whatever is left in the screen buffer. */
f32d4091 1149 mouse_off_maybe ();
aa9ce936 1150 dosmemput (screen_buf, screen_bp - screen_buf, (int)ScreenPrimary + offset);
039274cf 1151 if (screen_virtual_segment)
aa9ce936
EZ
1152 dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2);
1153 new_pos_X += (screen_bp - screen_buf) / 2;
1154
1155 /* We may have to output some codes to terminate the writing. */
1156 if (CODING_REQUIRE_FLUSHING (coding))
1157 {
1158 coding->mode |= CODING_MODE_LAST_BLOCK;
1159 encode_coding (coding, "", conversion_buffer, 0, conversion_buffer_size);
1160 if (coding->produced > 0)
1161 {
241424da 1162 screen_buf = alloca (coding->produced * 2);
aa9ce936
EZ
1163 for (screen_bp = screen_buf, bp = conversion_buffer;
1164 coding->produced--; bp++)
1165 {
1166 *screen_bp++ = (unsigned char)*bp;
1167 *screen_bp++ = ScreenAttrib;
1168 if (termscript)
1169 fputc (*bp, termscript);
1170 }
1171 offset += screen_bp - screen_buf;
1172 mouse_off_maybe ();
1173 dosmemput (screen_buf, screen_bp - screen_buf,
1174 (int)ScreenPrimary + offset);
1175 if (screen_virtual_segment)
1176 dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2);
1177 new_pos_X += (screen_bp - screen_buf) / 2;
1178 }
1179 }
f32d4091 1180}
aee81730 1181
41ad069b
EZ
1182/************************************************************************
1183 Mouse Highlight (and friends..)
1184 ************************************************************************/
1185
48c14970
EZ
1186/* If non-nil, dos_rawgetc generates an event to display that string.
1187 (The display is done in keyboard.c:read_char, by calling
1188 show_help_echo.) */
41ad069b
EZ
1189static Lisp_Object help_echo;
1190static Lisp_Object previous_help_echo; /* a helper temporary variable */
1191
48c14970
EZ
1192/* These record the window, the object and the position where the help
1193 echo string was generated. */
1194static Lisp_Object help_echo_window;
1195static Lisp_Object help_echo_object;
1196static int help_echo_pos;
1197
4a137db1
EZ
1198/* Non-zero means automatically select any window when the mouse
1199 cursor moves into it. */
ee8ceff8 1200int mouse_autoselect_window;
4a137db1 1201
ee8ceff8 1202/* Last window where we saw the mouse. Used by mouse-autoselect-window. */
9005a471
EZ
1203static Lisp_Object last_mouse_window;
1204
41ad069b
EZ
1205static int mouse_preempted = 0; /* non-zero when XMenu gobbles mouse events */
1206
1207/* Set the mouse pointer shape according to whether it is in the
1208 area where the mouse highlight is in effect. */
1209static void
1210IT_set_mouse_pointer (int mode)
1211{
1212 /* A no-op for now. DOS text-mode mouse pointer doesn't offer too
1213 many possibilities to change its shape, and the available
1214 functionality pretty much sucks (e.g., almost every reasonable
1215 shape will conceal the character it is on). Since the color of
1216 the pointer changes in the highlighted area, it is not clear to
1217 me whether anything else is required, anyway. */
1218}
1219
1220/* Display the active region described by mouse_face_*
1221 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1222static void
1223show_mouse_face (struct display_info *dpyinfo, int hl)
1224{
1225 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
1226 struct frame *f = XFRAME (WINDOW_FRAME (w));
1227 int i;
1228 struct face *fp;
1229
1230
1231 /* If window is in the process of being destroyed, don't bother
1232 doing anything. */
1233 if (w->current_matrix == NULL)
1234 goto set_cursor_shape;
1235
1236 /* Recognize when we are called to operate on rows that don't exist
1237 anymore. This can happen when a window is split. */
1238 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
1239 goto set_cursor_shape;
1240
1241 /* There's no sense to do anything if the mouse face isn't realized. */
1242 if (hl > 0)
1243 {
abf10ed7
KS
1244 if (dpyinfo->mouse_face_hidden)
1245 goto set_cursor_shape;
1246
41ad069b
EZ
1247 fp = FACE_FROM_ID (SELECTED_FRAME(), dpyinfo->mouse_face_face_id);
1248 if (!fp)
1249 goto set_cursor_shape;
1250 }
1251
1252 /* Note that mouse_face_beg_row etc. are window relative. */
1253 for (i = dpyinfo->mouse_face_beg_row;
1254 i <= dpyinfo->mouse_face_end_row;
1255 i++)
1256 {
1257 int start_hpos, end_hpos;
1258 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
1259
1260 /* Don't do anything if row doesn't have valid contents. */
1261 if (!row->enabled_p)
1262 continue;
1263
1264 /* For all but the first row, the highlight starts at column 0. */
1265 if (i == dpyinfo->mouse_face_beg_row)
1266 start_hpos = dpyinfo->mouse_face_beg_col;
1267 else
1268 start_hpos = 0;
1269
1270 if (i == dpyinfo->mouse_face_end_row)
1271 end_hpos = dpyinfo->mouse_face_end_col;
1272 else
1273 end_hpos = row->used[TEXT_AREA];
1274
1275 if (end_hpos <= start_hpos)
1276 continue;
48c14970
EZ
1277 /* Record that some glyphs of this row are displayed in
1278 mouse-face. */
1279 row->mouse_face_p = hl > 0;
41ad069b
EZ
1280 if (hl > 0)
1281 {
1282 int vpos = row->y + WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
1283 int kstart = start_hpos + WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
1284 int nglyphs = end_hpos - start_hpos;
1285 int offset = ScreenPrimary + 2*(vpos*screen_size_X + kstart) + 1;
1286 int start_offset = offset;
1287
1288 if (termscript)
1289 fprintf (termscript, "\n<MH+ %d-%d:%d>",
1290 kstart, kstart + nglyphs - 1, vpos);
1291
1292 mouse_off ();
1293 IT_set_face (dpyinfo->mouse_face_face_id);
1294 /* Since we are going to change only the _colors_ of the
1295 displayed text, there's no need to go through all the
1296 pain of generating and encoding the text from the glyphs.
1297 Instead, we simply poke the attribute byte of each
1298 affected position in video memory with the colors
1299 computed by IT_set_face! */
1300 _farsetsel (_dos_ds);
1301 while (nglyphs--)
1302 {
1303 _farnspokeb (offset, ScreenAttrib);
1304 offset += 2;
1305 }
1306 if (screen_virtual_segment)
1307 dosv_refresh_virtual_screen (start_offset, end_hpos - start_hpos);
1308 mouse_on ();
1309 }
1310 else
1311 {
1312 /* We are removing a previously-drawn mouse highlight. The
1313 safest way to do so is to redraw the glyphs anew, since
1314 all kinds of faces and display tables could have changed
1315 behind our back. */
1316 int nglyphs = end_hpos - start_hpos;
1317 int save_x = new_pos_X, save_y = new_pos_Y;
1318
1319 if (end_hpos >= row->used[TEXT_AREA])
1320 nglyphs = row->used[TEXT_AREA] - start_hpos;
1321
1322 /* IT_write_glyphs writes at cursor position, so we need to
1323 temporarily move cursor coordinates to the beginning of
1324 the highlight region. */
1325 new_pos_X = start_hpos + WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
1326 new_pos_Y = row->y + WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
1327
1328 if (termscript)
1329 fprintf (termscript, "<MH- %d-%d:%d>",
1330 new_pos_X, new_pos_X + nglyphs - 1, new_pos_Y);
1331 IT_write_glyphs (row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
1332 if (termscript)
1333 fputs ("\n", termscript);
1334 new_pos_X = save_x;
1335 new_pos_Y = save_y;
1336 }
1337 }
1338
1339 set_cursor_shape:
1340
1341 /* Change the mouse pointer shape. */
1342 IT_set_mouse_pointer (hl);
1343}
1344
1345/* Clear out the mouse-highlighted active region.
1346 Redraw it un-highlighted first. */
1347static void
1348clear_mouse_face (struct display_info *dpyinfo)
1349{
1350 if (! NILP (dpyinfo->mouse_face_window))
1351 show_mouse_face (dpyinfo, 0);
1352
1353 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1354 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1355 dpyinfo->mouse_face_window = Qnil;
1356}
1357
1358/* Find the glyph matrix position of buffer position POS in window W.
1359 *HPOS and *VPOS are set to the positions found. W's current glyphs
1360 must be up to date. If POS is above window start return (0, 0).
1361 If POS is after end of W, return end of last line in W. */
1362static int
1363fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
1364{
1365 int i;
1366 int lastcol;
1367 int maybe_next_line_p = 0;
1368 int line_start_position;
1369 int yb = window_text_bottom_y (w);
1370 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
1371 struct glyph_row *best_row = row;
1372
1373 while (row->y < yb)
1374 {
1375 if (row->used[TEXT_AREA])
1376 line_start_position = row->glyphs[TEXT_AREA]->charpos;
1377 else
1378 line_start_position = 0;
1379
1380 if (line_start_position > pos)
1381 break;
1382 /* If the position sought is the end of the buffer,
1383 don't include the blank lines at the bottom of the window. */
1384 else if (line_start_position == pos
1385 && pos == BUF_ZV (XBUFFER (w->buffer)))
1386 {
1387 maybe_next_line_p = 1;
1388 break;
1389 }
1390 else if (line_start_position > 0)
1391 best_row = row;
440ffd67
EZ
1392
1393 /* Don't overstep the last matrix row, lest we get into the
1394 never-never land... */
1395 if (row->y + 1 >= yb)
1396 break;
41ad069b
EZ
1397
1398 ++row;
1399 }
1400
1401 /* Find the right column within BEST_ROW. */
1402 lastcol = 0;
1403 row = best_row;
1404 for (i = 0; i < row->used[TEXT_AREA]; i++)
1405 {
1406 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
1407 int charpos;
1408
1409 charpos = glyph->charpos;
1410 if (charpos == pos)
1411 {
1412 *hpos = i;
1413 *vpos = row->y;
1414 return 1;
1415 }
1416 else if (charpos > pos)
1417 break;
1418 else if (charpos > 0)
1419 lastcol = i;
1420 }
1421
1422 /* If we're looking for the end of the buffer,
1423 and we didn't find it in the line we scanned,
1424 use the start of the following line. */
1425 if (maybe_next_line_p)
1426 {
1427 ++row;
1428 lastcol = 0;
1429 }
1430
1431 *vpos = row->y;
1432 *hpos = lastcol + 1;
1433 return 0;
1434}
1435
1436/* Take proper action when mouse has moved to the mode or top line of
1437 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
1438 mode line. X is relative to the start of the text display area of
377df9e2 1439 W, so the width of fringes and scroll bars must be subtracted
41ad069b
EZ
1440 to get a position relative to the start of the mode line. */
1441static void
1442IT_note_mode_line_highlight (struct window *w, int x, int mode_line_p)
1443{
1444 struct frame *f = XFRAME (w->frame);
1445 struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1446 struct glyph_row *row;
1447
1448 if (mode_line_p)
1449 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
1450 else
1451 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1452
1453 if (row->enabled_p)
1454 {
1455 extern Lisp_Object Qhelp_echo;
1456 struct glyph *glyph, *end;
1457 Lisp_Object help, map;
1458
1459 /* Find the glyph under X. */
1460 glyph = row->glyphs[TEXT_AREA]
1461 + x - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
1462 end = glyph + row->used[TEXT_AREA];
1463 if (glyph < end
1464 && STRINGP (glyph->object)
1465 && XSTRING (glyph->object)->intervals
1466 && glyph->charpos >= 0
1467 && glyph->charpos < XSTRING (glyph->object)->size)
1468 {
1469 /* If we're on a string with `help-echo' text property,
1470 arrange for the help to be displayed. This is done by
1471 setting the global variable help_echo to the help string. */
1472 help = Fget_text_property (make_number (glyph->charpos),
1473 Qhelp_echo, glyph->object);
b7e80413 1474 if (!NILP (help))
48c14970
EZ
1475 {
1476 help_echo = help;
1477 XSETWINDOW (help_echo_window, w);
1478 help_echo_object = glyph->object;
1479 help_echo_pos = glyph->charpos;
1480 }
41ad069b
EZ
1481 }
1482 }
1483}
1484
1485/* Take proper action when the mouse has moved to position X, Y on
1486 frame F as regards highlighting characters that have mouse-face
1487 properties. Also de-highlighting chars where the mouse was before.
1488 X and Y can be negative or out of range. */
1489static void
1490IT_note_mouse_highlight (struct frame *f, int x, int y)
1491{
1492 struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
440ffd67 1493 int portion = -1;
41ad069b
EZ
1494 Lisp_Object window;
1495 struct window *w;
1496
1497 /* When a menu is active, don't highlight because this looks odd. */
1498 if (mouse_preempted)
1499 return;
1500
abf10ed7 1501 if (NILP (Vmouse_highlight)
515d0d0e 1502 || !f->glyphs_initialized_p)
41ad069b
EZ
1503 return;
1504
1505 dpyinfo->mouse_face_mouse_x = x;
1506 dpyinfo->mouse_face_mouse_y = y;
1507 dpyinfo->mouse_face_mouse_frame = f;
1508
1509 if (dpyinfo->mouse_face_defer)
1510 return;
1511
1512 if (gc_in_progress)
1513 {
1514 dpyinfo->mouse_face_deferred_gc = 1;
1515 return;
1516 }
1517
1518 /* Which window is that in? */
1519 window = window_from_coordinates (f, x, y, &portion, 0);
1520
1521 /* If we were displaying active text in another window, clear that. */
1522 if (! EQ (window, dpyinfo->mouse_face_window))
1523 clear_mouse_face (dpyinfo);
1524
1525 /* Not on a window -> return. */
1526 if (!WINDOWP (window))
1527 return;
1528
1529 /* Convert to window-relative coordinates. */
1530 w = XWINDOW (window);
1531 x -= WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
1532 y -= WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
1533
1534 if (portion == 1 || portion == 3)
1535 {
1536 /* Mouse is on the mode or top line. */
1537 IT_note_mode_line_highlight (w, x, portion == 1);
1538 return;
1539 }
1540 else
1541 IT_set_mouse_pointer (0);
1542
1543 /* Are we in a window whose display is up to date?
1544 And verify the buffer's text has not changed. */
1545 if (/* Within text portion of the window. */
1546 portion == 0
1547 && EQ (w->window_end_valid, w->buffer)
1548 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
1549 && (XFASTINT (w->last_overlay_modified)
1550 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
1551 {
440ffd67 1552 int pos, i;
41ad069b
EZ
1553 struct glyph_row *row;
1554 struct glyph *glyph;
440ffd67 1555 int nrows = w->current_matrix->nrows;
41ad069b
EZ
1556
1557 /* Find the glyph under X/Y. */
1558 glyph = NULL;
440ffd67 1559 if (y >= 0 && y < nrows)
41ad069b
EZ
1560 {
1561 row = MATRIX_ROW (w->current_matrix, y);
440ffd67
EZ
1562 /* Give up if some row before the one we are looking for is
1563 not enabled. */
1564 for (i = 0; i <= y; i++)
1565 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
1566 break;
1567 if (i > y /* all rows upto and including the one at Y are enabled */
41ad069b
EZ
1568 && row->displays_text_p
1569 && x < window_box_width (w, TEXT_AREA))
1570 {
1571 glyph = row->glyphs[TEXT_AREA];
1572 if (x >= row->used[TEXT_AREA])
1573 glyph = NULL;
1574 else
1575 {
1576 glyph += x;
1577 if (!BUFFERP (glyph->object))
1578 glyph = NULL;
1579 }
1580 }
1581 }
1582
1583 /* Clear mouse face if X/Y not over text. */
1584 if (glyph == NULL)
1585 {
1586 clear_mouse_face (dpyinfo);
1587 return;
1588 }
1589
1590 if (!BUFFERP (glyph->object))
1591 abort ();
1592 pos = glyph->charpos;
1593
1594 /* Check for mouse-face and help-echo. */
1595 {
1596 extern Lisp_Object Qmouse_face;
1597 Lisp_Object mouse_face, overlay, position;
1598 Lisp_Object *overlay_vec;
1599 int len, noverlays;
1600 struct buffer *obuf;
1601 int obegv, ozv;
1602
1603 /* If we get an out-of-range value, return now; avoid an error. */
1604 if (pos > BUF_Z (XBUFFER (w->buffer)))
1605 return;
1606
1607 /* Make the window's buffer temporarily current for
1608 overlays_at and compute_char_face. */
1609 obuf = current_buffer;
1610 current_buffer = XBUFFER (w->buffer);
1611 obegv = BEGV;
1612 ozv = ZV;
1613 BEGV = BEG;
1614 ZV = Z;
1615
1616 /* Is this char mouse-active or does it have help-echo? */
1617 XSETINT (position, pos);
1618
1619 /* Put all the overlays we want in a vector in overlay_vec.
1620 Store the length in len. If there are more than 10, make
1621 enough space for all, and try again. */
1622 len = 10;
1623 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
99cd7364 1624 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
41ad069b
EZ
1625 if (noverlays > len)
1626 {
1627 len = noverlays;
1628 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
99cd7364
EZ
1629 noverlays = overlays_at (pos,
1630 0, &overlay_vec, &len, NULL, NULL, 0);
41ad069b
EZ
1631 }
1632
f0a4139c 1633 /* Sort overlays into increasing priority order. */
41ad069b
EZ
1634 noverlays = sort_overlays (overlay_vec, noverlays, w);
1635
1636 /* Check mouse-face highlighting. */
1637 if (! (EQ (window, dpyinfo->mouse_face_window)
1638 && y >= dpyinfo->mouse_face_beg_row
1639 && y <= dpyinfo->mouse_face_end_row
1640 && (y > dpyinfo->mouse_face_beg_row
1641 || x >= dpyinfo->mouse_face_beg_col)
1642 && (y < dpyinfo->mouse_face_end_row
1643 || x < dpyinfo->mouse_face_end_col
1644 || dpyinfo->mouse_face_past_end)))
1645 {
1646 /* Clear the display of the old active region, if any. */
1647 clear_mouse_face (dpyinfo);
1648
1649 /* Find highest priority overlay that has a mouse-face prop. */
1650 overlay = Qnil;
f0a4139c 1651 for (i = noverlays - 1; i >= 0; --i)
41ad069b
EZ
1652 {
1653 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
1654 if (!NILP (mouse_face))
1655 {
1656 overlay = overlay_vec[i];
1657 break;
1658 }
1659 }
1660
1661 /* If no overlay applies, get a text property. */
1662 if (NILP (overlay))
1663 mouse_face = Fget_text_property (position, Qmouse_face,
1664 w->buffer);
1665
1666 /* Handle the overlay case. */
1667 if (! NILP (overlay))
1668 {
1669 /* Find the range of text around this char that
1670 should be active. */
1671 Lisp_Object before, after;
1672 int ignore;
1673
1674 before = Foverlay_start (overlay);
1675 after = Foverlay_end (overlay);
1676 /* Record this as the current active region. */
1677 fast_find_position (w, XFASTINT (before),
1678 &dpyinfo->mouse_face_beg_col,
1679 &dpyinfo->mouse_face_beg_row);
1680 dpyinfo->mouse_face_past_end
1681 = !fast_find_position (w, XFASTINT (after),
1682 &dpyinfo->mouse_face_end_col,
1683 &dpyinfo->mouse_face_end_row);
1684 dpyinfo->mouse_face_window = window;
1685 dpyinfo->mouse_face_face_id
1686 = face_at_buffer_position (w, pos, 0, 0,
1687 &ignore, pos + 1, 1);
1688
1689 /* Display it as active. */
1690 show_mouse_face (dpyinfo, 1);
1691 }
1692 /* Handle the text property case. */
1693 else if (! NILP (mouse_face))
1694 {
1695 /* Find the range of text around this char that
1696 should be active. */
1697 Lisp_Object before, after, beginning, end;
1698 int ignore;
1699
1700 beginning = Fmarker_position (w->start);
1701 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
1702 - XFASTINT (w->window_end_pos)));
1703 before
1704 = Fprevious_single_property_change (make_number (pos + 1),
1705 Qmouse_face,
1706 w->buffer, beginning);
1707 after
1708 = Fnext_single_property_change (position, Qmouse_face,
1709 w->buffer, end);
1710 /* Record this as the current active region. */
1711 fast_find_position (w, XFASTINT (before),
1712 &dpyinfo->mouse_face_beg_col,
1713 &dpyinfo->mouse_face_beg_row);
1714 dpyinfo->mouse_face_past_end
1715 = !fast_find_position (w, XFASTINT (after),
1716 &dpyinfo->mouse_face_end_col,
1717 &dpyinfo->mouse_face_end_row);
1718 dpyinfo->mouse_face_window = window;
1719 dpyinfo->mouse_face_face_id
1720 = face_at_buffer_position (w, pos, 0, 0,
1721 &ignore, pos + 1, 1);
1722
1723 /* Display it as active. */
1724 show_mouse_face (dpyinfo, 1);
1725 }
1726 }
1727
1728 /* Look for a `help-echo' property. */
1729 {
1730 Lisp_Object help;
1731 extern Lisp_Object Qhelp_echo;
1732
1733 /* Check overlays first. */
1734 help = Qnil;
f0a4139c
EZ
1735 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
1736 {
1737 overlay = overlay_vec[i];
1738 help = Foverlay_get (overlay, Qhelp_echo);
1739 }
41ad069b 1740
b7e80413 1741 if (!NILP (help))
48c14970
EZ
1742 {
1743 help_echo = help;
1744 help_echo_window = window;
f0a4139c 1745 help_echo_object = overlay;
48c14970
EZ
1746 help_echo_pos = pos;
1747 }
1748 /* Try text properties. */
1749 else if (NILP (help)
1750 && ((STRINGP (glyph->object)
1751 && glyph->charpos >= 0
1752 && glyph->charpos < XSTRING (glyph->object)->size)
1753 || (BUFFERP (glyph->object)
1754 && glyph->charpos >= BEGV
1755 && glyph->charpos < ZV)))
1756 {
1757 help = Fget_text_property (make_number (glyph->charpos),
1758 Qhelp_echo, glyph->object);
1759 if (!NILP (help))
1760 {
1761 help_echo = help;
1762 help_echo_window = window;
1763 help_echo_object = glyph->object;
1764 help_echo_pos = glyph->charpos;
1765 }
1766 }
41ad069b
EZ
1767 }
1768
1769 BEGV = obegv;
1770 ZV = ozv;
1771 current_buffer = obuf;
1772 }
1773 }
1774}
1775
71f65669
EZ
1776static void
1777IT_clear_end_of_line (int first_unused)
f32d4091
KS
1778{
1779 char *spaces, *sp;
1780 int i, j;
039274cf 1781 int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
aa9ce936
EZ
1782 extern int fatal_error_in_progress;
1783
2d764c78 1784 if (new_pos_X >= first_unused || fatal_error_in_progress)
aa9ce936 1785 return;
f32d4091
KS
1786
1787 IT_set_face (0);
2d764c78 1788 i = (j = first_unused - new_pos_X) * 2;
e25d9653
EZ
1789 if (termscript)
1790 fprintf (termscript, "<CLR:EOL[%d..%d)>", new_pos_X, first_unused);
f32d4091 1791 spaces = sp = alloca (i);
aee81730 1792
f32d4091 1793 while (--j >= 0)
aee81730 1794 {
f32d4091
KS
1795 *sp++ = ' ';
1796 *sp++ = ScreenAttrib;
aee81730
RS
1797 }
1798
f32d4091 1799 mouse_off_maybe ();
039274cf
EZ
1800 dosmemput (spaces, i, (int)ScreenPrimary + offset);
1801 if (screen_virtual_segment)
1802 dosv_refresh_virtual_screen (offset, i / 2);
2d764c78
EZ
1803
1804 /* clear_end_of_line_raw on term.c leaves the cursor at first_unused.
1805 Let's follow their lead, in case someone relies on this. */
1806 new_pos_X = first_unused;
aee81730
RS
1807}
1808
71f65669 1809static void
f32d4091
KS
1810IT_clear_screen (void)
1811{
1812 if (termscript)
1813 fprintf (termscript, "<CLR:SCR>");
deece6f5
EZ
1814 /* We are sometimes called (from clear_garbaged_frames) when a new
1815 frame is being created, but its faces are not yet realized. In
1816 such a case we cannot call IT_set_face, since it will fail to find
1817 any valid faces and will abort. Instead, use the initial screen
1818 colors; that should mimic what a Unix tty does, which simply clears
1819 the screen with whatever default colors are in use. */
1820 if (FACE_FROM_ID (SELECTED_FRAME (), DEFAULT_FACE_ID) == NULL)
1821 ScreenAttrib = (initial_screen_colors[0] << 4) | initial_screen_colors[1];
1822 else
1823 IT_set_face (0);
f32d4091
KS
1824 mouse_off ();
1825 ScreenClear ();
039274cf
EZ
1826 if (screen_virtual_segment)
1827 dosv_refresh_virtual_screen (0, screen_size);
f32d4091
KS
1828 new_pos_X = new_pos_Y = 0;
1829}
1830
71f65669 1831static void
f32d4091
KS
1832IT_clear_to_end (void)
1833{
1834 if (termscript)
1835 fprintf (termscript, "<CLR:EOS>");
1836
1837 while (new_pos_Y < screen_size_Y) {
1838 new_pos_X = 0;
e25d9653 1839 IT_clear_end_of_line (screen_size_X);
f32d4091
KS
1840 new_pos_Y++;
1841 }
1842}
1843
71f65669 1844static void
f32d4091
KS
1845IT_cursor_to (int y, int x)
1846{
1847 if (termscript)
1848 fprintf (termscript, "\n<XY=%dx%d>", x, y);
1849 new_pos_X = x;
1850 new_pos_Y = y;
1851}
1852
fc171623
KH
1853static int cursor_cleared;
1854
d1d5dc19 1855static void
fc171623
KH
1856IT_display_cursor (int on)
1857{
1858 if (on && cursor_cleared)
1859 {
1860 ScreenSetCursor (current_pos_Y, current_pos_X);
1861 cursor_cleared = 0;
1862 }
1863 else if (!on && !cursor_cleared)
1864 {
1865 ScreenSetCursor (-1, -1);
1866 cursor_cleared = 1;
1867 }
1868}
1869
1870/* Emacs calls cursor-movement functions a lot when it updates the
1871 display (probably a legacy of old terminals where you cannot
1872 update a screen line without first moving the cursor there).
1873 However, cursor movement is expensive on MSDOS (it calls a slow
1874 BIOS function and requires 2 mode switches), while actual screen
1875 updates access the video memory directly and don't depend on
1876 cursor position. To avoid slowing down the redisplay, we cheat:
1877 all functions that move the cursor only set internal variables
1878 which record the cursor position, whereas the cursor is only
1879 moved to its final position whenever screen update is complete.
1880
1881 `IT_cmgoto' is called from the keyboard reading loop and when the
1882 frame update is complete. This means that we are ready for user
1883 input, so we update the cursor position to show where the point is,
1884 and also make the mouse pointer visible.
1885
1886 Special treatment is required when the cursor is in the echo area,
1887 to put the cursor at the end of the text displayed there. */
1888
71f65669
EZ
1889static void
1890IT_cmgoto (FRAME_PTR f)
fc171623
KH
1891{
1892 /* Only set the cursor to where it should be if the display is
1893 already in sync with the window contents. */
2d764c78
EZ
1894 int update_cursor_pos = 1; /* MODIFF == unchanged_modified; */
1895
1896 /* FIXME: This needs to be rewritten for the new redisplay, or
1897 removed. */
1898#if 0
06da1de1
EZ
1899 static int previous_pos_X = -1;
1900
2d764c78
EZ
1901 update_cursor_pos = 1; /* temporary!!! */
1902
06da1de1
EZ
1903 /* If the display is in sync, forget any previous knowledge about
1904 cursor position. This is primarily for unexpected events like
1905 C-g in the minibuffer. */
1906 if (update_cursor_pos && previous_pos_X >= 0)
1907 previous_pos_X = -1;
1908 /* If we are in the echo area, put the cursor at the
1909 end of the echo area message. */
fc171623
KH
1910 if (!update_cursor_pos
1911 && XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top) <= new_pos_Y)
1912 {
06da1de1
EZ
1913 int tem_X = current_pos_X, dummy;
1914
1915 if (echo_area_glyphs)
1916 {
1917 tem_X = echo_area_glyphs_length;
1918 /* Save current cursor position, to be restored after the
1919 echo area message is erased. Only remember one level
1920 of previous cursor position. */
1921 if (previous_pos_X == -1)
1922 ScreenGetCursor (&dummy, &previous_pos_X);
1923 }
1924 else if (previous_pos_X >= 0)
1925 {
1926 /* We wind up here after the echo area message is erased.
1927 Restore the cursor position we remembered above. */
1928 tem_X = previous_pos_X;
1929 previous_pos_X = -1;
1930 }
9a599a60 1931
06da1de1 1932 if (current_pos_X != tem_X)
9a599a60
EZ
1933 {
1934 new_pos_X = tem_X;
1935 update_cursor_pos = 1;
1936 }
fc171623 1937 }
2d764c78 1938#endif
fc171623
KH
1939
1940 if (update_cursor_pos
1941 && (current_pos_X != new_pos_X || current_pos_Y != new_pos_Y))
1942 {
1943 ScreenSetCursor (current_pos_Y = new_pos_Y, current_pos_X = new_pos_X);
1944 if (termscript)
1945 fprintf (termscript, "\n<CURSOR:%dx%d>", current_pos_X, current_pos_Y);
1946 }
1947
1948 /* Maybe cursor is invisible, so make it visible. */
1949 IT_display_cursor (1);
1950
1951 /* Mouse pointer should be always visible if we are waiting for
1952 keyboard input. */
1953 if (!mouse_visible)
1954 mouse_on ();
1955}
1956
71f65669 1957static void
41ad069b 1958IT_update_begin (struct frame *f)
f32d4091 1959{
41ad069b 1960 struct display_info *display_info = FRAME_X_DISPLAY_INFO (f);
b9f80d41 1961 struct frame *mouse_face_frame = display_info->mouse_face_mouse_frame;
41ad069b
EZ
1962
1963 BLOCK_INPUT;
1964
b9f80d41 1965 if (f && f == mouse_face_frame)
41ad069b
EZ
1966 {
1967 /* Don't do highlighting for mouse motion during the update. */
1968 display_info->mouse_face_defer = 1;
1969
1970 /* If F needs to be redrawn, simply forget about any prior mouse
1971 highlighting. */
1972 if (FRAME_GARBAGED_P (f))
1973 display_info->mouse_face_window = Qnil;
1974
1975 /* Can we tell that this update does not affect the window
1976 where the mouse highlight is? If so, no need to turn off.
48c14970
EZ
1977 Likewise, don't do anything if none of the enabled rows
1978 contains glyphs highlighted in mouse face. */
8ccb9a54
EZ
1979 if (!NILP (display_info->mouse_face_window)
1980 && WINDOWP (display_info->mouse_face_window))
41ad069b
EZ
1981 {
1982 struct window *w = XWINDOW (display_info->mouse_face_window);
1983 int i;
1984
8ccb9a54
EZ
1985 /* If the mouse highlight is in the window that was deleted
1986 (e.g., if it was popped by completion), clear highlight
1987 unconditionally. */
1988 if (NILP (w->buffer))
1989 display_info->mouse_face_window = Qnil;
1990 else
1991 {
1992 for (i = 0; i < w->desired_matrix->nrows; ++i)
48c14970
EZ
1993 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i)
1994 && MATRIX_ROW (w->current_matrix, i)->mouse_face_p)
8ccb9a54
EZ
1995 break;
1996 }
41ad069b 1997
8ccb9a54 1998 if (NILP (w->buffer) || i < w->desired_matrix->nrows)
41ad069b
EZ
1999 clear_mouse_face (display_info);
2000 }
2001 }
b9f80d41 2002 else if (mouse_face_frame && !FRAME_LIVE_P (mouse_face_frame))
41ad069b
EZ
2003 {
2004 /* If the frame with mouse highlight was deleted, invalidate the
2005 highlight info. */
2006 display_info->mouse_face_beg_row = display_info->mouse_face_beg_col = -1;
2007 display_info->mouse_face_end_row = display_info->mouse_face_end_col = -1;
2008 display_info->mouse_face_window = Qnil;
2009 display_info->mouse_face_deferred_gc = 0;
2010 display_info->mouse_face_mouse_frame = NULL;
2011 }
2012
2013 UNBLOCK_INPUT;
f32d4091
KS
2014}
2015
71f65669 2016static void
41ad069b 2017IT_update_end (struct frame *f)
f32d4091 2018{
41ad069b
EZ
2019 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
2020}
2021
8ba01a32
EZ
2022Lisp_Object Qcursor_type;
2023
41ad069b
EZ
2024static void
2025IT_frame_up_to_date (struct frame *f)
2026{
2027 struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
0c3cfc51
EZ
2028 Lisp_Object new_cursor, frame_desired_cursor;
2029 struct window *sw;
41ad069b
EZ
2030
2031 if (dpyinfo->mouse_face_deferred_gc
b9f80d41 2032 || (f && f == dpyinfo->mouse_face_mouse_frame))
41ad069b
EZ
2033 {
2034 BLOCK_INPUT;
2035 if (dpyinfo->mouse_face_mouse_frame)
2036 IT_note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
2037 dpyinfo->mouse_face_mouse_x,
2038 dpyinfo->mouse_face_mouse_y);
2039 dpyinfo->mouse_face_deferred_gc = 0;
2040 UNBLOCK_INPUT;
2041 }
2042
0c3cfc51
EZ
2043 /* Set the cursor type to whatever they wanted. In a minibuffer
2044 window, we want the cursor to appear only if we are reading input
2045 from this window, and we want the cursor to be taken from the
2046 frame parameters. For the selected window, we use either its
2047 buffer-local value or the value from the frame parameters if the
2048 buffer doesn't define its local value for the cursor type. */
2049 sw = XWINDOW (f->selected_window);
2050 frame_desired_cursor = Fcdr (Fassq (Qcursor_type, f->param_alist));
2051 if (cursor_in_echo_area
2052 && FRAME_HAS_MINIBUF_P (f)
2053 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window)
2054 && sw == XWINDOW (echo_area_window))
2055 new_cursor = frame_desired_cursor;
2056 else
2057 {
2058 struct buffer *b = XBUFFER (sw->buffer);
2059
2060 if (EQ (b->cursor_type, Qt))
2061 new_cursor = frame_desired_cursor;
2062 else if (NILP (b->cursor_type)) /* nil means no cursor */
2063 new_cursor = Fcons (Qbar, make_number (0));
2064 else
2065 new_cursor = b->cursor_type;
2066 }
2067
2068 IT_set_cursor_type (f, new_cursor);
8ba01a32 2069
41ad069b 2070 IT_cmgoto (f); /* position cursor when update is done */
f32d4091 2071}
1b94449f 2072
c77f6f1b
EZ
2073/* Copy LEN glyphs displayed on a single line whose vertical position
2074 is YPOS, beginning at horizontal position XFROM to horizontal
2075 position XTO, by moving blocks in the video memory. Used by
2076 functions that insert and delete glyphs. */
2077static void
2078IT_copy_glyphs (int xfrom, int xto, size_t len, int ypos)
2079{
2080 /* The offsets of source and destination relative to the
2081 conventional memorty selector. */
2082 int from = 2 * (xfrom + screen_size_X * ypos) + ScreenPrimary;
2083 int to = 2 * (xto + screen_size_X * ypos) + ScreenPrimary;
2084
2085 if (from == to || len <= 0)
2086 return;
2087
2088 _farsetsel (_dos_ds);
2089
2090 /* The source and destination might overlap, so we need to move
2091 glyphs non-destructively. */
2092 if (from > to)
2093 {
2094 for ( ; len; from += 2, to += 2, len--)
2095 _farnspokew (to, _farnspeekw (from));
2096 }
2097 else
2098 {
2099 from += (len - 1) * 2;
2100 to += (len - 1) * 2;
2101 for ( ; len; from -= 2, to -= 2, len--)
2102 _farnspokew (to, _farnspeekw (from));
2103 }
2104 if (screen_virtual_segment)
2105 dosv_refresh_virtual_screen (ypos * screen_size_X * 2, screen_size_X);
2106}
2107
2108/* Insert and delete glyphs. */
aa9ce936
EZ
2109static void
2110IT_insert_glyphs (start, len)
c77f6f1b 2111 register struct glyph *start;
aa9ce936
EZ
2112 register int len;
2113{
c77f6f1b
EZ
2114 int shift_by_width = screen_size_X - (new_pos_X + len);
2115
2116 /* Shift right the glyphs from the nominal cursor position to the
2117 end of this line. */
2118 IT_copy_glyphs (new_pos_X, new_pos_X + len, shift_by_width, new_pos_Y);
2119
2120 /* Now write the glyphs to be inserted. */
2121 IT_write_glyphs (start, len);
aa9ce936
EZ
2122}
2123
2124static void
2125IT_delete_glyphs (n)
2126 register int n;
2127{
2128 abort ();
2129}
2130
211c7152 2131/* set-window-configuration on window.c needs this. */
3bb1f22f
RS
2132void
2133x_set_menu_bar_lines (f, value, oldval)
2134 struct frame *f;
2135 Lisp_Object value, oldval;
2136{
211c7152
EZ
2137 set_menu_bar_lines (f, value, oldval);
2138}
3bb1f22f 2139
984f5aaa 2140/* This was copied from xfaces.c */
3bb1f22f 2141
984f5aaa
EZ
2142extern Lisp_Object Qbackground_color;
2143extern Lisp_Object Qforeground_color;
8ba01a32 2144Lisp_Object Qreverse;
211c7152 2145extern Lisp_Object Qtitle;
3bb1f22f 2146
48ffe371
RS
2147/* IT_set_terminal_modes is called when emacs is started,
2148 resumed, and whenever the screen is redrawn! */
f32d4091 2149
71f65669 2150static void
f32d4091
KS
2151IT_set_terminal_modes (void)
2152{
aee81730 2153 if (termscript)
f32d4091 2154 fprintf (termscript, "\n<SET_TERM>");
f32d4091
KS
2155
2156 screen_size_X = ScreenCols ();
2157 screen_size_Y = ScreenRows ();
2158 screen_size = screen_size_X * screen_size_Y;
aee81730 2159
f32d4091
KS
2160 new_pos_X = new_pos_Y = 0;
2161 current_pos_X = current_pos_Y = -1;
2162
2163 if (term_setup_done)
2164 return;
2165 term_setup_done = 1;
aee81730 2166
f32d4091
KS
2167 startup_screen_size_X = screen_size_X;
2168 startup_screen_size_Y = screen_size_Y;
c9adab25 2169 startup_screen_attrib = ScreenAttrib;
f32d4091 2170
039274cf
EZ
2171#if __DJGPP__ > 1
2172 /* Is DOS/V (or any other RSIS software which relocates
2173 the screen) installed? */
2174 {
2175 unsigned short es_value;
2176 __dpmi_regs regs;
2177
2178 regs.h.ah = 0xfe; /* get relocated screen address */
2179 if (ScreenPrimary == 0xb0000UL || ScreenPrimary == 0xb8000UL)
2180 regs.x.es = (ScreenPrimary >> 4) & 0xffff;
2181 else if (screen_old_address) /* already switched to Japanese mode once */
2182 regs.x.es = (screen_old_address >> 4) & 0xffff;
2183 else
2184 regs.x.es = ScreenMode () == 7 ? 0xb000 : 0xb800;
2185 regs.x.di = 0;
2186 es_value = regs.x.es;
2187 __dpmi_int (0x10, &regs);
2188
d1d5dc19 2189 if (regs.x.es != es_value)
039274cf 2190 {
d1d5dc19
EZ
2191 /* screen_old_address is only set if ScreenPrimary does NOT
2192 already point to the relocated buffer address returned by
2193 the Int 10h/AX=FEh call above. DJGPP v2.02 and later sets
2194 ScreenPrimary to that address at startup under DOS/V. */
2195 if (regs.x.es != (ScreenPrimary >> 4) & 0xffff)
2196 screen_old_address = ScreenPrimary;
039274cf
EZ
2197 screen_virtual_segment = regs.x.es;
2198 screen_virtual_offset = regs.x.di;
2199 ScreenPrimary = (screen_virtual_segment << 4) + screen_virtual_offset;
2200 }
2201 }
2202#endif /* __DJGPP__ > 1 */
2203
f32d4091
KS
2204 ScreenGetCursor (&startup_pos_Y, &startup_pos_X);
2205 ScreenRetrieve (startup_screen_buffer = xmalloc (screen_size * 2));
2206
2207 if (termscript)
c9adab25 2208 fprintf (termscript, "<SCREEN SAVED (dimensions=%dx%d)>\n",
039274cf 2209 screen_size_X, screen_size_Y);
76ac1508
RS
2210
2211 bright_bg ();
f32d4091
KS
2212}
2213
48ffe371
RS
2214/* IT_reset_terminal_modes is called when emacs is
2215 suspended or killed. */
f32d4091 2216
71f65669 2217static void
f32d4091
KS
2218IT_reset_terminal_modes (void)
2219{
c9adab25
KH
2220 int display_row_start = (int) ScreenPrimary;
2221 int saved_row_len = startup_screen_size_X * 2;
2222 int update_row_len = ScreenCols () * 2;
2223 int current_rows = ScreenRows ();
2224 int to_next_row = update_row_len;
2225 unsigned char *saved_row = startup_screen_buffer;
2226 int cursor_pos_X = ScreenCols () - 1;
2227 int cursor_pos_Y = ScreenRows () - 1;
2228
f32d4091 2229 if (termscript)
5063b150 2230 fprintf (termscript, "\n<RESET_TERM>");
f32d4091 2231
f32d4091
KS
2232 if (!term_setup_done)
2233 return;
2234
c9adab25 2235 mouse_off ();
b36701cc
RS
2236
2237 /* Leave the video system in the same state as we found it,
2238 as far as the blink/bright-background bit is concerned. */
2239 maybe_enable_blinking ();
06b1ea13 2240
c9adab25
KH
2241 /* We have a situation here.
2242 We cannot just do ScreenUpdate(startup_screen_buffer) because
2243 the luser could have changed screen dimensions inside Emacs
2244 and failed (or didn't want) to restore them before killing
2245 Emacs. ScreenUpdate() uses the *current* screen dimensions and
2246 thus will happily use memory outside what was allocated for
2247 `startup_screen_buffer'.
2248 Thus we only restore as much as the current screen dimensions
2249 can hold, and clear the rest (if the saved screen is smaller than
2250 the current) with the color attribute saved at startup. The cursor
2251 is also restored within the visible dimensions. */
2252
2253 ScreenAttrib = startup_screen_attrib;
c9adab25 2254
06b1ea13
EZ
2255 /* Don't restore the screen if we are exiting less than 2 seconds
2256 after startup: we might be crashing, and the screen might show
2257 some vital clues to what's wrong. */
2258 if (clock () - startup_time >= 2*CLOCKS_PER_SEC)
c9adab25 2259 {
06b1ea13 2260 ScreenClear ();
039274cf 2261 if (screen_virtual_segment)
06b1ea13
EZ
2262 dosv_refresh_virtual_screen (0, screen_size);
2263
2264 if (update_row_len > saved_row_len)
2265 update_row_len = saved_row_len;
2266 if (current_rows > startup_screen_size_Y)
2267 current_rows = startup_screen_size_Y;
2268
2269 if (termscript)
2270 fprintf (termscript, "<SCREEN RESTORED (dimensions=%dx%d)>\n",
2271 update_row_len / 2, current_rows);
2272
2273 while (current_rows--)
2274 {
2275 dosmemput (saved_row, update_row_len, display_row_start);
2276 if (screen_virtual_segment)
2277 dosv_refresh_virtual_screen (display_row_start - ScreenPrimary,
2278 update_row_len / 2);
2279 saved_row += saved_row_len;
2280 display_row_start += to_next_row;
2281 }
c9adab25
KH
2282 }
2283 if (startup_pos_X < cursor_pos_X)
2284 cursor_pos_X = startup_pos_X;
2285 if (startup_pos_Y < cursor_pos_Y)
2286 cursor_pos_Y = startup_pos_Y;
2287
2288 ScreenSetCursor (cursor_pos_Y, cursor_pos_X);
2289 xfree (startup_screen_buffer);
f32d4091
KS
2290
2291 term_setup_done = 0;
2292}
2293
71f65669
EZ
2294static void
2295IT_set_terminal_window (int foo)
f32d4091
KS
2296{
2297}
2298
2d764c78
EZ
2299/* Remember the screen colors of the curent frame, to serve as the
2300 default colors for newly-created frames. */
2d764c78
EZ
2301DEFUN ("msdos-remember-default-colors", Fmsdos_remember_default_colors,
2302 Smsdos_remember_default_colors, 1, 1, 0,
70da46c3 2303 doc: /* Remember the screen colors of the current frame. */)
2d764c78
EZ
2304 (frame)
2305 Lisp_Object frame;
2306{
2d764c78
EZ
2307 struct frame *f;
2308
b7826503 2309 CHECK_FRAME (frame);
2d764c78 2310 f= XFRAME (frame);
2d764c78 2311
ff12cd1d
EZ
2312 /* This function is called after applying default-frame-alist to the
2313 initial frame. At that time, if reverse-colors option was
2314 specified in default-frame-alist, it was already applied, and
2315 frame colors are reversed. We need to account for that. */
2316 if (EQ (Fcdr (Fassq (Qreverse, f->param_alist)), Qt))
2317 {
2318 initial_screen_colors[0] = FRAME_BACKGROUND_PIXEL (f);
2319 initial_screen_colors[1] = FRAME_FOREGROUND_PIXEL (f);
2320 }
2321 else
2322 {
2323 initial_screen_colors[0] = FRAME_FOREGROUND_PIXEL (f);
2324 initial_screen_colors[1] = FRAME_BACKGROUND_PIXEL (f);
2325 }
2d764c78
EZ
2326}
2327
f32d4091 2328void
3bb1f22f 2329IT_set_frame_parameters (f, alist)
c77f6f1b 2330 struct frame *f;
f32d4091
KS
2331 Lisp_Object alist;
2332{
2333 Lisp_Object tail;
db722735 2334 int length = XINT (Flength (alist));
2d764c78 2335 int i, j;
db722735
RS
2336 Lisp_Object *parms
2337 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
2338 Lisp_Object *values
2339 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
2d764c78 2340 /* Do we have to reverse the foreground and background colors? */
8ba01a32 2341 int reverse = EQ (Fcdr (Fassq (Qreverse, f->param_alist)), Qt);
2d764c78
EZ
2342 int was_reverse = reverse;
2343 int redraw = 0, fg_set = 0, bg_set = 0;
546701f5 2344 int need_to_reverse;
2d764c78
EZ
2345 unsigned long orig_fg;
2346 unsigned long orig_bg;
546701f5 2347 Lisp_Object frame_bg, frame_fg;
53704a07 2348 extern Lisp_Object Qdefault, QCforeground, QCbackground;
2d764c78
EZ
2349
2350 /* If we are creating a new frame, begin with the original screen colors
2351 used for the initial frame. */
2352 if (alist == Vdefault_frame_alist
2353 && initial_screen_colors[0] != -1 && initial_screen_colors[1] != -1)
2354 {
2355 FRAME_FOREGROUND_PIXEL (f) = initial_screen_colors[0];
2356 FRAME_BACKGROUND_PIXEL (f) = initial_screen_colors[1];
2357 }
2358 orig_fg = FRAME_FOREGROUND_PIXEL (f);
2359 orig_bg = FRAME_BACKGROUND_PIXEL (f);
546701f5
EZ
2360 frame_fg = Fcdr (Fassq (Qforeground_color, f->param_alist));
2361 frame_bg = Fcdr (Fassq (Qbackground_color, f->param_alist));
2362 /* frame_fg and frame_bg could be nil if, for example,
2363 f->param_alist is nil, e.g. if we are called from
2364 Fmake_terminal_frame. */
2365 if (NILP (frame_fg))
2366 frame_fg = build_string (unspecified_fg);
2367 if (NILP (frame_bg))
2368 frame_bg = build_string (unspecified_bg);
db722735
RS
2369
2370 /* Extract parm names and values into those vectors. */
2371 i = 0;
f32d4091
KS
2372 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
2373 {
db722735 2374 Lisp_Object elt;
f32d4091
KS
2375
2376 elt = Fcar (tail);
db722735 2377 parms[i] = Fcar (elt);
b7826503 2378 CHECK_SYMBOL (parms[i]);
db722735
RS
2379 values[i] = Fcdr (elt);
2380 i++;
2381 }
2382
2d764c78 2383 j = i;
db722735 2384
2d764c78
EZ
2385 for (i = 0; i < j; i++)
2386 {
1e21fe48
EZ
2387 Lisp_Object prop, val;
2388
2389 prop = parms[i];
2390 val = values[i];
2d764c78 2391
8ba01a32 2392 if (EQ (prop, Qreverse))
2d764c78
EZ
2393 reverse = EQ (val, Qt);
2394 }
546701f5
EZ
2395
2396 need_to_reverse = reverse && !was_reverse;
2397 if (termscript && need_to_reverse)
2d764c78
EZ
2398 fprintf (termscript, "<INVERSE-VIDEO>\n");
2399
2400 /* Now process the alist elements in reverse of specified order. */
db722735
RS
2401 for (i--; i >= 0; i--)
2402 {
1e21fe48
EZ
2403 Lisp_Object prop, val;
2404 Lisp_Object frame;
2405
2406 prop = parms[i];
2407 val = values[i];
f32d4091 2408
4e825084 2409 if (EQ (prop, Qforeground_color))
f32d4091 2410 {
546701f5 2411 unsigned long new_color = load_color (f, NULL, val, need_to_reverse
2d764c78
EZ
2412 ? LFACE_BACKGROUND_INDEX
2413 : LFACE_FOREGROUND_INDEX);
3b620731
EZ
2414 if (new_color != FACE_TTY_DEFAULT_COLOR
2415 && new_color != FACE_TTY_DEFAULT_FG_COLOR
2416 && new_color != FACE_TTY_DEFAULT_BG_COLOR)
f32d4091 2417 {
546701f5 2418 FRAME_FOREGROUND_PIXEL (f) = new_color;
1e21fe48
EZ
2419 /* Make sure the foreground of the default face for this
2420 frame is changed as well. */
2421 XSETFRAME (frame, f);
546701f5 2422 if (need_to_reverse)
1e21fe48 2423 {
1e21fe48
EZ
2424 Finternal_set_lisp_face_attribute (Qdefault, QCbackground,
2425 val, frame);
546701f5 2426 prop = Qbackground_color;
ff12cd1d 2427 bg_set = 1;
1e21fe48 2428 }
2d764c78 2429 else
1e21fe48 2430 {
1e21fe48
EZ
2431 Finternal_set_lisp_face_attribute (Qdefault, QCforeground,
2432 val, frame);
ff12cd1d 2433 fg_set = 1;
1e21fe48 2434 }
f32d4091 2435 redraw = 1;
76ac1508 2436 if (termscript)
a7cf9151 2437 fprintf (termscript, "<FGCOLOR %lu>\n", new_color);
f32d4091
KS
2438 }
2439 }
4e825084 2440 else if (EQ (prop, Qbackground_color))
f32d4091 2441 {
546701f5 2442 unsigned long new_color = load_color (f, NULL, val, need_to_reverse
2d764c78
EZ
2443 ? LFACE_FOREGROUND_INDEX
2444 : LFACE_BACKGROUND_INDEX);
3b620731
EZ
2445 if (new_color != FACE_TTY_DEFAULT_COLOR
2446 && new_color != FACE_TTY_DEFAULT_FG_COLOR
2447 && new_color != FACE_TTY_DEFAULT_BG_COLOR)
f32d4091 2448 {
546701f5 2449 FRAME_BACKGROUND_PIXEL (f) = new_color;
1e21fe48
EZ
2450 /* Make sure the background of the default face for this
2451 frame is changed as well. */
2452 XSETFRAME (frame, f);
546701f5 2453 if (need_to_reverse)
1e21fe48 2454 {
1e21fe48
EZ
2455 Finternal_set_lisp_face_attribute (Qdefault, QCforeground,
2456 val, frame);
546701f5 2457 prop = Qforeground_color;
ff12cd1d 2458 fg_set = 1;
1e21fe48 2459 }
2d764c78 2460 else
1e21fe48 2461 {
1e21fe48
EZ
2462 Finternal_set_lisp_face_attribute (Qdefault, QCbackground,
2463 val, frame);
ff12cd1d 2464 bg_set = 1;
1e21fe48 2465 }
f32d4091 2466 redraw = 1;
76ac1508 2467 if (termscript)
a7cf9151 2468 fprintf (termscript, "<BGCOLOR %lu>\n", new_color);
f32d4091
KS
2469 }
2470 }
211c7152
EZ
2471 else if (EQ (prop, Qtitle))
2472 {
2473 x_set_title (f, val);
2474 if (termscript)
2475 fprintf (termscript, "<TITLE: %s>\n", XSTRING (val)->data);
2476 }
8ba01a32
EZ
2477 else if (EQ (prop, Qcursor_type))
2478 {
2479 IT_set_cursor_type (f, val);
2480 if (termscript)
2481 fprintf (termscript, "<CTYPE: %s>\n",
a0738471
EZ
2482 EQ (val, Qbar) || EQ (val, Qhbar)
2483 || CONSP (val) && (EQ (XCAR (val), Qbar)
2484 || EQ (XCAR (val), Qhbar))
8ba01a32
EZ
2485 ? "bar" : "box");
2486 }
db722735 2487 store_frame_param (f, prop, val);
2d764c78 2488 }
db722735 2489
2d764c78
EZ
2490 /* If they specified "reverse", but not the colors, we need to swap
2491 the current frame colors. */
546701f5 2492 if (need_to_reverse)
2d764c78 2493 {
1e21fe48
EZ
2494 Lisp_Object frame;
2495
2d764c78
EZ
2496 if (!fg_set)
2497 {
1e21fe48 2498 XSETFRAME (frame, f);
ff12cd1d
EZ
2499 Finternal_set_lisp_face_attribute (Qdefault, QCforeground,
2500 tty_color_name (f, orig_bg),
53704a07 2501 frame);
2d764c78
EZ
2502 redraw = 1;
2503 }
2504 if (!bg_set)
2505 {
1e21fe48 2506 XSETFRAME (frame, f);
ff12cd1d
EZ
2507 Finternal_set_lisp_face_attribute (Qdefault, QCbackground,
2508 tty_color_name (f, orig_fg),
53704a07 2509 frame);
2d764c78
EZ
2510 redraw = 1;
2511 }
f32d4091
KS
2512 }
2513
2514 if (redraw)
2515 {
2d764c78
EZ
2516 face_change_count++; /* forces xdisp.c to recompute basic faces */
2517 if (f == SELECTED_FRAME())
3bb1f22f 2518 redraw_frame (f);
f32d4091
KS
2519 }
2520}
2521
a7cf9151
EZ
2522extern void init_frame_faces (FRAME_PTR);
2523
f32d4091
KS
2524#endif /* !HAVE_X_WINDOWS */
2525
2526
48ffe371
RS
2527/* Do we need the internal terminal? */
2528
f32d4091
KS
2529void
2530internal_terminal_init ()
2531{
2532 char *term = getenv ("TERM");
2533 char *colors;
2d764c78 2534 struct frame *sf = SELECTED_FRAME();
f32d4091
KS
2535
2536#ifdef HAVE_X_WINDOWS
2537 if (!inhibit_window_system)
2538 return;
2539#endif
2540
2541 internal_terminal
2542 = (!noninteractive) && term && !strcmp (term, "internal");
2543
2544 if (getenv ("EMACSTEST"))
5063b150 2545 termscript = fopen (getenv ("EMACSTEST"), "wt");
f32d4091
KS
2546
2547#ifndef HAVE_X_WINDOWS
2548 if (!internal_terminal || inhibit_window_system)
2549 {
2d764c78 2550 sf->output_method = output_termcap;
f32d4091
KS
2551 return;
2552 }
2553
2554 Vwindow_system = intern ("pc");
2555 Vwindow_system_version = make_number (1);
2d764c78 2556 sf->output_method = output_msdos_raw;
039274cf
EZ
2557
2558 /* If Emacs was dumped on DOS/V machine, forget the stale VRAM address. */
2559 screen_old_address = 0;
2560
2d764c78
EZ
2561 /* Forget the stale screen colors as well. */
2562 initial_screen_colors[0] = initial_screen_colors[1] = -1;
2563
f32d4091
KS
2564 bzero (&the_only_x_display, sizeof the_only_x_display);
2565 the_only_x_display.background_pixel = 7; /* White */
2566 the_only_x_display.foreground_pixel = 0; /* Black */
76ac1508 2567 bright_bg ();
5063b150 2568 colors = getenv ("EMACSCOLORS");
f32d4091
KS
2569 if (colors && strlen (colors) >= 2)
2570 {
76ac1508
RS
2571 /* The colors use 4 bits each (we enable bright background). */
2572 if (isdigit (colors[0]))
2573 colors[0] -= '0';
2574 else if (isxdigit (colors[0]))
2575 colors[0] -= (isupper (colors[0]) ? 'A' : 'a') - 10;
1bd7b2c7
RS
2576 if (colors[0] >= 0 && colors[0] < 16)
2577 the_only_x_display.foreground_pixel = colors[0];
76ac1508
RS
2578 if (isdigit (colors[1]))
2579 colors[1] -= '0';
2580 else if (isxdigit (colors[1]))
2581 colors[1] -= (isupper (colors[1]) ? 'A' : 'a') - 10;
2582 if (colors[1] >= 0 && colors[1] < 16)
1bd7b2c7 2583 the_only_x_display.background_pixel = colors[1];
f32d4091
KS
2584 }
2585 the_only_x_display.line_height = 1;
64ec6a02 2586 the_only_x_display.font = (XFontStruct *)1; /* must *not* be zero */
41ad069b
EZ
2587 the_only_x_display.display_info.mouse_face_mouse_frame = NULL;
2588 the_only_x_display.display_info.mouse_face_deferred_gc = 0;
2589 the_only_x_display.display_info.mouse_face_beg_row =
2590 the_only_x_display.display_info.mouse_face_beg_col = -1;
2591 the_only_x_display.display_info.mouse_face_end_row =
2592 the_only_x_display.display_info.mouse_face_end_col = -1;
2593 the_only_x_display.display_info.mouse_face_face_id = DEFAULT_FACE_ID;
2594 the_only_x_display.display_info.mouse_face_window = Qnil;
2595 the_only_x_display.display_info.mouse_face_mouse_x =
2596 the_only_x_display.display_info.mouse_face_mouse_y = 0;
2597 the_only_x_display.display_info.mouse_face_defer = 0;
abf10ed7 2598 the_only_x_display.display_info.mouse_face_hidden = 0;
f32d4091 2599
2d764c78 2600 init_frame_faces (sf);
f32d4091
KS
2601
2602 ring_bell_hook = IT_ring_bell;
aa9ce936
EZ
2603 insert_glyphs_hook = IT_insert_glyphs;
2604 delete_glyphs_hook = IT_delete_glyphs;
f32d4091
KS
2605 write_glyphs_hook = IT_write_glyphs;
2606 cursor_to_hook = raw_cursor_to_hook = IT_cursor_to;
2607 clear_to_end_hook = IT_clear_to_end;
2608 clear_end_of_line_hook = IT_clear_end_of_line;
2609 clear_frame_hook = IT_clear_screen;
f32d4091
KS
2610 update_begin_hook = IT_update_begin;
2611 update_end_hook = IT_update_end;
41ad069b 2612 frame_up_to_date_hook = IT_frame_up_to_date;
f32d4091
KS
2613
2614 /* These hooks are called by term.c without being checked. */
2615 set_terminal_modes_hook = IT_set_terminal_modes;
2616 reset_terminal_modes_hook = IT_reset_terminal_modes;
2617 set_terminal_window_hook = IT_set_terminal_window;
c77f6f1b 2618 char_ins_del_ok = 0;
f32d4091
KS
2619#endif
2620}
2621
2622dos_get_saved_screen (screen, rows, cols)
2623 char **screen;
2624 int *rows;
2625 int *cols;
2626{
2627#ifndef HAVE_X_WINDOWS
2628 *screen = startup_screen_buffer;
2629 *cols = startup_screen_size_X;
2630 *rows = startup_screen_size_Y;
039274cf 2631 return *screen != (char *)0;
f32d4091
KS
2632#else
2633 return 0;
2634#endif
2635}
3bb1f22f
RS
2636
2637#ifndef HAVE_X_WINDOWS
2638
2639/* We are not X, but we can emulate it well enough for our needs... */
2640void
2641check_x (void)
2642{
2d764c78
EZ
2643 if (! FRAME_MSDOS_P (SELECTED_FRAME()))
2644 error ("Not running under a window system");
3bb1f22f
RS
2645}
2646
2647#endif
2648
5063b150 2649\f
f32d4091
KS
2650/* ----------------------- Keyboard control ----------------------
2651 *
2652 * Keymaps reflect the following keyboard layout:
2653 *
2654 * 0 1 2 3 4 5 6 7 8 9 10 11 12 BS
2655 * TAB 15 16 17 18 19 20 21 22 23 24 25 26 (41)
2656 * CLOK 30 31 32 33 34 35 36 37 38 39 40 (41) RET
2657 * SH () 45 46 47 48 49 50 51 52 53 54 SHIFT
2658 * SPACE
2659 */
2660
d1d5dc19
EZ
2661#define Ignore 0x0000
2662#define Normal 0x0000 /* normal key - alt changes scan-code */
2663#define FctKey 0x1000 /* func key if c == 0, else c */
2664#define Special 0x2000 /* func key even if c != 0 */
2665#define ModFct 0x3000 /* special if mod-keys, else 'c' */
2666#define Map 0x4000 /* alt scan-code, map to unshift/shift key */
2667#define KeyPad 0x5000 /* map to insert/kp-0 depending on c == 0xe0 */
2668#define Grey 0x6000 /* Grey keypad key */
2669
2670#define Alt 0x0100 /* alt scan-code */
2671#define Ctrl 0x0200 /* ctrl scan-code */
2672#define Shift 0x0400 /* shift scan-code */
2673
f32d4091
KS
2674static int extended_kbd; /* 101 (102) keyboard present. */
2675
d1d5dc19
EZ
2676struct kbd_translate {
2677 unsigned char sc;
2678 unsigned char ch;
2679 unsigned short code;
2680};
2681
f32d4091
KS
2682struct dos_keyboard_map
2683{
2684 char *unshifted;
2685 char *shifted;
2686 char *alt_gr;
d1d5dc19 2687 struct kbd_translate *translate_table;
f32d4091
KS
2688};
2689
2690
2691static struct dos_keyboard_map us_keyboard = {
2692/* 0 1 2 3 4 5 */
2693/* 01234567890123456789012345678901234567890 12345678901234 */
2694 "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ",
2695/* 0123456789012345678901234567890123456789 012345678901234 */
2696 "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ",
d1d5dc19
EZ
2697 0, /* no Alt-Gr key */
2698 0 /* no translate table */
f32d4091
KS
2699};
2700
2701static struct dos_keyboard_map fr_keyboard = {
2702/* 0 1 2 3 4 5 */
2703/* 012 3456789012345678901234567890123456789012345678901234 */
2704