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