1 /* MS-DOS specific C utilities.
2 Copyright (C) 1993, 1994 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Contributed by Morten Welinder */
22 /* Note: some of the stuff here was taken from end of sysdep.c in demacs. */
30 #include <sys/param.h>
36 #include "termhooks.h"
41 /* #include <process.h> */
42 /* Damn that local process.h! Instead we can define P_WAIT ourselves. */
45 static int break_stat
; /* BREAK check mode status. */
46 static int stdin_stat
; /* stdin IOCTL status. */
47 static int extended_kbd
; /* 101 (102) keyboard present. */
49 int have_mouse
; /* Mouse present? */
50 static int mouse_last_x
;
51 static int mouse_last_y
;
53 /* Turn off Dos' Ctrl-C checking and inhibit interpretation of control chars
54 by Dos. Determine the keyboard type. */
58 union REGS inregs
, outregs
;
61 int86 (0x15, &inregs
, &outregs
);
62 extended_kbd
= (!outregs
.x
.cflag
) && (outregs
.h
.ah
== 0);
64 break_stat
= getcbrk ();
66 install_ctrl_break_check ();
67 have_mouse
= mouse_init1 ();
69 inregs
.x
.ax
= 0x4400; /* Get IOCTL status. */
70 inregs
.x
.bx
= 0x00; /* 0 = stdin. */
71 intdos (&inregs
, &outregs
);
72 stdin_stat
= outregs
.h
.dl
;
74 inregs
.x
.dx
= (outregs
.x
.dx
| 0x0020) & 0x0027; /* raw mode */
76 intdos (&inregs
, &outregs
);
77 return !outregs
.x
.cflag
;
80 /* Restore status of standard input and Ctrl-C checking. */
84 union REGS inregs
, outregs
;
87 if (have_mouse
) mouse_off ();
89 inregs
.x
.ax
= 0x4401; /* Set IOCTL status. */
90 inregs
.x
.bx
= 0x00; /* 0 = stdin. */
91 inregs
.x
.dx
= stdin_stat
;
92 intdos (&inregs
, &outregs
);
93 return !outregs
.x
.cflag
;
97 ibmpc_translate_map
[] =
99 /* --------------- 00 to 0f --------------- */
102 0xffb1, /* Keypad 1 */
103 0xffb2, /* Keypad 2 */
104 0xffb3, /* Keypad 3 */
105 0xffb4, /* Keypad 4 */
106 0xffb5, /* Keypad 5 */
107 0xffb6, /* Keypad 6 */
108 0xffb7, /* Keypad 7 */
109 0xffb8, /* Keypad 8 */
110 0xffb9, /* Keypad 9 */
111 0xffb0, /* Keypad 0 */
113 0xff08, /* Backspace */
114 0xff74, /* (Shift) Tab [Tab doesn't use this table] */
116 /* --------------- 10 to 1f --------------- */
117 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']',
118 0xff8d, /* Keypad Enter */
122 /* --------------- 20 to 2f --------------- */
123 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
125 '\\', 'z', 'x', 'c', 'v',
127 /* --------------- 30 to 3f --------------- */
128 'b', 'n', 'm', ',', '.',
141 /* --------------- 40 to 4f --------------- */
151 0xff55, /* Page Up */
154 0xffb5, /* Keypad 5 */
159 /* --------------- 50 to 5f --------------- */
161 0xff56, /* Page Down */
164 0xffbe, /* (Shift) F1 */
165 0xffbf, /* (Shift) F2 */
166 0xffc0, /* (Shift) F3 */
167 0xffc1, /* (Shift) F4 */
168 0xffc2, /* (Shift) F5 */
169 0xffc3, /* (Shift) F6 */
170 0xffc4, /* (Shift) F7 */
171 0xffc5, /* (Shift) F8 */
172 0xffc6, /* (Shift) F9 */
173 0xffc7, /* (Shift) F10 */
174 0xffbe, /* (Ctrl) F1 */
175 0xffbf, /* (Ctrl) F2 */
177 /* --------------- 60 to 6f --------------- */
178 0xffc0, /* (Ctrl) F3 */
179 0xffc1, /* (Ctrl) F4 */
180 0xffc2, /* (Ctrl) F5 */
181 0xffc3, /* (Ctrl) F6 */
182 0xffc4, /* (Ctrl) F7 */
183 0xffc5, /* (Ctrl) F8 */
184 0xffc6, /* (Ctrl) F9 */
185 0xffc7, /* (Ctrl) F10 */
186 0xffbe, /* (Alt) F1 */
187 0xffbf, /* (Alt) F2 */
188 0xffc0, /* (Alt) F3 */
189 0xffc1, /* (Alt) F4 */
190 0xffc2, /* (Alt) F5 */
191 0xffc3, /* (Alt) F6 */
192 0xffc4, /* (Alt) F7 */
193 0xffc5, /* (Alt) F8 */
195 /* --------------- 70 to 7f --------------- */
196 0xffc6, /* (Alt) F9 */
197 0xffc7, /* (Alt) F10 */
198 0xff6d, /* (Ctrl) Sys Rq */
199 0xff51, /* (Ctrl) Left */
200 0xff53, /* (Ctrl) Right */
201 0xff57, /* (Ctrl) End */
202 0xff56, /* (Ctrl) Page Down */
203 0xff50, /* (Ctrl) Home */
204 '1', '2', '3', '4', '5', '6', '7', '8', /* (Alt) */
206 /* --------------- 80 to 8f --------------- */
207 '9', '0', '-', '=', /* (Alt) */
208 0xff55, /* (Ctrl) Page Up */
211 0xffc8, /* (Shift) F11 */
212 0xffc9, /* (Shift) F12 */
213 0xffc8, /* (Ctrl) F11 */
214 0xffc9, /* (Ctrl) F12 */
215 0xffc8, /* (Alt) F11 */
216 0xffc9, /* (Alt) F12 */
217 0xff52, /* (Ctrl) Up */
218 0xffae, /* (Ctrl) Grey - */
219 0xffb5, /* (Ctrl) Keypad 5 */
221 /* --------------- 90 to 9f --------------- */
222 0xffab, /* (Ctrl) Grey + */
223 0xff54, /* (Ctrl) Down */
224 0xff63, /* (Ctrl) Insert */
225 0xffff, /* (Ctrl) Delete */
226 0xff09, /* (Ctrl) Tab */
227 0xffaf, /* (Ctrl) Grey / */
228 0xffaa, /* (Ctrl) Grey * */
229 0xff50, /* (Alt) Home */
230 0xff52, /* (Alt) Up */
231 0xff55, /* (Alt) Page Up */
233 0xff51, /* (Alt) Left */
235 0xff53, /* (Alt) Right */
237 0xff57, /* (Alt) End */
239 /* --------------- a0 to af --------------- */
240 0xff54, /* (Alt) Down */
241 0xff56, /* (Alt) Page Down */
242 0xff63, /* (Alt) Insert */
243 0xffff, /* (Alt) Delete */
244 0xffaf, /* (Alt) Grey / */
245 0xff09, /* (Alt) Tab */
246 0xff0d /* (Alt) Enter */
249 /* Get a char from keyboard. Function keys are put into the event queue. */
253 struct input_event event
;
256 int ctrl_p
, alt_p
, shift_p
;
258 /* Calculate modifier bits */
259 regs
.h
.ah
= extended_kbd
? 0x12 : 0x02;
260 int86 (0x16, ®s
, ®s
);
261 ctrl_p
= ((regs
.h
.al
& 4) != 0);
262 shift_p
= ((regs
.h
.al
& 3) != 0);
263 /* Please be very careful here not to break international keyboard support.
264 When Keyb.Com is loaded, the key marked `Alt Gr' is used for accessing
265 characters like { and } if their positions are overlaid. */
266 alt_p
= ((extended_kbd
? (regs
.h
.ah
& 2) : (regs
.h
.al
& 8)) != 0);
268 /* The following condition is equivalent to `kbhit ()', except that
269 it uses the bios to do its job. This pleases DESQview/X. */
270 while ((regs
.h
.ah
= extended_kbd
? 0x11 : 0x01),
271 int86 (0x16, ®s
, ®s
),
272 (regs
.x
.flags
& 0x40) == 0)
275 register unsigned char c
;
278 regs
.h
.ah
= extended_kbd
? 0x10 : 0x00;
279 int86 (0x16, ®s
, ®s
);
283 /* Determine from the scan code if a keypad key was pressed. */
284 if (c
>= '0' && c
<= '9' && sc
> 0xb)
285 sc
= (c
== '0') ? 0xb : (c
- '0' + 1), c
= 0;
286 else if (sc
== 0x53 && c
!= 0xe0)
288 code
= 0xffae; /* Keypad decimal point/comma. */
295 case 10: /* Ctrl Enter */
311 || (ctrl_p
&& shift_p
)
312 || (c
== 0xe0 && sc
!= 0) /* Pseudo-key */
313 || sc
== 0x37 /* Grey * */
314 || sc
== 0x4a /* Grey - */
315 || sc
== 0x4e /* Grey + */
316 || sc
== 0x0e) /* Back space *key*, not Ctrl-h */
318 if (sc
>= (sizeof (ibmpc_translate_map
) / sizeof (short)))
321 code
= ibmpc_translate_map
[sc
];
327 event
.kind
= non_ascii_keystroke
;
328 event
.code
= (code
& 0xff) + 0xff00;
332 /* Don't return S- if we don't have to. `shifted' is
333 supposed to be the shifted versions of the characters
334 in `unshifted'. Unfortunately, this is only true for
335 US keyboard layout. If anyone knows how to do this
336 right, please tell us. */
337 static char *unshifted
338 = "abcdefghijklmnopqrstuvwxyz,./=;[\\]'-`0123456789";
340 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ<>?+:{|}\"_~)!@#$%^&*(";
343 if (shift_p
&& (pos
= strchr (unshifted
, code
)))
345 c
= shifted
[pos
- unshifted
];
349 if (c
== 0) c
= code
;
350 event
.kind
= ascii_keystroke
;
354 = (shift_p
? shift_modifier
: 0)
355 + (ctrl_p
? ctrl_modifier
: 0)
356 + (alt_p
? meta_modifier
: 0);
357 /* EMACS == Enter Meta Alt Control Shift */
358 event
.frame_or_window
= selected_frame
;
359 gettimeofday (&tv
, NULL
);
360 event
.timestamp
= tv
.tv_usec
;
361 kbd_buffer_store_event (&event
);
369 int but
, press
, x
, y
, ok
;
371 /* Check for mouse movement *before* buttons. */
372 mouse_check_moved ();
374 for (but
= 0; but
< NUM_MOUSE_BUTTONS
; but
++)
375 for (press
= 0; press
< 2; press
++)
378 ok
= mouse_pressed (but
, &x
, &y
);
380 ok
= mouse_released (but
, &x
, &y
);
383 event
.kind
= mouse_click
;
386 = (shift_p
? shift_modifier
: 0)
387 + (ctrl_p
? ctrl_modifier
: 0)
388 + (alt_p
? meta_modifier
: 0)
389 + (press
? down_modifier
: up_modifier
);
392 event
.frame_or_window
= selected_frame
;
393 gettimeofday (&tv
, NULL
);
394 event
.timestamp
= tv
.tv_usec
;
395 kbd_buffer_store_event (&event
);
403 static int prev_get_char
= -1;
405 /* Return 1 if a key is ready to be read without suspending execution. */
408 if (prev_get_char
!= -1)
411 return ((prev_get_char
= dos_rawgetc ()) != -1);
414 /* Read a key. Return -1 if no key is ready. */
417 if (prev_get_char
!= -1)
419 int c
= prev_get_char
;
424 return dos_rawgetc ();
427 /* Hostnames for a pc are not really funny, but they are used in change log
428 so we emulate the best we can. */
429 gethostname (p
, size
)
433 char *q
= egetenv ("HOSTNAME");
440 /* Destructively turn backslashes into slashes. */
442 dostounix_filename (p
)
453 /* Destructively turn slashes into backslashes. */
455 unixtodos_filename (p
)
466 /* Get the default directory for a given drive. 0=def, 1=A, 2=B, ... */
468 getdefdir (drive
, dst
)
476 regs
.x
.si
= (int) dst
;
478 intdos (®s
, ®s
);
479 return !regs
.x
.cflag
;
482 /* Remove all CR's that are followed by a LF. */
486 register unsigned char *buf
;
488 unsigned char *np
= buf
;
489 unsigned char *startp
= buf
;
490 unsigned char *endp
= buf
+ n
;
495 while (buf
< endp
- 1)
499 if (*(++buf
) != 0x0a)
511 /* Run command as specified by ARGV in directory DIR.
512 The command is run with input from TEMPIN and output to file TEMPOUT. */
514 run_msdos_command (argv
, dir
, tempin
, tempout
)
515 unsigned char **argv
;
519 char *saveargv1
, *saveargv2
, **envv
;
520 char oldwd
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
521 int msshell
, result
= -1;
522 int in
, out
, inbak
, outbak
, errbak
;
525 /* Get current directory as MSDOS cwd is not per-process. */
528 cmd
= Ffile_name_nondirectory (build_string (argv
[0]));
529 msshell
= !NILP (Fmember (cmd
, Fsymbol_value (intern ("msdos-shells"))))
530 && !strcmp ("-c", argv
[1]);
538 char *p
= alloca (strlen (argv
[2]) + 1);
540 strcpy (argv
[2] = p
, saveargv2
);
541 while (*p
&& isspace (*p
))
543 while (*p
&& !isspace (*p
))
551 /* Build the environment array. */
553 extern Lisp_Object Vprocess_environment
;
554 Lisp_Object tmp
, lst
;
557 lst
= Vprocess_environment
;
558 len
= XFASTINT (Flength (lst
));
560 envv
= alloca ((len
+ 1) * sizeof (char *));
561 for (i
= 0; i
< len
; i
++)
565 CHECK_STRING (tmp
, 0);
566 envv
[i
] = alloca (XSTRING (tmp
)->size
+ 1);
567 strcpy (envv
[i
], XSTRING (tmp
)->data
);
569 envv
[len
] = (char *) 0;
573 chdir (XSTRING (dir
)->data
);
577 if (inbak
< 0 || outbak
< 0 || errbak
< 0)
578 goto done
; /* Allocation might fail due to lack of descriptors. */
583 result
= spawnve (P_WAIT
, argv
[0], argv
, envv
);
603 fprintf (stderr
, "%s not yet implemented\r\n", badfunc
);
608 /* A list of unimplemented functions that we silently ignore. */
609 unsigned alarm (s
) unsigned s
; {}
610 fork () { return 0; }
611 int kill (x
, y
) int x
, y
; { return -1; }
613 void volatile pause () {}
615 setpgrp () {return 0; }
616 setpriority (x
,y
,z
) int x
,y
,z
; { return 0; }
617 sigsetmask (x
) int x
; { return 0; }
618 unrequest_sigio () {}
628 int len
= strlen (path
);
629 char *tmp
= (char *) alloca (len
+ 1);
630 /* Gotta do this extern here due to the corresponding #define: */
633 if (*path
&& path
[1] == ':' && (getdisk () != tolower (path
[0]) - 'a'))
634 setdisk (tolower (path
[0]) - 'a');
637 if (strcmp (path
, "/") && strcmp (path
+ 1, ":/") && (path
[len
- 1] == '/'))
642 /* Sleep SECS. If KBDOK also return immediately if a key is pressed. */
644 sleep_or_kbd_hit (secs
, kbdok
)
650 gettimeofday (&t
, NULL
);
651 clnow
= t
.tv_sec
* 100 + t
.tv_usec
/ 10000;
652 clthen
= clnow
+ (100 * secs
);
656 gettimeofday (&t
, NULL
);
657 clnow
= t
.tv_sec
* 100 + t
.tv_usec
/ 10000;
658 if (kbdok
&& detect_input_pending ())
661 while (clnow
< clthen
);
664 /* The Emacs root directory as determined by init_environment. */
665 static char emacsroot
[MAXPATHLEN
];
668 rootrelativepath (rel
)
671 static char result
[MAXPATHLEN
+ 10];
673 strcpy (result
, emacsroot
);
674 strcat (result
, "/");
675 strcat (result
, rel
);
679 /* Define a lot of environment variables if not already defined. Don't
680 remove anything unless you know what you're doing -- lots of code will
681 break if one or more of these are missing. */
683 init_environment (argc
, argv
, skip_args
)
691 /* Find our root from argv[0]. Assuming argv[0] is, say,
692 "c:/emacs/bin/emacs.exe" our root will be "c:/emacs". */
693 len
= strlen (argv
[0]);
694 root
= alloca (len
+ 10); /* A little extra space for the stuff below. */
695 strcpy (root
, argv
[0]);
696 while (len
> 0 && root
[len
] != '/' && root
[len
] != ':')
699 if (len
> 4 && strcmp (root
+ len
- 4, "/bin") == 0)
700 root
[len
- 4] = '\0';
702 strcpy (root
, "c:/emacs"); /* Only under debuggers, I think. */
704 strcpy (emacsroot
, root
);
706 /* We default HOME to our root. */
707 setenv ("HOME", root
, 0);
709 /* We default EMACSPATH to root + "/bin". */
710 strcpy (root
+ len
, "/bin");
711 setenv ("EMACSPATH", root
, 0);
713 /* I don't expect anybody to ever use other terminals so the internal
714 terminal is the default. */
715 setenv ("TERM", "internal", 0);
717 /* SHELL is a bit tricky -- COMSPEC is the closest we come, but we must
718 downcase it and mirror the backslashes. */
719 s
= getenv ("COMSPEC");
720 if (!s
) s
= "c:/command.com";
721 t
= alloca (strlen (s
) + 1);
724 dostounix_filename (t
);
725 setenv ("SHELL", t
, 0);
727 /* PATH is also downcased and backslashes mirrored. */
730 t
= alloca (strlen (s
) + 3);
731 /* Current directory is always considered part of MsDos's path but it is
732 not normally mentioned. Now it is. */
733 strcat (strcpy (t
, ".;"), s
);
735 dostounix_filename (t
); /* Not a single file name, but this should work. */
736 setenv ("PATH", t
, 1);
738 /* In some sense all dos users have root privileges, so... */
739 setenv ("USER", "root", 0);
740 setenv ("NAME", getenv ("USER"), 0);
742 /* Time zone determined from country code. To make this possible, the
743 country code may not span more than one time zone. In other words,
744 in the USA, you lose. */
745 switch (dos_country_code
)
747 case 31: /* Belgium */
748 case 32: /* The Netherlands */
749 case 33: /* France */
751 case 36: /* Hungary */
752 case 38: /* Yugoslavia (or what's left of it?) */
754 case 41: /* Switzerland */
755 case 42: /* Tjekia */
756 case 45: /* Denmark */
757 case 46: /* Sweden */
758 case 47: /* Norway */
759 case 48: /* Poland */
760 case 49: /* Germany */
761 /* Daylight saving from last Sunday in March to last Sunday in
762 September, both at 2AM. */
763 setenv ("TZ", "MET-01METDST-02,M3.5.0/02:00,M9.5.0/02:00", 0);
765 case 44: /* United Kingdom */
766 case 351: /* Portugal */
767 case 354: /* Iceland */
768 setenv ("TZ", "GMT+00", 0);
772 setenv ("TZ", "???-09", 0);
774 case 90: /* Turkey */
775 case 358: /* Finland */
776 case 972: /* Israel */
777 setenv ("TZ", "EET-02", 0);
781 init_gettimeofday ();
784 /* Flash the screen as a substitute for BEEPs. */
787 do_visible_bell (xorattr
)
788 unsigned char xorattr
;
793 movl _ScreenPrimary,%%eax
800 xorb %%al,%%gs:(%%ebx)
816 : "m" (xorattr
), "g" (ScreenCols () * ScreenRows ())
817 : "%eax", "%ebx", /* "%gs",*/ "%ecx", "%edx");
820 /* At screen position (X,Y), output C characters from string S with
821 attribute A. Do it fast! */
824 output_string (x
, y
, s
, c
, a
)
829 char *t
= (char *)ScreenPrimary
+ 2 * (x
+ ScreenCols () * y
);
839 movw %%ax,%%gs:(%%edi)
845 : "m" (a
), "g" (t
), "g" (c
), "g" (s
)
846 : "%eax", "%ecx", /* "%gs",*/ "%esi", "%edi");
849 static int internal_terminal
= 0;
856 static char spaces
[] = " ";
859 unsigned char *cp
, *cp0
;
862 if (internal_terminal
&& f
== stdout
)
864 if (have_mouse
) mouse_off ();
866 count
= stdout
->_ptr
- stdout
->_base
;
880 ScreenAttrib
= *cp
++;
884 do_visible_bell (*cp
++);
893 i
= ScreenCols () - x
;
895 while (i
>= sizeof spaces
)
897 output_string (j
, y
, spaces
, sizeof spaces
,
903 output_string (j
, y
, spaces
, i
, ScreenAttrib
);
915 ScreenAttrib
^= *cp
++;
923 write (1, "\007", 1);
941 while (count
> 0 && *cp
>= ' ')
943 output_string (x
, y
, cp0
, cp
- cp0
, ScreenAttrib
);
948 ScreenSetCursor (y
, x
);
949 if (have_mouse
) mouse_on ();
952 /* This is a call to the original fflush. */
956 /* Do we need the internal terminal? */
958 internal_terminal_init ()
960 char *term
= getenv ("TERM");
963 = (!noninteractive
) && term
&& !strcmp (term
, "internal");
966 /* When time zones are set from Ms-Dos too may C-libraries are playing
967 tricks with time values. We solve this by defining our own version
968 of `gettimeofday' bypassing GO32. Our version needs to be initialized
969 once and after each call to `tzset' with TZ changed. */
971 static int daylight
, gmtoffset
;
974 gettimeofday (struct timeval
*tp
, struct timezone
*tzp
)
984 tmrec
.tm_year
= d
.da_year
- 1900;
985 tmrec
.tm_mon
= d
.da_mon
- 1;
986 tmrec
.tm_mday
= d
.da_day
;
987 tmrec
.tm_hour
= t
.ti_hour
;
988 tmrec
.tm_min
= t
.ti_min
;
989 tmrec
.tm_sec
= t
.ti_sec
;
990 tmrec
.tm_gmtoff
= gmtoffset
;
991 tmrec
.tm_isdst
= daylight
;
992 tp
->tv_sec
= mktime (&tmrec
);
993 tp
->tv_usec
= t
.ti_hund
* (1000000 / 100);
997 tzp
->tz_minuteswest
= gmtoffset
;
998 tzp
->tz_dsttime
= daylight
;
1004 init_gettimeofday ()
1011 ltm
= gtm
= time (NULL
);
1012 ltm
= mktime (lstm
= localtime (<m
));
1013 gtm
= mktime (gmtime (>m
));
1014 daylight
= lstm
->tm_isdst
;
1015 gmtoffset
= (int)(gtm
- ltm
) / 60;
1018 /* These must be global. */
1019 static _go32_dpmi_seginfo ctrl_break_vector
;
1020 static _go32_dpmi_registers ctrl_break_regs
;
1021 static int ctrlbreakinstalled
= 0;
1023 /* Interrupt level detection of Ctrl-Break. Don't do anything fancy here! */
1025 ctrl_break_func (regs
)
1026 _go32_dpmi_registers
*regs
;
1032 install_ctrl_break_check ()
1034 if (!ctrlbreakinstalled
)
1036 /* Don't press Ctrl-Break if you don't have either DPMI or Emacs
1037 was compiler with Djgpp 1.11 maintenance level 5 or later! */
1038 ctrlbreakinstalled
= 1;
1039 ctrl_break_vector
.pm_offset
= (int) ctrl_break_func
;
1040 _go32_dpmi_allocate_real_mode_callback_iret (&ctrl_break_vector
,
1042 _go32_dpmi_set_real_mode_interrupt_vector (0x1b, &ctrl_break_vector
);
1047 /* Mouse routines under devellopment follow. Coordinates are in screen
1048 positions and zero based. Mouse buttons are numbered from left to
1049 right and also zero based. */
1051 static int mouse_button_translate
[NUM_MOUSE_BUTTONS
];
1052 static int mouse_button_count
;
1061 regs
.x
.dx
= 8 * (ScreenCols () - 1);
1062 int86 (0x33, ®s
, ®s
);
1066 regs
.x
.dx
= 8 * (ScreenRows () - 1);
1067 int86 (0x33, ®s
, ®s
);
1069 mouse_moveto (ScreenCols () - 1, ScreenRows () - 1);
1079 int86 (0x33, ®s
, ®s
);
1088 int86 (0x33, ®s
, ®s
);
1098 mouse_last_x
= regs
.x
.cx
= x
* 8;
1099 mouse_last_y
= regs
.x
.dx
= y
* 8;
1100 int86 (0x33, ®s
, ®s
);
1104 mouse_pressed (b
, xp
, yp
)
1109 if (b
>= mouse_button_count
)
1112 regs
.x
.bx
= mouse_button_translate
[b
];
1113 int86 (0x33, ®s
, ®s
);
1115 *xp
= regs
.x
.cx
/ 8, *yp
= regs
.x
.dx
/ 8;
1116 return (regs
.x
.bx
!= 0);
1120 mouse_released (b
, xp
, yp
)
1125 if (b
>= mouse_button_count
)
1128 regs
.x
.bx
= mouse_button_translate
[b
];
1129 int86 (0x33, ®s
, ®s
);
1131 *xp
= regs
.x
.cx
/ 8, *yp
= regs
.x
.dx
/ 8;
1132 return (regs
.x
.bx
!= 0);
1136 mouse_get_pos (f
, bar_window
, part
, x
, y
, time
)
1138 Lisp_Object
*bar_window
, *x
, *y
;
1139 enum scroll_bar_part
*part
;
1140 unsigned long *time
;
1146 int86 (0x33, ®s
, ®s
);
1147 *f
= selected_frame
;
1149 gettimeofday (&tv
, NULL
);
1150 *x
= make_number (regs
.x
.cx
/ 8);
1151 *y
= make_number (regs
.x
.dx
/ 8);
1157 mouse_check_moved ()
1162 int86 (0x33, ®s
, ®s
);
1163 if (regs
.x
.cx
!= mouse_last_x
|| regs
.x
.dx
!= mouse_last_y
)
1166 mouse_last_x
= regs
.x
.cx
;
1167 mouse_last_y
= regs
.x
.dx
;
1177 if (!internal_terminal
)
1181 int86 (0x33, ®s
, ®s
);
1182 present
= (regs
.x
.ax
& 0xffff) == 0xffff;
1185 /* Reportedly, the above doesn't work for some mouse drivers. There
1186 is an additional detection method that should work, but might be
1187 a little slower. Use that as an alternative. */
1189 int86 (0x33, ®s
, ®s
);
1190 present
= (regs
.x
.ax
& 0xffff) == 0xffff;
1197 mouse_button_count
= 3;
1198 mouse_button_translate
[0] = 0; /* Left */
1199 mouse_button_translate
[1] = 2; /* Middle */
1200 mouse_button_translate
[2] = 1; /* Right */
1204 mouse_button_count
= 2;
1205 mouse_button_translate
[0] = 0;
1206 mouse_button_translate
[1] = 1;
1208 mouse_position_hook
= &mouse_get_pos
;
1214 /* See xterm.c for more info. */
1216 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1218 register int pix_x
, pix_y
;
1219 register int *x
, *y
;
1220 void /* XRectangle */ *bounds
;
1223 if (bounds
) abort ();
1225 /* Ignore clipping. */
1232 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1235 register int *pix_x
, *pix_y
;