1 /* MS-DOS specific C utilities.
2 Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
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. */
32 #include <sys/param.h>
36 #include <sys/stat.h> /* for _fixpath */
39 #include <libc/dosio.h> /* for _USE_LFN */
45 #include "termhooks.h"
46 #include "dispextern.h"
53 /* #include <process.h> */
54 /* Damn that local process.h! Instead we can define P_WAIT ourselves. */
69 /* If other `malloc' than ours is used, force our `sbrk' behave like
70 Unix programs expect (resize memory blocks to keep them contiguous).
71 If `sbrk' from `ralloc.c' is NOT used, also zero-out sbrk'ed memory,
72 because that's what `gmalloc' expects to get. */
76 int _crt0_startup_flags
= _CRT0_FLAG_UNIX_SBRK
;
77 #else /* not REL_ALLOC */
78 int _crt0_startup_flags
= (_CRT0_FLAG_UNIX_SBRK
| _CRT0_FLAG_FILL_SBRK_MEMORY
);
79 #endif /* not REL_ALLOC */
80 #endif /* GNU_MALLOC */
82 #endif /* not SYSTEM_MALLOC */
83 #endif /* __DJGPP__ > 1 */
102 /* ------------------------ Mouse control ---------------------------
104 * Coordinates are in screen positions and zero based.
105 * Mouse buttons are numbered from left to right and also zero based.
108 int have_mouse
; /* 0: no, 1: enabled, -1: disabled */
109 static int mouse_visible
;
111 static int mouse_last_x
;
112 static int mouse_last_y
;
114 static int mouse_button_translate
[NUM_MOUSE_BUTTONS
];
115 static int mouse_button_count
;
122 if (have_mouse
> 0 && !mouse_visible
)
125 fprintf (termscript
, "<M_ON>");
127 int86 (0x33, ®s
, ®s
);
137 if (have_mouse
> 0 && mouse_visible
)
140 fprintf (termscript
, "<M_OFF>");
142 int86 (0x33, ®s
, ®s
);
154 fprintf (termscript
, "<M_XY=%dx%d>", x
, y
);
156 mouse_last_x
= regs
.x
.cx
= x
* 8;
157 mouse_last_y
= regs
.x
.dx
= y
* 8;
158 int86 (0x33, ®s
, ®s
);
162 mouse_pressed (b
, xp
, yp
)
167 if (b
>= mouse_button_count
)
170 regs
.x
.bx
= mouse_button_translate
[b
];
171 int86 (0x33, ®s
, ®s
);
173 *xp
= regs
.x
.cx
/ 8, *yp
= regs
.x
.dx
/ 8;
174 return (regs
.x
.bx
!= 0);
178 mouse_released (b
, xp
, yp
)
183 if (b
>= mouse_button_count
)
186 regs
.x
.bx
= mouse_button_translate
[b
];
187 int86 (0x33, ®s
, ®s
);
189 *xp
= regs
.x
.cx
/ 8, *yp
= regs
.x
.dx
/ 8;
190 return (regs
.x
.bx
!= 0);
194 mouse_get_xy (int *x
, int *y
)
199 int86 (0x33, ®s
, ®s
);
205 mouse_get_pos (f
, insist
, bar_window
, part
, x
, y
, time
)
208 Lisp_Object
*bar_window
, *x
, *y
;
209 enum scroll_bar_part
*part
;
216 int86 (0x33, ®s
, ®s
);
219 mouse_get_xy (&ix
, &iy
);
220 selected_frame
->mouse_moved
= 0;
221 *x
= make_number (ix
);
222 *y
= make_number (iy
);
223 *time
= event_timestamp ();
231 mouse_get_xy (&x
, &y
);
232 selected_frame
->mouse_moved
|= (x
!= mouse_last_x
|| y
!= mouse_last_y
);
243 fprintf (termscript
, "<M_INIT>");
246 int86 (0x33, ®s
, ®s
);
250 regs
.x
.dx
= 8 * (ScreenCols () - 1);
251 int86 (0x33, ®s
, ®s
);
255 regs
.x
.dx
= 8 * (ScreenRows () - 1);
256 int86 (0x33, ®s
, ®s
);
262 /* ------------------------- Screen control ----------------------
266 static int internal_terminal
= 0;
268 #ifndef HAVE_X_WINDOWS
269 extern unsigned char ScreenAttrib
;
270 static int screen_face
;
271 static int highlight
;
273 static int screen_size_X
;
274 static int screen_size_Y
;
275 static int screen_size
;
277 static int current_pos_X
;
278 static int current_pos_Y
;
279 static int new_pos_X
;
280 static int new_pos_Y
;
282 static void *startup_screen_buffer
;
283 static int startup_screen_size_X
;
284 static int startup_screen_size_Y
;
285 static int startup_pos_X
;
286 static int startup_pos_Y
;
287 static unsigned char startup_screen_attrib
;
289 static int term_setup_done
;
291 /* Similar to the_only_frame. */
292 struct x_output the_only_x_display
;
294 /* This is never dereferenced. */
295 Display
*x_current_display
;
298 #define SCREEN_SET_CURSOR() \
299 if (current_pos_X != new_pos_X || current_pos_Y != new_pos_Y) \
300 ScreenSetCursor (current_pos_Y = new_pos_Y, current_pos_X = new_pos_X)
303 dos_direct_output (y
, x
, buf
, len
)
309 int t
= (int) ScreenPrimary
+ 2 * (x
+ y
* screen_size_X
);
312 dosmemput (buf
++, 1, t
);
318 /* Flash the screen as a substitute for BEEPs. */
322 do_visible_bell (xorattr
)
323 unsigned char xorattr
;
328 movl _ScreenPrimary,%%eax
335 xorb %%al,%%gs:(%%ebx)
351 : "m" (xorattr
), "g" (screen_size
)
352 : "%eax", "%ebx", /* "%gs",*/ "%ecx", "%edx");
356 ScreenVisualBell (void)
358 /* This creates an xor-mask that will swap the default fore- and
359 background colors. */
360 do_visible_bell (((the_only_x_display
.foreground_pixel
361 ^ the_only_x_display
.background_pixel
)
366 #ifndef HAVE_X_WINDOWS
368 /* Set the screen dimensions so that it can show no less than
369 ROWS x COLS frame. */
372 dos_set_window_size (rows
, cols
)
376 Lisp_Object video_mode
;
377 int video_mode_value
;
380 int current_rows
= ScreenRows (), current_cols
= ScreenCols ();
382 if (*rows
== current_rows
&& *cols
== current_cols
)
385 /* Do we have a VGA? */
387 int86 (0x10, ®s
, ®s
);
388 if (regs
.h
.al
== 0x1a && regs
.h
.bl
> 5 && regs
.h
.bl
< 13)
393 /* If the user specified a special video mode for these dimensions,
395 sprintf (video_name
, "screen-dimensions-%dx%d", *rows
, *cols
);
396 video_mode
= XSYMBOL (Fintern_soft (build_string (video_name
),
399 if (INTEGERP (video_mode
)
400 && (video_mode_value
= XINT (video_mode
)) > 0)
402 regs
.x
.ax
= video_mode_value
;
403 int86 (0x10, ®s
, ®s
);
406 int86 (0x10, ®s
, ®s
);
410 /* Must hardware-reset the mouse, or else it won't update
411 its notion of screen dimensions for some non-standard
412 video modes. This is *painfully* slow... */
414 int86 (0x33, ®s
, ®s
);
418 /* Find one of the dimensions supported by standard EGA/VGA
419 which gives us at least the required dimensions. */
428 } std_dimension
[] = {
438 while (i
< sizeof (std_dimension
) / sizeof (std_dimension
[0]))
440 if (std_dimension
[i
].need_vga
<= have_vga
441 && std_dimension
[i
].rows
>= *rows
)
443 if (std_dimension
[i
].rows
!= current_rows
444 || *cols
!= current_cols
)
445 _set_screen_lines (std_dimension
[i
].rows
);
452 #else /* not __DJGPP__ > 1 */
454 else if (*rows
<= 25)
456 if (current_rows
!= 25 || current_cols
!= 80)
459 int86 (0x10, ®s
, ®s
);
462 int86 (0x10, ®s
, ®s
);
465 int86 (0x10, ®s
, ®s
);
467 int86 (0x10, ®s
, ®s
);
470 else if (*rows
<= 50)
471 if (have_vga
&& (current_rows
!= 50 || current_cols
!= 80)
472 || *rows
<= 43 && (current_rows
!= 43 || current_cols
!= 80))
475 int86 (0x10, ®s
, ®s
);
478 int86 (0x10, ®s
, ®s
);
481 int86 (0x10, ®s
, ®s
);
484 int86 (0x10, ®s
, ®s
);
486 #endif /* not __DJGPP__ > 1 */
494 /* Tell the caller what dimensions have been REALLY set. */
495 *rows
= ScreenRows ();
496 *cols
= ScreenCols ();
499 /* If we write a character in the position where the mouse is,
500 the mouse cursor may need to be refreshed. */
510 mouse_get_xy (&x
, &y
);
511 if (y
!= new_pos_Y
|| x
< new_pos_X
)
527 union REGS inregs
, outregs
;
530 intdos (&inregs
, &outregs
);
535 IT_set_face (int face
)
538 extern struct face
*intern_face (/* FRAME_PTR, struct face * */);
540 if (face
== 1 || (face
== 0 && highlight
))
541 fp
= FRAME_MODE_LINE_FACE (foo
);
542 else if (face
<= 0 || face
>= FRAME_N_COMPUTED_FACES (foo
))
543 fp
= FRAME_DEFAULT_FACE (foo
);
545 fp
= intern_face (selected_frame
, FRAME_COMPUTED_FACES (foo
)[face
]);
547 fprintf (termscript
, "<FACE:%d:%d>", FACE_FOREGROUND (fp
), FACE_BACKGROUND (fp
));
549 ScreenAttrib
= (FACE_BACKGROUND (fp
) << 4) | FACE_FOREGROUND (fp
);
553 IT_write_glyphs (GLYPH
*str
, int len
)
557 unsigned char *buf
, *bp
;
559 if (len
== 0) return;
561 buf
= bp
= alloca (len
* 2);
565 newface
= FAST_GLYPH_FACE (*str
);
566 if (newface
!= screen_face
)
567 IT_set_face (newface
);
568 ch
= FAST_GLYPH_CHAR (*str
);
569 *bp
++ = (unsigned char)ch
;
570 *bp
++ = ScreenAttrib
;
573 fputc (ch
, termscript
);
578 dosmemput (buf
, 2 * len
,
579 (int)ScreenPrimary
+ 2 * (new_pos_X
+ screen_size_X
* new_pos_Y
));
584 IT_clear_end_of_line (first_unused
)
591 fprintf (termscript
, "<CLR:EOL>");
592 i
= (j
= screen_size_X
- new_pos_X
) * 2;
593 spaces
= sp
= alloca (i
);
598 *sp
++ = ScreenAttrib
;
602 dosmemput (spaces
, i
,
603 (int)ScreenPrimary
+ 2 * (new_pos_X
+ screen_size_X
* new_pos_Y
));
607 IT_clear_screen (void)
610 fprintf (termscript
, "<CLR:SCR>");
614 new_pos_X
= new_pos_Y
= 0;
618 IT_clear_to_end (void)
621 fprintf (termscript
, "<CLR:EOS>");
623 while (new_pos_Y
< screen_size_Y
) {
625 IT_clear_end_of_line (0);
631 IT_cursor_to (int y
, int x
)
634 fprintf (termscript
, "\n<XY=%dx%d>", x
, y
);
640 IT_reassert_line_highlight (new, vpos
)
644 IT_set_face (0); /* To possibly clear the highlighting. */
648 IT_change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
650 highlight
= new_highlight
;
651 IT_set_face (0); /* To possibly clear the highlighting. */
652 IT_cursor_to (vpos
, 0);
653 IT_clear_end_of_line (first_unused_hpos
);
660 IT_set_face (0); /* To possibly clear the highlighting. */
669 /* This was more or less copied from xterm.c */
672 IT_set_menu_bar_lines (window
, n
)
676 struct window
*w
= XWINDOW (window
);
678 XSETFASTINT (w
->last_modified
, 0);
679 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
680 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
682 /* Handle just the top child in a vertical split. */
683 if (!NILP (w
->vchild
))
684 IT_set_menu_bar_lines (w
->vchild
, n
);
686 /* Adjust all children in a horizontal split. */
687 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
689 w
= XWINDOW (window
);
690 IT_set_menu_bar_lines (window
, n
);
694 /* IT_set_terminal_modes is called when emacs is started,
695 resumed, and whenever the screen is redrawn! */
698 IT_set_terminal_modes (void)
705 fprintf (termscript
, "\n<SET_TERM>");
708 screen_size_X
= ScreenCols ();
709 screen_size_Y
= ScreenRows ();
710 screen_size
= screen_size_X
* screen_size_Y
;
712 new_pos_X
= new_pos_Y
= 0;
713 current_pos_X
= current_pos_Y
= -1;
719 startup_screen_size_X
= screen_size_X
;
720 startup_screen_size_Y
= screen_size_Y
;
721 startup_screen_attrib
= ScreenAttrib
;
723 ScreenGetCursor (&startup_pos_Y
, &startup_pos_X
);
724 ScreenRetrieve (startup_screen_buffer
= xmalloc (screen_size
* 2));
727 fprintf (termscript
, "<SCREEN SAVED (dimensions=%dx%d)>\n",
728 screen_size_X
, screen_size_Y
);
731 /* IT_reset_terminal_modes is called when emacs is
732 suspended or killed. */
735 IT_reset_terminal_modes (void)
737 int display_row_start
= (int) ScreenPrimary
;
738 int saved_row_len
= startup_screen_size_X
* 2;
739 int update_row_len
= ScreenCols () * 2;
740 int current_rows
= ScreenRows ();
741 int to_next_row
= update_row_len
;
742 unsigned char *saved_row
= startup_screen_buffer
;
743 int cursor_pos_X
= ScreenCols () - 1;
744 int cursor_pos_Y
= ScreenRows () - 1;
747 fprintf (termscript
, "\n<RESET_TERM>");
751 if (!term_setup_done
)
756 /* We have a situation here.
757 We cannot just do ScreenUpdate(startup_screen_buffer) because
758 the luser could have changed screen dimensions inside Emacs
759 and failed (or didn't want) to restore them before killing
760 Emacs. ScreenUpdate() uses the *current* screen dimensions and
761 thus will happily use memory outside what was allocated for
762 `startup_screen_buffer'.
763 Thus we only restore as much as the current screen dimensions
764 can hold, and clear the rest (if the saved screen is smaller than
765 the current) with the color attribute saved at startup. The cursor
766 is also restored within the visible dimensions. */
768 ScreenAttrib
= startup_screen_attrib
;
771 if (update_row_len
> saved_row_len
)
772 update_row_len
= saved_row_len
;
773 if (current_rows
> startup_screen_size_Y
)
774 current_rows
= startup_screen_size_Y
;
777 fprintf (termscript
, "<SCREEN RESTORED (dimensions=%dx%d)>\n",
778 update_row_len
/ 2, current_rows
);
780 while (current_rows
--)
782 dosmemput (saved_row
, update_row_len
, display_row_start
);
783 saved_row
+= saved_row_len
;
784 display_row_start
+= to_next_row
;
786 if (startup_pos_X
< cursor_pos_X
)
787 cursor_pos_X
= startup_pos_X
;
788 if (startup_pos_Y
< cursor_pos_Y
)
789 cursor_pos_Y
= startup_pos_Y
;
791 ScreenSetCursor (cursor_pos_Y
, cursor_pos_X
);
792 xfree (startup_screen_buffer
);
798 IT_set_terminal_window (void)
803 IT_set_frame_parameters (frame
, alist
)
809 extern unsigned long load_color ();
810 FRAME_PTR f
= (FRAME_PTR
) &the_only_frame
;
813 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
815 Lisp_Object elt
, prop
, val
;
820 CHECK_SYMBOL (prop
, 1);
822 if (EQ (prop
, intern ("foreground-color")))
824 unsigned long new_color
= load_color (f
, val
);
827 FRAME_FOREGROUND_PIXEL (f
) = new_color
;
831 else if (EQ (prop
, intern ("background-color")))
833 unsigned long new_color
= load_color (f
, val
);
836 FRAME_BACKGROUND_PIXEL (f
) = new_color
& ~8;
840 else if (EQ (prop
, intern ("menu-bar-lines")))
843 int old
= FRAME_MENU_BAR_LINES (the_only_frame
);
849 FRAME_MENU_BAR_LINES (f
) = new;
850 IT_set_menu_bar_lines (the_only_frame
.root_window
, new - old
);
856 recompute_basic_faces (f
);
857 Fredraw_frame (Fselected_frame ());
861 #endif /* !HAVE_X_WINDOWS */
864 /* Do we need the internal terminal? */
867 internal_terminal_init ()
869 char *term
= getenv ("TERM");
872 #ifdef HAVE_X_WINDOWS
873 if (!inhibit_window_system
)
878 = (!noninteractive
) && term
&& !strcmp (term
, "internal");
880 if (getenv ("EMACSTEST"))
881 termscript
= fopen (getenv ("EMACSTEST"), "wt");
883 #ifndef HAVE_X_WINDOWS
884 if (!internal_terminal
|| inhibit_window_system
)
886 the_only_frame
.output_method
= output_termcap
;
890 Vwindow_system
= intern ("pc");
891 Vwindow_system_version
= make_number (1);
893 bzero (&the_only_x_display
, sizeof the_only_x_display
);
894 the_only_x_display
.background_pixel
= 7; /* White */
895 the_only_x_display
.foreground_pixel
= 0; /* Black */
896 colors
= getenv ("EMACSCOLORS");
897 if (colors
&& strlen (colors
) >= 2)
899 /* Foreground colrs use 4 bits, background only 3. */
900 if (isxdigit (colors
[0]) && !isdigit (colors
[0]))
901 colors
[0] += 10 - (isupper (colors
[0]) ? 'A' : 'a');
902 if (colors
[0] >= 0 && colors
[0] < 16)
903 the_only_x_display
.foreground_pixel
= colors
[0];
904 if (colors
[1] >= 0 && colors
[1] < 8)
905 the_only_x_display
.background_pixel
= colors
[1];
907 the_only_x_display
.line_height
= 1;
908 the_only_frame
.output_data
.x
= &the_only_x_display
;
909 the_only_frame
.output_method
= output_msdos_raw
;
910 the_only_x_display
.font
= (XFontStruct
*)1; /* must *not* be zero */
912 init_frame_faces ((FRAME_PTR
) &the_only_frame
);
914 ring_bell_hook
= IT_ring_bell
;
915 write_glyphs_hook
= IT_write_glyphs
;
916 cursor_to_hook
= raw_cursor_to_hook
= IT_cursor_to
;
917 clear_to_end_hook
= IT_clear_to_end
;
918 clear_end_of_line_hook
= IT_clear_end_of_line
;
919 clear_frame_hook
= IT_clear_screen
;
920 change_line_highlight_hook
= IT_change_line_highlight
;
921 update_begin_hook
= IT_update_begin
;
922 update_end_hook
= IT_update_end
;
923 reassert_line_highlight_hook
= IT_reassert_line_highlight
;
925 /* These hooks are called by term.c without being checked. */
926 set_terminal_modes_hook
= IT_set_terminal_modes
;
927 reset_terminal_modes_hook
= IT_reset_terminal_modes
;
928 set_terminal_window_hook
= IT_set_terminal_window
;
932 dos_get_saved_screen (screen
, rows
, cols
)
937 #ifndef HAVE_X_WINDOWS
938 *screen
= startup_screen_buffer
;
939 *cols
= startup_screen_size_X
;
940 *rows
= startup_screen_size_Y
;
947 /* ----------------------- Keyboard control ----------------------
949 * Keymaps reflect the following keyboard layout:
951 * 0 1 2 3 4 5 6 7 8 9 10 11 12 BS
952 * TAB 15 16 17 18 19 20 21 22 23 24 25 26 (41)
953 * CLOK 30 31 32 33 34 35 36 37 38 39 40 (41) RET
954 * SH () 45 46 47 48 49 50 51 52 53 54 SHIFT
958 static int extended_kbd
; /* 101 (102) keyboard present. */
960 struct dos_keyboard_map
968 static struct dos_keyboard_map us_keyboard
= {
970 /* 01234567890123456789012345678901234567890 12345678901234 */
971 "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ",
972 /* 0123456789012345678901234567890123456789 012345678901234 */
973 "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ",
974 0 /* no Alt-Gr key */
977 static struct dos_keyboard_map fr_keyboard
= {
979 /* 012 3456789012345678901234567890123456789012345678901234 */
980 "ý&\82\",(-\8a_\80\85)= azertyuiop^$ qsdfghjklm\97* wxcvbnm;:! ",
981 /* 0123456789012345678901234567890123456789012345678901234 */
982 " 1234567890ø+ AZERTYUIOPù\9c QSDFGHJKLM%æ WXCVBN?./õ ",
983 /* 01234567 89012345678901234567890123456789012345678901234 */
987 static struct dos_keyboard_map dk_keyboard
= {
989 /* 0123456789012345678901234567890123456789012345678901234 */
990 "«1234567890+| qwertyuiop\86~ asdfghjkl\91\9b' zxcvbnm,.- ",
991 /* 01 23456789012345678901234567890123456789012345678901234 */
992 "õ!\"#$%&/()=?` QWERTYUIOP\8f^ ASDFGHJKL\92\9d* ZXCVBNM;:_ ",
993 /* 0123456789012345678901234567890123456789012345678901234 */
997 static struct keyboard_layout_list
1000 struct dos_keyboard_map
*keyboard_map
;
1001 } keyboard_layout_list
[] =
1008 static struct dos_keyboard_map
*keyboard
;
1009 static int keyboard_map_all
;
1012 dos_set_keyboard (code
, always
)
1018 /* Initialize to US settings, for countries that don't have their own. */
1019 keyboard
= keyboard_layout_list
[0].keyboard_map
;
1020 keyboard_map_all
= always
;
1021 dos_keyboard_layout
= 1;
1023 for (i
= 0; i
< (sizeof (keyboard_layout_list
)/sizeof (struct keyboard_layout_list
)); i
++)
1024 if (code
== keyboard_layout_list
[i
].country_code
)
1026 keyboard
= keyboard_layout_list
[i
].keyboard_map
;
1027 keyboard_map_all
= always
;
1028 dos_keyboard_layout
= code
;
1034 #define Ignore 0x0000
1035 #define Normal 0x0000 /* normal key - alt changes scan-code */
1036 #define FctKey 0x1000 /* func key if c == 0, else c */
1037 #define Special 0x2000 /* func key even if c != 0 */
1038 #define ModFct 0x3000 /* special if mod-keys, else 'c' */
1039 #define Map 0x4000 /* alt scan-code, map to unshift/shift key */
1040 #define KeyPad 0x5000 /* map to insert/kp-0 depending on c == 0xe0 */
1041 #define Grey 0x6000 /* Grey keypad key */
1043 #define Alt 0x0100 /* alt scan-code */
1044 #define Ctrl 0x0200 /* ctrl scan-code */
1045 #define Shift 0x0400 /* shift scan-code */
1049 unsigned char char_code
; /* normal code */
1050 unsigned char meta_code
; /* M- code */
1051 unsigned char keypad_code
; /* keypad code */
1052 unsigned char editkey_code
; /* edit key */
1053 } keypad_translate_map
[] = {
1054 '0', '0', 0xb0, /* kp-0 */ 0x63, /* insert */
1055 '1', '1', 0xb1, /* kp-1 */ 0x57, /* end */
1056 '2', '2', 0xb2, /* kp-2 */ 0x54, /* down */
1057 '3', '3', 0xb3, /* kp-3 */ 0x56, /* next */
1058 '4', '4', 0xb4, /* kp-4 */ 0x51, /* left */
1059 '5', '5', 0xb5, /* kp-5 */ 0xb5, /* kp-5 */
1060 '6', '6', 0xb6, /* kp-6 */ 0x53, /* right */
1061 '7', '7', 0xb7, /* kp-7 */ 0x50, /* home */
1062 '8', '8', 0xb8, /* kp-8 */ 0x52, /* up */
1063 '9', '9', 0xb9, /* kp-9 */ 0x55, /* prior */
1064 '.', '-', 0xae, /* kp-decimal */ 0xff /* delete */
1069 unsigned char char_code
; /* normal code */
1070 unsigned char keypad_code
; /* keypad code */
1071 } grey_key_translate_map
[] = {
1072 '/', 0xaf, /* kp-decimal */
1073 '*', 0xaa, /* kp-multiply */
1074 '-', 0xad, /* kp-subtract */
1075 '+', 0xab, /* kp-add */
1076 '\r', 0x8d /* kp-enter */
1079 static unsigned short
1080 ibmpc_translate_map
[] =
1082 /* --------------- 00 to 0f --------------- */
1083 Normal
| 0xff, /* Ctrl Break + Alt-NNN */
1084 Alt
| ModFct
| 0x1b, /* Escape */
1085 Normal
| 1, /* '1' */
1086 Normal
| 2, /* '2' */
1087 Normal
| 3, /* '3' */
1088 Normal
| 4, /* '4' */
1089 Normal
| 5, /* '5' */
1090 Normal
| 6, /* '6' */
1091 Normal
| 7, /* '7' */
1092 Normal
| 8, /* '8' */
1093 Normal
| 9, /* '9' */
1094 Normal
| 10, /* '0' */
1095 Normal
| 11, /* '-' */
1096 Normal
| 12, /* '=' */
1097 Special
| 0x08, /* Backspace */
1098 ModFct
| 0x74, /* Tab/Backtab */
1100 /* --------------- 10 to 1f --------------- */
1113 ModFct
| 0x0d, /* Return */
1118 /* --------------- 20 to 2f --------------- */
1127 Map
| 40, /* '\'' */
1129 Ignore
, /* Left shift */
1130 Map
| 41, /* '\\' */
1136 /* --------------- 30 to 3f --------------- */
1143 Ignore
, /* Right shift */
1144 Grey
| 1, /* Grey * */
1146 Normal
| ' ', /* ' ' */
1147 Ignore
, /* Caps Lock */
1148 FctKey
| 0xbe, /* F1 */
1149 FctKey
| 0xbf, /* F2 */
1150 FctKey
| 0xc0, /* F3 */
1151 FctKey
| 0xc1, /* F4 */
1152 FctKey
| 0xc2, /* F5 */
1154 /* --------------- 40 to 4f --------------- */
1155 FctKey
| 0xc3, /* F6 */
1156 FctKey
| 0xc4, /* F7 */
1157 FctKey
| 0xc5, /* F8 */
1158 FctKey
| 0xc6, /* F9 */
1159 FctKey
| 0xc7, /* F10 */
1160 Ignore
, /* Num Lock */
1161 Ignore
, /* Scroll Lock */
1162 KeyPad
| 7, /* Home */
1163 KeyPad
| 8, /* Up */
1164 KeyPad
| 9, /* Page Up */
1165 Grey
| 2, /* Grey - */
1166 KeyPad
| 4, /* Left */
1167 KeyPad
| 5, /* Keypad 5 */
1168 KeyPad
| 6, /* Right */
1169 Grey
| 3, /* Grey + */
1170 KeyPad
| 1, /* End */
1172 /* --------------- 50 to 5f --------------- */
1173 KeyPad
| 2, /* Down */
1174 KeyPad
| 3, /* Page Down */
1175 KeyPad
| 0, /* Insert */
1176 KeyPad
| 10, /* Delete */
1177 Shift
| FctKey
| 0xbe, /* (Shift) F1 */
1178 Shift
| FctKey
| 0xbf, /* (Shift) F2 */
1179 Shift
| FctKey
| 0xc0, /* (Shift) F3 */
1180 Shift
| FctKey
| 0xc1, /* (Shift) F4 */
1181 Shift
| FctKey
| 0xc2, /* (Shift) F5 */
1182 Shift
| FctKey
| 0xc3, /* (Shift) F6 */
1183 Shift
| FctKey
| 0xc4, /* (Shift) F7 */
1184 Shift
| FctKey
| 0xc5, /* (Shift) F8 */
1185 Shift
| FctKey
| 0xc6, /* (Shift) F9 */
1186 Shift
| FctKey
| 0xc7, /* (Shift) F10 */
1187 Ctrl
| FctKey
| 0xbe, /* (Ctrl) F1 */
1188 Ctrl
| FctKey
| 0xbf, /* (Ctrl) F2 */
1190 /* --------------- 60 to 6f --------------- */
1191 Ctrl
| FctKey
| 0xc0, /* (Ctrl) F3 */
1192 Ctrl
| FctKey
| 0xc1, /* (Ctrl) F4 */
1193 Ctrl
| FctKey
| 0xc2, /* (Ctrl) F5 */
1194 Ctrl
| FctKey
| 0xc3, /* (Ctrl) F6 */
1195 Ctrl
| FctKey
| 0xc4, /* (Ctrl) F7 */
1196 Ctrl
| FctKey
| 0xc5, /* (Ctrl) F8 */
1197 Ctrl
| FctKey
| 0xc6, /* (Ctrl) F9 */
1198 Ctrl
| FctKey
| 0xc7, /* (Ctrl) F10 */
1199 Alt
| FctKey
| 0xbe, /* (Alt) F1 */
1200 Alt
| FctKey
| 0xbf, /* (Alt) F2 */
1201 Alt
| FctKey
| 0xc0, /* (Alt) F3 */
1202 Alt
| FctKey
| 0xc1, /* (Alt) F4 */
1203 Alt
| FctKey
| 0xc2, /* (Alt) F5 */
1204 Alt
| FctKey
| 0xc3, /* (Alt) F6 */
1205 Alt
| FctKey
| 0xc4, /* (Alt) F7 */
1206 Alt
| FctKey
| 0xc5, /* (Alt) F8 */
1208 /* --------------- 70 to 7f --------------- */
1209 Alt
| FctKey
| 0xc6, /* (Alt) F9 */
1210 Alt
| FctKey
| 0xc7, /* (Alt) F10 */
1211 Ctrl
| FctKey
| 0x6d, /* (Ctrl) Sys Rq */
1212 Ctrl
| KeyPad
| 4, /* (Ctrl) Left */
1213 Ctrl
| KeyPad
| 6, /* (Ctrl) Right */
1214 Ctrl
| KeyPad
| 1, /* (Ctrl) End */
1215 Ctrl
| KeyPad
| 3, /* (Ctrl) Page Down */
1216 Ctrl
| KeyPad
| 7, /* (Ctrl) Home */
1217 Alt
| Map
| 1, /* '1' */
1218 Alt
| Map
| 2, /* '2' */
1219 Alt
| Map
| 3, /* '3' */
1220 Alt
| Map
| 4, /* '4' */
1221 Alt
| Map
| 5, /* '5' */
1222 Alt
| Map
| 6, /* '6' */
1223 Alt
| Map
| 7, /* '7' */
1224 Alt
| Map
| 8, /* '8' */
1226 /* --------------- 80 to 8f --------------- */
1227 Alt
| Map
| 9, /* '9' */
1228 Alt
| Map
| 10, /* '0' */
1229 Alt
| Map
| 11, /* '-' */
1230 Alt
| Map
| 12, /* '=' */
1231 Ctrl
| KeyPad
| 9, /* (Ctrl) Page Up */
1232 FctKey
| 0xc8, /* F11 */
1233 FctKey
| 0xc9, /* F12 */
1234 Shift
| FctKey
| 0xc8, /* (Shift) F11 */
1235 Shift
| FctKey
| 0xc9, /* (Shift) F12 */
1236 Ctrl
| FctKey
| 0xc8, /* (Ctrl) F11 */
1237 Ctrl
| FctKey
| 0xc9, /* (Ctrl) F12 */
1238 Alt
| FctKey
| 0xc8, /* (Alt) F11 */
1239 Alt
| FctKey
| 0xc9, /* (Alt) F12 */
1240 Ctrl
| KeyPad
| 8, /* (Ctrl) Up */
1241 Ctrl
| Grey
| 2, /* (Ctrl) Grey - */
1242 Ctrl
| KeyPad
| 5, /* (Ctrl) Keypad 5 */
1244 /* --------------- 90 to 9f --------------- */
1245 Ctrl
| Grey
| 3, /* (Ctrl) Grey + */
1246 Ctrl
| KeyPad
| 2, /* (Ctrl) Down */
1247 Ctrl
| KeyPad
| 0, /* (Ctrl) Insert */
1248 Ctrl
| KeyPad
| 10, /* (Ctrl) Delete */
1249 Ctrl
| FctKey
| 0x09, /* (Ctrl) Tab */
1250 Ctrl
| Grey
| 0, /* (Ctrl) Grey / */
1251 Ctrl
| Grey
| 1, /* (Ctrl) Grey * */
1252 Alt
| FctKey
| 0x50, /* (Alt) Home */
1253 Alt
| FctKey
| 0x52, /* (Alt) Up */
1254 Alt
| FctKey
| 0x55, /* (Alt) Page Up */
1255 Ignore
, /* NO KEY */
1256 Alt
| FctKey
| 0x51, /* (Alt) Left */
1257 Ignore
, /* NO KEY */
1258 Alt
| FctKey
| 0x53, /* (Alt) Right */
1259 Ignore
, /* NO KEY */
1260 Alt
| FctKey
| 0x57, /* (Alt) End */
1262 /* --------------- a0 to af --------------- */
1263 Alt
| KeyPad
| 2, /* (Alt) Down */
1264 Alt
| KeyPad
| 3, /* (Alt) Page Down */
1265 Alt
| KeyPad
| 0, /* (Alt) Insert */
1266 Alt
| KeyPad
| 10, /* (Alt) Delete */
1267 Alt
| Grey
| 0, /* (Alt) Grey / */
1268 Alt
| FctKey
| 0x09, /* (Alt) Tab */
1269 Alt
| Grey
| 4 /* (Alt) Keypad Enter */
1272 /* These bit-positions corresponds to values returned by BIOS */
1273 #define SHIFT_P 0x0003 /* two bits! */
1274 #define CTRL_P 0x0004
1275 #define ALT_P 0x0008
1276 #define SCRLOCK_P 0x0010
1277 #define NUMLOCK_P 0x0020
1278 #define CAPSLOCK_P 0x0040
1279 #define ALT_GR_P 0x0800
1280 #define SUPER_P 0x4000 /* pseudo */
1281 #define HYPER_P 0x8000 /* pseudo */
1284 dos_get_modifiers (keymask
)
1291 /* Calculate modifier bits */
1292 regs
.h
.ah
= extended_kbd
? 0x12 : 0x02;
1293 int86 (0x16, ®s
, ®s
);
1297 mask
= regs
.h
.al
& (SHIFT_P
| CTRL_P
| ALT_P
|
1298 SCRLOCK_P
| NUMLOCK_P
| CAPSLOCK_P
);
1302 mask
= regs
.h
.al
& (SHIFT_P
|
1303 SCRLOCK_P
| NUMLOCK_P
| CAPSLOCK_P
);
1305 /* Do not break international keyboard support. */
1306 /* When Keyb.Com is loaded, the right Alt key is */
1307 /* used for accessing characters like { and } */
1308 if (regs
.h
.ah
& 2) /* Left ALT pressed ? */
1311 if ((regs
.h
.ah
& 8) != 0) /* Right ALT pressed ? */
1314 if (dos_hyper_key
== 1)
1317 modifiers
|= hyper_modifier
;
1319 else if (dos_super_key
== 1)
1322 modifiers
|= super_modifier
;
1326 if (regs
.h
.ah
& 1) /* Left CTRL pressed ? */
1329 if (regs
.h
.ah
& 4) /* Right CTRL pressed ? */
1331 if (dos_hyper_key
== 2)
1334 modifiers
|= hyper_modifier
;
1336 else if (dos_super_key
== 2)
1339 modifiers
|= super_modifier
;
1347 modifiers
|= shift_modifier
;
1349 modifiers
|= ctrl_modifier
;
1351 modifiers
|= meta_modifier
;
1358 #define NUM_RECENT_DOSKEYS (100)
1359 int recent_doskeys_index
; /* Index for storing next element into recent_doskeys */
1360 int total_doskeys
; /* Total number of elements stored into recent_doskeys */
1361 Lisp_Object recent_doskeys
; /* A vector, holding the last 100 keystrokes */
1363 DEFUN ("recent-doskeys", Frecent_doskeys
, Srecent_doskeys
, 0, 0, 0,
1364 "Return vector of last 100 keyboard input values seen in dos_rawgetc.\n\
1365 Each input key receives two values in this vector: first the ASCII code,\n\
1366 and then the scan code.")
1369 Lisp_Object
*keys
= XVECTOR (recent_doskeys
)->contents
;
1372 if (total_doskeys
< NUM_RECENT_DOSKEYS
)
1373 return Fvector (total_doskeys
, keys
);
1376 val
= Fvector (NUM_RECENT_DOSKEYS
, keys
);
1377 bcopy (keys
+ recent_doskeys_index
,
1378 XVECTOR (val
)->contents
,
1379 (NUM_RECENT_DOSKEYS
- recent_doskeys_index
) * sizeof (Lisp_Object
));
1381 XVECTOR (val
)->contents
+ NUM_RECENT_DOSKEYS
- recent_doskeys_index
,
1382 recent_doskeys_index
* sizeof (Lisp_Object
));
1387 /* Get a char from keyboard. Function keys are put into the event queue. */
1392 struct input_event event
;
1395 #ifndef HAVE_X_WINDOWS
1396 SCREEN_SET_CURSOR ();
1397 if (!mouse_visible
) mouse_on ();
1400 /* The following condition is equivalent to `kbhit ()', except that
1401 it uses the bios to do its job. This pleases DESQview/X. */
1402 while ((regs
.h
.ah
= extended_kbd
? 0x11 : 0x01),
1403 int86 (0x16, ®s
, ®s
),
1404 (regs
.x
.flags
& 0x40) == 0)
1407 register unsigned char c
;
1408 int sc
, code
, mask
, kp_mode
;
1411 regs
.h
.ah
= extended_kbd
? 0x10 : 0x00;
1412 int86 (0x16, ®s
, ®s
);
1417 XVECTOR (recent_doskeys
)->contents
[recent_doskeys_index
++]
1419 if (recent_doskeys_index
== NUM_RECENT_DOSKEYS
)
1420 recent_doskeys_index
= 0;
1421 XVECTOR (recent_doskeys
)->contents
[recent_doskeys_index
++]
1423 if (recent_doskeys_index
== NUM_RECENT_DOSKEYS
)
1424 recent_doskeys_index
= 0;
1426 modifiers
= dos_get_modifiers (&mask
);
1428 #ifndef HAVE_X_WINDOWS
1429 if (!NILP (Vdos_display_scancodes
))
1432 sprintf (buf
, "%02x:%02x*%04x",
1433 (unsigned) (sc
&0xff), (unsigned) c
, mask
);
1434 dos_direct_output (screen_size_Y
- 2, screen_size_X
- 12, buf
, 10);
1442 case 10: /* Ctrl Grey Enter */
1443 code
= Ctrl
| Grey
| 4;
1445 case 13: /* Grey Enter */
1448 case '/': /* Grey / */
1458 if (sc
>= (sizeof (ibmpc_translate_map
) / sizeof (short)))
1460 if ((code
= ibmpc_translate_map
[sc
]) == Ignore
)
1467 modifiers
|= meta_modifier
;
1469 modifiers
|= ctrl_modifier
;
1471 modifiers
|= shift_modifier
;
1474 switch (code
& 0xf000)
1477 if (c
&& !(mask
& (SHIFT_P
| ALT_P
| CTRL_P
| HYPER_P
| SUPER_P
)))
1479 c
= 0; /* Special */
1492 if (c
== 0) /* ctrl-break */
1494 return c
; /* ALT-nnn */
1496 if (!keyboard_map_all
)
1505 if (c
&& !(mask
& ALT_P
) && !((mask
& SHIFT_P
) && (mask
& CTRL_P
)))
1506 if (!keyboard_map_all
)
1510 if (mask
& ALT_P
&& code
<= 10 && code
> 0 && dos_keypad_mode
& 0x200)
1511 mask
|= SHIFT_P
; /* ALT-1 => M-! etc. */
1515 code
= keyboard
->shifted
[code
];
1517 modifiers
&= ~shift_modifier
;
1520 if ((mask
& ALT_GR_P
) && keyboard
->alt_gr
&& keyboard
->alt_gr
[code
] != ' ')
1521 code
= keyboard
->alt_gr
[code
];
1523 code
= keyboard
->unshifted
[code
];
1528 if (c
== 0xe0) /* edit key */
1531 if ((mask
& (NUMLOCK_P
|CTRL_P
|SHIFT_P
|ALT_P
)) == NUMLOCK_P
) /* numlock on */
1532 kp_mode
= dos_keypad_mode
& 0x03;
1534 kp_mode
= (dos_keypad_mode
>> 4) & 0x03;
1539 if (code
== 10 && dos_decimal_point
)
1540 return dos_decimal_point
;
1541 return keypad_translate_map
[code
].char_code
;
1544 code
= 0xff00 | keypad_translate_map
[code
].keypad_code
;
1548 code
= keypad_translate_map
[code
].meta_code
;
1549 modifiers
= meta_modifier
;
1553 code
= 0xff00 | keypad_translate_map
[code
].editkey_code
;
1560 kp_mode
= ((mask
& (NUMLOCK_P
|CTRL_P
|SHIFT_P
|ALT_P
)) == NUMLOCK_P
) ? 0x04 : 0x40;
1561 if (dos_keypad_mode
& kp_mode
)
1562 code
= 0xff00 | grey_key_translate_map
[code
].keypad_code
;
1564 code
= grey_key_translate_map
[code
].char_code
;
1573 event
.kind
= non_ascii_keystroke
;
1575 event
.kind
= ascii_keystroke
;
1577 event
.modifiers
= modifiers
;
1578 XSETFRAME (event
.frame_or_window
, selected_frame
);
1579 event
.timestamp
= event_timestamp ();
1580 kbd_buffer_store_event (&event
);
1585 int but
, press
, x
, y
, ok
;
1587 /* Check for mouse movement *before* buttons. */
1588 mouse_check_moved ();
1590 for (but
= 0; but
< NUM_MOUSE_BUTTONS
; but
++)
1591 for (press
= 0; press
< 2; press
++)
1593 int button_num
= but
;
1596 ok
= mouse_pressed (but
, &x
, &y
);
1598 ok
= mouse_released (but
, &x
, &y
);
1601 /* Allow a simultaneous press/release of Mouse-1 and
1602 Mouse-2 to simulate Mouse-3 on two-button mice. */
1603 if (mouse_button_count
== 2 && but
< 2)
1605 int x2
, y2
; /* don't clobber original coordinates */
1607 /* If only one button is pressed, wait 100 msec and
1608 check again. This way, Speedy Gonzales isn't
1609 punished, while the slow get their chance. */
1610 if (press
&& mouse_pressed (1-but
, &x2
, &y2
)
1611 || !press
&& mouse_released (1-but
, &x2
, &y2
))
1616 if (press
&& mouse_pressed (1-but
, &x2
, &y2
)
1617 || !press
&& mouse_released (1-but
, &x2
, &y2
))
1622 event
.kind
= mouse_click
;
1623 event
.code
= button_num
;
1624 event
.modifiers
= dos_get_modifiers (0)
1625 | (press
? down_modifier
: up_modifier
);
1628 XSETFRAME (event
.frame_or_window
, selected_frame
);
1629 event
.timestamp
= event_timestamp ();
1630 kbd_buffer_store_event (&event
);
1638 static int prev_get_char
= -1;
1640 /* Return 1 if a key is ready to be read without suspending execution. */
1644 if (prev_get_char
!= -1)
1647 return ((prev_get_char
= dos_rawgetc ()) != -1);
1650 /* Read a key. Return -1 if no key is ready. */
1654 if (prev_get_char
!= -1)
1656 int c
= prev_get_char
;
1661 return dos_rawgetc ();
1664 #ifndef HAVE_X_WINDOWS
1665 /* See xterm.c for more info. */
1667 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1669 register int pix_x
, pix_y
;
1670 register int *x
, *y
;
1671 void /* XRectangle */ *bounds
;
1674 if (bounds
) abort ();
1676 /* Ignore clipping. */
1683 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1686 register int *pix_x
, *pix_y
;
1692 /* Simulation of X's menus. Nothing too fancy here -- just make it work
1695 Actually, I don't know the meaning of all the parameters of the functions
1696 here -- I only know how they are called by xmenu.c. I could of course
1697 grab the nearest Xlib manual (down the hall, second-to-last door on the
1698 left), but I don't think it's worth the effort. */
1705 menu
= (XMenu
*) xmalloc (sizeof (XMenu
));
1706 menu
->allocated
= menu
->count
= menu
->panecount
= menu
->width
= 0;
1710 /* Allocate some (more) memory for MENU ensuring that there is room for one
1714 IT_menu_make_room (XMenu
*menu
)
1716 if (menu
->allocated
== 0)
1718 int count
= menu
->allocated
= 10;
1719 menu
->text
= (char **) xmalloc (count
* sizeof (char *));
1720 menu
->submenu
= (XMenu
**) xmalloc (count
* sizeof (XMenu
*));
1721 menu
->panenumber
= (int *) xmalloc (count
* sizeof (int));
1723 else if (menu
->allocated
== menu
->count
)
1725 int count
= menu
->allocated
= menu
->allocated
+ 10;
1727 = (char **) xrealloc (menu
->text
, count
* sizeof (char *));
1729 = (XMenu
**) xrealloc (menu
->submenu
, count
* sizeof (XMenu
*));
1731 = (int *) xrealloc (menu
->panenumber
, count
* sizeof (int));
1735 /* Search the given menu structure for a given pane number. */
1738 IT_menu_search_pane (XMenu
*menu
, int pane
)
1743 for (i
= 0; i
< menu
->count
; i
++)
1744 if (menu
->submenu
[i
])
1746 if (pane
== menu
->panenumber
[i
])
1747 return menu
->submenu
[i
];
1748 if ((try = IT_menu_search_pane (menu
->submenu
[i
], pane
)))
1754 /* Determine how much screen space a given menu needs. */
1757 IT_menu_calc_size (XMenu
*menu
, int *width
, int *height
)
1759 int i
, h2
, w2
, maxsubwidth
, maxheight
;
1762 maxheight
= menu
->count
;
1763 for (i
= 0; i
< menu
->count
; i
++)
1765 if (menu
->submenu
[i
])
1767 IT_menu_calc_size (menu
->submenu
[i
], &w2
, &h2
);
1768 if (w2
> maxsubwidth
) maxsubwidth
= w2
;
1769 if (i
+ h2
> maxheight
) maxheight
= i
+ h2
;
1772 *width
= menu
->width
+ maxsubwidth
;
1773 *height
= maxheight
;
1776 /* Display MENU at (X,Y) using FACES. */
1779 IT_menu_display (XMenu
*menu
, int y
, int x
, int *faces
)
1781 int i
, j
, face
, width
;
1785 int enabled
, mousehere
;
1788 width
= menu
->width
;
1789 text
= (GLYPH
*) xmalloc ((width
+ 2) * sizeof (GLYPH
));
1790 ScreenGetCursor (&row
, &col
);
1791 mouse_get_xy (&mx
, &my
);
1793 for (i
= 0; i
< menu
->count
; i
++)
1795 IT_cursor_to (y
+ i
, x
);
1797 = (!menu
->submenu
[i
] && menu
->panenumber
[i
]) || (menu
->submenu
[i
]);
1798 mousehere
= (y
+ i
== my
&& x
<= mx
&& mx
< x
+ width
+ 2);
1799 face
= faces
[enabled
+ mousehere
* 2];
1801 *p
++ = FAST_MAKE_GLYPH (' ', face
);
1802 for (j
= 0, q
= menu
->text
[i
]; *q
; j
++)
1803 *p
++ = FAST_MAKE_GLYPH (*q
++, face
);
1804 for (; j
< width
; j
++)
1805 *p
++ = FAST_MAKE_GLYPH (' ', face
);
1806 *p
++ = FAST_MAKE_GLYPH (menu
->submenu
[i
] ? 16 : ' ', face
);
1807 IT_write_glyphs (text
, width
+ 2);
1810 IT_cursor_to (row
, col
);
1814 /* --------------------------- X Menu emulation ---------------------- */
1816 /* Report availability of menus. */
1824 /* Create a brand new menu structure. */
1827 XMenuCreate (Display
*foo1
, Window foo2
, char *foo3
)
1829 return IT_menu_create ();
1832 /* Create a new pane and place it on the outer-most level. It is not
1833 clear that it should be placed out there, but I don't know what else
1837 XMenuAddPane (Display
*foo
, XMenu
*menu
, char *txt
, int enable
)
1844 IT_menu_make_room (menu
);
1845 menu
->submenu
[menu
->count
] = IT_menu_create ();
1846 menu
->text
[menu
->count
] = txt
;
1847 menu
->panenumber
[menu
->count
] = ++menu
->panecount
;
1849 if ((len
= strlen (txt
)) > menu
->width
)
1851 return menu
->panecount
;
1854 /* Create a new item in a menu pane. */
1857 XMenuAddSelection (Display
*bar
, XMenu
*menu
, int pane
,
1858 int foo
, char *txt
, int enable
)
1863 if (!(menu
= IT_menu_search_pane (menu
, pane
)))
1865 IT_menu_make_room (menu
);
1866 menu
->submenu
[menu
->count
] = (XMenu
*) 0;
1867 menu
->text
[menu
->count
] = txt
;
1868 menu
->panenumber
[menu
->count
] = enable
;
1870 if ((len
= strlen (txt
)) > menu
->width
)
1875 /* Decide where the menu would be placed if requested at (X,Y). */
1878 XMenuLocate (Display
*foo0
, XMenu
*menu
, int foo1
, int foo2
, int x
, int y
,
1879 int *ulx
, int *uly
, int *width
, int *height
)
1881 IT_menu_calc_size (menu
, width
, height
);
1887 struct IT_menu_state
1889 void *screen_behind
;
1896 /* Display menu, wait for user's response, and return that response. */
1899 XMenuActivate (Display
*foo
, XMenu
*menu
, int *pane
, int *selidx
,
1900 int x0
, int y0
, unsigned ButtonMask
, char **txt
)
1902 struct IT_menu_state
*state
;
1906 int faces
[4], selectface
;
1907 int leave
, result
, onepane
;
1908 int title_faces
[4]; /* face to display the menu title */
1910 /* Just in case we got here without a mouse present... */
1911 if (have_mouse
<= 0)
1912 return XM_IA_SELECT
;
1914 state
= alloca (menu
->panecount
* sizeof (struct IT_menu_state
));
1915 screensize
= screen_size
* 2;
1917 = compute_glyph_face (&the_only_frame
,
1920 intern ("msdos-menu-passive-face")),
1923 = compute_glyph_face (&the_only_frame
,
1926 intern ("msdos-menu-active-face")),
1929 = face_name_id_number (&the_only_frame
, intern ("msdos-menu-select-face"));
1930 faces
[2] = compute_glyph_face (&the_only_frame
, selectface
, faces
[0]);
1931 faces
[3] = compute_glyph_face (&the_only_frame
, selectface
, faces
[1]);
1933 /* Make sure the menu title is always displayed with
1934 `msdos-menu-active-face', no matter where the mouse pointer is. */
1935 for (i
= 0; i
< 4; i
++)
1936 title_faces
[i
] = faces
[3];
1939 state
[0].menu
= menu
;
1941 ScreenRetrieve (state
[0].screen_behind
= xmalloc (screensize
));
1943 IT_menu_display (menu
, y0
- 1, x0
- 1, title_faces
); /* display menu title */
1944 if ((onepane
= menu
->count
== 1 && menu
->submenu
[0]))
1946 menu
->width
= menu
->submenu
[0]->width
;
1947 state
[0].menu
= menu
->submenu
[0];
1951 state
[0].menu
= menu
;
1953 state
[0].x
= x0
- 1;
1955 state
[0].pane
= onepane
;
1957 mouse_last_x
= -1; /* A hack that forces display. */
1961 if (!mouse_visible
) mouse_on ();
1962 mouse_check_moved ();
1963 if (selected_frame
->mouse_moved
)
1965 selected_frame
->mouse_moved
= 0;
1966 result
= XM_IA_SELECT
;
1967 mouse_get_xy (&x
, &y
);
1968 for (i
= 0; i
< statecount
; i
++)
1969 if (state
[i
].x
<= x
&& x
< state
[i
].x
+ state
[i
].menu
->width
+ 2)
1971 int dy
= y
- state
[i
].y
;
1972 if (0 <= dy
&& dy
< state
[i
].menu
->count
)
1974 if (!state
[i
].menu
->submenu
[dy
])
1975 if (state
[i
].menu
->panenumber
[dy
])
1976 result
= XM_SUCCESS
;
1978 result
= XM_IA_SELECT
;
1979 *pane
= state
[i
].pane
- 1;
1981 /* We hit some part of a menu, so drop extra menus that
1982 have been opened. That does not include an open and
1984 if (i
!= statecount
- 2
1985 || state
[i
].menu
->submenu
[dy
] != state
[i
+1].menu
)
1986 while (i
!= statecount
- 1)
1990 ScreenUpdate (state
[statecount
].screen_behind
);
1991 xfree (state
[statecount
].screen_behind
);
1993 if (i
== statecount
- 1 && state
[i
].menu
->submenu
[dy
])
1995 IT_menu_display (state
[i
].menu
,
1999 state
[statecount
].menu
= state
[i
].menu
->submenu
[dy
];
2000 state
[statecount
].pane
= state
[i
].menu
->panenumber
[dy
];
2002 ScreenRetrieve (state
[statecount
].screen_behind
2003 = xmalloc (screensize
));
2005 = state
[i
].x
+ state
[i
].menu
->width
+ 2;
2006 state
[statecount
].y
= y
;
2011 IT_menu_display (state
[statecount
- 1].menu
,
2012 state
[statecount
- 1].y
,
2013 state
[statecount
- 1].x
,
2016 for (b
= 0; b
< mouse_button_count
; b
++)
2018 (void) mouse_pressed (b
, &x
, &y
);
2019 if (mouse_released (b
, &x
, &y
))
2025 ScreenUpdate (state
[0].screen_behind
);
2026 while (statecount
--)
2027 xfree (state
[statecount
].screen_behind
);
2031 /* Dispose of a menu. */
2034 XMenuDestroy (Display
*foo
, XMenu
*menu
)
2037 if (menu
->allocated
)
2039 for (i
= 0; i
< menu
->count
; i
++)
2040 if (menu
->submenu
[i
])
2041 XMenuDestroy (foo
, menu
->submenu
[i
]);
2043 xfree (menu
->submenu
);
2044 xfree (menu
->panenumber
);
2050 x_pixel_width (struct frame
*f
)
2052 return FRAME_WIDTH (f
);
2056 x_pixel_height (struct frame
*f
)
2058 return FRAME_HEIGHT (f
);
2060 #endif /* !HAVE_X_WINDOWS */
2062 /* ----------------------- DOS / UNIX conversion --------------------- */
2064 /* Destructively turn backslashes into slashes. */
2067 dostounix_filename (p
)
2078 /* Destructively turn slashes into backslashes. */
2081 unixtodos_filename (p
)
2092 /* Get the default directory for a given drive. 0=def, 1=A, 2=B, ... */
2093 void msdos_downcase_filename (unsigned char *);
2096 getdefdir (drive
, dst
)
2100 char in_path
[4], *p
= in_path
;
2103 /* Generate "X:." (when drive is X) or "." (when drive is 0). */
2106 *p
++ = drive
+ 'A' - 1;
2113 _fixpath (in_path
, dst
);
2117 msdos_downcase_filename (dst
);
2123 /* Remove all CR's that are followed by a LF. */
2128 register unsigned char *buf
;
2130 unsigned char *np
= buf
;
2131 unsigned char *startp
= buf
;
2132 unsigned char *endp
= buf
+ n
;
2137 while (buf
< endp
- 1)
2141 if (*(++buf
) != 0x0a)
2152 #if defined(__DJGPP__) && __DJGPP__ == 2 && __DJGPP_MINOR__ == 0
2154 /* In DJGPP v2.0, library `write' can call `malloc', which might
2155 cause relocation of the buffer whose address we get in ADDR.
2156 Here is a version of `write' that avoids calling `malloc',
2157 to serve us until such time as the library is fixed.
2158 Actually, what we define here is called `__write', because
2159 `write' is a stub that just jmp's to `__write' (to be
2160 POSIXLY-correct with respect to the global name-space). */
2162 #include <io.h> /* for _write */
2163 #include <libc/dosio.h> /* for __file_handle_modes[] */
2165 static char xbuf
[64 * 1024]; /* DOS cannot write more in one chunk */
2167 #define XBUF_END (xbuf + sizeof (xbuf) - 1)
2170 __write (int handle
, const void *buffer
, size_t count
)
2175 if(__file_handle_modes
[handle
] & O_BINARY
)
2176 return _write (handle
, buffer
, count
);
2180 const char *bp
= buffer
;
2181 int total_written
= 0;
2182 int nmoved
= 0, ncr
= 0;
2186 /* The next test makes sure there's space for at least 2 more
2187 characters in xbuf[], so both CR and LF can be put there. */
2199 if (xbp
>= XBUF_END
|| !count
)
2201 size_t to_write
= nmoved
+ ncr
;
2202 int written
= _write (handle
, xbuf
, to_write
);
2207 total_written
+= nmoved
; /* CRs aren't counted in ret value */
2209 /* If some, but not all were written (disk full?), return
2210 an estimate of the total written bytes not counting CRs. */
2211 if (written
< to_write
)
2212 return total_written
- (to_write
- written
) * nmoved
/to_write
;
2219 return total_written
;
2223 #endif /* __DJGPP__ == 2 && __DJGPP_MINOR__ == 0 */
2225 DEFUN ("msdos-long-file-names", Fmsdos_long_file_names
, Smsdos_long_file_names
,
2227 "Return non-nil if long file names are supported on MSDOS.")
2230 return (_USE_LFN
? Qt
: Qnil
);
2233 /* Convert alphabetic characters in a filename to lower-case. */
2236 msdos_downcase_filename (p
)
2237 register unsigned char *p
;
2239 /* Under LFN we expect to get pathnames in their true case. */
2240 if (NILP (Fmsdos_long_file_names ()))
2242 if (*p
>= 'A' && *p
<= 'Z')
2246 DEFUN ("msdos-downcase-filename", Fmsdos_downcase_filename
, Smsdos_downcase_filename
,
2248 "Convert alphabetic characters in FILENAME to lower case and return that.\n\
2249 When long filenames are supported, doesn't change FILENAME.")
2251 Lisp_Object filename
;
2253 char *fname
= XSTRING (filename
)->data
;
2255 msdos_downcase_filename (fname
);
2256 return make_string (fname
, XSTRING (filename
)->size
);
2259 /* The Emacs root directory as determined by init_environment. */
2261 static char emacsroot
[MAXPATHLEN
];
2264 rootrelativepath (rel
)
2267 static char result
[MAXPATHLEN
+ 10];
2269 strcpy (result
, emacsroot
);
2270 strcat (result
, "/");
2271 strcat (result
, rel
);
2275 /* Define a lot of environment variables if not already defined. Don't
2276 remove anything unless you know what you're doing -- lots of code will
2277 break if one or more of these are missing. */
2280 init_environment (argc
, argv
, skip_args
)
2288 /* Find our root from argv[0]. Assuming argv[0] is, say,
2289 "c:/emacs/bin/emacs.exe" our root will be "c:/emacs". */
2290 root
= alloca (MAXPATHLEN
+ 20);
2291 _fixpath (argv
[0], root
);
2293 len
= strlen (root
);
2294 while (len
> 0 && root
[len
] != '/' && root
[len
] != ':')
2297 if (len
> 4 && strcmp (root
+ len
- 4, "/bin") == 0)
2298 root
[len
- 4] = '\0';
2300 strcpy (root
, "c:/emacs"); /* Only under debuggers, I think. */
2301 len
= strlen (root
);
2302 strcpy (emacsroot
, root
);
2304 /* We default HOME to our root. */
2305 setenv ("HOME", root
, 0);
2307 /* We default EMACSPATH to root + "/bin". */
2308 strcpy (root
+ len
, "/bin");
2309 setenv ("EMACSPATH", root
, 0);
2311 /* I don't expect anybody to ever use other terminals so the internal
2312 terminal is the default. */
2313 setenv ("TERM", "internal", 0);
2315 #ifdef HAVE_X_WINDOWS
2316 /* Emacs expects DISPLAY to be set. */
2317 setenv ("DISPLAY", "unix:0.0", 0);
2320 /* SHELL is a bit tricky -- COMSPEC is the closest we come, but we must
2321 downcase it and mirror the backslashes. */
2322 s
= getenv ("COMSPEC");
2323 if (!s
) s
= "c:/command.com";
2324 t
= alloca (strlen (s
) + 1);
2327 dostounix_filename (t
);
2328 setenv ("SHELL", t
, 0);
2330 /* PATH is also downcased and backslashes mirrored. */
2331 s
= getenv ("PATH");
2333 t
= alloca (strlen (s
) + 3);
2334 /* Current directory is always considered part of MsDos's path but it is
2335 not normally mentioned. Now it is. */
2336 strcat (strcpy (t
, ".;"), s
);
2338 dostounix_filename (t
); /* Not a single file name, but this should work. */
2339 setenv ("PATH", t
, 1);
2341 /* In some sense all dos users have root privileges, so... */
2342 setenv ("USER", "root", 0);
2343 setenv ("NAME", getenv ("USER"), 0);
2345 /* Time zone determined from country code. To make this possible, the
2346 country code may not span more than one time zone. In other words,
2347 in the USA, you lose. */
2349 switch (dos_country_code
)
2351 case 31: /* Belgium */
2352 case 32: /* The Netherlands */
2353 case 33: /* France */
2354 case 34: /* Spain */
2355 case 36: /* Hungary */
2356 case 38: /* Yugoslavia (or what's left of it?) */
2357 case 39: /* Italy */
2358 case 41: /* Switzerland */
2359 case 42: /* Tjekia */
2360 case 45: /* Denmark */
2361 case 46: /* Sweden */
2362 case 47: /* Norway */
2363 case 48: /* Poland */
2364 case 49: /* Germany */
2365 /* Daylight saving from last Sunday in March to last Sunday in
2366 September, both at 2AM. */
2367 setenv ("TZ", "MET-01METDST-02,M3.5.0/02:00,M9.5.0/02:00", 0);
2369 case 44: /* United Kingdom */
2370 case 351: /* Portugal */
2371 case 354: /* Iceland */
2372 setenv ("TZ", "GMT+00", 0);
2374 case 81: /* Japan */
2375 case 82: /* Korea */
2376 setenv ("TZ", "JST-09", 0);
2378 case 90: /* Turkey */
2379 case 358: /* Finland */
2380 setenv ("TZ", "EET-02", 0);
2382 case 972: /* Israel */
2383 /* This is an approximation. (For exact rules, use the
2384 `zoneinfo/israel' file which comes with DJGPP, but you need
2385 to install it in `/usr/share/zoneinfo/' directory first.) */
2386 setenv ("TZ", "IST-02IDT-03,M4.1.6/00:00,M9.5.6/01:00", 0);
2394 static int break_stat
; /* BREAK check mode status. */
2395 static int stdin_stat
; /* stdin IOCTL status. */
2399 /* These must be global. */
2400 static _go32_dpmi_seginfo ctrl_break_vector
;
2401 static _go32_dpmi_registers ctrl_break_regs
;
2402 static int ctrlbreakinstalled
= 0;
2404 /* Interrupt level detection of Ctrl-Break. Don't do anything fancy here! */
2407 ctrl_break_func (regs
)
2408 _go32_dpmi_registers
*regs
;
2414 install_ctrl_break_check ()
2416 if (!ctrlbreakinstalled
)
2418 /* Don't press Ctrl-Break if you don't have either DPMI or Emacs
2419 was compiler with Djgpp 1.11 maintenance level 5 or later! */
2420 ctrlbreakinstalled
= 1;
2421 ctrl_break_vector
.pm_offset
= (int) ctrl_break_func
;
2422 _go32_dpmi_allocate_real_mode_callback_iret (&ctrl_break_vector
,
2424 _go32_dpmi_set_real_mode_interrupt_vector (0x1b, &ctrl_break_vector
);
2428 #endif /* __DJGPP__ < 2 */
2430 /* Turn off Dos' Ctrl-C checking and inhibit interpretation of
2431 control chars by DOS. Determine the keyboard type. */
2436 union REGS inregs
, outregs
;
2437 static int first_time
= 1;
2439 break_stat
= getcbrk ();
2442 install_ctrl_break_check ();
2448 int86 (0x15, &inregs
, &outregs
);
2449 extended_kbd
= (!outregs
.x
.cflag
) && (outregs
.h
.ah
== 0);
2453 if (internal_terminal
2454 #ifdef HAVE_X_WINDOWS
2455 && inhibit_window_system
2459 inregs
.x
.ax
= 0x0021;
2460 int86 (0x33, &inregs
, &outregs
);
2461 have_mouse
= (outregs
.x
.ax
& 0xffff) == 0xffff;
2464 /* Reportedly, the above doesn't work for some mouse drivers. There
2465 is an additional detection method that should work, but might be
2466 a little slower. Use that as an alternative. */
2467 inregs
.x
.ax
= 0x0000;
2468 int86 (0x33, &inregs
, &outregs
);
2469 have_mouse
= (outregs
.x
.ax
& 0xffff) == 0xffff;
2474 have_mouse
= 1; /* enable mouse */
2477 if (outregs
.x
.bx
== 3)
2479 mouse_button_count
= 3;
2480 mouse_button_translate
[0] = 0; /* Left */
2481 mouse_button_translate
[1] = 2; /* Middle */
2482 mouse_button_translate
[2] = 1; /* Right */
2486 mouse_button_count
= 2;
2487 mouse_button_translate
[0] = 0;
2488 mouse_button_translate
[1] = 1;
2490 mouse_position_hook
= &mouse_get_pos
;
2499 stdin_stat
= setmode (fileno (stdin
), O_BINARY
);
2500 return (stdin_stat
!= -1);
2503 return (setmode (fileno (stdin
), O_BINARY
) != -1);
2505 #else /* __DJGPP__ < 2 */
2509 /* I think it is wrong to overwrite `stdin_stat' every time
2510 but the first one this function is called, but I don't
2511 want to change the way it used to work in v1.x.--EZ */
2513 inregs
.x
.ax
= 0x4400; /* Get IOCTL status. */
2514 inregs
.x
.bx
= 0x00; /* 0 = stdin. */
2515 intdos (&inregs
, &outregs
);
2516 stdin_stat
= outregs
.h
.dl
;
2518 inregs
.x
.dx
= stdin_stat
| 0x0020; /* raw mode */
2519 inregs
.x
.ax
= 0x4401; /* Set IOCTL status */
2520 intdos (&inregs
, &outregs
);
2521 return !outregs
.x
.cflag
;
2523 #endif /* __DJGPP__ < 2 */
2526 /* Restore status of standard input and Ctrl-C checking. */
2531 union REGS inregs
, outregs
;
2533 setcbrk (break_stat
);
2538 return (setmode (fileno (stdin
), stdin_stat
) != -1);
2540 #else /* not __DJGPP__ >= 2 */
2542 inregs
.x
.ax
= 0x4401; /* Set IOCTL status. */
2543 inregs
.x
.bx
= 0x00; /* 0 = stdin. */
2544 inregs
.x
.dx
= stdin_stat
;
2545 intdos (&inregs
, &outregs
);
2546 return !outregs
.x
.cflag
;
2548 #endif /* not __DJGPP__ >= 2 */
2552 /* Run command as specified by ARGV in directory DIR.
2553 The command is run with input from TEMPIN, output to
2554 file TEMPOUT and stderr to TEMPERR. */
2557 run_msdos_command (argv
, dir
, tempin
, tempout
, temperr
)
2558 unsigned char **argv
;
2560 int tempin
, tempout
, temperr
;
2562 char *saveargv1
, *saveargv2
, **envv
;
2563 char oldwd
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
2564 int msshell
, result
= -1;
2565 int in
, out
, inbak
, outbak
, errbak
;
2569 /* Get current directory as MSDOS cwd is not per-process. */
2572 cmd
= Ffile_name_nondirectory (build_string (argv
[0]));
2573 msshell
= !NILP (Fmember (cmd
, Fsymbol_value (intern ("msdos-shells"))))
2574 && !strcmp ("-c", argv
[1]);
2577 saveargv1
= argv
[1];
2578 saveargv2
= argv
[2];
2582 char *p
= alloca (strlen (argv
[2]) + 1);
2584 strcpy (argv
[2] = p
, saveargv2
);
2585 while (*p
&& isspace (*p
))
2587 while (*p
&& !isspace (*p
))
2595 /* Build the environment array. */
2597 extern Lisp_Object Vprocess_environment
;
2598 Lisp_Object tmp
, lst
;
2601 lst
= Vprocess_environment
;
2602 len
= XFASTINT (Flength (lst
));
2604 envv
= alloca ((len
+ 1) * sizeof (char *));
2605 for (i
= 0; i
< len
; i
++)
2609 CHECK_STRING (tmp
, 0);
2610 envv
[i
] = alloca (XSTRING (tmp
)->size
+ 1);
2611 strcpy (envv
[i
], XSTRING (tmp
)->data
);
2613 envv
[len
] = (char *) 0;
2617 chdir (XSTRING (dir
)->data
);
2621 if (inbak
< 0 || outbak
< 0 || errbak
< 0)
2622 goto done
; /* Allocation might fail due to lack of descriptors. */
2625 mouse_get_xy (&x
, &y
);
2627 dos_ttcooked (); /* do it here while 0 = stdin */
2635 if (msshell
&& !argv
[3])
2637 /* MS-DOS native shells are too restrictive. For starters, they
2638 cannot grok commands longer than 126 characters. In DJGPP v2
2639 and later, `system' is much smarter, so we'll call it instead. */
2641 extern char **environ
;
2644 /* A shell gets a single argument--its full command
2645 line--whose original was saved in `saveargv2'. */
2646 result
= system (saveargv2
);
2650 #endif /* __DJGPP__ > 1 */
2652 result
= spawnve (P_WAIT
, argv
[0], argv
, envv
);
2665 mouse_moveto (x
, y
);
2672 argv
[1] = saveargv1
;
2673 argv
[2] = saveargv2
;
2681 fprintf (stderr
, "%s not yet implemented\r\n", badfunc
);
2688 /* ------------------------- Compatibility functions -------------------
2693 /* Hostnames for a pc are not really funny,
2694 but they are used in change log so we emulate the best we can. */
2696 gethostname (p
, size
)
2700 char *q
= egetenv ("HOSTNAME");
2707 /* When time zones are set from Ms-Dos too many C-libraries are playing
2708 tricks with time values. We solve this by defining our own version
2709 of `gettimeofday' bypassing GO32. Our version needs to be initialized
2710 once and after each call to `tzset' with TZ changed. That is
2711 accomplished by aliasing tzset to init_gettimeofday. */
2713 static struct tm time_rec
;
2716 gettimeofday (struct timeval
*tp
, struct timezone
*tzp
)
2724 if (t
.ti_hour
< time_rec
.tm_hour
) /* midnight wrap */
2728 time_rec
.tm_year
= d
.da_year
- 1900;
2729 time_rec
.tm_mon
= d
.da_mon
- 1;
2730 time_rec
.tm_mday
= d
.da_day
;
2733 time_rec
.tm_hour
= t
.ti_hour
;
2734 time_rec
.tm_min
= t
.ti_min
;
2735 time_rec
.tm_sec
= t
.ti_sec
;
2738 tm
.tm_gmtoff
= dos_timezone_offset
;
2740 tp
->tv_sec
= mktime (&tm
); /* may modify tm */
2741 tp
->tv_usec
= t
.ti_hund
* (1000000 / 100);
2743 /* Ignore tzp; it's obsolescent. */
2747 #endif /* __DJGPP__ < 2 */
2750 * A list of unimplemented functions that we silently ignore.
2754 unsigned alarm (s
) unsigned s
; {}
2755 fork () { return 0; }
2756 int kill (x
, y
) int x
, y
; { return -1; }
2758 void volatile pause () {}
2759 sigsetmask (x
) int x
; { return 0; }
2763 setpgrp () {return 0; }
2764 setpriority (x
,y
,z
) int x
,y
,z
; { return 0; }
2765 sigblock (mask
) int mask
; { return 0; }
2766 unrequest_sigio () {}
2769 #include "sysselect.h"
2771 #ifndef EMACS_TIME_ZERO_OR_NEG_P
2772 #define EMACS_TIME_ZERO_OR_NEG_P(time) \
2773 ((long)(time).tv_sec < 0 \
2774 || ((time).tv_sec == 0 \
2775 && (long)(time).tv_usec <= 0))
2779 /* Only event queue is checked. */
2780 /* We don't have to call timer_check here
2781 because wait_reading_process_input takes care of that. */
2783 sys_select (nfds
, rfds
, wfds
, efds
, timeout
)
2785 SELECT_TYPE
*rfds
, *wfds
, *efds
;
2786 EMACS_TIME
*timeout
;
2794 check_input
= FD_ISSET (0, rfds
);
2805 /* If we are looking only for the terminal, with no timeout,
2806 just read it and wait -- that's more efficient. */
2809 while (!detect_input_pending ())
2818 EMACS_TIME clnow
, cllast
, cldiff
;
2821 EMACS_SET_SECS_USECS (cllast
, t
.ti_sec
, t
.ti_hund
* 10000L);
2823 while (!check_input
|| !detect_input_pending ())
2826 EMACS_SET_SECS_USECS (clnow
, t
.ti_sec
, t
.ti_hund
* 10000L);
2827 EMACS_SUB_TIME (cldiff
, clnow
, cllast
);
2829 /* When seconds wrap around, we assume that no more than
2830 1 minute passed since last `gettime'. */
2831 if (EMACS_TIME_NEG_P (cldiff
))
2832 EMACS_SET_SECS (cldiff
, EMACS_SECS (cldiff
) + 60);
2833 EMACS_SUB_TIME (*timeout
, *timeout
, cldiff
);
2835 /* Stop when timeout value crosses zero. */
2836 if (EMACS_TIME_ZERO_OR_NEG_P (*timeout
))
2851 * Define overlaid functions:
2853 * chdir -> sys_chdir
2854 * tzset -> init_gettimeofday
2855 * abort -> dos_abort
2860 extern int chdir ();
2866 int len
= strlen (path
);
2867 char *tmp
= (char *)path
;
2869 if (*tmp
&& tmp
[1] == ':')
2871 if (getdisk () != tolower (tmp
[0]) - 'a')
2872 setdisk (tolower (tmp
[0]) - 'a');
2873 tmp
+= 2; /* strip drive: KFS 1995-07-06 */
2877 if (len
> 1 && (tmp
[len
- 1] == '/'))
2879 char *tmp1
= (char *) alloca (len
+ 1);
2890 extern void tzset (void);
2893 init_gettimeofday ()
2899 ltm
= gtm
= time (NULL
);
2900 ltm
= mktime (lstm
= localtime (<m
));
2901 gtm
= mktime (gmtime (>m
));
2902 time_rec
.tm_hour
= 99; /* force gettimeofday to get date */
2903 time_rec
.tm_isdst
= lstm
->tm_isdst
;
2904 dos_timezone_offset
= time_rec
.tm_gmtoff
= (int)(gtm
- ltm
) / 60;
2911 dos_abort (file
, line
)
2915 char buffer1
[200], buffer2
[400];
2918 sprintf (buffer1
, "<EMACS FATAL ERROR IN %s LINE %d>", file
, line
);
2919 for (i
= j
= 0; buffer1
[i
]; i
++) {
2920 buffer2
[j
++] = buffer1
[i
];
2921 buffer2
[j
++] = 0x70;
2923 dosmemput (buffer2
, j
, (int)ScreenPrimary
);
2924 ScreenSetCursor (2, 0);
2932 ScreenSetCursor (10, 0);
2933 cputs ("\r\n\nEmacs aborted!\r\n");
2935 /* Generate traceback, so we could tell whodunit. */
2936 signal (SIGINT
, SIG_DFL
);
2937 __asm__
__volatile__ ("movb $0x1b,%al;call ___djgpp_hw_exception");
2945 recent_doskeys
= Fmake_vector (make_number (NUM_RECENT_DOSKEYS
), Qnil
);
2946 staticpro (&recent_doskeys
);
2948 defsubr (&Srecent_doskeys
);
2949 defsubr (&Smsdos_long_file_names
);
2950 defsubr (&Smsdos_downcase_filename
);