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