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