Mercurial > emacs
view src/msdos.c @ 8624:2768933d85ad
(xmenu_show): Do nothing special for ButtonPress in the menu.
Call XtDispatchEvent for all ButtonRelease events.
xlwmenu.c now deals with posting the menu.
Check for events in subwidgets of the menu
when deciding whether to queue them for later handling.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Thu, 25 Aug 1994 05:05:50 +0000 |
parents | d48c2b01fba5 |
children | 3c4437496ebc |
line wrap: on
line source
/* MS-DOS specific C utilities. Copyright (C) 1993, 1994 Free Software Foundation, Inc. This file is part of GNU Emacs. GNU Emacs is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Contributed by Morten Welinder */ /* Note: some of the stuff here was taken from end of sysdep.c in demacs. */ #include <config.h> #ifdef MSDOS #include "lisp.h" #include <stdio.h> #include <stdlib.h> #include <sys/param.h> #include <sys/time.h> #include <dos.h> #include "dosfns.h" #include "msdos.h" #include "systime.h" #include "termhooks.h" #include "frame.h" #include <go32.h> #include <pc.h> #include <ctype.h> /* #include <process.h> */ /* Damn that local process.h! Instead we can define P_WAIT ourselves. */ #define P_WAIT 1 static int break_stat; /* BREAK check mode status. */ static int stdin_stat; /* stdin IOCTL status. */ static int extended_kbd; /* 101 (102) keyboard present. */ int have_mouse; /* Mouse present? */ static int mouse_last_x; static int mouse_last_y; /* Turn off Dos' Ctrl-C checking and inhibit interpretation of control chars by Dos. Determine the keyboard type. */ int dos_ttraw () { union REGS inregs, outregs; inregs.h.ah = 0xc0; int86 (0x15, &inregs, &outregs); extended_kbd = (!outregs.x.cflag) && (outregs.h.ah == 0); break_stat = getcbrk (); setcbrk (0); install_ctrl_break_check (); have_mouse = mouse_init1 (); inregs.x.ax = 0x4400; /* Get IOCTL status. */ inregs.x.bx = 0x00; /* 0 = stdin. */ intdos (&inregs, &outregs); stdin_stat = outregs.h.dl; inregs.x.dx = (outregs.x.dx | 0x0020) & 0x0027; /* raw mode */ inregs.h.al = 0x01; intdos (&inregs, &outregs); return !outregs.x.cflag; } /* Restore status of standard input and Ctrl-C checking. */ int dos_ttcooked () { union REGS inregs, outregs; setcbrk (break_stat); if (have_mouse) mouse_off (); inregs.x.ax = 0x4401; /* Set IOCTL status. */ inregs.x.bx = 0x00; /* 0 = stdin. */ inregs.x.dx = stdin_stat; intdos (&inregs, &outregs); return !outregs.x.cflag; } static unsigned short ibmpc_translate_map[] = { /* --------------- 00 to 0f --------------- */ 0, /* Ctrl Break */ 0xff1b, /* Escape */ 0xffb1, /* Keypad 1 */ 0xffb2, /* Keypad 2 */ 0xffb3, /* Keypad 3 */ 0xffb4, /* Keypad 4 */ 0xffb5, /* Keypad 5 */ 0xffb6, /* Keypad 6 */ 0xffb7, /* Keypad 7 */ 0xffb8, /* Keypad 8 */ 0xffb9, /* Keypad 9 */ 0xffb0, /* Keypad 0 */ '-', '=', 0xff08, /* Backspace */ 0xff74, /* (Shift) Tab [Tab doesn't use this table] */ /* --------------- 10 to 1f --------------- */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 0xff8d, /* Keypad Enter */ 0, /* Ctrl */ 'a', 's', /* --------------- 20 to 2f --------------- */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, /* Left shift */ '\\', 'z', 'x', 'c', 'v', /* --------------- 30 to 3f --------------- */ 'b', 'n', 'm', ',', '.', 0xffaf, /* Grey / */ 0, /* Right shift */ 0xffaa, /* Grey * */ 0, /* Alt */ ' ', 0, /* Caps Lock */ 0xffbe, /* F1 */ 0xffbf, /* F2 */ 0xffc0, /* F3 */ 0xffc1, /* F4 */ 0xffc2, /* F5 */ /* --------------- 40 to 4f --------------- */ 0xffc3, /* F6 */ 0xffc4, /* F7 */ 0xffc5, /* F8 */ 0xffc6, /* F9 */ 0xffc7, /* F10 */ 0, /* Num Lock */ 0, /* Scroll Lock */ 0xff50, /* Home */ 0xff52, /* Up */ 0xff55, /* Page Up */ 0xffad, /* Grey - */ 0xff51, /* Left */ 0xffb5, /* Keypad 5 */ 0xff53, /* Right */ 0xffab, /* Grey + */ 0xff57, /* End */ /* --------------- 50 to 5f --------------- */ 0xff54, /* Down */ 0xff56, /* Page Down */ 0xff63, /* Insert */ 0xffff, /* Delete */ 0xffbe, /* (Shift) F1 */ 0xffbf, /* (Shift) F2 */ 0xffc0, /* (Shift) F3 */ 0xffc1, /* (Shift) F4 */ 0xffc2, /* (Shift) F5 */ 0xffc3, /* (Shift) F6 */ 0xffc4, /* (Shift) F7 */ 0xffc5, /* (Shift) F8 */ 0xffc6, /* (Shift) F9 */ 0xffc7, /* (Shift) F10 */ 0xffbe, /* (Ctrl) F1 */ 0xffbf, /* (Ctrl) F2 */ /* --------------- 60 to 6f --------------- */ 0xffc0, /* (Ctrl) F3 */ 0xffc1, /* (Ctrl) F4 */ 0xffc2, /* (Ctrl) F5 */ 0xffc3, /* (Ctrl) F6 */ 0xffc4, /* (Ctrl) F7 */ 0xffc5, /* (Ctrl) F8 */ 0xffc6, /* (Ctrl) F9 */ 0xffc7, /* (Ctrl) F10 */ 0xffbe, /* (Alt) F1 */ 0xffbf, /* (Alt) F2 */ 0xffc0, /* (Alt) F3 */ 0xffc1, /* (Alt) F4 */ 0xffc2, /* (Alt) F5 */ 0xffc3, /* (Alt) F6 */ 0xffc4, /* (Alt) F7 */ 0xffc5, /* (Alt) F8 */ /* --------------- 70 to 7f --------------- */ 0xffc6, /* (Alt) F9 */ 0xffc7, /* (Alt) F10 */ 0xff6d, /* (Ctrl) Sys Rq */ 0xff51, /* (Ctrl) Left */ 0xff53, /* (Ctrl) Right */ 0xff57, /* (Ctrl) End */ 0xff56, /* (Ctrl) Page Down */ 0xff50, /* (Ctrl) Home */ '1', '2', '3', '4', '5', '6', '7', '8', /* (Alt) */ /* --------------- 80 to 8f --------------- */ '9', '0', '-', '=', /* (Alt) */ 0xff55, /* (Ctrl) Page Up */ 0xffc8, /* F11 */ 0xffc9, /* F12 */ 0xffc8, /* (Shift) F11 */ 0xffc9, /* (Shift) F12 */ 0xffc8, /* (Ctrl) F11 */ 0xffc9, /* (Ctrl) F12 */ 0xffc8, /* (Alt) F11 */ 0xffc9, /* (Alt) F12 */ 0xff52, /* (Ctrl) Up */ 0xffae, /* (Ctrl) Grey - */ 0xffb5, /* (Ctrl) Keypad 5 */ /* --------------- 90 to 9f --------------- */ 0xffab, /* (Ctrl) Grey + */ 0xff54, /* (Ctrl) Down */ 0xff63, /* (Ctrl) Insert */ 0xffff, /* (Ctrl) Delete */ 0xff09, /* (Ctrl) Tab */ 0xffaf, /* (Ctrl) Grey / */ 0xffaa, /* (Ctrl) Grey * */ 0xff50, /* (Alt) Home */ 0xff52, /* (Alt) Up */ 0xff55, /* (Alt) Page Up */ 0, /* NO KEY */ 0xff51, /* (Alt) Left */ 0, /* NO KEY */ 0xff53, /* (Alt) Right */ 0, /* NO KEY */ 0xff57, /* (Alt) End */ /* --------------- a0 to af --------------- */ 0xff54, /* (Alt) Down */ 0xff56, /* (Alt) Page Down */ 0xff63, /* (Alt) Insert */ 0xffff, /* (Alt) Delete */ 0xffaf, /* (Alt) Grey / */ 0xff09, /* (Alt) Tab */ 0xff0d /* (Alt) Enter */ }; /* Get a char from keyboard. Function keys are put into the event queue. */ static int dos_rawgetc () { struct input_event event; struct timeval tv; union REGS regs; int ctrl_p, alt_p, shift_p; /* Calculate modifier bits */ regs.h.ah = extended_kbd ? 0x12 : 0x02; int86 (0x16, ®s, ®s); ctrl_p = ((regs.h.al & 4) != 0); shift_p = ((regs.h.al & 3) != 0); /* Please be very careful here not to break international keyboard support. When Keyb.Com is loaded, the key marked `Alt Gr' is used for accessing characters like { and } if their positions are overlaid. */ alt_p = ((extended_kbd ? (regs.h.ah & 2) : (regs.h.al & 8)) != 0); /* The following condition is equivalent to `kbhit ()', except that it uses the bios to do its job. This pleases DESQview/X. */ while ((regs.h.ah = extended_kbd ? 0x11 : 0x01), int86 (0x16, ®s, ®s), (regs.x.flags & 0x40) == 0) { union REGS regs; register unsigned char c; int sc, code; regs.h.ah = extended_kbd ? 0x10 : 0x00; int86 (0x16, ®s, ®s); c = regs.h.al; sc = regs.h.ah; /* Determine from the scan code if a keypad key was pressed. */ if (c >= '0' && c <= '9' && sc > 0xb) sc = (c == '0') ? 0xb : (c - '0' + 1), c = 0; else if (sc == 0x53 && c != 0xe0) { code = 0xffae; /* Keypad decimal point/comma. */ goto nonascii; } else if (sc == 0xe0) { switch (c) { case 10: /* Ctrl Enter */ case 13: sc = 0x1c; break; case '/': sc = 0x35; break; default: sc = 0; }; c = 0; } if (c == 0 || c == ' ' || alt_p || (ctrl_p && shift_p) || (c == 0xe0 && sc != 0) /* Pseudo-key */ || sc == 0x37 /* Grey * */ || sc == 0x4a /* Grey - */ || sc == 0x4e /* Grey + */ || sc == 0x0e) /* Back space *key*, not Ctrl-h */ { if (sc >= (sizeof (ibmpc_translate_map) / sizeof (short))) code = 0; else code = ibmpc_translate_map[sc]; if (code != 0) { if (code >= 0x100) { nonascii: event.kind = non_ascii_keystroke; event.code = (code & 0xff) + 0xff00; } else { /* Don't return S- if we don't have to. `shifted' is supposed to be the shifted versions of the characters in `unshifted'. Unfortunately, this is only true for US keyboard layout. If anyone knows how to do this right, please tell us. */ static char *unshifted = "abcdefghijklmnopqrstuvwxyz,./=;[\\]'-`0123456789"; static char *shifted = "ABCDEFGHIJKLMNOPQRSTUVWXYZ<>?+:{|}\"_~)!@#$%^&*("; char *pos; if (shift_p && (pos = strchr (unshifted, code))) { c = shifted[pos - unshifted]; shift_p = 0; } else if (c == 0) c = code; event.kind = ascii_keystroke; event.code = c; } event.modifiers = (shift_p ? shift_modifier : 0) + (ctrl_p ? ctrl_modifier : 0) + (alt_p ? meta_modifier : 0); /* EMACS == Enter Meta Alt Control Shift */ event.frame_or_window = selected_frame; gettimeofday (&tv, NULL); event.timestamp = tv.tv_usec; kbd_buffer_store_event (&event); } } else return c; } if (have_mouse) { int but, press, x, y, ok; /* Check for mouse movement *before* buttons. */ mouse_check_moved (); for (but = 0; but < NUM_MOUSE_BUTTONS; but++) for (press = 0; press < 2; press++) { if (press) ok = mouse_pressed (but, &x, &y); else ok = mouse_released (but, &x, &y); if (ok) { event.kind = mouse_click; event.code = but; event.modifiers = (shift_p ? shift_modifier : 0) + (ctrl_p ? ctrl_modifier : 0) + (alt_p ? meta_modifier : 0) + (press ? down_modifier : up_modifier); event.x = x; event.y = y; event.frame_or_window = selected_frame; gettimeofday (&tv, NULL); event.timestamp = tv.tv_usec; kbd_buffer_store_event (&event); } } } return -1; } static int prev_get_char = -1; /* Return 1 if a key is ready to be read without suspending execution. */ dos_keysns () { if (prev_get_char != -1) return 1; else return ((prev_get_char = dos_rawgetc ()) != -1); } /* Read a key. Return -1 if no key is ready. */ dos_keyread () { if (prev_get_char != -1) { int c = prev_get_char; prev_get_char = -1; return c; } else return dos_rawgetc (); } /* Hostnames for a pc are not really funny, but they are used in change log so we emulate the best we can. */ gethostname (p, size) char *p; int size; { char *q = egetenv ("HOSTNAME"); if (!q) q = "pc"; strcpy (p, q); return 0; } /* Destructively turn backslashes into slashes. */ void dostounix_filename (p) register char *p; { while (*p) { if (*p == '\\') *p = '/'; p++; } } /* Destructively turn slashes into backslashes. */ void unixtodos_filename (p) register char *p; { while (*p) { if (*p == '/') *p = '\\'; p++; } } /* Get the default directory for a given drive. 0=def, 1=A, 2=B, ... */ int getdefdir (drive, dst) int drive; char *dst; { union REGS regs; *dst++ = '/'; regs.h.dl = drive; regs.x.si = (int) dst; regs.h.ah = 0x47; intdos (®s, ®s); return !regs.x.cflag; } /* Remove all CR's that are followed by a LF. */ int crlf_to_lf (n, buf) register int n; register unsigned char *buf; { unsigned char *np = buf; unsigned char *startp = buf; unsigned char *endp = buf + n; unsigned char c; if (n == 0) return n; while (buf < endp - 1) { if (*buf == 0x0d) { if (*(++buf) != 0x0a) *np++ = 0x0d; } else *np++ = *buf++; } if (buf < endp) *np++ = *buf++; return np - startp; } /* Run command as specified by ARGV in directory DIR. The command is run with input from TEMPIN and output to file TEMPOUT. */ int run_msdos_command (argv, dir, tempin, tempout) unsigned char **argv; Lisp_Object dir; int tempin, tempout; { char *saveargv1, *saveargv2, **envv; char oldwd[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */ int msshell, result = -1; int in, out, inbak, outbak, errbak; Lisp_Object cmd; /* Get current directory as MSDOS cwd is not per-process. */ getwd (oldwd); cmd = Ffile_name_nondirectory (build_string (argv[0])); msshell = !NILP (Fmember (cmd, Fsymbol_value (intern ("msdos-shells")))) && !strcmp ("-c", argv[1]); if (msshell) { saveargv1 = argv[1]; saveargv2 = argv[2]; argv[1] = "/c"; if (argv[2]) { char *p = alloca (strlen (argv[2]) + 1); strcpy (argv[2] = p, saveargv2); while (*p && isspace (*p)) p++; while (*p && !isspace (*p)) if (*p == '/') *p++ = '\\'; else p++; } } /* Build the environment array. */ { extern Lisp_Object Vprocess_environment; Lisp_Object tmp, lst; int i, len; lst = Vprocess_environment; len = XFASTINT (Flength (lst)); envv = alloca ((len + 1) * sizeof (char *)); for (i = 0; i < len; i++) { tmp = Fcar (lst); lst = Fcdr (lst); CHECK_STRING (tmp, 0); envv[i] = alloca (XSTRING (tmp)->size + 1); strcpy (envv[i], XSTRING (tmp)->data); } envv[len] = (char *) 0; } if (XTYPE (dir) == Lisp_String) chdir (XSTRING (dir)->data); inbak = dup (0); outbak = dup (1); errbak = dup (2); if (inbak < 0 || outbak < 0 || errbak < 0) goto done; /* Allocation might fail due to lack of descriptors. */ dup2 (tempin, 0); dup2 (tempout, 1); dup2 (tempout, 2); dos_ttcooked (); result = spawnve (P_WAIT, argv[0], argv, envv); dos_ttraw (); dup2 (inbak, 0); dup2 (outbak, 1); dup2 (errbak, 2); done: chdir (oldwd); if (msshell) { argv[1] = saveargv1; argv[2] = saveargv2; } return result; } croak (badfunc) char *badfunc; { fprintf (stderr, "%s not yet implemented\r\n", badfunc); reset_sys_modes (); exit (1); } /* A list of unimplemented functions that we silently ignore. */ unsigned alarm (s) unsigned s; {} fork () { return 0; } int kill (x, y) int x, y; { return -1; } nice (p) int p; {} void volatile pause () {} request_sigio () {} setpgrp () {return 0; } setpriority (x,y,z) int x,y,z; { return 0; } sigsetmask (x) int x; { return 0; } unrequest_sigio () {} #ifdef chdir #undef chdir #endif int sys_chdir (path) const char* path; { int len = strlen (path); char *tmp = (char *) alloca (len + 1); /* Gotta do this extern here due to the corresponding #define: */ extern int chdir (); if (*path && path[1] == ':' && (getdisk () != tolower (path[0]) - 'a')) setdisk (tolower (path[0]) - 'a'); strcpy (tmp, path); if (strcmp (path, "/") && strcmp (path + 1, ":/") && (path[len - 1] == '/')) tmp[len - 1] = 0; return chdir (tmp); } /* Sleep SECS. If KBDOK also return immediately if a key is pressed. */ void sleep_or_kbd_hit (secs, kbdok) int secs, kbdok; { long clnow, clthen; struct timeval t; gettimeofday (&t, NULL); clnow = t.tv_sec * 100 + t.tv_usec / 10000; clthen = clnow + (100 * secs); do { gettimeofday (&t, NULL); clnow = t.tv_sec * 100 + t.tv_usec / 10000; if (kbdok && detect_input_pending ()) return; } while (clnow < clthen); } /* The Emacs root directory as determined by init_environment. */ static char emacsroot[MAXPATHLEN]; char * rootrelativepath (rel) char *rel; { static char result[MAXPATHLEN + 10]; strcpy (result, emacsroot); strcat (result, "/"); strcat (result, rel); return result; } /* Define a lot of environment variables if not already defined. Don't remove anything unless you know what you're doing -- lots of code will break if one or more of these are missing. */ void init_environment (argc, argv, skip_args) int argc; char **argv; int skip_args; { char *s, *t, *root; int len; /* Find our root from argv[0]. Assuming argv[0] is, say, "c:/emacs/bin/emacs.exe" our root will be "c:/emacs". */ len = strlen (argv[0]); root = alloca (len + 10); /* A little extra space for the stuff below. */ strcpy (root, argv[0]); while (len > 0 && root[len] != '/' && root[len] != ':') len--; root[len] = '\0'; if (len > 4 && strcmp (root + len - 4, "/bin") == 0) root[len - 4] = '\0'; else strcpy (root, "c:/emacs"); /* Only under debuggers, I think. */ len = strlen (root); strcpy (emacsroot, root); /* We default HOME to our root. */ setenv ("HOME", root, 0); /* We default EMACSPATH to root + "/bin". */ strcpy (root + len, "/bin"); setenv ("EMACSPATH", root, 0); /* I don't expect anybody to ever use other terminals so the internal terminal is the default. */ setenv ("TERM", "internal", 0); /* SHELL is a bit tricky -- COMSPEC is the closest we come, but we must downcase it and mirror the backslashes. */ s = getenv ("COMSPEC"); if (!s) s = "c:/command.com"; t = alloca (strlen (s) + 1); strcpy (t, s); strlwr (t); dostounix_filename (t); setenv ("SHELL", t, 0); /* PATH is also downcased and backslashes mirrored. */ s = getenv ("PATH"); if (!s) s = ""; t = alloca (strlen (s) + 3); /* Current directory is always considered part of MsDos's path but it is not normally mentioned. Now it is. */ strcat (strcpy (t, ".;"), s); strlwr (t); dostounix_filename (t); /* Not a single file name, but this should work. */ setenv ("PATH", t, 1); /* In some sense all dos users have root privileges, so... */ setenv ("USER", "root", 0); setenv ("NAME", getenv ("USER"), 0); /* Time zone determined from country code. To make this possible, the country code may not span more than one time zone. In other words, in the USA, you lose. */ switch (dos_country_code) { case 31: /* Belgium */ case 32: /* The Netherlands */ case 33: /* France */ case 34: /* Spain */ case 36: /* Hungary */ case 38: /* Yugoslavia (or what's left of it?) */ case 39: /* Italy */ case 41: /* Switzerland */ case 42: /* Tjekia */ case 45: /* Denmark */ case 46: /* Sweden */ case 47: /* Norway */ case 48: /* Poland */ case 49: /* Germany */ /* Daylight saving from last Sunday in March to last Sunday in September, both at 2AM. */ setenv ("TZ", "MET-01METDST-02,M3.5.0/02:00,M9.5.0/02:00", 0); break; case 44: /* United Kingdom */ case 351: /* Portugal */ case 354: /* Iceland */ setenv ("TZ", "GMT+00", 0); break; case 81: /* Japan */ case 82: /* Korea */ setenv ("TZ", "???-09", 0); break; case 90: /* Turkey */ case 358: /* Finland */ case 972: /* Israel */ setenv ("TZ", "EET-02", 0); break; } tzset (); init_gettimeofday (); } /* Flash the screen as a substitute for BEEPs. */ static void do_visible_bell (xorattr) unsigned char xorattr; { asm volatile (" movb $1,%%dl visible_bell_0: movl _ScreenPrimary,%%eax call dosmemsetup movl %%eax,%%ebx movl %1,%%ecx movb %0,%%al incl %%ebx visible_bell_1: xorb %%al,%%gs:(%%ebx) addl $2,%%ebx decl %%ecx jne visible_bell_1 decb %%dl jne visible_bell_3 visible_bell_2: movzwl %%ax,%%eax movzwl %%ax,%%eax movzwl %%ax,%%eax movzwl %%ax,%%eax decw %%cx jne visible_bell_2 jmp visible_bell_0 visible_bell_3:" : /* no output */ : "m" (xorattr), "g" (ScreenCols () * ScreenRows ()) : "%eax", "%ebx", /* "%gs",*/ "%ecx", "%edx"); } /* At screen position (X,Y), output C characters from string S with attribute A. Do it fast! */ static void output_string (x, y, s, c, a) int x, y, c; unsigned char *s; unsigned char a; { char *t = (char *)ScreenPrimary + 2 * (x + ScreenCols () * y); asm volatile (" movl %1,%%eax call dosmemsetup movl %%eax,%%edi movb %0,%%ah movl %2,%%ecx movl %3,%%esi output_string1: movb (%%esi),%%al movw %%ax,%%gs:(%%edi) addl $2,%%edi incl %%esi decl %%ecx jne output_string1" : /* no output */ : "m" (a), "g" (t), "g" (c), "g" (s) : "%eax", "%ecx", /* "%gs",*/ "%esi", "%edi"); } static int internal_terminal = 0; #undef fflush int internal_flush (f) FILE *f; { static char spaces[] = " "; static int x; static int y; unsigned char *cp, *cp0; int count, i, j; if (internal_terminal && f == stdout) { if (have_mouse) mouse_off (); cp = stdout->_base; count = stdout->_ptr - stdout->_base; while (count > 0) { switch (*cp++) { case 27: switch (*cp++) { case '@': y = *cp++; x = *cp++; count -= 4; break; case 'A': ScreenAttrib = *cp++; count -= 3; break; case 'B': do_visible_bell (*cp++); count -= 3; break; case 'C': ScreenClear (); x = y = 0; count -= 2; break; case 'E': i = ScreenCols () - x; j = x; while (i >= sizeof spaces) { output_string (j, y, spaces, sizeof spaces, ScreenAttrib); j += sizeof spaces; i -= sizeof spaces; } if (i > 0) output_string (j, y, spaces, i, ScreenAttrib); count -= 2; break; case 'R': x++; count -= 2; break; case 'U': y--; count -= 2; break; case 'X': ScreenAttrib ^= *cp++; count -= 3; break; default: count -= 2; } break; case 7: write (1, "\007", 1); count--; break; case 8: x--; count--; break; case 13: x = 0; count--; break; case 10: y++; count--; break; default: cp0 = cp - 1; count--; while (count > 0 && *cp >= ' ') cp++, count--; output_string (x, y, cp0, cp - cp0, ScreenAttrib); x += (cp - cp0); } } fpurge (stdout); ScreenSetCursor (y, x); if (have_mouse) mouse_on (); } else /* This is a call to the original fflush. */ fflush (f); } /* Do we need the internal terminal? */ void internal_terminal_init () { char *term = getenv ("TERM"); internal_terminal = (!noninteractive) && term && !strcmp (term, "internal"); } /* When time zones are set from Ms-Dos too may C-libraries are playing tricks with time values. We solve this by defining our own version of `gettimeofday' bypassing GO32. Our version needs to be initialized once and after each call to `tzset' with TZ changed. */ static int daylight, gmtoffset; int gettimeofday (struct timeval *tp, struct timezone *tzp) { if (tp) { struct time t; struct date d; struct tm tmrec; gettime (&t); getdate (&d); tmrec.tm_year = d.da_year - 1900; tmrec.tm_mon = d.da_mon - 1; tmrec.tm_mday = d.da_day; tmrec.tm_hour = t.ti_hour; tmrec.tm_min = t.ti_min; tmrec.tm_sec = t.ti_sec; tmrec.tm_gmtoff = gmtoffset; tmrec.tm_isdst = daylight; tp->tv_sec = mktime (&tmrec); tp->tv_usec = t.ti_hund * (1000000 / 100); } if (tzp) { tzp->tz_minuteswest = gmtoffset; tzp->tz_dsttime = daylight; } return 0; } void init_gettimeofday () { time_t ltm, gtm; struct tm *lstm; daylight = 0; gmtoffset = 0; ltm = gtm = time (NULL); ltm = mktime (lstm = localtime (<m)); gtm = mktime (gmtime (>m)); daylight = lstm->tm_isdst; gmtoffset = (int)(gtm - ltm) / 60; } /* These must be global. */ static _go32_dpmi_seginfo ctrl_break_vector; static _go32_dpmi_registers ctrl_break_regs; static int ctrlbreakinstalled = 0; /* Interrupt level detection of Ctrl-Break. Don't do anything fancy here! */ void ctrl_break_func (regs) _go32_dpmi_registers *regs; { Vquit_flag = Qt; } void install_ctrl_break_check () { if (!ctrlbreakinstalled) { /* Don't press Ctrl-Break if you don't have either DPMI or Emacs was compiler with Djgpp 1.11 maintenance level 5 or later! */ ctrlbreakinstalled = 1; ctrl_break_vector.pm_offset = (int) ctrl_break_func; _go32_dpmi_allocate_real_mode_callback_iret (&ctrl_break_vector, &ctrl_break_regs); _go32_dpmi_set_real_mode_interrupt_vector (0x1b, &ctrl_break_vector); } } /* Mouse routines under devellopment follow. Coordinates are in screen positions and zero based. Mouse buttons are numbered from left to right and also zero based. */ static int mouse_button_translate[NUM_MOUSE_BUTTONS]; static int mouse_button_count; void mouse_init () { union REGS regs; regs.x.ax = 0x0007; regs.x.cx = 0; regs.x.dx = 8 * (ScreenCols () - 1); int86 (0x33, ®s, ®s); regs.x.ax = 0x0008; regs.x.cx = 0; regs.x.dx = 8 * (ScreenRows () - 1); int86 (0x33, ®s, ®s); mouse_moveto (ScreenCols () - 1, ScreenRows () - 1); mouse_on (); } void mouse_on () { union REGS regs; regs.x.ax = 0x0001; int86 (0x33, ®s, ®s); } void mouse_off () { union REGS regs; regs.x.ax = 0x0002; int86 (0x33, ®s, ®s); } void mouse_moveto (x, y) int x, y; { union REGS regs; regs.x.ax = 0x0004; mouse_last_x = regs.x.cx = x * 8; mouse_last_y = regs.x.dx = y * 8; int86 (0x33, ®s, ®s); } int mouse_pressed (b, xp, yp) int b, *xp, *yp; { union REGS regs; if (b >= mouse_button_count) return 0; regs.x.ax = 0x0005; regs.x.bx = mouse_button_translate[b]; int86 (0x33, ®s, ®s); if (regs.x.bx) *xp = regs.x.cx / 8, *yp = regs.x.dx / 8; return (regs.x.bx != 0); } int mouse_released (b, xp, yp) int b, *xp, *yp; { union REGS regs; if (b >= mouse_button_count) return 0; regs.x.ax = 0x0006; regs.x.bx = mouse_button_translate[b]; int86 (0x33, ®s, ®s); if (regs.x.bx) *xp = regs.x.cx / 8, *yp = regs.x.dx / 8; return (regs.x.bx != 0); } void mouse_get_pos (f, bar_window, part, x, y, time) FRAME_PTR *f; Lisp_Object *bar_window, *x, *y; enum scroll_bar_part *part; unsigned long *time; { union REGS regs; struct timeval tv; regs.x.ax = 0x0003; int86 (0x33, ®s, ®s); *f = selected_frame; *bar_window = Qnil; gettimeofday (&tv, NULL); *x = make_number (regs.x.cx / 8); *y = make_number (regs.x.dx / 8); *time = tv.tv_usec; mouse_moved = 0; } void mouse_check_moved () { union REGS regs; regs.x.ax = 0x0003; int86 (0x33, ®s, ®s); if (regs.x.cx != mouse_last_x || regs.x.dx != mouse_last_y) { mouse_moved = 1; mouse_last_x = regs.x.cx; mouse_last_y = regs.x.dx; } } int mouse_init1 () { union REGS regs; int present; if (!internal_terminal) return 0; regs.x.ax = 0x0021; int86 (0x33, ®s, ®s); present = (regs.x.ax & 0xffff) == 0xffff; if (!present) { /* Reportedly, the above doesn't work for some mouse drivers. There is an additional detection method that should work, but might be a little slower. Use that as an alternative. */ regs.x.ax = 0x0000; int86 (0x33, ®s, ®s); present = (regs.x.ax & 0xffff) == 0xffff; } if (present) { if (regs.x.bx == 3) { mouse_button_count = 3; mouse_button_translate[0] = 0; /* Left */ mouse_button_translate[1] = 2; /* Middle */ mouse_button_translate[2] = 1; /* Right */ } else { mouse_button_count = 2; mouse_button_translate[0] = 0; mouse_button_translate[1] = 1; } mouse_position_hook = &mouse_get_pos; mouse_init (); } return present; } /* See xterm.c for more info. */ void pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip) FRAME_PTR f; register int pix_x, pix_y; register int *x, *y; void /* XRectangle */ *bounds; int noclip; { if (bounds) abort (); /* Ignore clipping. */ *x = pix_x; *y = pix_y; } void glyph_to_pixel_coords (f, x, y, pix_x, pix_y) FRAME_PTR f; register int x, y; register int *pix_x, *pix_y; { *pix_x = x; *pix_y = y; } #endif /* MSDOS */