1 /* MS-DOS specific C utilities. -*- coding: raw-text -*-
2 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002,
3 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 /* Contributed by Morten Welinder */
22 /* New display, keyboard, and mouse control by Kim F. Storm */
24 /* Note: some of the stuff here was taken from end of sysdep.c in demacs. */
34 #include <sys/param.h>
38 #include <string.h> /* for memset and string functions */
39 #include <sys/stat.h> /* for _fixpath */
40 #include <unistd.h> /* for chdir, dup, dup2, etc. */
41 #include <dir.h> /* for getdisk */
42 #pragma pack(0) /* dir.h does a pack(4), which isn't GCC's default */
44 #include <io.h> /* for setmode */
45 #include <dpmi.h> /* for __dpmi_xxx stuff */
46 #include <sys/farptr.h> /* for _farsetsel, _farnspokeb */
47 #include <libc/dosio.h> /* for _USE_LFN */
48 #include <conio.h> /* for cputs */
53 #include "termhooks.h"
55 #include "dispextern.h"
58 #include "character.h"
64 #include "blockinput.h"
66 #include "intervals.h"
70 /* #include <process.h> */
71 /* Damn that local process.h! Instead we can define P_WAIT ourselves. */
79 #define _dos_ds _go32_info_block.selector_for_linear_memory
83 #include "syssignal.h"
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. */
96 int _crt0_startup_flags
= _CRT0_FLAG_UNIX_SBRK
;
97 #else /* not REL_ALLOC */
98 int _crt0_startup_flags
= (_CRT0_FLAG_UNIX_SBRK
| _CRT0_FLAG_FILL_SBRK_MEMORY
);
99 #endif /* not REL_ALLOC */
100 #endif /* GNU_MALLOC */
102 #endif /* not SYSTEM_MALLOC */
105 event_timestamp (void)
121 /* ------------------------ Mouse control ---------------------------
123 * Coordinates are in screen positions and zero based.
124 * Mouse buttons are numbered from left to right and also zero based.
127 /* This used to be in termhooks.h, but mainstream Emacs code no longer
128 uses it, and it was removed... */
129 #define NUM_MOUSE_BUTTONS (5)
131 int have_mouse
; /* 0: no, 1: enabled, -1: disabled */
132 static int mouse_visible
;
134 static int mouse_last_x
;
135 static int mouse_last_y
;
137 static int mouse_button_translate
[NUM_MOUSE_BUTTONS
];
138 static int mouse_button_count
;
145 if (have_mouse
> 0 && !mouse_visible
)
147 struct tty_display_info
*tty
= CURTTY ();
150 fprintf (tty
->termscript
, "<M_ON>");
152 int86 (0x33, ®s
, ®s
);
162 if (have_mouse
> 0 && mouse_visible
)
164 struct tty_display_info
*tty
= CURTTY ();
167 fprintf (tty
->termscript
, "<M_OFF>");
169 int86 (0x33, ®s
, ®s
);
175 mouse_setup_buttons (int n_buttons
)
179 mouse_button_count
= 3;
180 mouse_button_translate
[0] = 0; /* Left */
181 mouse_button_translate
[1] = 2; /* Middle */
182 mouse_button_translate
[2] = 1; /* Right */
184 else /* two, what else? */
186 mouse_button_count
= 2;
187 mouse_button_translate
[0] = 0;
188 mouse_button_translate
[1] = 1;
192 DEFUN ("msdos-set-mouse-buttons", Fmsdos_set_mouse_buttons
, Smsdos_set_mouse_buttons
,
193 1, 1, "NSet number of mouse buttons to: ",
194 doc
: /* Set the number of mouse buttons to use by Emacs.
195 This is useful with mice that report the number of buttons inconsistently,
196 e.g., if the number of buttons is reported as 3, but Emacs only sees 2 of
197 them. This happens with wheeled mice on Windows 9X, for example. */)
199 Lisp_Object nbuttons
;
203 CHECK_NUMBER (nbuttons
);
206 xsignal2 (Qargs_out_of_range
,
207 build_string ("only 2 or 3 mouse buttons are supported"),
209 mouse_setup_buttons (n
);
214 mouse_get_xy (int *x
, int *y
)
219 int86 (0x33, ®s
, ®s
);
225 mouse_moveto (int x
, int y
)
228 struct tty_display_info
*tty
= CURTTY ();
231 fprintf (tty
->termscript
, "<M_XY=%dx%d>", x
, y
);
233 mouse_last_x
= regs
.x
.cx
= x
* 8;
234 mouse_last_y
= regs
.x
.dx
= y
* 8;
235 int86 (0x33, ®s
, ®s
);
239 mouse_pressed (int b
, int *xp
, int *yp
)
243 if (b
>= mouse_button_count
)
246 regs
.x
.bx
= mouse_button_translate
[b
];
247 int86 (0x33, ®s
, ®s
);
249 *xp
= regs
.x
.cx
/ 8, *yp
= regs
.x
.dx
/ 8;
250 return (regs
.x
.bx
!= 0);
254 mouse_released (int b
, int *xp
, int *yp
)
258 if (b
>= mouse_button_count
)
261 regs
.x
.bx
= mouse_button_translate
[b
];
262 int86 (0x33, ®s
, ®s
);
264 *xp
= regs
.x
.cx
/ 8, *yp
= regs
.x
.dx
/ 8;
265 return (regs
.x
.bx
!= 0);
269 mouse_button_depressed (int b
, int *xp
, int *yp
)
273 if (b
>= mouse_button_count
)
276 int86 (0x33, ®s
, ®s
);
277 if ((regs
.x
.bx
& (1 << mouse_button_translate
[b
])) != 0)
287 mouse_get_pos (FRAME_PTR
*f
, int insist
, Lisp_Object
*bar_window
,
288 enum scroll_bar_part
*part
, Lisp_Object
*x
, Lisp_Object
*y
,
292 Lisp_Object frame
, tail
;
294 /* Clear the mouse-moved flag for every frame on this display. */
295 FOR_EACH_FRAME (tail
, frame
)
296 XFRAME (frame
)->mouse_moved
= 0;
298 *f
= SELECTED_FRAME();
300 mouse_get_xy (&ix
, &iy
);
301 *time
= event_timestamp ();
302 *x
= make_number (mouse_last_x
= ix
);
303 *y
= make_number (mouse_last_y
= iy
);
307 mouse_check_moved (void)
311 mouse_get_xy (&x
, &y
);
312 SELECTED_FRAME()->mouse_moved
|= (x
!= mouse_last_x
|| y
!= mouse_last_y
);
317 /* Force the mouse driver to ``forget'' about any button clicks until
320 mouse_clear_clicks (void)
324 for (b
= 0; b
< mouse_button_count
; b
++)
326 int dummy_x
, dummy_y
;
328 (void) mouse_pressed (b
, &dummy_x
, &dummy_y
);
329 (void) mouse_released (b
, &dummy_x
, &dummy_y
);
337 struct tty_display_info
*tty
= CURTTY ();
340 fprintf (tty
->termscript
, "<M_INIT>");
343 int86 (0x33, ®s
, ®s
);
345 /* Reset the mouse last press/release info. It seems that Windows
346 doesn't do that automatically when function 21h is called, which
347 causes Emacs to ``remember'' the click that switched focus to the
348 window just before Emacs was started from that window. */
349 mouse_clear_clicks ();
353 regs
.x
.dx
= 8 * (ScreenCols () - 1);
354 int86 (0x33, ®s
, ®s
);
358 regs
.x
.dx
= 8 * (ScreenRows () - 1);
359 int86 (0x33, ®s
, ®s
);
365 /* ------------------------- Screen control ----------------------
369 static int internal_terminal
= 0;
371 #ifndef HAVE_X_WINDOWS
372 extern unsigned char ScreenAttrib
;
373 static int screen_face
;
375 static int screen_size_X
;
376 static int screen_size_Y
;
377 static int screen_size
;
379 static int current_pos_X
;
380 static int current_pos_Y
;
381 static int new_pos_X
;
382 static int new_pos_Y
;
384 static void *startup_screen_buffer
;
385 static int startup_screen_size_X
;
386 static int startup_screen_size_Y
;
387 static int startup_pos_X
;
388 static int startup_pos_Y
;
389 static unsigned char startup_screen_attrib
;
391 static clock_t startup_time
;
393 static int term_setup_done
;
395 static unsigned short outside_cursor
;
397 /* Similar to the_only_frame. */
398 struct tty_display_info the_only_display_info
;
400 /* Support for DOS/V (allows Japanese characters to be displayed on
401 standard, non-Japanese, ATs). Only supported for DJGPP v2 and later. */
403 /* Holds the address of the text-mode screen buffer. */
404 static unsigned long screen_old_address
= 0;
405 /* Segment and offset of the virtual screen. If 0, DOS/V is NOT loaded. */
406 static unsigned short screen_virtual_segment
= 0;
407 static unsigned short screen_virtual_offset
= 0;
408 /* A flag to control how to display unibyte 8-bit characters. */
409 extern int unibyte_display_via_language_environment
;
411 extern Lisp_Object Qcursor_type
;
412 extern Lisp_Object Qbar
, Qhbar
;
414 /* The screen colors of the current frame, which serve as the default
415 colors for newly-created frames. */
416 static int initial_screen_colors
[2];
418 /* Update the screen from a part of relocated DOS/V screen buffer which
419 begins at OFFSET and includes COUNT characters. */
421 dosv_refresh_virtual_screen (int offset
, int count
)
425 if (offset
< 0 || count
< 0) /* paranoia; invalid values crash DOS/V */
428 regs
.h
.ah
= 0xff; /* update relocated screen */
429 regs
.x
.es
= screen_virtual_segment
;
430 regs
.x
.di
= screen_virtual_offset
+ offset
;
432 __dpmi_int (0x10, ®s
);
436 dos_direct_output (int y
, int x
, char *buf
, int len
)
438 int t0
= 2 * (x
+ y
* screen_size_X
);
439 int t
= t0
+ (int) ScreenPrimary
;
442 /* This is faster. */
443 for (_farsetsel (_dos_ds
); --len
>= 0; t
+= 2, buf
++)
444 _farnspokeb (t
, *buf
);
446 if (screen_virtual_segment
)
447 dosv_refresh_virtual_screen (t0
, l0
);
451 #ifndef HAVE_X_WINDOWS
453 static int blink_bit
= -1; /* the state of the blink bit at startup */
455 /* Enable bright background colors. */
461 /* Remember the original state of the blink/bright-background bit.
462 It is stored at 0040:0065h in the BIOS data area. */
464 blink_bit
= (_farpeekb (_dos_ds
, 0x465) & 0x20) == 0x20;
468 int86 (0x10, ®s
, ®s
);
471 /* Disable bright background colors (and enable blinking) if we found
472 the video system in that state at startup. */
474 maybe_enable_blinking (void)
482 int86 (0x10, ®s
, ®s
);
486 /* Return non-zero if the system has a VGA adapter. */
493 int86 (0x10, ®s
, ®s
);
494 if (regs
.h
.al
== 0x1a && regs
.h
.bl
> 5 && regs
.h
.bl
< 13)
499 /* Set the screen dimensions so that it can show no less than
500 ROWS x COLS frame. */
503 dos_set_window_size (int *rows
, int *cols
)
507 Lisp_Object video_mode
;
508 int video_mode_value
, have_vga
= 0;
509 int current_rows
= ScreenRows (), current_cols
= ScreenCols ();
511 if (*rows
== current_rows
&& *cols
== current_cols
)
515 have_vga
= vga_installed ();
517 /* If the user specified a special video mode for these dimensions,
519 sprintf (video_name
, "screen-dimensions-%dx%d", *rows
, *cols
);
520 video_mode
= Fsymbol_value (Fintern_soft (build_string (video_name
), Qnil
));
522 if (INTEGERP (video_mode
)
523 && (video_mode_value
= XINT (video_mode
)) > 0)
525 regs
.x
.ax
= video_mode_value
;
526 int86 (0x10, ®s
, ®s
);
530 /* Must hardware-reset the mouse, or else it won't update
531 its notion of screen dimensions for some non-standard
532 video modes. This is *painfully* slow... */
534 int86 (0x33, ®s
, ®s
);
538 /* Find one of the dimensions supported by standard EGA/VGA
539 which gives us at least the required dimensions. */
544 } std_dimension
[] = {
554 while (i
< sizeof (std_dimension
) / sizeof (std_dimension
[0]))
556 if (std_dimension
[i
].need_vga
<= have_vga
557 && std_dimension
[i
].rows
>= *rows
)
559 if (std_dimension
[i
].rows
!= current_rows
560 || *cols
!= current_cols
)
561 _set_screen_lines (std_dimension
[i
].rows
);
575 /* Tell the caller what dimensions have been REALLY set. */
576 *rows
= ScreenRows ();
577 *cols
= ScreenCols ();
579 /* Update Emacs' notion of screen dimensions. */
580 screen_size_X
= *cols
;
581 screen_size_Y
= *rows
;
582 screen_size
= *cols
* *rows
;
584 /* If the dimensions changed, the mouse highlight info is invalid. */
585 if (current_rows
!= *rows
|| current_cols
!= *cols
)
587 struct frame
*f
= SELECTED_FRAME();
588 struct tty_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
589 Lisp_Object window
= dpyinfo
->mouse_face_window
;
591 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
593 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
594 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
595 dpyinfo
->mouse_face_window
= Qnil
;
599 /* Enable bright background colors. */
602 /* FIXME: I'm not sure the above will run at all on DOS/V. But let's
603 be defensive anyway. */
604 if (screen_virtual_segment
)
605 dosv_refresh_virtual_screen (0, *cols
* *rows
);
608 /* If we write a character in the position where the mouse is,
609 the mouse cursor may need to be refreshed. */
612 mouse_off_maybe (void)
619 mouse_get_xy (&x
, &y
);
620 if (y
!= new_pos_Y
|| x
< new_pos_X
)
626 #define DEFAULT_CURSOR_START (-1)
627 #define DEFAULT_CURSOR_WIDTH (-1)
628 #define BOX_CURSOR_WIDTH (-32)
630 /* Set cursor to begin at scan line START_LINE in the character cell
631 and extend for WIDTH scan lines. Scan lines are counted from top
632 of the character cell, starting from zero. */
634 msdos_set_cursor_shape (struct frame
*f
, int start_line
, int width
)
636 unsigned desired_cursor
;
638 int max_line
, top_line
, bot_line
;
639 struct tty_display_info
*tty
= FRAME_TTY (f
);
641 /* Avoid the costly BIOS call if F isn't the currently selected
642 frame. Allow for NULL as unconditionally meaning the selected
644 if (f
&& f
!= SELECTED_FRAME())
648 fprintf (tty
->termscript
, "\nCURSOR SHAPE=(%d,%d)", start_line
, width
);
650 /* The character cell size in scan lines is stored at 40:85 in the
652 max_line
= _farpeekw (_dos_ds
, 0x485) - 1;
655 default: /* this relies on CGA cursor emulation being ON! */
672 if (width
== BOX_CURSOR_WIDTH
)
677 else if (start_line
!= DEFAULT_CURSOR_START
)
679 top_line
= start_line
;
680 bot_line
= top_line
- width
- 1;
682 else if (width
!= DEFAULT_CURSOR_WIDTH
)
685 bot_line
= -1 - width
;
688 top_line
= bot_line
+ 1;
692 /* [31, 0] seems to DTRT for all screen sizes. */
696 else /* WIDTH is positive */
698 if (start_line
!= DEFAULT_CURSOR_START
)
699 bot_line
= start_line
;
700 top_line
= bot_line
- (width
- 1);
703 /* If the current cursor shape is already what they want, we are
705 desired_cursor
= ((top_line
& 0x1f) << 8) | (bot_line
& 0x1f);
706 if (desired_cursor
== _farpeekw (_dos_ds
, 0x460))
710 regs
.x
.cx
= desired_cursor
;
711 __dpmi_int (0x10, ®s
);
715 IT_set_cursor_type (struct frame
*f
, Lisp_Object cursor_type
)
717 if (EQ (cursor_type
, Qbar
) || EQ (cursor_type
, Qhbar
))
719 /* Just BAR means the normal EGA/VGA cursor. */
720 msdos_set_cursor_shape (f
, DEFAULT_CURSOR_START
, DEFAULT_CURSOR_WIDTH
);
722 else if (CONSP (cursor_type
)
723 && (EQ (XCAR (cursor_type
), Qbar
)
724 || EQ (XCAR (cursor_type
), Qhbar
)))
726 Lisp_Object bar_parms
= XCDR (cursor_type
);
729 if (INTEGERP (bar_parms
))
731 /* Feature: negative WIDTH means cursor at the top
732 of the character cell, zero means invisible cursor. */
733 width
= XINT (bar_parms
);
734 msdos_set_cursor_shape (f
, width
>= 0 ? DEFAULT_CURSOR_START
: 0,
737 else if (CONSP (bar_parms
)
738 && INTEGERP (XCAR (bar_parms
))
739 && INTEGERP (XCDR (bar_parms
)))
741 int start_line
= XINT (XCDR (bar_parms
));
743 width
= XINT (XCAR (bar_parms
));
744 msdos_set_cursor_shape (f
, start_line
, width
);
749 /* Treat anything unknown as "box cursor". This includes nil, so
750 that a frame which doesn't specify a cursor type gets a box,
751 which is the default in Emacs. */
752 msdos_set_cursor_shape (f
, 0, BOX_CURSOR_WIDTH
);
757 IT_ring_bell (struct frame
*f
)
766 union REGS inregs
, outregs
;
769 intdos (&inregs
, &outregs
);
773 /* Given a face id FACE, extract the face parameters to be used for
774 display until the face changes. The face parameters (actually, its
775 color) are used to construct the video attribute byte for each
776 glyph during the construction of the buffer that is then blitted to
779 IT_set_face (int face
)
781 struct frame
*sf
= SELECTED_FRAME();
782 struct face
*fp
= FACE_FROM_ID (sf
, face
);
783 struct face
*dfp
= FACE_FROM_ID (sf
, DEFAULT_FACE_ID
);
784 unsigned long fg
, bg
, dflt_fg
, dflt_bg
;
785 struct tty_display_info
*tty
= FRAME_TTY (sf
);
790 /* The default face for the frame should always be realized and
798 dflt_fg
= dfp
->foreground
;
799 dflt_bg
= dfp
->background
;
801 /* Don't use invalid colors. In particular, FACE_TTY_DEFAULT_* colors
802 mean use the colors of the default face. Note that we assume all
803 16 colors to be available for the background, since Emacs switches
804 on this mode (and loses the blinking attribute) at startup. */
805 if (fg
== FACE_TTY_DEFAULT_COLOR
|| fg
== FACE_TTY_DEFAULT_FG_COLOR
)
806 fg
= FRAME_FOREGROUND_PIXEL (sf
);
807 else if (fg
== FACE_TTY_DEFAULT_BG_COLOR
)
808 fg
= FRAME_BACKGROUND_PIXEL (sf
);
809 if (bg
== FACE_TTY_DEFAULT_COLOR
|| bg
== FACE_TTY_DEFAULT_BG_COLOR
)
810 bg
= FRAME_BACKGROUND_PIXEL (sf
);
811 else if (bg
== FACE_TTY_DEFAULT_FG_COLOR
)
812 bg
= FRAME_FOREGROUND_PIXEL (sf
);
814 /* Make sure highlighted lines really stand out, come what may. */
815 if (fp
->tty_reverse_p
&& (fg
== dflt_fg
&& bg
== dflt_bg
))
817 unsigned long tem
= fg
;
822 /* If the user requested inverse video, obey. */
825 unsigned long tem2
= fg
;
831 fprintf (tty
->termscript
, "<FACE %d: %d/%d[FG:%d/BG:%d]>", face
,
832 fp
->foreground
, fp
->background
, fg
, bg
);
833 if (fg
>= 0 && fg
< 16)
835 ScreenAttrib
&= 0xf0;
838 if (bg
>= 0 && bg
< 16)
840 ScreenAttrib
&= 0x0f;
841 ScreenAttrib
|= ((bg
& 0x0f) << 4);
845 /* According to RBIL (INTERRUP.A, V-1000), 160 is the maximum possible
846 width of a DOS display in any known text mode. We multiply by 2 to
847 accomodate the screen attribute byte. */
848 #define MAX_SCREEN_BUF 160*2
850 Lisp_Object Vdos_unsupported_char_glyph
;
851 extern unsigned char *encode_terminal_code (struct glyph
*, int,
852 struct coding_system
*);
854 IT_write_glyphs (struct frame
*f
, struct glyph
*str
, int str_len
)
856 unsigned char screen_buf
[MAX_SCREEN_BUF
], *screen_bp
, *bp
;
857 int offset
= 2 * (new_pos_X
+ screen_size_X
* new_pos_Y
);
858 register int sl
= str_len
;
859 struct tty_display_info
*tty
= FRAME_TTY (f
);
861 unsigned char *conversion_buffer
;
863 /* Do we need to consider conversion of unibyte characters to
865 int convert_unibyte_characters
866 = (NILP (current_buffer
->enable_multibyte_characters
)
867 && unibyte_display_via_language_environment
);
869 /* If terminal_coding does any conversion, use it, otherwise use
870 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
871 because it always returns 1 if terminal_coding.src_multibyte is 1. */
872 struct coding_system
*coding
= FRAME_TERMINAL_CODING (f
);
874 if (!(coding
->common_flags
& CODING_REQUIRE_ENCODING_MASK
))
875 coding
= &safe_terminal_coding
;
877 if (str_len
<= 0) return;
879 sf
= SELECTED_FRAME();
881 /* Since faces get cached and uncached behind our back, we can't
882 rely on their indices in the cache being consistent across
883 invocations. So always reset the screen face to the default
884 face of the frame, before writing glyphs, and let the glyphs
885 set the right face if it's different from the default. */
886 IT_set_face (DEFAULT_FACE_ID
);
888 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
890 coding
->mode
&= ~CODING_MODE_LAST_BLOCK
;
891 screen_bp
= &screen_buf
[0];
897 /* If the face of this glyph is different from the current
898 screen face, update the screen attribute byte. */
900 if (cf
!= screen_face
)
901 IT_set_face (cf
); /* handles invalid faces gracefully */
903 /* Identify a run of glyphs with the same face. */
904 for (n
= 1; n
< sl
; ++n
)
905 if (str
[n
].face_id
!= cf
)
909 /* This is the last glyph. */
910 coding
->mode
|= CODING_MODE_LAST_BLOCK
;
912 conversion_buffer
= encode_terminal_code (str
, n
, coding
);
913 if (coding
->produced
> 0)
915 /* Copy the encoded bytes to the screen buffer. */
916 for (bp
= conversion_buffer
; coding
->produced
--; bp
++)
918 /* Paranoia: discard bytes that would overrun the end of
919 the screen buffer. */
920 if (screen_bp
- screen_buf
<= MAX_SCREEN_BUF
- 2)
922 *screen_bp
++ = (unsigned char)*bp
;
923 *screen_bp
++ = ScreenAttrib
;
926 fputc (*bp
, tty
->termscript
);
929 /* Update STR and its remaining length. */
934 /* Dump whatever we have in the screen buffer. */
936 dosmemput (screen_buf
, screen_bp
- screen_buf
, (int)ScreenPrimary
+ offset
);
937 if (screen_virtual_segment
)
938 dosv_refresh_virtual_screen (offset
, (screen_bp
- screen_buf
) / 2);
939 new_pos_X
+= (screen_bp
- screen_buf
) / 2;
942 /************************************************************************
943 Mouse Highlight (and friends..)
944 ************************************************************************/
946 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
947 static Lisp_Object last_mouse_window
;
949 static int mouse_preempted
= 0; /* non-zero when XMenu gobbles mouse events */
951 /* Set the mouse pointer shape according to whether it is in the
952 area where the mouse highlight is in effect. */
954 IT_set_mouse_pointer (int mode
)
956 /* A no-op for now. DOS text-mode mouse pointer doesn't offer too
957 many possibilities to change its shape, and the available
958 functionality pretty much sucks (e.g., almost every reasonable
959 shape will conceal the character it is on). Since the color of
960 the pointer changes in the highlighted area, it is not clear to
961 me whether anything else is required, anyway. */
964 /* Display the active region described by mouse_face_*
965 in its mouse-face if HL > 0, in its normal face if HL = 0. */
967 show_mouse_face (struct tty_display_info
*dpyinfo
, int hl
)
969 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
970 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
973 struct tty_display_info
*tty
= FRAME_TTY (f
);
976 /* If window is in the process of being destroyed, don't bother
978 if (w
->current_matrix
== NULL
)
979 goto set_cursor_shape
;
981 /* Recognize when we are called to operate on rows that don't exist
982 anymore. This can happen when a window is split. */
983 if (dpyinfo
->mouse_face_end_row
>= w
->current_matrix
->nrows
)
984 goto set_cursor_shape
;
986 /* There's no sense to do anything if the mouse face isn't realized. */
989 if (dpyinfo
->mouse_face_hidden
)
990 goto set_cursor_shape
;
992 fp
= FACE_FROM_ID (SELECTED_FRAME(), dpyinfo
->mouse_face_face_id
);
994 goto set_cursor_shape
;
997 /* Note that mouse_face_beg_row etc. are window relative. */
998 for (i
= dpyinfo
->mouse_face_beg_row
;
999 i
<= dpyinfo
->mouse_face_end_row
;
1002 int start_hpos
, end_hpos
;
1003 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, i
);
1005 /* Don't do anything if row doesn't have valid contents. */
1006 if (!row
->enabled_p
)
1009 /* For all but the first row, the highlight starts at column 0. */
1010 if (i
== dpyinfo
->mouse_face_beg_row
)
1011 start_hpos
= dpyinfo
->mouse_face_beg_col
;
1015 if (i
== dpyinfo
->mouse_face_end_row
)
1016 end_hpos
= dpyinfo
->mouse_face_end_col
;
1018 end_hpos
= row
->used
[TEXT_AREA
];
1020 if (end_hpos
<= start_hpos
)
1022 /* Record that some glyphs of this row are displayed in
1024 row
->mouse_face_p
= hl
> 0;
1027 int vpos
= row
->y
+ WINDOW_TOP_EDGE_Y (w
);
1028 int kstart
= start_hpos
+ WINDOW_LEFT_EDGE_X (w
);
1029 int nglyphs
= end_hpos
- start_hpos
;
1030 int offset
= ScreenPrimary
+ 2*(vpos
*screen_size_X
+ kstart
) + 1;
1031 int start_offset
= offset
;
1033 if (tty
->termscript
)
1034 fprintf (tty
->termscript
, "\n<MH+ %d-%d:%d>",
1035 kstart
, kstart
+ nglyphs
- 1, vpos
);
1038 IT_set_face (dpyinfo
->mouse_face_face_id
);
1039 /* Since we are going to change only the _colors_ of the
1040 displayed text, there's no need to go through all the
1041 pain of generating and encoding the text from the glyphs.
1042 Instead, we simply poke the attribute byte of each
1043 affected position in video memory with the colors
1044 computed by IT_set_face! */
1045 _farsetsel (_dos_ds
);
1048 _farnspokeb (offset
, ScreenAttrib
);
1051 if (screen_virtual_segment
)
1052 dosv_refresh_virtual_screen (start_offset
, end_hpos
- start_hpos
);
1057 /* We are removing a previously-drawn mouse highlight. The
1058 safest way to do so is to redraw the glyphs anew, since
1059 all kinds of faces and display tables could have changed
1061 int nglyphs
= end_hpos
- start_hpos
;
1062 int save_x
= new_pos_X
, save_y
= new_pos_Y
;
1064 if (end_hpos
>= row
->used
[TEXT_AREA
])
1065 nglyphs
= row
->used
[TEXT_AREA
] - start_hpos
;
1067 /* IT_write_glyphs writes at cursor position, so we need to
1068 temporarily move cursor coordinates to the beginning of
1069 the highlight region. */
1070 new_pos_X
= start_hpos
+ WINDOW_LEFT_EDGE_X (w
);
1071 new_pos_Y
= row
->y
+ WINDOW_TOP_EDGE_Y (w
);
1073 if (tty
->termscript
)
1074 fprintf (tty
->termscript
, "<MH- %d-%d:%d>",
1075 new_pos_X
, new_pos_X
+ nglyphs
- 1, new_pos_Y
);
1076 IT_write_glyphs (f
, row
->glyphs
[TEXT_AREA
] + start_hpos
, nglyphs
);
1077 if (tty
->termscript
)
1078 fputs ("\n", tty
->termscript
);
1085 /* Change the mouse pointer shape. */
1086 IT_set_mouse_pointer (hl
);
1089 /* Clear out the mouse-highlighted active region.
1090 Redraw it un-highlighted first. */
1092 clear_mouse_face (struct tty_display_info
*dpyinfo
)
1094 if (!dpyinfo
->mouse_face_hidden
&& ! NILP (dpyinfo
->mouse_face_window
))
1095 show_mouse_face (dpyinfo
, 0);
1097 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1098 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1099 dpyinfo
->mouse_face_window
= Qnil
;
1102 /* Find the glyph matrix position of buffer position POS in window W.
1103 *HPOS and *VPOS are set to the positions found. W's current glyphs
1104 must be up to date. If POS is above window start return (0, 0).
1105 If POS is after end of W, return end of last line in W. */
1107 fast_find_position (struct window
*w
, int pos
, int *hpos
, int *vpos
)
1109 int i
, lastcol
, line_start_position
, maybe_next_line_p
= 0;
1110 int yb
= window_text_bottom_y (w
);
1111 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, 0), *best_row
= row
;
1115 if (row
->used
[TEXT_AREA
])
1116 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
1118 line_start_position
= 0;
1120 if (line_start_position
> pos
)
1122 /* If the position sought is the end of the buffer,
1123 don't include the blank lines at the bottom of the window. */
1124 else if (line_start_position
== pos
1125 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
1127 maybe_next_line_p
= 1;
1130 else if (line_start_position
> 0)
1133 /* Don't overstep the last matrix row, lest we get into the
1134 never-never land... */
1135 if (row
->y
+ 1 >= yb
)
1141 /* Find the right column within BEST_ROW. */
1144 for (i
= 0; i
< row
->used
[TEXT_AREA
]; i
++)
1146 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
] + i
;
1149 charpos
= glyph
->charpos
;
1156 else if (charpos
> pos
)
1158 else if (charpos
> 0)
1162 /* If we're looking for the end of the buffer,
1163 and we didn't find it in the line we scanned,
1164 use the start of the following line. */
1165 if (maybe_next_line_p
)
1172 *hpos
= lastcol
+ 1;
1176 /* Take proper action when mouse has moved to the mode or top line of
1177 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
1178 mode line. X is relative to the start of the text display area of
1179 W, so the width of fringes and scroll bars must be subtracted
1180 to get a position relative to the start of the mode line. */
1182 IT_note_mode_line_highlight (struct window
*w
, int x
, int mode_line_p
)
1184 struct frame
*f
= XFRAME (w
->frame
);
1185 struct tty_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
1186 struct glyph_row
*row
;
1189 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
1191 row
= MATRIX_HEADER_LINE_ROW (w
->current_matrix
);
1195 extern Lisp_Object Qhelp_echo
;
1196 struct glyph
*glyph
, *end
;
1197 Lisp_Object help
, map
;
1199 /* Find the glyph under X. */
1200 glyph
= (row
->glyphs
[TEXT_AREA
]
1202 /* in case someone implements scroll bars some day... */
1203 - WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w
));
1204 end
= glyph
+ row
->used
[TEXT_AREA
];
1206 && STRINGP (glyph
->object
)
1207 && STRING_INTERVALS (glyph
->object
)
1208 && glyph
->charpos
>= 0
1209 && glyph
->charpos
< SCHARS (glyph
->object
))
1211 /* If we're on a string with `help-echo' text property,
1212 arrange for the help to be displayed. This is done by
1213 setting the global variable help_echo to the help string. */
1214 help
= Fget_text_property (make_number (glyph
->charpos
),
1215 Qhelp_echo
, glyph
->object
);
1218 help_echo_string
= help
;
1219 XSETWINDOW (help_echo_window
, w
);
1220 help_echo_object
= glyph
->object
;
1221 help_echo_pos
= glyph
->charpos
;
1227 /* Take proper action when the mouse has moved to position X, Y on
1228 frame F as regards highlighting characters that have mouse-face
1229 properties. Also de-highlighting chars where the mouse was before.
1230 X and Y can be negative or out of range. */
1232 IT_note_mouse_highlight (struct frame
*f
, int x
, int y
)
1234 struct tty_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
1235 enum window_part part
= ON_NOTHING
;
1239 /* When a menu is active, don't highlight because this looks odd. */
1240 if (mouse_preempted
)
1243 if (NILP (Vmouse_highlight
)
1244 || !f
->glyphs_initialized_p
)
1247 dpyinfo
->mouse_face_mouse_x
= x
;
1248 dpyinfo
->mouse_face_mouse_y
= y
;
1249 dpyinfo
->mouse_face_mouse_frame
= f
;
1251 if (dpyinfo
->mouse_face_defer
)
1256 dpyinfo
->mouse_face_deferred_gc
= 1;
1260 /* Which window is that in? */
1261 window
= window_from_coordinates (f
, x
, y
, &part
, &x
, &y
, 0);
1263 /* If we were displaying active text in another window, clear that. */
1264 if (! EQ (window
, dpyinfo
->mouse_face_window
))
1265 clear_mouse_face (dpyinfo
);
1267 /* Not on a window -> return. */
1268 if (!WINDOWP (window
))
1271 /* Convert to window-relative coordinates. */
1272 w
= XWINDOW (window
);
1274 if (part
== ON_MODE_LINE
|| part
== ON_HEADER_LINE
)
1276 /* Mouse is on the mode or top line. */
1277 IT_note_mode_line_highlight (w
, x
, part
== ON_MODE_LINE
);
1281 IT_set_mouse_pointer (0);
1283 /* Are we in a window whose display is up to date?
1284 And verify the buffer's text has not changed. */
1286 && EQ (w
->window_end_valid
, w
->buffer
)
1287 && XFASTINT (w
->last_modified
) == BUF_MODIFF (XBUFFER (w
->buffer
))
1288 && (XFASTINT (w
->last_overlay_modified
)
1289 == BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
))))
1291 int pos
, i
, nrows
= w
->current_matrix
->nrows
;
1292 struct glyph_row
*row
;
1293 struct glyph
*glyph
;
1295 /* Find the glyph under X/Y. */
1297 if (y
>= 0 && y
< nrows
)
1299 row
= MATRIX_ROW (w
->current_matrix
, y
);
1300 /* Give up if some row before the one we are looking for is
1302 for (i
= 0; i
<= y
; i
++)
1303 if (!MATRIX_ROW (w
->current_matrix
, i
)->enabled_p
)
1305 if (i
> y
/* all rows upto and including the one at Y are enabled */
1306 && row
->displays_text_p
1307 && x
< window_box_width (w
, TEXT_AREA
))
1309 glyph
= row
->glyphs
[TEXT_AREA
];
1310 if (x
>= row
->used
[TEXT_AREA
])
1315 if (!BUFFERP (glyph
->object
))
1321 /* Clear mouse face if X/Y not over text. */
1324 clear_mouse_face (dpyinfo
);
1328 if (!BUFFERP (glyph
->object
))
1330 pos
= glyph
->charpos
;
1332 /* Check for mouse-face and help-echo. */
1334 extern Lisp_Object Qmouse_face
;
1335 Lisp_Object mouse_face
, overlay
, position
, *overlay_vec
;
1336 int noverlays
, obegv
, ozv
;
1337 struct buffer
*obuf
;
1339 /* If we get an out-of-range value, return now; avoid an error. */
1340 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1343 /* Make the window's buffer temporarily current for
1344 overlays_at and compute_char_face. */
1345 obuf
= current_buffer
;
1346 current_buffer
= XBUFFER (w
->buffer
);
1352 /* Is this char mouse-active or does it have help-echo? */
1353 XSETINT (position
, pos
);
1355 /* Put all the overlays we want in a vector in overlay_vec. */
1356 GET_OVERLAYS_AT (pos
, overlay_vec
, noverlays
, NULL
, 0);
1357 /* Sort overlays into increasing priority order. */
1358 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1360 /* Check mouse-face highlighting. */
1361 if (! (EQ (window
, dpyinfo
->mouse_face_window
)
1362 && y
>= dpyinfo
->mouse_face_beg_row
1363 && y
<= dpyinfo
->mouse_face_end_row
1364 && (y
> dpyinfo
->mouse_face_beg_row
1365 || x
>= dpyinfo
->mouse_face_beg_col
)
1366 && (y
< dpyinfo
->mouse_face_end_row
1367 || x
< dpyinfo
->mouse_face_end_col
1368 || dpyinfo
->mouse_face_past_end
)))
1370 /* Clear the display of the old active region, if any. */
1371 clear_mouse_face (dpyinfo
);
1373 /* Find highest priority overlay that has a mouse-face prop. */
1375 for (i
= noverlays
- 1; i
>= 0; --i
)
1377 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1378 if (!NILP (mouse_face
))
1380 overlay
= overlay_vec
[i
];
1385 /* If no overlay applies, get a text property. */
1387 mouse_face
= Fget_text_property (position
, Qmouse_face
,
1390 /* Handle the overlay case. */
1391 if (! NILP (overlay
))
1393 /* Find the range of text around this char that
1394 should be active. */
1395 Lisp_Object before
, after
;
1398 before
= Foverlay_start (overlay
);
1399 after
= Foverlay_end (overlay
);
1400 /* Record this as the current active region. */
1401 fast_find_position (w
, XFASTINT (before
),
1402 &dpyinfo
->mouse_face_beg_col
,
1403 &dpyinfo
->mouse_face_beg_row
);
1404 dpyinfo
->mouse_face_past_end
1405 = !fast_find_position (w
, XFASTINT (after
),
1406 &dpyinfo
->mouse_face_end_col
,
1407 &dpyinfo
->mouse_face_end_row
);
1408 dpyinfo
->mouse_face_window
= window
;
1409 dpyinfo
->mouse_face_face_id
1410 = face_at_buffer_position (w
, pos
, 0, 0,
1412 !dpyinfo
->mouse_face_hidden
,
1415 /* Display it as active. */
1416 show_mouse_face (dpyinfo
, 1);
1418 /* Handle the text property case. */
1419 else if (! NILP (mouse_face
))
1421 /* Find the range of text around this char that
1422 should be active. */
1423 Lisp_Object before
, after
, beginning
, end
;
1426 beginning
= Fmarker_position (w
->start
);
1427 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
1428 - XFASTINT (w
->window_end_pos
)));
1430 = Fprevious_single_property_change (make_number (pos
+ 1),
1432 w
->buffer
, beginning
);
1434 = Fnext_single_property_change (position
, Qmouse_face
,
1436 /* Record this as the current active region. */
1437 fast_find_position (w
, XFASTINT (before
),
1438 &dpyinfo
->mouse_face_beg_col
,
1439 &dpyinfo
->mouse_face_beg_row
);
1440 dpyinfo
->mouse_face_past_end
1441 = !fast_find_position (w
, XFASTINT (after
),
1442 &dpyinfo
->mouse_face_end_col
,
1443 &dpyinfo
->mouse_face_end_row
);
1444 dpyinfo
->mouse_face_window
= window
;
1445 dpyinfo
->mouse_face_face_id
1446 = face_at_buffer_position (w
, pos
, 0, 0,
1448 !dpyinfo
->mouse_face_hidden
,
1451 /* Display it as active. */
1452 show_mouse_face (dpyinfo
, 1);
1456 /* Look for a `help-echo' property. */
1459 extern Lisp_Object Qhelp_echo
;
1461 /* Check overlays first. */
1463 for (i
= noverlays
- 1; i
>= 0 && NILP (help
); --i
)
1465 overlay
= overlay_vec
[i
];
1466 help
= Foverlay_get (overlay
, Qhelp_echo
);
1471 help_echo_string
= help
;
1472 help_echo_window
= window
;
1473 help_echo_object
= overlay
;
1474 help_echo_pos
= pos
;
1476 /* Try text properties. */
1477 else if (NILP (help
)
1478 && ((STRINGP (glyph
->object
)
1479 && glyph
->charpos
>= 0
1480 && glyph
->charpos
< SCHARS (glyph
->object
))
1481 || (BUFFERP (glyph
->object
)
1482 && glyph
->charpos
>= BEGV
1483 && glyph
->charpos
< ZV
)))
1485 help
= Fget_text_property (make_number (glyph
->charpos
),
1486 Qhelp_echo
, glyph
->object
);
1489 help_echo_string
= help
;
1490 help_echo_window
= window
;
1491 help_echo_object
= glyph
->object
;
1492 help_echo_pos
= glyph
->charpos
;
1499 current_buffer
= obuf
;
1505 IT_clear_end_of_line (struct frame
*f
, int first_unused
)
1508 int i
, j
, offset
= 2 * (new_pos_X
+ screen_size_X
* new_pos_Y
);
1509 extern int fatal_error_in_progress
;
1510 struct tty_display_info
*tty
= FRAME_TTY (f
);
1512 if (new_pos_X
>= first_unused
|| fatal_error_in_progress
)
1516 i
= (j
= first_unused
- new_pos_X
) * 2;
1517 if (tty
->termscript
)
1518 fprintf (tty
->termscript
, "<CLR:EOL[%d..%d)>", new_pos_X
, first_unused
);
1519 spaces
= sp
= alloca (i
);
1524 *sp
++ = ScreenAttrib
;
1528 dosmemput (spaces
, i
, (int)ScreenPrimary
+ offset
);
1529 if (screen_virtual_segment
)
1530 dosv_refresh_virtual_screen (offset
, i
/ 2);
1532 /* clear_end_of_line_raw on term.c leaves the cursor at first_unused.
1533 Let's follow their lead, in case someone relies on this. */
1534 new_pos_X
= first_unused
;
1538 IT_clear_screen (struct frame
*f
)
1540 struct tty_display_info
*tty
= FRAME_TTY (f
);
1542 if (tty
->termscript
)
1543 fprintf (tty
->termscript
, "<CLR:SCR>");
1544 /* We are sometimes called (from clear_garbaged_frames) when a new
1545 frame is being created, but its faces are not yet realized. In
1546 such a case we cannot call IT_set_face, since it will fail to find
1547 any valid faces and will abort. Instead, use the initial screen
1548 colors; that should mimic what a Unix tty does, which simply clears
1549 the screen with whatever default colors are in use. */
1550 if (FACE_FROM_ID (SELECTED_FRAME (), DEFAULT_FACE_ID
) == NULL
)
1551 ScreenAttrib
= (initial_screen_colors
[0] << 4) | initial_screen_colors
[1];
1556 if (screen_virtual_segment
)
1557 dosv_refresh_virtual_screen (0, screen_size
);
1558 new_pos_X
= new_pos_Y
= 0;
1562 IT_clear_to_end (struct frame
*f
)
1564 struct tty_display_info
*tty
= FRAME_TTY (f
);
1566 if (tty
->termscript
)
1567 fprintf (tty
->termscript
, "<CLR:EOS>");
1569 while (new_pos_Y
< screen_size_Y
) {
1571 IT_clear_end_of_line (f
, screen_size_X
);
1577 IT_cursor_to (struct frame
*f
, int y
, int x
)
1579 struct tty_display_info
*tty
= FRAME_TTY (f
);
1581 if (tty
->termscript
)
1582 fprintf (tty
->termscript
, "\n<XY=%dx%d>", x
, y
);
1587 static int cursor_cleared
;
1590 IT_display_cursor (int on
)
1592 struct tty_display_info
*tty
= CURTTY ();
1594 if (on
&& cursor_cleared
)
1596 ScreenSetCursor (current_pos_Y
, current_pos_X
);
1598 if (tty
->termscript
)
1599 fprintf (tty
->termscript
, "\nCURSOR ON");
1601 else if (!on
&& !cursor_cleared
)
1603 ScreenSetCursor (-1, -1);
1605 if (tty
->termscript
)
1606 fprintf (tty
->termscript
, "\nCURSOR OFF");
1610 /* Emacs calls cursor-movement functions a lot when it updates the
1611 display (probably a legacy of old terminals where you cannot
1612 update a screen line without first moving the cursor there).
1613 However, cursor movement is expensive on MSDOS (it calls a slow
1614 BIOS function and requires 2 mode switches), while actual screen
1615 updates access the video memory directly and don't depend on
1616 cursor position. To avoid slowing down the redisplay, we cheat:
1617 all functions that move the cursor only set internal variables
1618 which record the cursor position, whereas the cursor is only
1619 moved to its final position whenever screen update is complete.
1621 `IT_cmgoto' is called from the keyboard reading loop and when the
1622 frame update is complete. This means that we are ready for user
1623 input, so we update the cursor position to show where the point is,
1624 and also make the mouse pointer visible.
1626 Special treatment is required when the cursor is in the echo area,
1627 to put the cursor at the end of the text displayed there. */
1630 IT_cmgoto (FRAME_PTR f
)
1632 /* Only set the cursor to where it should be if the display is
1633 already in sync with the window contents. */
1634 int update_cursor_pos
= 1; /* MODIFF == unchanged_modified; */
1635 struct tty_display_info
*tty
= FRAME_TTY (f
);
1637 /* FIXME: This needs to be rewritten for the new redisplay, or
1640 static int previous_pos_X
= -1;
1642 update_cursor_pos
= 1; /* temporary!!! */
1644 /* If the display is in sync, forget any previous knowledge about
1645 cursor position. This is primarily for unexpected events like
1646 C-g in the minibuffer. */
1647 if (update_cursor_pos
&& previous_pos_X
>= 0)
1648 previous_pos_X
= -1;
1649 /* If we are in the echo area, put the cursor at the
1650 end of the echo area message. */
1651 if (!update_cursor_pos
1652 && WINDOW_TOP_EDGE_LINE (XWINDOW (FRAME_MINIBUF_WINDOW (f
))) <= new_pos_Y
)
1654 int tem_X
= current_pos_X
, dummy
;
1656 if (echo_area_glyphs
)
1658 tem_X
= echo_area_glyphs_length
;
1659 /* Save current cursor position, to be restored after the
1660 echo area message is erased. Only remember one level
1661 of previous cursor position. */
1662 if (previous_pos_X
== -1)
1663 ScreenGetCursor (&dummy
, &previous_pos_X
);
1665 else if (previous_pos_X
>= 0)
1667 /* We wind up here after the echo area message is erased.
1668 Restore the cursor position we remembered above. */
1669 tem_X
= previous_pos_X
;
1670 previous_pos_X
= -1;
1673 if (current_pos_X
!= tem_X
)
1676 update_cursor_pos
= 1;
1681 if (update_cursor_pos
1682 && (current_pos_X
!= new_pos_X
|| current_pos_Y
!= new_pos_Y
))
1684 ScreenSetCursor (current_pos_Y
= new_pos_Y
, current_pos_X
= new_pos_X
);
1685 if (tty
->termscript
)
1686 fprintf (tty
->termscript
, "\n<CURSOR:%dx%d>", current_pos_X
, current_pos_Y
);
1689 /* Maybe cursor is invisible, so make it visible. */
1690 IT_display_cursor (1);
1692 /* Mouse pointer should be always visible if we are waiting for
1699 IT_update_begin (struct frame
*f
)
1701 struct tty_display_info
*display_info
= FRAME_X_DISPLAY_INFO (f
);
1702 struct frame
*mouse_face_frame
= display_info
->mouse_face_mouse_frame
;
1704 if (display_info
->termscript
)
1705 fprintf (display_info
->termscript
, "\n\n<UPDATE_BEGIN");
1709 if (f
&& f
== mouse_face_frame
)
1711 /* Don't do highlighting for mouse motion during the update. */
1712 display_info
->mouse_face_defer
= 1;
1714 /* If F needs to be redrawn, simply forget about any prior mouse
1716 if (FRAME_GARBAGED_P (f
))
1717 display_info
->mouse_face_window
= Qnil
;
1719 /* Can we tell that this update does not affect the window
1720 where the mouse highlight is? If so, no need to turn off.
1721 Likewise, don't do anything if none of the enabled rows
1722 contains glyphs highlighted in mouse face. */
1723 if (!NILP (display_info
->mouse_face_window
)
1724 && WINDOWP (display_info
->mouse_face_window
))
1726 struct window
*w
= XWINDOW (display_info
->mouse_face_window
);
1729 /* If the mouse highlight is in the window that was deleted
1730 (e.g., if it was popped by completion), clear highlight
1732 if (NILP (w
->buffer
))
1733 display_info
->mouse_face_window
= Qnil
;
1736 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1737 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
)
1738 && MATRIX_ROW (w
->current_matrix
, i
)->mouse_face_p
)
1742 if (NILP (w
->buffer
) || i
< w
->desired_matrix
->nrows
)
1743 clear_mouse_face (display_info
);
1746 else if (mouse_face_frame
&& !FRAME_LIVE_P (mouse_face_frame
))
1748 /* If the frame with mouse highlight was deleted, invalidate the
1750 display_info
->mouse_face_beg_row
= display_info
->mouse_face_beg_col
= -1;
1751 display_info
->mouse_face_end_row
= display_info
->mouse_face_end_col
= -1;
1752 display_info
->mouse_face_window
= Qnil
;
1753 display_info
->mouse_face_deferred_gc
= 0;
1754 display_info
->mouse_face_mouse_frame
= NULL
;
1761 IT_update_end (struct frame
*f
)
1763 struct tty_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
1765 if (dpyinfo
->termscript
)
1766 fprintf (dpyinfo
->termscript
, "\n<UPDATE_END\n");
1767 dpyinfo
->mouse_face_defer
= 0;
1771 IT_frame_up_to_date (struct frame
*f
)
1773 struct tty_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
1774 Lisp_Object new_cursor
, frame_desired_cursor
;
1777 if (dpyinfo
->mouse_face_deferred_gc
1778 || (f
&& f
== dpyinfo
->mouse_face_mouse_frame
))
1781 if (dpyinfo
->mouse_face_mouse_frame
)
1782 IT_note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1783 dpyinfo
->mouse_face_mouse_x
,
1784 dpyinfo
->mouse_face_mouse_y
);
1785 dpyinfo
->mouse_face_deferred_gc
= 0;
1789 /* Set the cursor type to whatever they wanted. In a minibuffer
1790 window, we want the cursor to appear only if we are reading input
1791 from this window, and we want the cursor to be taken from the
1792 frame parameters. For the selected window, we use either its
1793 buffer-local value or the value from the frame parameters if the
1794 buffer doesn't define its local value for the cursor type. */
1795 sw
= XWINDOW (f
->selected_window
);
1796 frame_desired_cursor
= Fcdr (Fassq (Qcursor_type
, f
->param_alist
));
1797 if (cursor_in_echo_area
1798 && FRAME_HAS_MINIBUF_P (f
)
1799 && EQ (FRAME_MINIBUF_WINDOW (f
), echo_area_window
)
1800 && sw
== XWINDOW (echo_area_window
))
1801 new_cursor
= frame_desired_cursor
;
1804 struct buffer
*b
= XBUFFER (sw
->buffer
);
1806 if (EQ (b
->cursor_type
, Qt
))
1807 new_cursor
= frame_desired_cursor
;
1808 else if (NILP (b
->cursor_type
)) /* nil means no cursor */
1809 new_cursor
= Fcons (Qbar
, make_number (0));
1811 new_cursor
= b
->cursor_type
;
1814 IT_set_cursor_type (f
, new_cursor
);
1816 IT_cmgoto (f
); /* position cursor when update is done */
1819 /* Copy LEN glyphs displayed on a single line whose vertical position
1820 is YPOS, beginning at horizontal position XFROM to horizontal
1821 position XTO, by moving blocks in the video memory. Used by
1822 functions that insert and delete glyphs. */
1824 IT_copy_glyphs (int xfrom
, int xto
, size_t len
, int ypos
)
1826 /* The offsets of source and destination relative to the
1827 conventional memorty selector. */
1828 int from
= 2 * (xfrom
+ screen_size_X
* ypos
) + ScreenPrimary
;
1829 int to
= 2 * (xto
+ screen_size_X
* ypos
) + ScreenPrimary
;
1831 if (from
== to
|| len
<= 0)
1834 _farsetsel (_dos_ds
);
1836 /* The source and destination might overlap, so we need to move
1837 glyphs non-destructively. */
1840 for ( ; len
; from
+= 2, to
+= 2, len
--)
1841 _farnspokew (to
, _farnspeekw (from
));
1845 from
+= (len
- 1) * 2;
1846 to
+= (len
- 1) * 2;
1847 for ( ; len
; from
-= 2, to
-= 2, len
--)
1848 _farnspokew (to
, _farnspeekw (from
));
1850 if (screen_virtual_segment
)
1851 dosv_refresh_virtual_screen (ypos
* screen_size_X
* 2, screen_size_X
);
1854 /* Insert and delete glyphs. */
1856 IT_insert_glyphs (struct frame
*f
, struct glyph
*start
, int len
)
1858 int shift_by_width
= screen_size_X
- (new_pos_X
+ len
);
1860 /* Shift right the glyphs from the nominal cursor position to the
1861 end of this line. */
1862 IT_copy_glyphs (new_pos_X
, new_pos_X
+ len
, shift_by_width
, new_pos_Y
);
1864 /* Now write the glyphs to be inserted. */
1865 IT_write_glyphs (f
, start
, len
);
1869 IT_delete_glyphs (struct frame
*f
, int n
)
1874 /* set-window-configuration on window.c needs this. */
1876 x_set_menu_bar_lines (struct frame
*f
, Lisp_Object value
, Lisp_Object oldval
)
1878 set_menu_bar_lines (f
, value
, oldval
);
1881 /* This was copied from xfaces.c */
1883 extern Lisp_Object Qbackground_color
;
1884 extern Lisp_Object Qforeground_color
;
1885 Lisp_Object Qreverse
;
1886 extern Lisp_Object Qtitle
;
1888 /* IT_set_terminal_modes is called when emacs is started,
1889 resumed, and whenever the screen is redrawn! */
1892 IT_set_terminal_modes (struct terminal
*term
)
1894 struct tty_display_info
*tty
;
1896 /* If called with initial terminal, it's too early to do anything
1898 if (term
->type
== output_initial
)
1901 tty
= term
->display_info
.tty
;
1903 if (tty
->termscript
)
1904 fprintf (tty
->termscript
, "\n<SET_TERM>");
1906 screen_size_X
= ScreenCols ();
1907 screen_size_Y
= ScreenRows ();
1908 screen_size
= screen_size_X
* screen_size_Y
;
1910 new_pos_X
= new_pos_Y
= 0;
1911 current_pos_X
= current_pos_Y
= -1;
1913 if (term_setup_done
)
1915 term_setup_done
= 1;
1917 startup_screen_size_X
= screen_size_X
;
1918 startup_screen_size_Y
= screen_size_Y
;
1919 startup_screen_attrib
= ScreenAttrib
;
1921 /* Is DOS/V (or any other RSIS software which relocates
1922 the screen) installed? */
1924 unsigned short es_value
;
1927 regs
.h
.ah
= 0xfe; /* get relocated screen address */
1928 if (ScreenPrimary
== 0xb0000UL
|| ScreenPrimary
== 0xb8000UL
)
1929 regs
.x
.es
= (ScreenPrimary
>> 4) & 0xffff;
1930 else if (screen_old_address
) /* already switched to Japanese mode once */
1931 regs
.x
.es
= (screen_old_address
>> 4) & 0xffff;
1933 regs
.x
.es
= ScreenMode () == 7 ? 0xb000 : 0xb800;
1935 es_value
= regs
.x
.es
;
1936 __dpmi_int (0x10, ®s
);
1938 if (regs
.x
.es
!= es_value
)
1940 /* screen_old_address is only set if ScreenPrimary does NOT
1941 already point to the relocated buffer address returned by
1942 the Int 10h/AX=FEh call above. DJGPP v2.02 and later sets
1943 ScreenPrimary to that address at startup under DOS/V. */
1944 if (regs
.x
.es
!= (ScreenPrimary
>> 4) & 0xffff)
1945 screen_old_address
= ScreenPrimary
;
1946 screen_virtual_segment
= regs
.x
.es
;
1947 screen_virtual_offset
= regs
.x
.di
;
1948 ScreenPrimary
= (screen_virtual_segment
<< 4) + screen_virtual_offset
;
1952 ScreenGetCursor (&startup_pos_Y
, &startup_pos_X
);
1953 ScreenRetrieve (startup_screen_buffer
= xmalloc (screen_size
* 2));
1958 /* IT_reset_terminal_modes is called when emacs is
1959 suspended or killed. */
1962 IT_reset_terminal_modes (struct terminal
*term
)
1964 int display_row_start
= (int) ScreenPrimary
;
1965 int saved_row_len
= startup_screen_size_X
* 2;
1966 int update_row_len
= ScreenCols () * 2, current_rows
= ScreenRows ();
1967 int to_next_row
= update_row_len
;
1968 unsigned char *saved_row
= startup_screen_buffer
;
1969 int cursor_pos_X
= ScreenCols () - 1, cursor_pos_Y
= ScreenRows () - 1;
1970 struct tty_display_info
*tty
= term
->display_info
.tty
;
1972 if (tty
->termscript
)
1973 fprintf (tty
->termscript
, "\n<RESET_TERM>");
1975 if (!term_setup_done
)
1980 /* Leave the video system in the same state as we found it,
1981 as far as the blink/bright-background bit is concerned. */
1982 maybe_enable_blinking ();
1984 /* We have a situation here.
1985 We cannot just do ScreenUpdate(startup_screen_buffer) because
1986 the luser could have changed screen dimensions inside Emacs
1987 and failed (or didn't want) to restore them before killing
1988 Emacs. ScreenUpdate() uses the *current* screen dimensions and
1989 thus will happily use memory outside what was allocated for
1990 `startup_screen_buffer'.
1991 Thus we only restore as much as the current screen dimensions
1992 can hold, and clear the rest (if the saved screen is smaller than
1993 the current) with the color attribute saved at startup. The cursor
1994 is also restored within the visible dimensions. */
1996 ScreenAttrib
= startup_screen_attrib
;
1998 /* Don't restore the screen if we are exiting less than 2 seconds
1999 after startup: we might be crashing, and the screen might show
2000 some vital clues to what's wrong. */
2001 if (clock () - startup_time
>= 2*CLOCKS_PER_SEC
)
2004 if (screen_virtual_segment
)
2005 dosv_refresh_virtual_screen (0, screen_size
);
2007 if (update_row_len
> saved_row_len
)
2008 update_row_len
= saved_row_len
;
2009 if (current_rows
> startup_screen_size_Y
)
2010 current_rows
= startup_screen_size_Y
;
2012 if (tty
->termscript
)
2013 fprintf (tty
->termscript
, "<SCREEN RESTORED (dimensions=%dx%d)>\n",
2014 update_row_len
/ 2, current_rows
);
2016 while (current_rows
--)
2018 dosmemput (saved_row
, update_row_len
, display_row_start
);
2019 if (screen_virtual_segment
)
2020 dosv_refresh_virtual_screen (display_row_start
- ScreenPrimary
,
2021 update_row_len
/ 2);
2022 saved_row
+= saved_row_len
;
2023 display_row_start
+= to_next_row
;
2026 if (startup_pos_X
< cursor_pos_X
)
2027 cursor_pos_X
= startup_pos_X
;
2028 if (startup_pos_Y
< cursor_pos_Y
)
2029 cursor_pos_Y
= startup_pos_Y
;
2031 ScreenSetCursor (cursor_pos_Y
, cursor_pos_X
);
2032 xfree (startup_screen_buffer
);
2033 startup_screen_buffer
= NULL
;
2035 term_setup_done
= 0;
2039 IT_set_terminal_window (struct frame
*f
, int foo
)
2043 /* Remember the screen colors of the curent frame, to serve as the
2044 default colors for newly-created frames. */
2045 DEFUN ("msdos-remember-default-colors", Fmsdos_remember_default_colors
,
2046 Smsdos_remember_default_colors
, 1, 1, 0,
2047 doc
: /* Remember the screen colors of the current frame. */)
2053 CHECK_FRAME (frame
);
2056 /* This function is called after applying default-frame-alist to the
2057 initial frame. At that time, if reverse-colors option was
2058 specified in default-frame-alist, it was already applied, and
2059 frame colors are reversed. */
2060 initial_screen_colors
[0] = FRAME_FOREGROUND_PIXEL (f
);
2061 initial_screen_colors
[1] = FRAME_BACKGROUND_PIXEL (f
);
2065 IT_set_frame_parameters (struct frame
*f
, Lisp_Object alist
)
2068 int i
, j
, length
= XINT (Flength (alist
));
2070 = (Lisp_Object
*) alloca (length
* sizeof (Lisp_Object
));
2072 = (Lisp_Object
*) alloca (length
* sizeof (Lisp_Object
));
2073 /* Do we have to reverse the foreground and background colors? */
2074 int reverse
= EQ (Fcdr (Fassq (Qreverse
, f
->param_alist
)), Qt
);
2075 int redraw
= 0, fg_set
= 0, bg_set
= 0;
2076 unsigned long orig_fg
, orig_bg
;
2077 Lisp_Object frame_bg
, frame_fg
;
2078 struct tty_display_info
*tty
= FRAME_TTY (f
);
2079 extern Lisp_Object Qmenu_bar_lines
;
2080 extern Lisp_Object Vmenu_bar_mode
;
2081 int menu_bar_lines_defined
=
2082 !NILP (Fassq (Qmenu_bar_lines
, Vdefault_frame_alist
));
2084 /* If we are creating a new frame, begin with the original screen colors
2085 used for the initial frame. */
2086 if (!f
->default_face_done_p
2087 && initial_screen_colors
[0] != -1 && initial_screen_colors
[1] != -1)
2089 FRAME_FOREGROUND_PIXEL (f
) = initial_screen_colors
[0];
2090 FRAME_BACKGROUND_PIXEL (f
) = initial_screen_colors
[1];
2091 init_frame_faces (f
);
2092 f
->default_face_done_p
= 1;
2094 orig_fg
= reverse
? FRAME_BACKGROUND_PIXEL (f
) : FRAME_FOREGROUND_PIXEL (f
);
2095 orig_bg
= reverse
? FRAME_FOREGROUND_PIXEL (f
) : FRAME_BACKGROUND_PIXEL (f
);
2097 /* Extract parm names and values into those vectors. */
2099 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
2104 parms
[i
] = Fcar (elt
);
2105 CHECK_SYMBOL (parms
[i
]);
2106 values
[i
] = Fcdr (elt
);
2112 for (i
= 0; i
< j
; i
++)
2114 Lisp_Object prop
, val
;
2119 if (EQ (prop
, Qreverse
))
2120 reverse
= EQ (val
, Qt
);
2121 else if (!menu_bar_lines_defined
&& EQ (prop
, Qmenu_bar_lines
))
2122 menu_bar_lines_defined
= 1;
2125 if (tty
->termscript
&& reverse
)
2126 fprintf (tty
->termscript
, "<INVERSE-VIDEO>\n");
2128 /* Now process the alist elements in reverse of specified order. */
2129 for (i
--; i
>= 0; i
--)
2131 Lisp_Object prop
, val
;
2136 if (EQ (prop
, Qforeground_color
))
2138 unsigned long new_color
= load_color (f
, NULL
, val
, reverse
2139 ? LFACE_BACKGROUND_INDEX
2140 : LFACE_FOREGROUND_INDEX
);
2141 if (new_color
!= FACE_TTY_DEFAULT_COLOR
2142 && new_color
!= FACE_TTY_DEFAULT_FG_COLOR
2143 && new_color
!= FACE_TTY_DEFAULT_BG_COLOR
)
2147 FRAME_FOREGROUND_PIXEL (f
) = new_color
;
2148 /* Make sure the foreground of the default face for
2149 this frame is changed as well. */
2150 update_face_from_frame_parameter (f
, Qforeground_color
, val
);
2152 if (tty
->termscript
)
2153 fprintf (tty
->termscript
, "<FGCOLOR %lu>\n", new_color
);
2157 FRAME_BACKGROUND_PIXEL (f
) = new_color
;
2158 update_face_from_frame_parameter (f
, Qbackground_color
, val
);
2160 if (tty
->termscript
)
2161 fprintf (tty
->termscript
, "<BGCOLOR %lu>\n", new_color
);
2166 else if (EQ (prop
, Qbackground_color
))
2168 unsigned long new_color
= load_color (f
, NULL
, val
, reverse
2169 ? LFACE_FOREGROUND_INDEX
2170 : LFACE_BACKGROUND_INDEX
);
2171 if (new_color
!= FACE_TTY_DEFAULT_COLOR
2172 && new_color
!= FACE_TTY_DEFAULT_FG_COLOR
2173 && new_color
!= FACE_TTY_DEFAULT_BG_COLOR
)
2177 FRAME_BACKGROUND_PIXEL (f
) = new_color
;
2178 /* Make sure the background of the default face for
2179 this frame is changed as well. */
2181 update_face_from_frame_parameter (f
, Qbackground_color
, val
);
2182 if (tty
->termscript
)
2183 fprintf (tty
->termscript
, "<BGCOLOR %lu>\n", new_color
);
2187 FRAME_FOREGROUND_PIXEL (f
) = new_color
;
2189 update_face_from_frame_parameter (f
, Qforeground_color
, val
);
2190 if (tty
->termscript
)
2191 fprintf (tty
->termscript
, "<FGCOLOR %lu>\n", new_color
);
2196 else if (EQ (prop
, Qtitle
))
2198 x_set_title (f
, val
);
2199 if (tty
->termscript
)
2200 fprintf (tty
->termscript
, "<TITLE: %s>\n", SDATA (val
));
2202 else if (EQ (prop
, Qcursor_type
))
2204 IT_set_cursor_type (f
, val
);
2205 if (tty
->termscript
)
2206 fprintf (tty
->termscript
, "<CTYPE: %s>\n",
2207 EQ (val
, Qbar
) || EQ (val
, Qhbar
)
2208 || CONSP (val
) && (EQ (XCAR (val
), Qbar
)
2209 || EQ (XCAR (val
), Qhbar
))
2212 else if (EQ (prop
, Qtty_type
))
2214 internal_terminal_init ();
2215 if (tty
->termscript
)
2216 fprintf (tty
->termscript
, "<TERM_INIT done, TTY_TYPE: %.*s>\n",
2217 SBYTES (val
), SDATA (val
));
2219 store_frame_param (f
, prop
, val
);
2222 /* If menu-bar-lines is neither in the frame parameters nor in
2223 default-frame-alist, set it according to menu-bar-mode. */
2224 if (!menu_bar_lines_defined
)
2226 store_frame_param (f
, Qmenu_bar_lines
,
2227 NILP (Vmenu_bar_mode
)
2228 ? make_number (0) : make_number (1));
2229 if (tty
->termscript
)
2230 fprintf (tty
->termscript
, "<MENU BAR LINES DEFAULTED: %d\n",
2231 !NILP (Vmenu_bar_mode
));
2234 /* If they specified "reverse", but not the colors, we need to swap
2235 the current frame colors. */
2242 FRAME_FOREGROUND_PIXEL (f
) = orig_bg
;
2243 update_face_from_frame_parameter (f
, Qforeground_color
,
2244 tty_color_name (f
, orig_bg
));
2249 FRAME_BACKGROUND_PIXEL (f
) = orig_fg
;
2250 update_face_from_frame_parameter (f
, Qbackground_color
,
2251 tty_color_name (f
, orig_fg
));
2258 face_change_count
++; /* forces xdisp.c to recompute basic faces */
2259 if (f
== SELECTED_FRAME())
2264 extern void init_frame_faces (FRAME_PTR
);
2266 #endif /* !HAVE_X_WINDOWS */
2269 /* Do we need the internal terminal? */
2272 internal_terminal_init (void)
2274 static int init_needed
= 1;
2275 char *term
= getenv ("TERM"), *colors
;
2276 struct frame
*sf
= SELECTED_FRAME();
2277 struct tty_display_info
*tty
;
2279 #ifdef HAVE_X_WINDOWS
2280 if (!inhibit_window_system
)
2284 /* If this is the initial terminal, we are done here. */
2285 if (sf
->output_method
== output_initial
)
2289 = (!noninteractive
) && term
&& !strcmp (term
, "internal");
2291 #ifndef HAVE_X_WINDOWS
2292 if (!internal_terminal
|| inhibit_window_system
)
2294 sf
->output_method
= output_termcap
;
2298 tty
= FRAME_TTY (sf
);
2299 current_kboard
->Vwindow_system
= Qpc
;
2300 sf
->output_method
= output_msdos_raw
;
2303 if (!tty
->termscript
&& getenv ("EMACSTEST"))
2304 tty
->termscript
= fopen (getenv ("EMACSTEST"), "wt");
2305 if (tty
->termscript
)
2307 time_t now
= time (NULL
);
2308 struct tm
*tnow
= localtime (&now
);
2311 strftime (tbuf
, sizeof (tbuf
) - 1, "%a %b %e %Y %H:%M:%S %Z", tnow
);
2312 fprintf (tty
->termscript
, "\nEmacs session started at %s\n", tbuf
);
2313 fprintf (tty
->termscript
, "=====================\n\n");
2316 Vinitial_window_system
= Qpc
;
2317 Vwindow_system_version
= make_number (23); /* RE Emacs version */
2318 tty
->terminal
->type
= output_msdos_raw
;
2320 /* If Emacs was dumped on DOS/V machine, forget the stale VRAM
2322 screen_old_address
= 0;
2324 /* Forget the stale screen colors as well. */
2325 initial_screen_colors
[0] = initial_screen_colors
[1] = -1;
2327 FRAME_BACKGROUND_PIXEL (SELECTED_FRAME ()) = 7; /* White */
2328 FRAME_FOREGROUND_PIXEL (SELECTED_FRAME ()) = 0; /* Black */
2330 colors
= getenv ("EMACSCOLORS");
2331 if (colors
&& strlen (colors
) >= 2)
2333 /* The colors use 4 bits each (we enable bright background). */
2334 if (isdigit (colors
[0]))
2336 else if (isxdigit (colors
[0]))
2337 colors
[0] -= (isupper (colors
[0]) ? 'A' : 'a') - 10;
2338 if (colors
[0] >= 0 && colors
[0] < 16)
2339 FRAME_FOREGROUND_PIXEL (SELECTED_FRAME ()) = colors
[0];
2340 if (isdigit (colors
[1]))
2342 else if (isxdigit (colors
[1]))
2343 colors
[1] -= (isupper (colors
[1]) ? 'A' : 'a') - 10;
2344 if (colors
[1] >= 0 && colors
[1] < 16)
2345 FRAME_BACKGROUND_PIXEL (SELECTED_FRAME ()) = colors
[1];
2347 the_only_display_info
.mouse_face_mouse_frame
= NULL
;
2348 the_only_display_info
.mouse_face_deferred_gc
= 0;
2349 the_only_display_info
.mouse_face_beg_row
=
2350 the_only_display_info
.mouse_face_beg_col
= -1;
2351 the_only_display_info
.mouse_face_end_row
=
2352 the_only_display_info
.mouse_face_end_col
= -1;
2353 the_only_display_info
.mouse_face_face_id
= DEFAULT_FACE_ID
;
2354 the_only_display_info
.mouse_face_window
= Qnil
;
2355 the_only_display_info
.mouse_face_mouse_x
=
2356 the_only_display_info
.mouse_face_mouse_y
= 0;
2357 the_only_display_info
.mouse_face_defer
= 0;
2358 the_only_display_info
.mouse_face_hidden
= 0;
2360 if (have_mouse
) /* detected in dos_ttraw, which see */
2362 have_mouse
= 1; /* enable mouse */
2364 mouse_setup_buttons (mouse_button_count
);
2365 tty
->terminal
->mouse_position_hook
= &mouse_get_pos
;
2369 if (tty
->termscript
&& screen_size
)
2370 fprintf (tty
->termscript
, "<SCREEN SAVED (dimensions=%dx%d)>\n",
2371 screen_size_X
, screen_size_Y
);
2373 init_frame_faces (sf
);
2380 initialize_msdos_display (struct terminal
*term
)
2382 term
->rif
= 0; /* we don't support window-based display */
2383 term
->cursor_to_hook
= term
->raw_cursor_to_hook
= IT_cursor_to
;
2384 term
->clear_to_end_hook
= IT_clear_to_end
;
2385 term
->clear_frame_hook
= IT_clear_screen
;
2386 term
->clear_end_of_line_hook
= IT_clear_end_of_line
;
2387 term
->ins_del_lines_hook
= 0;
2388 term
->insert_glyphs_hook
= IT_insert_glyphs
;
2389 term
->write_glyphs_hook
= IT_write_glyphs
;
2390 term
->delete_glyphs_hook
= IT_delete_glyphs
;
2391 term
->ring_bell_hook
= IT_ring_bell
;
2392 term
->reset_terminal_modes_hook
= IT_reset_terminal_modes
;
2393 term
->set_terminal_modes_hook
= IT_set_terminal_modes
;
2394 term
->set_terminal_window_hook
= IT_set_terminal_window
;
2395 term
->update_begin_hook
= IT_update_begin
;
2396 term
->update_end_hook
= IT_update_end
;
2397 term
->frame_up_to_date_hook
= IT_frame_up_to_date
;
2398 term
->mouse_position_hook
= 0; /* set later by dos_ttraw */
2399 term
->frame_rehighlight_hook
= 0;
2400 term
->frame_raise_lower_hook
= 0;
2401 term
->set_vertical_scroll_bar_hook
= 0;
2402 term
->condemn_scroll_bars_hook
= 0;
2403 term
->redeem_scroll_bar_hook
= 0;
2404 term
->judge_scroll_bars_hook
= 0;
2405 term
->read_socket_hook
= &tty_read_avail_input
; /* from keyboard.c */
2409 dos_get_saved_screen (char **screen
, int *rows
, int *cols
)
2411 #ifndef HAVE_X_WINDOWS
2412 *screen
= startup_screen_buffer
;
2413 *cols
= startup_screen_size_X
;
2414 *rows
= startup_screen_size_Y
;
2415 return *screen
!= (char *)0;
2421 #ifndef HAVE_X_WINDOWS
2423 /* We are not X, but we can emulate it well enough for our needs... */
2427 if (! FRAME_MSDOS_P (SELECTED_FRAME()))
2428 error ("Not running under a window system");
2434 /* ----------------------- Keyboard control ----------------------
2436 * Keymaps reflect the following keyboard layout:
2438 * 0 1 2 3 4 5 6 7 8 9 10 11 12 BS
2439 * TAB 15 16 17 18 19 20 21 22 23 24 25 26 (41)
2440 * CLOK 30 31 32 33 34 35 36 37 38 39 40 (41) RET
2441 * SH () 45 46 47 48 49 50 51 52 53 54 SHIFT
2445 #define Ignore 0x0000
2446 #define Normal 0x0000 /* normal key - alt changes scan-code */
2447 #define FctKey 0x1000 /* func key if c == 0, else c */
2448 #define Special 0x2000 /* func key even if c != 0 */
2449 #define ModFct 0x3000 /* special if mod-keys, else 'c' */
2450 #define Map 0x4000 /* alt scan-code, map to unshift/shift key */
2451 #define KeyPad 0x5000 /* map to insert/kp-0 depending on c == 0xe0 */
2452 #define Grey 0x6000 /* Grey keypad key */
2454 #define Alt 0x0100 /* alt scan-code */
2455 #define Ctrl 0x0200 /* ctrl scan-code */
2456 #define Shift 0x0400 /* shift scan-code */
2458 static int extended_kbd
; /* 101 (102) keyboard present. */
2460 struct kbd_translate
{
2463 unsigned short code
;
2466 struct dos_keyboard_map
2471 struct kbd_translate
*translate_table
;
2475 static struct dos_keyboard_map us_keyboard
= {
2477 /* 01234567890123456789012345678901234567890 12345678901234 */
2478 "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ",
2479 /* 0123456789012345678901234567890123456789 012345678901234 */
2480 "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ",
2481 0, /* no Alt-Gr key */
2482 0 /* no translate table */
2485 static struct dos_keyboard_map fr_keyboard
= {
2487 /* 012 3456789012345678901234567890123456789012345678901234 */
2488 "ý&\82\",(-\8a_\80\85)= azertyuiop^$ qsdfghjklm\97* wxcvbnm;:! ",
2489 /* 0123456789012345678901234567890123456789012345678901234 */
2490 " 1234567890ø+ AZERTYUIOPù\9c QSDFGHJKLM%æ WXCVBN?./õ ",
2491 /* 01234567 89012345678901234567890123456789012345678901234 */
2493 0 /* no translate table */
2497 * Italian keyboard support, country code 39.
2500 * added also {,},` as, respectively, AltGr-8, AltGr-9, AltGr-'
2501 * Donated by Stefano Brozzi <brozzis@mag00.cedi.unipr.it>
2504 static struct kbd_translate it_kbd_translate_table
[] = {
2505 { 0x56, 0x3c, Normal
| 13 },
2506 { 0x56, 0x3e, Normal
| 27 },
2509 static struct dos_keyboard_map it_keyboard
= {
2511 /* 0 123456789012345678901234567890123456789012345678901234 */
2512 "\\1234567890'\8d< qwertyuiop\8a+> asdfghjkl\95\85\97 zxcvbnm,.- ",
2513 /* 01 23456789012345678901234567890123456789012345678901234 */
2514 "|!\"\9c$%&/()=?^> QWERTYUIOP\82* ASDFGHJKL\87øõ ZXCVBNM;:_ ",
2515 /* 0123456789012345678901234567890123456789012345678901234 */
2517 it_kbd_translate_table
2520 static struct dos_keyboard_map dk_keyboard
= {
2522 /* 0123456789012345678901234567890123456789012345678901234 */
2523 "«1234567890+| qwertyuiop\86~ asdfghjkl\91\9b' zxcvbnm,.- ",
2524 /* 01 23456789012345678901234567890123456789012345678901234 */
2525 "õ!\"#$%&/()=?` QWERTYUIOP\8f^ ASDFGHJKL\92\9d* ZXCVBNM;:_ ",
2526 /* 0123456789012345678901234567890123456789012345678901234 */
2528 0 /* no translate table */
2531 static struct kbd_translate jp_kbd_translate_table
[] = {
2532 { 0x73, 0x5c, Normal
| 0 },
2533 { 0x73, 0x5f, Normal
| 0 },
2534 { 0x73, 0x1c, Map
| 0 },
2535 { 0x7d, 0x5c, Normal
| 13 },
2536 { 0x7d, 0x7c, Normal
| 13 },
2537 { 0x7d, 0x1c, Map
| 13 },
2540 static struct dos_keyboard_map jp_keyboard
= {
2542 /* 0123456789012 345678901234567890123456789012345678901234 */
2543 "\\1234567890-^\\ qwertyuiop@[ asdfghjkl;:] zxcvbnm,./ ",
2544 /* 01 23456789012345678901234567890123456789012345678901234 */
2545 "_!\"#$%&'()~=~| QWERTYUIOP`{ ASDFGHJKL+*} ZXCVBNM<>? ",
2546 0, /* no Alt-Gr key */
2547 jp_kbd_translate_table
2550 static struct keyboard_layout_list
2553 struct dos_keyboard_map
*keyboard_map
;
2554 } keyboard_layout_list
[] =
2563 static struct dos_keyboard_map
*keyboard
;
2564 static int keyboard_map_all
;
2565 static int international_keyboard
;
2568 dos_set_keyboard (int code
, int always
)
2571 _go32_dpmi_registers regs
;
2573 /* See if Keyb.Com is installed (for international keyboard support).
2574 Note: calling Int 2Fh via int86 wedges the DOS box on some versions
2575 of Windows 9X! So don't do that! */
2577 regs
.x
.ss
= regs
.x
.sp
= regs
.x
.flags
= 0;
2578 _go32_dpmi_simulate_int (0x2f, ®s
);
2579 if (regs
.h
.al
== 0xff)
2580 international_keyboard
= 1;
2582 /* Initialize to US settings, for countries that don't have their own. */
2583 keyboard
= keyboard_layout_list
[0].keyboard_map
;
2584 keyboard_map_all
= always
;
2585 dos_keyboard_layout
= 1;
2587 for (i
= 0; i
< (sizeof (keyboard_layout_list
)/sizeof (struct keyboard_layout_list
)); i
++)
2588 if (code
== keyboard_layout_list
[i
].country_code
)
2590 keyboard
= keyboard_layout_list
[i
].keyboard_map
;
2591 keyboard_map_all
= always
;
2592 dos_keyboard_layout
= code
;
2600 unsigned char char_code
; /* normal code */
2601 unsigned char meta_code
; /* M- code */
2602 unsigned char keypad_code
; /* keypad code */
2603 unsigned char editkey_code
; /* edit key */
2604 } keypad_translate_map
[] = {
2605 '0', '0', 0xb0, /* kp-0 */ 0x63, /* insert */
2606 '1', '1', 0xb1, /* kp-1 */ 0x57, /* end */
2607 '2', '2', 0xb2, /* kp-2 */ 0x54, /* down */
2608 '3', '3', 0xb3, /* kp-3 */ 0x56, /* next */
2609 '4', '4', 0xb4, /* kp-4 */ 0x51, /* left */
2610 '5', '5', 0xb5, /* kp-5 */ 0xb5, /* kp-5 */
2611 '6', '6', 0xb6, /* kp-6 */ 0x53, /* right */
2612 '7', '7', 0xb7, /* kp-7 */ 0x50, /* home */
2613 '8', '8', 0xb8, /* kp-8 */ 0x52, /* up */
2614 '9', '9', 0xb9, /* kp-9 */ 0x55, /* prior */
2615 '.', '-', 0xae, /* kp-decimal */ 0xff /* delete */
2620 unsigned char char_code
; /* normal code */
2621 unsigned char keypad_code
; /* keypad code */
2622 } grey_key_translate_map
[] = {
2623 '/', 0xaf, /* kp-decimal */
2624 '*', 0xaa, /* kp-multiply */
2625 '-', 0xad, /* kp-subtract */
2626 '+', 0xab, /* kp-add */
2627 '\r', 0x8d /* kp-enter */
2630 static unsigned short
2631 ibmpc_translate_map
[] =
2633 /* --------------- 00 to 0f --------------- */
2634 Normal
| 0xff, /* Ctrl Break + Alt-NNN */
2635 Alt
| ModFct
| 0x1b, /* Escape */
2636 Normal
| 1, /* '1' */
2637 Normal
| 2, /* '2' */
2638 Normal
| 3, /* '3' */
2639 Normal
| 4, /* '4' */
2640 Normal
| 5, /* '5' */
2641 Normal
| 6, /* '6' */
2642 Normal
| 7, /* '7' */
2643 Normal
| 8, /* '8' */
2644 Normal
| 9, /* '9' */
2645 Normal
| 10, /* '0' */
2646 Normal
| 11, /* '-' */
2647 Normal
| 12, /* '=' */
2648 Special
| 0x08, /* Backspace */
2649 ModFct
| 0x74, /* Tab/Backtab */
2651 /* --------------- 10 to 1f --------------- */
2664 ModFct
| 0x0d, /* Return */
2669 /* --------------- 20 to 2f --------------- */
2678 Map
| 40, /* '\'' */
2680 Ignore
, /* Left shift */
2681 Map
| 41, /* '\\' */
2687 /* --------------- 30 to 3f --------------- */
2694 Ignore
, /* Right shift */
2695 Grey
| 1, /* Grey * */
2697 Normal
| 55, /* ' ' */
2698 Ignore
, /* Caps Lock */
2699 FctKey
| 0xbe, /* F1 */
2700 FctKey
| 0xbf, /* F2 */
2701 FctKey
| 0xc0, /* F3 */
2702 FctKey
| 0xc1, /* F4 */
2703 FctKey
| 0xc2, /* F5 */
2705 /* --------------- 40 to 4f --------------- */
2706 FctKey
| 0xc3, /* F6 */
2707 FctKey
| 0xc4, /* F7 */
2708 FctKey
| 0xc5, /* F8 */
2709 FctKey
| 0xc6, /* F9 */
2710 FctKey
| 0xc7, /* F10 */
2711 Ignore
, /* Num Lock */
2712 Ignore
, /* Scroll Lock */
2713 KeyPad
| 7, /* Home */
2714 KeyPad
| 8, /* Up */
2715 KeyPad
| 9, /* Page Up */
2716 Grey
| 2, /* Grey - */
2717 KeyPad
| 4, /* Left */
2718 KeyPad
| 5, /* Keypad 5 */
2719 KeyPad
| 6, /* Right */
2720 Grey
| 3, /* Grey + */
2721 KeyPad
| 1, /* End */
2723 /* --------------- 50 to 5f --------------- */
2724 KeyPad
| 2, /* Down */
2725 KeyPad
| 3, /* Page Down */
2726 KeyPad
| 0, /* Insert */
2727 KeyPad
| 10, /* Delete */
2728 Shift
| FctKey
| 0xbe, /* (Shift) F1 */
2729 Shift
| FctKey
| 0xbf, /* (Shift) F2 */
2730 Shift
| FctKey
| 0xc0, /* (Shift) F3 */
2731 Shift
| FctKey
| 0xc1, /* (Shift) F4 */
2732 Shift
| FctKey
| 0xc2, /* (Shift) F5 */
2733 Shift
| FctKey
| 0xc3, /* (Shift) F6 */
2734 Shift
| FctKey
| 0xc4, /* (Shift) F7 */
2735 Shift
| FctKey
| 0xc5, /* (Shift) F8 */
2736 Shift
| FctKey
| 0xc6, /* (Shift) F9 */
2737 Shift
| FctKey
| 0xc7, /* (Shift) F10 */
2738 Ctrl
| FctKey
| 0xbe, /* (Ctrl) F1 */
2739 Ctrl
| FctKey
| 0xbf, /* (Ctrl) F2 */
2741 /* --------------- 60 to 6f --------------- */
2742 Ctrl
| FctKey
| 0xc0, /* (Ctrl) F3 */
2743 Ctrl
| FctKey
| 0xc1, /* (Ctrl) F4 */
2744 Ctrl
| FctKey
| 0xc2, /* (Ctrl) F5 */
2745 Ctrl
| FctKey
| 0xc3, /* (Ctrl) F6 */
2746 Ctrl
| FctKey
| 0xc4, /* (Ctrl) F7 */
2747 Ctrl
| FctKey
| 0xc5, /* (Ctrl) F8 */
2748 Ctrl
| FctKey
| 0xc6, /* (Ctrl) F9 */
2749 Ctrl
| FctKey
| 0xc7, /* (Ctrl) F10 */
2750 Alt
| FctKey
| 0xbe, /* (Alt) F1 */
2751 Alt
| FctKey
| 0xbf, /* (Alt) F2 */
2752 Alt
| FctKey
| 0xc0, /* (Alt) F3 */
2753 Alt
| FctKey
| 0xc1, /* (Alt) F4 */
2754 Alt
| FctKey
| 0xc2, /* (Alt) F5 */
2755 Alt
| FctKey
| 0xc3, /* (Alt) F6 */
2756 Alt
| FctKey
| 0xc4, /* (Alt) F7 */
2757 Alt
| FctKey
| 0xc5, /* (Alt) F8 */
2759 /* --------------- 70 to 7f --------------- */
2760 Alt
| FctKey
| 0xc6, /* (Alt) F9 */
2761 Alt
| FctKey
| 0xc7, /* (Alt) F10 */
2762 Ctrl
| FctKey
| 0x6d, /* (Ctrl) Sys Rq */
2763 Ctrl
| KeyPad
| 4, /* (Ctrl) Left */
2764 Ctrl
| KeyPad
| 6, /* (Ctrl) Right */
2765 Ctrl
| KeyPad
| 1, /* (Ctrl) End */
2766 Ctrl
| KeyPad
| 3, /* (Ctrl) Page Down */
2767 Ctrl
| KeyPad
| 7, /* (Ctrl) Home */
2768 Alt
| Map
| 1, /* '1' */
2769 Alt
| Map
| 2, /* '2' */
2770 Alt
| Map
| 3, /* '3' */
2771 Alt
| Map
| 4, /* '4' */
2772 Alt
| Map
| 5, /* '5' */
2773 Alt
| Map
| 6, /* '6' */
2774 Alt
| Map
| 7, /* '7' */
2775 Alt
| Map
| 8, /* '8' */
2777 /* --------------- 80 to 8f --------------- */
2778 Alt
| Map
| 9, /* '9' */
2779 Alt
| Map
| 10, /* '0' */
2780 Alt
| Map
| 11, /* '-' */
2781 Alt
| Map
| 12, /* '=' */
2782 Ctrl
| KeyPad
| 9, /* (Ctrl) Page Up */
2783 FctKey
| 0xc8, /* F11 */
2784 FctKey
| 0xc9, /* F12 */
2785 Shift
| FctKey
| 0xc8, /* (Shift) F11 */
2786 Shift
| FctKey
| 0xc9, /* (Shift) F12 */
2787 Ctrl
| FctKey
| 0xc8, /* (Ctrl) F11 */
2788 Ctrl
| FctKey
| 0xc9, /* (Ctrl) F12 */
2789 Alt
| FctKey
| 0xc8, /* (Alt) F11 */
2790 Alt
| FctKey
| 0xc9, /* (Alt) F12 */
2791 Ctrl
| KeyPad
| 8, /* (Ctrl) Up */
2792 Ctrl
| Grey
| 2, /* (Ctrl) Grey - */
2793 Ctrl
| KeyPad
| 5, /* (Ctrl) Keypad 5 */
2795 /* --------------- 90 to 9f --------------- */
2796 Ctrl
| Grey
| 3, /* (Ctrl) Grey + */
2797 Ctrl
| KeyPad
| 2, /* (Ctrl) Down */
2798 Ctrl
| KeyPad
| 0, /* (Ctrl) Insert */
2799 Ctrl
| KeyPad
| 10, /* (Ctrl) Delete */
2800 Ctrl
| FctKey
| 0x09, /* (Ctrl) Tab */
2801 Ctrl
| Grey
| 0, /* (Ctrl) Grey / */
2802 Ctrl
| Grey
| 1, /* (Ctrl) Grey * */
2803 Alt
| FctKey
| 0x50, /* (Alt) Home */
2804 Alt
| FctKey
| 0x52, /* (Alt) Up */
2805 Alt
| FctKey
| 0x55, /* (Alt) Page Up */
2806 Ignore
, /* NO KEY */
2807 Alt
| FctKey
| 0x51, /* (Alt) Left */
2808 Ignore
, /* NO KEY */
2809 Alt
| FctKey
| 0x53, /* (Alt) Right */
2810 Ignore
, /* NO KEY */
2811 Alt
| FctKey
| 0x57, /* (Alt) End */
2813 /* --------------- a0 to af --------------- */
2814 Alt
| KeyPad
| 2, /* (Alt) Down */
2815 Alt
| KeyPad
| 3, /* (Alt) Page Down */
2816 Alt
| KeyPad
| 0, /* (Alt) Insert */
2817 Alt
| KeyPad
| 10, /* (Alt) Delete */
2818 Alt
| Grey
| 0, /* (Alt) Grey / */
2819 Alt
| FctKey
| 0x09, /* (Alt) Tab */
2820 Alt
| Grey
| 4 /* (Alt) Keypad Enter */
2823 /* These bit-positions corresponds to values returned by BIOS */
2824 #define SHIFT_P 0x0003 /* two bits! */
2825 #define CTRL_P 0x0004
2826 #define ALT_P 0x0008
2827 #define SCRLOCK_P 0x0010
2828 #define NUMLOCK_P 0x0020
2829 #define CAPSLOCK_P 0x0040
2830 #define ALT_GR_P 0x0800
2831 #define SUPER_P 0x4000 /* pseudo */
2832 #define HYPER_P 0x8000 /* pseudo */
2835 dos_get_modifiers (int *keymask
)
2838 int mask
, modifiers
= 0;
2840 /* Calculate modifier bits */
2841 regs
.h
.ah
= extended_kbd
? 0x12 : 0x02;
2842 int86 (0x16, ®s
, ®s
);
2846 mask
= regs
.h
.al
& (SHIFT_P
| CTRL_P
| ALT_P
|
2847 SCRLOCK_P
| NUMLOCK_P
| CAPSLOCK_P
);
2851 mask
= regs
.h
.al
& (SHIFT_P
|
2852 SCRLOCK_P
| NUMLOCK_P
| CAPSLOCK_P
);
2854 /* Do not break international keyboard support. */
2855 /* When Keyb.Com is loaded, the right Alt key is */
2856 /* used for accessing characters like { and } */
2857 if (regs
.h
.ah
& 2) /* Left ALT pressed ? */
2860 if ((regs
.h
.ah
& 8) != 0) /* Right ALT pressed ? */
2863 if (dos_hyper_key
== 1)
2866 modifiers
|= hyper_modifier
;
2868 else if (dos_super_key
== 1)
2871 modifiers
|= super_modifier
;
2873 else if (!international_keyboard
)
2875 /* If Keyb.Com is NOT installed, let Right Alt behave
2876 like the Left Alt. */
2882 if (regs
.h
.ah
& 1) /* Left CTRL pressed ? */
2885 if (regs
.h
.ah
& 4) /* Right CTRL pressed ? */
2887 if (dos_hyper_key
== 2)
2890 modifiers
|= hyper_modifier
;
2892 else if (dos_super_key
== 2)
2895 modifiers
|= super_modifier
;
2903 modifiers
|= shift_modifier
;
2905 modifiers
|= ctrl_modifier
;
2907 modifiers
|= meta_modifier
;
2914 #define NUM_RECENT_DOSKEYS (100)
2915 int recent_doskeys_index
; /* Index for storing next element into recent_doskeys */
2916 int total_doskeys
; /* Total number of elements stored into recent_doskeys */
2917 Lisp_Object recent_doskeys
; /* A vector, holding the last 100 keystrokes */
2919 DEFUN ("recent-doskeys", Frecent_doskeys
, Srecent_doskeys
, 0, 0, 0,
2920 doc
: /* Return vector of last 100 keyboard input values seen in dos_rawgetc.
2921 Each input key receives two values in this vector: first the ASCII code,
2922 and then the scan code. */)
2925 Lisp_Object val
, *keys
= XVECTOR (recent_doskeys
)->contents
;
2927 if (total_doskeys
< NUM_RECENT_DOSKEYS
)
2928 return Fvector (total_doskeys
, keys
);
2931 val
= Fvector (NUM_RECENT_DOSKEYS
, keys
);
2932 memcpy (XVECTOR (val
)->contents
, keys
+ recent_doskeys_index
,
2933 (NUM_RECENT_DOSKEYS
- recent_doskeys_index
) * sizeof (Lisp_Object
));
2934 memcpy (XVECTOR (val
)->contents
+ NUM_RECENT_DOSKEYS
- recent_doskeys_index
,
2935 keys
, recent_doskeys_index
* sizeof (Lisp_Object
));
2940 /* Get a char from keyboard. Function keys are put into the event queue. */
2944 struct input_event event
;
2946 struct tty_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (SELECTED_FRAME());
2949 #ifndef HAVE_X_WINDOWS
2950 /* Maybe put the cursor where it should be. */
2951 IT_cmgoto (SELECTED_FRAME());
2954 /* The following condition is equivalent to `kbhit ()', except that
2955 it uses the bios to do its job. This pleases DESQview/X. */
2956 while ((regs
.h
.ah
= extended_kbd
? 0x11 : 0x01),
2957 int86 (0x16, ®s
, ®s
),
2958 (regs
.x
.flags
& 0x40) == 0)
2961 register unsigned char c
;
2962 int modifiers
, sc
, code
= -1, mask
, kp_mode
;
2964 regs
.h
.ah
= extended_kbd
? 0x10 : 0x00;
2965 int86 (0x16, ®s
, ®s
);
2970 XVECTOR (recent_doskeys
)->contents
[recent_doskeys_index
++]
2972 if (recent_doskeys_index
== NUM_RECENT_DOSKEYS
)
2973 recent_doskeys_index
= 0;
2974 XVECTOR (recent_doskeys
)->contents
[recent_doskeys_index
++]
2976 if (recent_doskeys_index
== NUM_RECENT_DOSKEYS
)
2977 recent_doskeys_index
= 0;
2979 modifiers
= dos_get_modifiers (&mask
);
2981 #ifndef HAVE_X_WINDOWS
2982 if (!NILP (Vdos_display_scancodes
))
2985 sprintf (buf
, "%02x:%02x*%04x",
2986 (unsigned) (sc
&0xff), (unsigned) c
, mask
);
2987 dos_direct_output (screen_size_Y
- 2, screen_size_X
- 12, buf
, 10);
2995 case 10: /* Ctrl Grey Enter */
2996 code
= Ctrl
| Grey
| 4;
2998 case 13: /* Grey Enter */
3001 case '/': /* Grey / */
3011 /* Try the keyboard-private translation table first. */
3012 if (keyboard
->translate_table
)
3014 struct kbd_translate
*p
= keyboard
->translate_table
;
3018 if (p
->sc
== sc
&& p
->ch
== c
)
3026 /* If the private table didn't translate it, use the general
3030 if (sc
>= (sizeof (ibmpc_translate_map
) / sizeof (short)))
3032 if ((code
= ibmpc_translate_map
[sc
]) == Ignore
)
3039 /* We only look at the keyboard Ctrl/Shift/Alt keys when
3040 Emacs is ready to read a key. Therefore, if they press
3041 `Alt-x' when Emacs is busy, by the time we get to
3042 `dos_get_modifiers', they might have already released the
3043 Alt key, and Emacs gets just `x', which is BAD.
3044 However, for keys with the `Map' property set, the ASCII
3045 code returns zero only if Alt is pressed. So, when we DON'T
3046 have to support international_keyboard, we don't have to
3047 distinguish between the left and right Alt keys, and we
3048 can set the META modifier for any keys with the `Map'
3049 property if they return zero ASCII code (c = 0). */
3051 || ( (code
& 0xf000) == Map
&& !international_keyboard
))
3052 modifiers
|= meta_modifier
;
3054 modifiers
|= ctrl_modifier
;
3056 modifiers
|= shift_modifier
;
3059 switch (code
& 0xf000)
3062 if (c
&& !(mask
& (SHIFT_P
| ALT_P
| CTRL_P
| HYPER_P
| SUPER_P
)))
3064 c
= 0; /* Special */
3077 if (c
== 0) /* ctrl-break */
3079 return c
; /* ALT-nnn */
3081 if (!keyboard_map_all
)
3090 if (c
&& !(mask
& ALT_P
) && !((mask
& SHIFT_P
) && (mask
& CTRL_P
)))
3091 if (!keyboard_map_all
)
3095 if (mask
& ALT_P
&& code
<= 10 && code
> 0 && dos_keypad_mode
& 0x200)
3096 mask
|= SHIFT_P
; /* ALT-1 => M-! etc. */
3100 code
= keyboard
->shifted
[code
];
3102 modifiers
&= ~shift_modifier
;
3105 if ((mask
& ALT_GR_P
) && keyboard
->alt_gr
&& keyboard
->alt_gr
[code
] != ' ')
3106 code
= keyboard
->alt_gr
[code
];
3108 code
= keyboard
->unshifted
[code
];
3113 if (c
== 0xe0) /* edit key */
3116 if ((mask
& (NUMLOCK_P
|CTRL_P
|SHIFT_P
|ALT_P
)) == NUMLOCK_P
) /* numlock on */
3117 kp_mode
= dos_keypad_mode
& 0x03;
3119 kp_mode
= (dos_keypad_mode
>> 4) & 0x03;
3124 if (code
== 10 && dos_decimal_point
)
3125 return dos_decimal_point
;
3126 return keypad_translate_map
[code
].char_code
;
3129 code
= 0xff00 | keypad_translate_map
[code
].keypad_code
;
3133 code
= keypad_translate_map
[code
].meta_code
;
3134 modifiers
= meta_modifier
;
3138 code
= 0xff00 | keypad_translate_map
[code
].editkey_code
;
3145 kp_mode
= ((mask
& (NUMLOCK_P
|CTRL_P
|SHIFT_P
|ALT_P
)) == NUMLOCK_P
) ? 0x04 : 0x40;
3146 if (dos_keypad_mode
& kp_mode
)
3147 code
= 0xff00 | grey_key_translate_map
[code
].keypad_code
;
3149 code
= grey_key_translate_map
[code
].char_code
;
3157 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
3159 clear_mouse_face (dpyinfo
);
3160 dpyinfo
->mouse_face_hidden
= 1;
3164 event
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
3166 event
.kind
= ASCII_KEYSTROKE_EVENT
;
3168 event
.modifiers
= modifiers
;
3169 event
.frame_or_window
= selected_frame
;
3171 event
.timestamp
= event_timestamp ();
3172 kbd_buffer_store_event (&event
);
3175 if (have_mouse
> 0 && !mouse_preempted
)
3177 int but
, press
, x
, y
, ok
;
3178 int mouse_prev_x
= mouse_last_x
, mouse_prev_y
= mouse_last_y
;
3179 Lisp_Object mouse_window
= Qnil
;
3181 /* Check for mouse movement *before* buttons. */
3182 mouse_check_moved ();
3184 /* If the mouse moved from the spot of its last sighting, we
3185 might need to update mouse highlight. */
3186 if (mouse_last_x
!= mouse_prev_x
|| mouse_last_y
!= mouse_prev_y
)
3188 if (dpyinfo
->mouse_face_hidden
)
3190 dpyinfo
->mouse_face_hidden
= 0;
3191 clear_mouse_face (dpyinfo
);
3194 /* Generate SELECT_WINDOW_EVENTs when needed. */
3195 if (!NILP (Vmouse_autoselect_window
))
3197 mouse_window
= window_from_coordinates (SELECTED_FRAME(),
3201 /* A window will be selected only when it is not
3202 selected now, and the last mouse movement event was
3203 not in it. A minibuffer window will be selected iff
3205 if (WINDOWP (mouse_window
)
3206 && !EQ (mouse_window
, last_mouse_window
)
3207 && !EQ (mouse_window
, selected_window
))
3209 event
.kind
= SELECT_WINDOW_EVENT
;
3210 event
.frame_or_window
= mouse_window
;
3212 event
.timestamp
= event_timestamp ();
3213 kbd_buffer_store_event (&event
);
3215 last_mouse_window
= mouse_window
;
3218 last_mouse_window
= Qnil
;
3220 previous_help_echo_string
= help_echo_string
;
3221 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
3223 IT_note_mouse_highlight (SELECTED_FRAME(),
3224 mouse_last_x
, mouse_last_y
);
3225 /* If the contents of the global variable help_echo has
3226 changed, generate a HELP_EVENT. */
3227 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
3229 event
.kind
= HELP_EVENT
;
3230 event
.frame_or_window
= selected_frame
;
3231 event
.arg
= help_echo_object
;
3232 event
.x
= WINDOWP (help_echo_window
)
3233 ? help_echo_window
: selected_frame
;
3234 event
.y
= help_echo_string
;
3235 event
.timestamp
= event_timestamp ();
3236 event
.code
= help_echo_pos
;
3237 kbd_buffer_store_event (&event
);
3241 for (but
= 0; but
< NUM_MOUSE_BUTTONS
; but
++)
3242 for (press
= 0; press
< 2; press
++)
3244 int button_num
= but
;
3247 ok
= mouse_pressed (but
, &x
, &y
);
3249 ok
= mouse_released (but
, &x
, &y
);
3252 /* Allow a simultaneous press/release of Mouse-1 and
3253 Mouse-2 to simulate Mouse-3 on two-button mice. */
3254 if (mouse_button_count
== 2 && but
< 2)
3256 int x2
, y2
; /* don't clobber original coordinates */
3258 /* If only one button is pressed, wait 100 msec and
3259 check again. This way, Speedy Gonzales isn't
3260 punished, while the slow get their chance. */
3261 if (press
&& mouse_pressed (1-but
, &x2
, &y2
)
3262 || !press
&& mouse_released (1-but
, &x2
, &y2
))
3267 if (press
&& mouse_pressed (1-but
, &x2
, &y2
)
3268 || !press
&& mouse_released (1-but
, &x2
, &y2
))
3273 event
.kind
= MOUSE_CLICK_EVENT
;
3274 event
.code
= button_num
;
3275 event
.modifiers
= dos_get_modifiers (0)
3276 | (press
? down_modifier
: up_modifier
);
3277 event
.x
= make_number (x
);
3278 event
.y
= make_number (y
);
3279 event
.frame_or_window
= selected_frame
;
3281 event
.timestamp
= event_timestamp ();
3282 kbd_buffer_store_event (&event
);
3290 static int prev_get_char
= -1;
3292 /* Return 1 if a key is ready to be read without suspending execution. */
3296 if (prev_get_char
!= -1)
3299 return ((prev_get_char
= dos_rawgetc ()) != -1);
3302 /* Read a key. Return -1 if no key is ready. */
3306 if (prev_get_char
!= -1)
3308 int c
= prev_get_char
;
3313 return dos_rawgetc ();
3316 #ifndef HAVE_X_WINDOWS
3318 /* Simulation of X's menus. Nothing too fancy here -- just make it work
3321 Actually, I don't know the meaning of all the parameters of the functions
3322 here -- I only know how they are called by xmenu.c. I could of course
3323 grab the nearest Xlib manual (down the hall, second-to-last door on the
3324 left), but I don't think it's worth the effort. */
3326 /* These hold text of the current and the previous menu help messages. */
3327 static char *menu_help_message
, *prev_menu_help_message
;
3328 /* Pane number and item number of the menu item which generated the
3329 last menu help message. */
3330 static int menu_help_paneno
, menu_help_itemno
;
3333 IT_menu_create (void)
3337 menu
= (XMenu
*) xmalloc (sizeof (XMenu
));
3338 menu
->allocated
= menu
->count
= menu
->panecount
= menu
->width
= 0;
3342 /* Allocate some (more) memory for MENU ensuring that there is room for one
3346 IT_menu_make_room (XMenu
*menu
)
3348 if (menu
->allocated
== 0)
3350 int count
= menu
->allocated
= 10;
3351 menu
->text
= (char **) xmalloc (count
* sizeof (char *));
3352 menu
->submenu
= (XMenu
**) xmalloc (count
* sizeof (XMenu
*));
3353 menu
->panenumber
= (int *) xmalloc (count
* sizeof (int));
3354 menu
->help_text
= (char **) xmalloc (count
* sizeof (char *));
3356 else if (menu
->allocated
== menu
->count
)
3358 int count
= menu
->allocated
= menu
->allocated
+ 10;
3360 = (char **) xrealloc (menu
->text
, count
* sizeof (char *));
3362 = (XMenu
**) xrealloc (menu
->submenu
, count
* sizeof (XMenu
*));
3364 = (int *) xrealloc (menu
->panenumber
, count
* sizeof (int));
3366 = (char **) xrealloc (menu
->help_text
, count
* sizeof (char *));
3370 /* Search the given menu structure for a given pane number. */
3373 IT_menu_search_pane (XMenu
*menu
, int pane
)
3378 for (i
= 0; i
< menu
->count
; i
++)
3379 if (menu
->submenu
[i
])
3381 if (pane
== menu
->panenumber
[i
])
3382 return menu
->submenu
[i
];
3383 if ((try = IT_menu_search_pane (menu
->submenu
[i
], pane
)))
3389 /* Determine how much screen space a given menu needs. */
3392 IT_menu_calc_size (XMenu
*menu
, int *width
, int *height
)
3394 int i
, h2
, w2
, maxsubwidth
, maxheight
;
3397 maxheight
= menu
->count
;
3398 for (i
= 0; i
< menu
->count
; i
++)
3400 if (menu
->submenu
[i
])
3402 IT_menu_calc_size (menu
->submenu
[i
], &w2
, &h2
);
3403 if (w2
> maxsubwidth
) maxsubwidth
= w2
;
3404 if (i
+ h2
> maxheight
) maxheight
= i
+ h2
;
3407 *width
= menu
->width
+ maxsubwidth
;
3408 *height
= maxheight
;
3411 /* Display MENU at (X,Y) using FACES. */
3413 #define BUILD_CHAR_GLYPH(GLYPH, CODE, FACE_ID, PADDING_P) \
3416 (GLYPH).type = CHAR_GLYPH; \
3417 SET_CHAR_GLYPH ((GLYPH), CODE, FACE_ID, PADDING_P); \
3418 (GLYPH).charpos = -1; \
3423 IT_menu_display (XMenu
*menu
, int y
, int x
, int pn
, int *faces
, int disp_help
)
3425 int i
, j
, face
, width
, mx
, my
, enabled
, mousehere
, row
, col
;
3426 struct glyph
*text
, *p
;
3427 const unsigned char *q
;
3428 struct frame
*sf
= SELECTED_FRAME();
3430 menu_help_message
= NULL
;
3432 width
= menu
->width
;
3433 /* We multiply width by 2 to account for possible control characters.
3434 FIXME: cater to non-ASCII characters in menus. */
3435 text
= (struct glyph
*) xmalloc ((width
* 2 + 2) * sizeof (struct glyph
));
3436 ScreenGetCursor (&row
, &col
);
3437 mouse_get_xy (&mx
, &my
);
3438 IT_update_begin (sf
);
3439 for (i
= 0; i
< menu
->count
; i
++)
3441 int max_width
= width
+ 2;
3443 IT_cursor_to (sf
, y
+ i
, x
);
3445 = (!menu
->submenu
[i
] && menu
->panenumber
[i
]) || (menu
->submenu
[i
]);
3446 mousehere
= (y
+ i
== my
&& x
<= mx
&& mx
< x
+ max_width
);
3447 face
= faces
[enabled
+ mousehere
* 2];
3448 /* The following if clause means that we display the menu help
3449 strings even if the menu item is currently disabled. */
3450 if (disp_help
&& enabled
+ mousehere
* 2 >= 2)
3452 menu_help_message
= menu
->help_text
[i
];
3453 menu_help_paneno
= pn
- 1;
3454 menu_help_itemno
= i
;
3457 BUILD_CHAR_GLYPH (*p
, ' ', face
, 0);
3459 for (j
= 0, q
= menu
->text
[i
]; *q
; j
++)
3461 unsigned c
= STRING_CHAR_ADVANCE (q
);
3465 BUILD_CHAR_GLYPH (*p
, c
, face
, 0);
3468 else /* make '^x' */
3470 BUILD_CHAR_GLYPH (*p
, '^', face
, 0);
3473 BUILD_CHAR_GLYPH (*p
, c
+ 64, face
, 0);
3477 /* Don't let the menu text overflow into the next screen row. */
3478 if (x
+ max_width
> screen_size_X
)
3480 max_width
= screen_size_X
- x
;
3481 text
[max_width
- 1].u
.ch
= '$'; /* indicate it's truncated */
3483 for (; j
< max_width
- 2; j
++, p
++)
3484 BUILD_CHAR_GLYPH (*p
, ' ', face
, 0);
3486 /* 16 is the character code of a character that on DOS terminal
3487 produces a nice-looking right-pointing arrow glyph. */
3488 BUILD_CHAR_GLYPH (*p
, menu
->submenu
[i
] ? 16 : ' ', face
, 0);
3490 IT_write_glyphs (sf
, text
, max_width
);
3493 IT_cursor_to (sf
, row
, col
);
3497 /* --------------------------- X Menu emulation ---------------------- */
3499 /* Report availability of menus. */
3502 have_menus_p (void) { return 1; }
3504 /* Create a brand new menu structure. */
3507 XMenuCreate (Display
*foo1
, Window foo2
, char *foo3
)
3509 return IT_menu_create ();
3512 /* Create a new pane and place it on the outer-most level. It is not
3513 clear that it should be placed out there, but I don't know what else
3517 XMenuAddPane (Display
*foo
, XMenu
*menu
, char *txt
, int enable
)
3525 IT_menu_make_room (menu
);
3526 menu
->submenu
[menu
->count
] = IT_menu_create ();
3527 menu
->text
[menu
->count
] = txt
;
3528 menu
->panenumber
[menu
->count
] = ++menu
->panecount
;
3529 menu
->help_text
[menu
->count
] = NULL
;
3532 /* Adjust length for possible control characters (which will
3533 be written as ^x). */
3534 for (len
= strlen (txt
), p
= txt
; *p
; p
++)
3538 if (len
> menu
->width
)
3541 return menu
->panecount
;
3544 /* Create a new item in a menu pane. */
3547 XMenuAddSelection (Display
*bar
, XMenu
*menu
, int pane
,
3548 int foo
, char *txt
, int enable
, char *help_text
)
3554 if (!(menu
= IT_menu_search_pane (menu
, pane
)))
3556 IT_menu_make_room (menu
);
3557 menu
->submenu
[menu
->count
] = (XMenu
*) 0;
3558 menu
->text
[menu
->count
] = txt
;
3559 menu
->panenumber
[menu
->count
] = enable
;
3560 menu
->help_text
[menu
->count
] = help_text
;
3563 /* Adjust length for possible control characters (which will
3564 be written as ^x). */
3565 for (len
= strlen (txt
), p
= txt
; *p
; p
++)
3569 if (len
> menu
->width
)
3575 /* Decide where the menu would be placed if requested at (X,Y). */
3578 XMenuLocate (Display
*foo0
, XMenu
*menu
, int foo1
, int foo2
, int x
, int y
,
3579 int *ulx
, int *uly
, int *width
, int *height
)
3581 IT_menu_calc_size (menu
, width
, height
);
3587 struct IT_menu_state
3589 void *screen_behind
;
3596 /* Display menu, wait for user's response, and return that response. */
3599 XMenuActivate (Display
*foo
, XMenu
*menu
, int *pane
, int *selidx
,
3600 int x0
, int y0
, unsigned ButtonMask
, char **txt
,
3601 void (*help_callback
)(char *, int, int))
3603 struct IT_menu_state
*state
;
3604 int statecount
, x
, y
, i
, b
, screensize
, leave
, result
, onepane
;
3605 int title_faces
[4]; /* face to display the menu title */
3606 int faces
[4], buffers_num_deleted
= 0;
3607 struct frame
*sf
= SELECTED_FRAME();
3608 Lisp_Object saved_echo_area_message
, selectface
;
3610 /* Just in case we got here without a mouse present... */
3611 if (have_mouse
<= 0)
3612 return XM_IA_SELECT
;
3613 /* Don't allow non-positive x0 and y0, lest the menu will wrap
3614 around the display. */
3620 /* We will process all the mouse events directly, so we had
3621 better prevent dos_rawgetc from stealing them from us. */
3624 state
= alloca (menu
->panecount
* sizeof (struct IT_menu_state
));
3625 screensize
= screen_size
* 2;
3627 = lookup_derived_face (sf
, intern ("msdos-menu-passive-face"),
3628 DEFAULT_FACE_ID
, 1);
3630 = lookup_derived_face (sf
, intern ("msdos-menu-active-face"),
3631 DEFAULT_FACE_ID
, 1);
3632 selectface
= intern ("msdos-menu-select-face");
3633 faces
[2] = lookup_derived_face (sf
, selectface
,
3635 faces
[3] = lookup_derived_face (sf
, selectface
,
3638 /* Make sure the menu title is always displayed with
3639 `msdos-menu-active-face', no matter where the mouse pointer is. */
3640 for (i
= 0; i
< 4; i
++)
3641 title_faces
[i
] = faces
[3];
3645 /* Don't let the title for the "Buffers" popup menu include a
3646 digit (which is ugly).
3648 This is a terrible kludge, but I think the "Buffers" case is
3649 the only one where the title includes a number, so it doesn't
3650 seem to be necessary to make this more general. */
3651 if (strncmp (menu
->text
[0], "Buffers 1", 9) == 0)
3653 menu
->text
[0][7] = '\0';
3654 buffers_num_deleted
= 1;
3657 /* We need to save the current echo area message, so that we could
3658 restore it below, before we exit. See the commentary below,
3659 before the call to message_with_string. */
3660 saved_echo_area_message
= Fcurrent_message ();
3661 state
[0].menu
= menu
;
3663 ScreenRetrieve (state
[0].screen_behind
= xmalloc (screensize
));
3665 /* Turn off the cursor. Otherwise it shows through the menu
3666 panes, which is ugly. */
3667 IT_display_cursor (0);
3669 /* Display the menu title. */
3670 IT_menu_display (menu
, y0
- 1, x0
- 1, 1, title_faces
, 0);
3671 if (buffers_num_deleted
)
3672 menu
->text
[0][7] = ' ';
3673 if ((onepane
= menu
->count
== 1 && menu
->submenu
[0]))
3675 menu
->width
= menu
->submenu
[0]->width
;
3676 state
[0].menu
= menu
->submenu
[0];
3680 state
[0].menu
= menu
;
3682 state
[0].x
= x0
- 1;
3684 state
[0].pane
= onepane
;
3686 mouse_last_x
= -1; /* A hack that forces display. */
3690 if (!mouse_visible
) mouse_on ();
3691 mouse_check_moved ();
3692 if (sf
->mouse_moved
)
3694 sf
->mouse_moved
= 0;
3695 result
= XM_IA_SELECT
;
3696 mouse_get_xy (&x
, &y
);
3697 for (i
= 0; i
< statecount
; i
++)
3698 if (state
[i
].x
<= x
&& x
< state
[i
].x
+ state
[i
].menu
->width
+ 2)
3700 int dy
= y
- state
[i
].y
;
3701 if (0 <= dy
&& dy
< state
[i
].menu
->count
)
3703 if (!state
[i
].menu
->submenu
[dy
])
3704 if (state
[i
].menu
->panenumber
[dy
])
3705 result
= XM_SUCCESS
;
3707 result
= XM_IA_SELECT
;
3708 *pane
= state
[i
].pane
- 1;
3710 /* We hit some part of a menu, so drop extra menus that
3711 have been opened. That does not include an open and
3713 if (i
!= statecount
- 2
3714 || state
[i
].menu
->submenu
[dy
] != state
[i
+1].menu
)
3715 while (i
!= statecount
- 1)
3719 ScreenUpdate (state
[statecount
].screen_behind
);
3720 if (screen_virtual_segment
)
3721 dosv_refresh_virtual_screen (0, screen_size
);
3722 xfree (state
[statecount
].screen_behind
);
3724 if (i
== statecount
- 1 && state
[i
].menu
->submenu
[dy
])
3726 IT_menu_display (state
[i
].menu
,
3731 state
[statecount
].menu
= state
[i
].menu
->submenu
[dy
];
3732 state
[statecount
].pane
= state
[i
].menu
->panenumber
[dy
];
3734 ScreenRetrieve (state
[statecount
].screen_behind
3735 = xmalloc (screensize
));
3737 = state
[i
].x
+ state
[i
].menu
->width
+ 2;
3738 state
[statecount
].y
= y
;
3743 IT_menu_display (state
[statecount
- 1].menu
,
3744 state
[statecount
- 1].y
,
3745 state
[statecount
- 1].x
,
3746 state
[statecount
- 1].pane
,
3751 if ((menu_help_message
|| prev_menu_help_message
)
3752 && menu_help_message
!= prev_menu_help_message
)
3754 help_callback (menu_help_message
,
3755 menu_help_paneno
, menu_help_itemno
);
3756 IT_display_cursor (0);
3757 prev_menu_help_message
= menu_help_message
;
3759 /* We are busy-waiting for the mouse to move, so let's be nice
3760 to other Windows applications by releasing our time slice. */
3763 for (b
= 0; b
< mouse_button_count
&& !leave
; b
++)
3765 /* Only leave if user both pressed and released the mouse, and in
3766 that order. This avoids popping down the menu pane unless
3767 the user is really done with it. */
3768 if (mouse_pressed (b
, &x
, &y
))
3770 while (mouse_button_depressed (b
, &x
, &y
))
3774 (void) mouse_released (b
, &x
, &y
);
3779 ScreenUpdate (state
[0].screen_behind
);
3780 if (screen_virtual_segment
)
3781 dosv_refresh_virtual_screen (0, screen_size
);
3783 /* We have a situation here. ScreenUpdate has just restored the
3784 screen contents as it was before we started drawing this menu.
3785 That includes any echo area message that could have been
3786 displayed back then. (In reality, that echo area message will
3787 almost always be the ``keystroke echo'' that echoes the sequence
3788 of menu items chosen by the user.) However, if the menu had some
3789 help messages, then displaying those messages caused Emacs to
3790 forget about the original echo area message. So when
3791 ScreenUpdate restored it, it created a discrepancy between the
3792 actual screen contents and what Emacs internal data structures
3795 To avoid this conflict, we force Emacs to restore the original
3796 echo area message as we found it when we entered this function.
3797 The irony of this is that we then erase the restored message
3798 right away, so the only purpose of restoring it is so that
3799 erasing it works correctly... */
3800 if (! NILP (saved_echo_area_message
))
3801 message_with_string ("%s", saved_echo_area_message
, 0);
3803 while (statecount
--)
3804 xfree (state
[statecount
].screen_behind
);
3805 IT_display_cursor (1); /* turn cursor back on */
3806 /* Clean up any mouse events that are waiting inside Emacs event queue.
3807 These events are likely to be generated before the menu was even
3808 displayed, probably because the user pressed and released the button
3809 (which invoked the menu) too quickly. If we don't remove these events,
3810 Emacs will process them after we return and surprise the user. */
3811 discard_mouse_events ();
3812 mouse_clear_clicks ();
3813 if (!kbd_buffer_events_waiting (1))
3814 clear_input_pending ();
3815 /* Allow mouse events generation by dos_rawgetc. */
3820 /* Dispose of a menu. */
3823 XMenuDestroy (Display
*foo
, XMenu
*menu
)
3826 if (menu
->allocated
)
3828 for (i
= 0; i
< menu
->count
; i
++)
3829 if (menu
->submenu
[i
])
3830 XMenuDestroy (foo
, menu
->submenu
[i
]);
3832 xfree (menu
->submenu
);
3833 xfree (menu
->panenumber
);
3834 xfree (menu
->help_text
);
3837 menu_help_message
= prev_menu_help_message
= NULL
;
3841 x_pixel_width (struct frame
*f
)
3843 return FRAME_COLS (f
);
3847 x_pixel_height (struct frame
*f
)
3849 return FRAME_LINES (f
);
3851 #endif /* !HAVE_X_WINDOWS */
3853 /* ----------------------- DOS / UNIX conversion --------------------- */
3855 void msdos_downcase_filename (unsigned char *);
3857 /* Destructively turn backslashes into slashes. */
3860 dostounix_filename (char *p
)
3862 msdos_downcase_filename (p
);
3872 /* Destructively turn slashes into backslashes. */
3875 unixtodos_filename (char *p
)
3877 if (p
[1] == ':' && *p
>= 'A' && *p
<= 'Z')
3891 /* Get the default directory for a given drive. 0=def, 1=A, 2=B, ... */
3894 getdefdir (int drive
, char *dst
)
3896 char in_path
[4], *p
= in_path
, e
= errno
;
3898 /* Generate "X:." (when drive is X) or "." (when drive is 0). */
3901 *p
++ = drive
+ 'A' - 1;
3908 _fixpath (in_path
, dst
);
3909 /* _fixpath can set errno to ENOSYS on non-LFN systems because
3910 it queries the LFN support, so ignore that error. */
3911 if ((errno
&& errno
!= ENOSYS
) || *dst
== '\0')
3914 msdos_downcase_filename (dst
);
3921 emacs_root_dir (void)
3923 static char root_dir
[4];
3925 sprintf (root_dir
, "%c:/", 'A' + getdisk ());
3926 root_dir
[0] = tolower (root_dir
[0]);
3930 /* Remove all CR's that are followed by a LF. */
3933 crlf_to_lf (int n
, unsigned char *buf
)
3935 unsigned char *np
= buf
, *startp
= buf
, *endp
= buf
+ n
;
3939 while (buf
< endp
- 1)
3943 if (*(++buf
) != 0x0a)
3954 DEFUN ("msdos-long-file-names", Fmsdos_long_file_names
, Smsdos_long_file_names
,
3956 doc
: /* Return non-nil if long file names are supported on MS-DOS. */)
3959 return (_USE_LFN
? Qt
: Qnil
);
3962 /* Convert alphabetic characters in a filename to lower-case. */
3965 msdos_downcase_filename (unsigned char *p
)
3967 /* Always lower-case drive letters a-z, even if the filesystem
3968 preserves case in filenames.
3969 This is so MSDOS filenames could be compared by string comparison
3970 functions that are case-sensitive. Even case-preserving filesystems
3971 do not distinguish case in drive letters. */
3972 if (p
[1] == ':' && *p
>= 'A' && *p
<= 'Z')
3978 /* Under LFN we expect to get pathnames in their true case. */
3979 if (NILP (Fmsdos_long_file_names ()))
3981 if (*p
>= 'A' && *p
<= 'Z')
3985 DEFUN ("msdos-downcase-filename", Fmsdos_downcase_filename
, Smsdos_downcase_filename
,
3987 doc
: /* Convert alphabetic characters in FILENAME to lower case and return that.
3988 When long filenames are supported, doesn't change FILENAME.
3989 If FILENAME is not a string, returns nil.
3990 The argument object is never altered--the value is a copy. */)
3992 Lisp_Object filename
;
3996 if (! STRINGP (filename
))
3999 tem
= Fcopy_sequence (filename
);
4000 msdos_downcase_filename (SDATA (tem
));
4004 /* The Emacs root directory as determined by init_environment. */
4006 static char emacsroot
[MAXPATHLEN
];
4009 rootrelativepath (char *rel
)
4011 static char result
[MAXPATHLEN
+ 10];
4013 strcpy (result
, emacsroot
);
4014 strcat (result
, "/");
4015 strcat (result
, rel
);
4019 /* Define a lot of environment variables if not already defined. Don't
4020 remove anything unless you know what you're doing -- lots of code will
4021 break if one or more of these are missing. */
4024 init_environment (int argc
, char **argv
, int skip_args
)
4028 static const char * const tempdirs
[] = {
4029 "$TMPDIR", "$TEMP", "$TMP", "c:/"
4031 const int imax
= sizeof (tempdirs
) / sizeof (tempdirs
[0]);
4033 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
4034 temporary files and assume "/tmp" if $TMPDIR is unset, which
4035 will break on DOS/Windows. Refuse to work if we cannot find
4036 a directory, not even "c:/", usable for that purpose. */
4037 for (i
= 0; i
< imax
; i
++)
4039 const char *tmp
= tempdirs
[i
];
4040 char buf
[FILENAME_MAX
];
4046 tmp
= getenv (tmp
+ 1);
4050 /* Some lusers set TMPDIR=e:, probably because some losing
4051 programs cannot handle multiple slashes if they use e:/.
4052 e: fails in `access' below, so we interpret e: as e:/. */
4053 tmp_len
= strlen(tmp
);
4054 if (tmp
[tmp_len
- 1] != '/' && tmp
[tmp_len
- 1] != '\\')
4057 buf
[tmp_len
++] = '/', buf
[tmp_len
] = 0;
4062 /* Note that `access' can lie to us if the directory resides on a
4063 read-only filesystem, like CD-ROM or a write-protected floppy.
4064 The only way to be really sure is to actually create a file and
4065 see if it succeeds. But I think that's too much to ask. */
4066 if (tmp
&& access (tmp
, D_OK
) == 0)
4068 setenv ("TMPDIR", tmp
, 1);
4075 Fcons (build_string ("no usable temporary directories found!!"),
4077 "While setting TMPDIR: ");
4079 /* Note the startup time, so we know not to clear the screen if we
4080 exit immediately; see IT_reset_terminal_modes.
4081 (Yes, I know `clock' returns zero the first time it's called, but
4082 I do this anyway, in case some wiseguy changes that at some point.) */
4083 startup_time
= clock ();
4085 /* Find our root from argv[0]. Assuming argv[0] is, say,
4086 "c:/emacs/bin/emacs.exe" our root will be "c:/emacs". */
4087 root
= alloca (MAXPATHLEN
+ 20);
4088 _fixpath (argv
[0], root
);
4089 msdos_downcase_filename (root
);
4090 len
= strlen (root
);
4091 while (len
> 0 && root
[len
] != '/' && root
[len
] != ':')
4095 && (strcmp (root
+ len
- 4, "/bin") == 0
4096 || strcmp (root
+ len
- 4, "/src") == 0)) /* under a debugger */
4097 root
[len
- 4] = '\0';
4099 strcpy (root
, "c:/emacs"); /* let's be defensive */
4100 len
= strlen (root
);
4101 strcpy (emacsroot
, root
);
4103 /* We default HOME to our root. */
4104 setenv ("HOME", root
, 0);
4106 /* We default EMACSPATH to root + "/bin". */
4107 strcpy (root
+ len
, "/bin");
4108 setenv ("EMACSPATH", root
, 0);
4110 /* I don't expect anybody to ever use other terminals so the internal
4111 terminal is the default. */
4112 setenv ("TERM", "internal", 0);
4114 #ifdef HAVE_X_WINDOWS
4115 /* Emacs expects DISPLAY to be set. */
4116 setenv ("DISPLAY", "unix:0.0", 0);
4119 /* SHELL is a bit tricky -- COMSPEC is the closest we come, but we must
4120 downcase it and mirror the backslashes. */
4121 s
= getenv ("COMSPEC");
4122 if (!s
) s
= "c:/command.com";
4123 t
= alloca (strlen (s
) + 1);
4125 dostounix_filename (t
);
4126 setenv ("SHELL", t
, 0);
4128 /* PATH is also downcased and backslashes mirrored. */
4129 s
= getenv ("PATH");
4131 t
= alloca (strlen (s
) + 3);
4132 /* Current directory is always considered part of MsDos's path but it is
4133 not normally mentioned. Now it is. */
4134 strcat (strcpy (t
, ".;"), s
);
4135 dostounix_filename (t
); /* Not a single file name, but this should work. */
4136 setenv ("PATH", t
, 1);
4138 /* In some sense all dos users have root privileges, so... */
4139 setenv ("USER", "root", 0);
4140 setenv ("NAME", getenv ("USER"), 0);
4142 /* Time zone determined from country code. To make this possible, the
4143 country code may not span more than one time zone. In other words,
4144 in the USA, you lose. */
4146 switch (dos_country_code
)
4148 case 31: /* Belgium */
4149 case 32: /* The Netherlands */
4150 case 33: /* France */
4151 case 34: /* Spain */
4152 case 36: /* Hungary */
4153 case 38: /* Yugoslavia (or what's left of it?) */
4154 case 39: /* Italy */
4155 case 41: /* Switzerland */
4156 case 42: /* Tjekia */
4157 case 45: /* Denmark */
4158 case 46: /* Sweden */
4159 case 47: /* Norway */
4160 case 48: /* Poland */
4161 case 49: /* Germany */
4162 /* Daylight saving from last Sunday in March to last Sunday in
4163 September, both at 2AM. */
4164 setenv ("TZ", "MET-01METDST-02,M3.5.0/02:00,M9.5.0/02:00", 0);
4166 case 44: /* United Kingdom */
4167 case 351: /* Portugal */
4168 case 354: /* Iceland */
4169 setenv ("TZ", "GMT+00", 0);
4171 case 81: /* Japan */
4172 case 82: /* Korea */
4173 setenv ("TZ", "JST-09", 0);
4175 case 90: /* Turkey */
4176 case 358: /* Finland */
4177 setenv ("TZ", "EET-02", 0);
4179 case 972: /* Israel */
4180 /* This is an approximation. (For exact rules, use the
4181 `zoneinfo/israel' file which comes with DJGPP, but you need
4182 to install it in `/usr/share/zoneinfo/' directory first.) */
4183 setenv ("TZ", "IST-02IDT-03,M4.1.6/00:00,M9.5.6/01:00", 0);
4191 static int break_stat
; /* BREAK check mode status. */
4192 static int stdin_stat
; /* stdin IOCTL status. */
4194 /* Turn off Dos' Ctrl-C checking and inhibit interpretation of
4195 control chars by DOS. Determine the keyboard type. */
4198 dos_ttraw (struct tty_display_info
*tty
)
4200 union REGS inregs
, outregs
;
4201 static int first_time
= 1;
4203 /* If we are called for the initial terminal, it's too early to do
4204 anything, and termscript isn't set up. */
4205 if (tty
->terminal
->type
== output_initial
)
4208 break_stat
= getcbrk ();
4214 int86 (0x15, &inregs
, &outregs
);
4215 extended_kbd
= (!outregs
.x
.cflag
) && (outregs
.h
.ah
== 0);
4220 #ifdef HAVE_X_WINDOWS
4221 && inhibit_window_system
4225 inregs
.x
.ax
= 0x0021;
4226 int86 (0x33, &inregs
, &outregs
);
4227 have_mouse
= (outregs
.x
.ax
& 0xffff) == 0xffff;
4230 /* Reportedly, the above doesn't work for some mouse drivers. There
4231 is an additional detection method that should work, but might be
4232 a little slower. Use that as an alternative. */
4233 inregs
.x
.ax
= 0x0000;
4234 int86 (0x33, &inregs
, &outregs
);
4235 have_mouse
= (outregs
.x
.ax
& 0xffff) == 0xffff;
4238 mouse_button_count
= outregs
.x
.bx
;
4240 #ifndef HAVE_X_WINDOWS
4241 /* Save the cursor shape used outside Emacs. */
4242 outside_cursor
= _farpeekw (_dos_ds
, 0x460);
4248 stdin_stat
= setmode (fileno (stdin
), O_BINARY
);
4249 return (stdin_stat
!= -1);
4252 return (setmode (fileno (stdin
), O_BINARY
) != -1);
4255 /* Restore status of standard input and Ctrl-C checking. */
4260 union REGS inregs
, outregs
;
4262 setcbrk (break_stat
);
4265 #ifndef HAVE_X_WINDOWS
4266 /* Restore the cursor shape we found on startup. */
4270 inregs
.x
.cx
= outside_cursor
;
4271 int86 (0x10, &inregs
, &outregs
);
4275 return (setmode (fileno (stdin
), stdin_stat
) != -1);
4279 /* Run command as specified by ARGV in directory DIR.
4280 The command is run with input from TEMPIN, output to
4281 file TEMPOUT and stderr to TEMPERR. */
4284 run_msdos_command (unsigned char **argv
, const char *working_dir
,
4285 int tempin
, int tempout
, int temperr
, char **envv
)
4287 char *saveargv1
, *saveargv2
, *lowcase_argv0
, *pa
, *pl
;
4288 char oldwd
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
4289 int msshell
, result
= -1, inbak
, outbak
, errbak
, x
, y
;
4292 /* Get current directory as MSDOS cwd is not per-process. */
4295 /* If argv[0] is the shell, it might come in any lettercase.
4296 Since `Fmember' is case-sensitive, we need to downcase
4297 argv[0], even if we are on case-preserving filesystems. */
4298 lowcase_argv0
= alloca (strlen (argv
[0]) + 1);
4299 for (pa
= argv
[0], pl
= lowcase_argv0
; *pa
; pl
++)
4302 if (*pl
>= 'A' && *pl
<= 'Z')
4307 cmd
= Ffile_name_nondirectory (build_string (lowcase_argv0
));
4308 msshell
= !NILP (Fmember (cmd
, Fsymbol_value (intern ("msdos-shells"))))
4309 && !strcmp ("-c", argv
[1]);
4312 saveargv1
= argv
[1];
4313 saveargv2
= argv
[2];
4315 /* We only need to mirror slashes if a DOS shell will be invoked
4316 not via `system' (which does the mirroring itself). Yes, that
4317 means DJGPP v1.x will lose here. */
4318 if (argv
[2] && argv
[3])
4320 char *p
= alloca (strlen (argv
[2]) + 1);
4322 strcpy (argv
[2] = p
, saveargv2
);
4323 while (*p
&& isspace (*p
))
4335 chdir (working_dir
);
4339 if (inbak
< 0 || outbak
< 0 || errbak
< 0)
4340 goto done
; /* Allocation might fail due to lack of descriptors. */
4343 mouse_get_xy (&x
, &y
);
4345 if (!noninteractive
)
4346 dos_ttcooked (); /* do it here while 0 = stdin */
4352 if (msshell
&& !argv
[3])
4354 /* MS-DOS native shells are too restrictive. For starters, they
4355 cannot grok commands longer than 126 characters. In DJGPP v2
4356 and later, `system' is much smarter, so we'll call it instead. */
4360 /* A shell gets a single argument--its full command
4361 line--whose original was saved in `saveargv2'. */
4363 /* Don't let them pass empty command lines to `system', since
4364 with some shells it will try to invoke an interactive shell,
4365 which will hang Emacs. */
4366 for (cmnd
= saveargv2
; *cmnd
&& isspace (*cmnd
); cmnd
++)
4370 extern char **environ
;
4371 char **save_env
= environ
;
4372 int save_system_flags
= __system_flags
;
4374 /* Request the most powerful version of `system'. We need
4375 all the help we can get to avoid calling stock DOS shells. */
4376 __system_flags
= (__system_redirect
4377 | __system_use_shell
4378 | __system_allow_multiple_cmds
4379 | __system_allow_long_cmds
4380 | __system_handle_null_commands
4381 | __system_emulate_chdir
);
4384 result
= system (cmnd
);
4385 __system_flags
= save_system_flags
;
4389 result
= 0; /* emulate Unixy shell behavior with empty cmd line */
4392 result
= spawnve (P_WAIT
, argv
[0], argv
, envv
);
4397 emacs_close (inbak
);
4398 emacs_close (outbak
);
4399 emacs_close (errbak
);
4401 if (!noninteractive
)
4402 dos_ttraw (CURTTY ());
4406 mouse_moveto (x
, y
);
4409 /* Some programs might change the meaning of the highest bit of the
4410 text attribute byte, so we get blinking characters instead of the
4411 bright background colors. Restore that. */
4412 if (!noninteractive
)
4419 argv
[1] = saveargv1
;
4420 argv
[2] = saveargv2
;
4426 croak (char *badfunc
)
4428 fprintf (stderr
, "%s not yet implemented\r\n", badfunc
);
4429 reset_all_sys_modes ();
4434 * A few unimplemented functions that we silently ignore.
4436 int setpgrp (void) {return 0; }
4437 int setpriority (int x
, int y
, int z
) { return 0; }
4439 #if __DJGPP__ == 2 && __DJGPP_MINOR__ < 2
4441 /* Augment DJGPP library POSIX signal functions. This is needed
4442 as of DJGPP v2.01, but might be in the library in later releases. */
4444 #include <libc/bss.h>
4446 /* A counter to know when to re-initialize the static sets. */
4447 static int sigprocmask_count
= -1;
4449 /* Which signals are currently blocked (initially none). */
4450 static sigset_t current_mask
;
4452 /* Which signals are pending (initially none). */
4453 static sigset_t msdos_pending_signals
;
4455 /* Previous handlers to restore when the blocked signals are unblocked. */
4456 typedef void (*sighandler_t
)(int);
4457 static sighandler_t prev_handlers
[320];
4459 /* A signal handler which just records that a signal occurred
4460 (it will be raised later, if and when the signal is unblocked). */
4462 sig_suspender (int signo
)
4464 sigaddset (&msdos_pending_signals
, signo
);
4468 sigprocmask (int how
, const sigset_t
*new_set
, sigset_t
*old_set
)
4473 /* If called for the first time, initialize. */
4474 if (sigprocmask_count
!= __bss_count
)
4476 sigprocmask_count
= __bss_count
;
4477 sigemptyset (&msdos_pending_signals
);
4478 sigemptyset (¤t_mask
);
4479 for (signo
= 0; signo
< 320; signo
++)
4480 prev_handlers
[signo
] = SIG_ERR
;
4484 *old_set
= current_mask
;
4489 if (how
!= SIG_BLOCK
&& how
!= SIG_UNBLOCK
&& how
!= SIG_SETMASK
)
4495 sigemptyset (&new_mask
);
4497 /* DJGPP supports upto 320 signals. */
4498 for (signo
= 0; signo
< 320; signo
++)
4500 if (sigismember (¤t_mask
, signo
))
4501 sigaddset (&new_mask
, signo
);
4502 else if (sigismember (new_set
, signo
) && how
!= SIG_UNBLOCK
)
4504 sigaddset (&new_mask
, signo
);
4506 /* SIGKILL is silently ignored, as on other platforms. */
4507 if (signo
!= SIGKILL
&& prev_handlers
[signo
] == SIG_ERR
)
4508 prev_handlers
[signo
] = signal (signo
, sig_suspender
);
4510 if (( how
== SIG_UNBLOCK
4511 && sigismember (&new_mask
, signo
)
4512 && sigismember (new_set
, signo
))
4513 || (how
== SIG_SETMASK
4514 && sigismember (&new_mask
, signo
)
4515 && !sigismember (new_set
, signo
)))
4517 sigdelset (&new_mask
, signo
);
4518 if (prev_handlers
[signo
] != SIG_ERR
)
4520 signal (signo
, prev_handlers
[signo
]);
4521 prev_handlers
[signo
] = SIG_ERR
;
4523 if (sigismember (&msdos_pending_signals
, signo
))
4525 sigdelset (&msdos_pending_signals
, signo
);
4530 current_mask
= new_mask
;
4534 #endif /* not __DJGPP_MINOR__ < 2 */
4537 #include "sysselect.h"
4539 #ifndef EMACS_TIME_ZERO_OR_NEG_P
4540 #define EMACS_TIME_ZERO_OR_NEG_P(time) \
4541 ((long)(time).tv_sec < 0 \
4542 || ((time).tv_sec == 0 \
4543 && (long)(time).tv_usec <= 0))
4546 /* This yields the rest of the current time slice to the task manager.
4547 It should be called by any code which knows that it has nothing
4548 useful to do except idle.
4550 I don't use __dpmi_yield here, since versions of library before 2.02
4551 called Int 2Fh/AX=1680h there in a way that would wedge the DOS box
4552 on some versions of Windows 9X. */
4555 dos_yield_time_slice (void)
4557 _go32_dpmi_registers r
;
4560 r
.x
.ss
= r
.x
.sp
= r
.x
.flags
= 0;
4561 _go32_dpmi_simulate_int (0x2f, &r
);
4566 /* Only event queue is checked. */
4567 /* We don't have to call timer_check here
4568 because wait_reading_process_output takes care of that. */
4570 sys_select (int nfds
, SELECT_TYPE
*rfds
, SELECT_TYPE
*wfds
, SELECT_TYPE
*efds
,
4571 EMACS_TIME
*timeout
)
4579 check_input
= FD_ISSET (0, rfds
);
4590 /* If we are looking only for the terminal, with no timeout,
4591 just read it and wait -- that's more efficient. */
4594 while (!detect_input_pending ())
4596 dos_yield_time_slice ();
4601 EMACS_TIME clnow
, cllast
, cldiff
;
4604 EMACS_SET_SECS_USECS (cllast
, t
.ti_sec
, t
.ti_hund
* 10000L);
4606 while (!check_input
|| !detect_input_pending ())
4609 EMACS_SET_SECS_USECS (clnow
, t
.ti_sec
, t
.ti_hund
* 10000L);
4610 EMACS_SUB_TIME (cldiff
, clnow
, cllast
);
4612 /* When seconds wrap around, we assume that no more than
4613 1 minute passed since last `gettime'. */
4614 if (EMACS_TIME_NEG_P (cldiff
))
4615 EMACS_SET_SECS (cldiff
, EMACS_SECS (cldiff
) + 60);
4616 EMACS_SUB_TIME (*timeout
, *timeout
, cldiff
);
4618 /* Stop when timeout value crosses zero. */
4619 if (EMACS_TIME_ZERO_OR_NEG_P (*timeout
))
4622 dos_yield_time_slice ();
4632 * Define overlaid functions:
4634 * chdir -> sys_chdir
4635 * tzset -> init_gettimeofday
4636 * abort -> dos_abort
4641 extern int chdir (const char *);
4644 sys_chdir (const char *path
)
4646 int len
= strlen (path
);
4647 char *tmp
= (char *)path
;
4649 if (*tmp
&& tmp
[1] == ':')
4651 if (getdisk () != tolower (tmp
[0]) - 'a')
4652 setdisk (tolower (tmp
[0]) - 'a');
4653 tmp
+= 2; /* strip drive: KFS 1995-07-06 */
4657 if (len
> 1 && (tmp
[len
- 1] == '/'))
4659 char *tmp1
= (char *) alloca (len
+ 1);
4670 extern void tzset (void);
4673 init_gettimeofday (void)
4679 ltm
= gtm
= time (NULL
);
4680 ltm
= mktime (lstm
= localtime (<m
));
4681 gtm
= mktime (gmtime (>m
));
4682 time_rec
.tm_hour
= 99; /* force gettimeofday to get date */
4683 time_rec
.tm_isdst
= lstm
->tm_isdst
;
4684 dos_timezone_offset
= time_rec
.tm_gmtoff
= (int)(gtm
- ltm
) / 60;
4691 dos_abort (char *file
, int line
)
4693 char buffer1
[200], buffer2
[400];
4696 sprintf (buffer1
, "<EMACS FATAL ERROR IN %s LINE %d>", file
, line
);
4697 for (i
= j
= 0; buffer1
[i
]; i
++) {
4698 buffer2
[j
++] = buffer1
[i
];
4699 buffer2
[j
++] = 0x70;
4701 dosmemput (buffer2
, j
, (int)ScreenPrimary
);
4702 ScreenSetCursor (2, 0);
4710 ScreenSetCursor (10, 0);
4711 cputs ("\r\n\nEmacs aborted!\r\n");
4712 #if __DJGPP__ == 2 && __DJGPP_MINOR__ < 2
4713 if (screen_virtual_segment
)
4714 dosv_refresh_virtual_screen (2 * 10 * screen_size_X
, 4 * screen_size_X
);
4715 /* Generate traceback, so we could tell whodunit. */
4716 signal (SIGINT
, SIG_DFL
);
4717 __asm__
__volatile__ ("movb $0x1b,%al;call ___djgpp_hw_exception");
4718 #else /* __DJGPP_MINOR__ >= 2 */
4720 #endif /* __DJGPP_MINOR__ >= 2 */
4725 /* The following variables are required so that cus-start.el won't
4726 complain about unbound variables. */
4727 #ifndef subprocesses
4728 /* Nonzero means delete a process right away if it exits (process.c). */
4729 static int delete_exited_processes
;
4733 syms_of_msdos (void)
4735 recent_doskeys
= Fmake_vector (make_number (NUM_RECENT_DOSKEYS
), Qnil
);
4736 staticpro (&recent_doskeys
);
4738 #ifndef HAVE_X_WINDOWS
4740 /* The following two are from xfns.c: */
4741 Qreverse
= intern ("reverse");
4742 staticpro (&Qreverse
);
4744 DEFVAR_LISP ("dos-unsupported-char-glyph", &Vdos_unsupported_char_glyph
,
4745 doc
: /* *Glyph to display instead of chars not supported by current codepage.
4746 This variable is used only by MS-DOS terminals. */);
4747 Vdos_unsupported_char_glyph
= make_number ('\177');
4750 #ifndef subprocesses
4751 DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes
,
4752 doc
: /* *Non-nil means delete processes immediately when they exit.
4753 A value of nil means don't delete them until `list-processes' is run. */);
4754 delete_exited_processes
= 0;
4757 defsubr (&Srecent_doskeys
);
4758 defsubr (&Smsdos_long_file_names
);
4759 defsubr (&Smsdos_downcase_filename
);
4760 defsubr (&Smsdos_remember_default_colors
);
4761 defsubr (&Smsdos_set_mouse_buttons
);
4766 /* arch-tag: db404e92-52a5-475f-9eb2-1cb78dd05f30
4767 (do not change this comment) */