(Fcall_process): Fix previous change (now !MSDOS only).
[bpt/emacs.git] / src / dosfns.c
CommitLineData
1b94449f
RS
1/* MS-DOS specific Lisp utilities. Coded by Manabu Higashida, 1991.
2 Major changes May-July 1993 Morten Welinder (only 10% original code left)
3 Copyright (C) 1991, 1993 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
edfc0d45 9the Free Software Foundation; either version 2, or (at your option)
1b94449f
RS
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
1b94449f
RS
21
22
48984716 23#include <config.h>
1b94449f
RS
24
25#ifdef MSDOS
26/* The entire file is within this conditional */
27
28#include <stdio.h>
29#include <dos.h>
30#include "lisp.h"
31#include "buffer.h"
32#include "termchar.h"
33#include "termhooks.h"
34#include "frame.h"
35#include "dosfns.h"
36#include "msdos.h"
5f08dc78 37#include <go32.h>
1b94449f 38
1b94449f
RS
39DEFUN ("int86", Fint86, Sint86, 2, 2, 0,
40 "Call specific MSDOS interrupt number INTERRUPT with REGISTERS.\n\
41Return the updated REGISTER vector.\n\
42\n\
43INTERRUPT should be an integer in the range 0 to 255.\n\
44REGISTERS should be a vector produced by `make-register' and\n\
45`set-register-value'.")
e20104ba
EN
46 (interrupt, registers)
47 Lisp_Object interrupt, registers;
1b94449f
RS
48{
49 register int i;
50 int no;
51 union REGS inregs, outregs;
52 Lisp_Object val;
53
e20104ba
EN
54 CHECK_NUMBER (interrupt, 0);
55 no = (unsigned long) XINT (interrupt);
56 CHECK_VECTOR (registers, 1);
57 if (no < 0 || no > 0xff || XVECTOR (registers)-> size != 8)
1b94449f
RS
58 return Qnil;
59 for (i = 0; i < 8; i++)
e20104ba 60 CHECK_NUMBER (XVECTOR (registers)->contents[i], 1);
1b94449f 61
e20104ba
EN
62 inregs.x.ax = (unsigned long) XFASTINT (XVECTOR (registers)->contents[0]);
63 inregs.x.bx = (unsigned long) XFASTINT (XVECTOR (registers)->contents[1]);
64 inregs.x.cx = (unsigned long) XFASTINT (XVECTOR (registers)->contents[2]);
65 inregs.x.dx = (unsigned long) XFASTINT (XVECTOR (registers)->contents[3]);
66 inregs.x.si = (unsigned long) XFASTINT (XVECTOR (registers)->contents[4]);
67 inregs.x.di = (unsigned long) XFASTINT (XVECTOR (registers)->contents[5]);
68 inregs.x.cflag = (unsigned long) XFASTINT (XVECTOR (registers)->contents[6]);
69 inregs.x.flags = (unsigned long) XFASTINT (XVECTOR (registers)->contents[7]);
1b94449f
RS
70
71 int86 (no, &inregs, &outregs);
72
e20104ba
EN
73 XVECTOR (registers)->contents[0] = make_number (outregs.x.ax);
74 XVECTOR (registers)->contents[1] = make_number (outregs.x.bx);
75 XVECTOR (registers)->contents[2] = make_number (outregs.x.cx);
76 XVECTOR (registers)->contents[3] = make_number (outregs.x.dx);
77 XVECTOR (registers)->contents[4] = make_number (outregs.x.si);
78 XVECTOR (registers)->contents[5] = make_number (outregs.x.di);
79 XVECTOR (registers)->contents[6] = make_number (outregs.x.cflag);
80 XVECTOR (registers)->contents[7] = make_number (outregs.x.flags);
1b94449f 81
e20104ba 82 return registers;
1b94449f
RS
83}
84
5f08dc78
KS
85DEFUN ("msdos-memget", Fdos_memget, Sdos_memget, 2, 2, 0,
86 "Read DOS memory at offset ADDRESS into VECTOR.\n\
87Return the updated VECTOR.")
e20104ba
EN
88 (address, vector)
89 Lisp_Object address, vector;
5f08dc78
KS
90{
91 register int i;
92 int offs, len;
93 char *buf;
94 Lisp_Object val;
95
e20104ba
EN
96 CHECK_NUMBER (address, 0);
97 offs = (unsigned long) XINT (address);
98 CHECK_VECTOR (vector, 1);
99 len = XVECTOR (vector)-> size;
100 if (len < 1 || len > 2048 || address < 0 || address > 0xfffff - len)
5f08dc78
KS
101 return Qnil;
102 buf = alloca (len);
103 dosmemget (offs, len, buf);
104
105 for (i = 0; i < len; i++)
e20104ba 106 XVECTOR (vector)->contents[i] = make_number (buf[i]);
5f08dc78 107
e20104ba 108 return vector;
5f08dc78
KS
109}
110
111DEFUN ("msdos-memput", Fdos_memput, Sdos_memput, 2, 2, 0,
112 "Write DOS memory at offset ADDRESS from VECTOR.")
e20104ba
EN
113 (address, vector)
114 Lisp_Object address, vector;
5f08dc78
KS
115{
116 register int i;
117 int offs, len;
118 char *buf;
119 Lisp_Object val;
120
e20104ba
EN
121 CHECK_NUMBER (address, 0);
122 offs = (unsigned long) XINT (address);
123 CHECK_VECTOR (vector, 1);
124 len = XVECTOR (vector)-> size;
125 if (len < 1 || len > 2048 || address < 0 || address > 0xfffff - len)
5f08dc78
KS
126 return Qnil;
127 buf = alloca (len);
128
129 for (i = 0; i < len; i++)
130 {
e20104ba
EN
131 CHECK_NUMBER (XVECTOR (vector)->contents[i], 1);
132 buf[i] = (unsigned char) XFASTINT (XVECTOR (vector)->contents[i]) & 0xFF;
5f08dc78
KS
133 }
134
135 dosmemput (buf, len, offs);
136 return Qt;
137}
138
139DEFUN ("msdos-set-keyboard", Fmsdos_set_keyboard, Smsdos_set_keyboard, 1, 2, 0,
e20104ba 140 "Set keyboard layout according to COUNTRY-CODE.\n\
5f08dc78
KS
141If the optional argument ALLKEYS is non-nil, the keyboard is mapped for\n\
142all keys; otherwise it is only used when the ALT key is pressed.\n\
143The current keyboard layout is available in dos-keyboard-code.")
144 (country_code, allkeys)
145 Lisp_Object country_code;
146{
147 CHECK_NUMBER (country_code, 0);
148 if (!dos_set_keyboard (XINT (country_code), !NILP (allkeys)))
149 return Qnil;
150 return Qt;
151}
152
87485d6f
MW
153#ifndef HAVE_X_WINDOWS
154/* Later we might want to control the mouse interface with this function,
155 e.g., with respect to non-80 column screen modes. */
156
157DEFUN ("msdos-mouse-p", Fmsdos_mouse_p, Smsdos_mouse_p, 0, 0, 0, "\
158Report whether a mouse is present.")
159 ()
160{
161 if (have_mouse)
162 return Qt;
163 else
164 return Qnil;
165}
166
167DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
168 "Move the mouse pointer to the center of character cell (X,Y) in FRAME.\n\
169WARNING: If you use this under X windows,\n\
170you should call `unfocus-frame' afterwards.")
171 (frame, x, y)
172 Lisp_Object frame, x, y;
173{
174 mouse_moveto (XINT (x), XINT (y));
ac3b0279 175 return Qnil;
87485d6f
MW
176}
177
178/* Function to translate colour names to integers. See lisp/term/pc-win.el
179 for its definition. */
180
181Lisp_Object Qmsdos_color_translate;
182#endif
183
ac3b0279
RS
184
185DEFUN ("msdos-mouse-init", Fmsdos_mouse_init, Smsdos_mouse_init, 0, 0, "",
186 "Initialize and enable mouse if available.")
187 ()
188{
5f08dc78
KS
189 if (have_mouse)
190 {
191 have_mouse = 1;
192 mouse_init ();
193 return Qt;
194 }
ac3b0279
RS
195 return Qnil;
196}
197
198DEFUN ("msdos-mouse-enable", Fmsdos_mouse_enable, Smsdos_mouse_enable, 0, 0, "",
199 "Enable mouse if available.")
200 ()
201{
202 if (have_mouse)
203 {
5f08dc78
KS
204 have_mouse = 1;
205 mouse_on ();
ac3b0279
RS
206 }
207 return have_mouse ? Qt : Qnil;
208}
209
210DEFUN ("msdos-mouse-disable", Fmsdos_mouse_disable, Smsdos_mouse_disable, 0, 0, "",
211 "Disable mouse if available.")
212 ()
213{
214 mouse_off ();
215 if (have_mouse) have_mouse = -1;
216 return Qnil;
217}
218
5f08dc78
KS
219DEFUN ("insert-startup-screen", Finsert_startup_screen, Sinsert_startup_screen, 0, 0, "", "\
220Insert copy of screen contents prior to starting emacs.\n\
221Return nil if startup screen is not available.")
222 ()
223{
224 char *s;
225 int rows, cols;
226 int i, j;
227
228 if (!dos_get_saved_screen (&s, &rows, &cols))
229 return Qnil;
230
231 for (i = 0; i < rows; i++)
232 {
233 for (j = 0; j < cols; j++)
234 {
235 insert_char (*s, 1);
236 s += 2;
237 }
238 insert_char ('\n', 1);
239 }
240
241 return Qt;
242}
87485d6f 243\f
5f08dc78 244/* country info */
1b94449f
RS
245int dos_country_code;
246int dos_codepage;
5f08dc78
KS
247int dos_timezone_offset;
248int dos_decimal_point;
249int dos_keyboard_layout;
250unsigned char dos_country_info[DOS_COUNTRY_INFO];
251
252int dos_hyper_key;
253int dos_super_key;
254int dos_keypad_mode;
1b94449f 255
5f08dc78
KS
256Lisp_Object Vdos_version;
257Lisp_Object Vdos_display_scancodes;
5f08dc78 258
1b94449f
RS
259void
260init_dosfns ()
261{
262 union REGS regs;
263 _go32_dpmi_seginfo info;
264 _go32_dpmi_registers dpmiregs;
265
87485d6f 266#ifndef SYSTEM_MALLOC
1b94449f 267 get_lim_data (); /* why the hell isn't this called elsewhere? */
87485d6f 268#endif
1b94449f
RS
269
270 regs.x.ax = 0x3000;
271 intdos (&regs, &regs);
272 Vdos_version = Fcons (make_number (regs.h.al), make_number (regs.h.ah));
273
274 /* Obtain the country code by calling Dos via Dpmi. Don't rely on GO32. */
5f08dc78 275 info.size = (sizeof(dos_country_info) + 15) / 16;
1b94449f
RS
276 if (_go32_dpmi_allocate_dos_memory (&info))
277 dos_country_code = 1;
278 else
279 {
280 dpmiregs.x.ax = 0x3800;
281 dpmiregs.x.ds = info.rm_segment;
282 dpmiregs.x.dx = 0;
283 dpmiregs.x.ss = dpmiregs.x.sp = 0;
284 _go32_dpmi_simulate_int (0x21, &dpmiregs);
285 dos_country_code = dpmiregs.x.bx;
5f08dc78 286 dosmemget (info.rm_segment * 16, DOS_COUNTRY_INFO, dos_country_info);
1b94449f
RS
287 _go32_dpmi_free_dos_memory (&info);
288 }
5f08dc78 289 dos_set_keyboard (dos_country_code, 0);
1b94449f
RS
290
291 regs.x.ax = 0x6601;
292 intdos (&regs, &regs);
293 if (regs.x.cflag)
294 /* Estimate code page from country code */
295 switch (dos_country_code)
296 {
297 case 45: /* Denmark */
298 case 47: /* Norway */
299 dos_codepage = 865;
300 break;
301 default:
302 /* US */
303 dos_codepage = 437;
304 }
305 else
306 dos_codepage = regs.x.bx & 0xffff;
307}
308\f
309/*
310 * Define everything
311 */
312syms_of_dosfns ()
313{
1b94449f 314 defsubr (&Sint86);
5f08dc78
KS
315 defsubr (&Sdos_memget);
316 defsubr (&Sdos_memput);
ac3b0279
RS
317 defsubr (&Smsdos_mouse_init);
318 defsubr (&Smsdos_mouse_enable);
5f08dc78
KS
319 defsubr (&Smsdos_set_keyboard);
320 defsubr (&Sinsert_startup_screen);
ac3b0279 321 defsubr (&Smsdos_mouse_disable);
87485d6f
MW
322#ifndef HAVE_X_WINDOWS
323 defsubr (&Smsdos_mouse_p);
324 defsubr (&Sset_mouse_position);
325
326 Qmsdos_color_translate = intern ("msdos-color-translate");
327 staticpro (&Qmsdos_color_translate);
328#endif
1b94449f
RS
329
330 DEFVAR_INT ("dos-country-code", &dos_country_code,
331 "The country code returned by Dos when Emacs was started.\n\
332Usually this is the international telephone prefix.");
333
334 DEFVAR_INT ("dos-codepage", &dos_codepage,
5f08dc78 335 "The codepage active when Emacs was started.\n\
24ba360b
RS
336The following are known:\n\
337 437 United States\n\
338 850 Multilingual (Latin I)\n\
339 852 Slavic (Latin II)\n\
340 857 Turkish\n\
341 860 Portugal\n\
342 861 Iceland\n\
343 863 Canada (French)\n\
1b94449f
RS
344 865 Norway/Denmark");
345
5f08dc78
KS
346 DEFVAR_INT ("dos-timezone-offset", &dos_timezone_offset,
347 "The current timezone offset to UTC in minutes.
348Implicitly modified when the TZ variable is changed.");
349
1b94449f
RS
350 DEFVAR_LISP ("dos-version", &Vdos_version,
351 "The (MAJOR . MINOR) Dos version (subject to modification with setver).");
5f08dc78
KS
352
353 DEFVAR_LISP ("dos-display-scancodes", &Vdos_display_scancodes,
354 "*When non-nil, the keyboard scan-codes are displayed at the bottom right\n\
355corner of the display (typically at the end of the mode line).\n\
356The output format is: scan code:char code*modifiers.");
357 Vdos_display_scancodes = Qnil;
358
5f08dc78
KS
359 DEFVAR_INT ("dos-hyper-key", &dos_hyper_key,
360 "*If set to 1, use right ALT key as hyper key.\n\
361If set to 2, use right CTRL key as hyper key.");
362 dos_hyper_key = 0;
363
364 DEFVAR_INT ("dos-super-key", &dos_super_key,
365 "*If set to 1, use right ALT key as super key.\n\
366If set to 2, use right CTRL key as super key.");
367 dos_super_key = 0;
368
369 DEFVAR_INT ("dos-keypad-mode", &dos_keypad_mode,
370 "*Controls what key code is returned by a key in the numeric keypad.\n\
371The `numlock ON' action is only taken if no modifier keys are pressed.\n\
372The value is an integer constructed by adding the following bits together:\n\
373 \n\
374 0x00 Digit key returns digit (if numlock ON)\n\
375 0x01 Digit key returns kp-digit (if numlock ON)\n\
376 0x02 Digit key returns M-digit (if numlock ON)\n\
377 0x03 Digit key returns edit key (if numlock ON)\n\
378 \n\
379 0x00 Grey key returns char (if numlock ON)\n\
380 0x04 Grey key returns kp-key (if numlock ON)\n\
381 \n\
382 0x00 Digit key returns digit (if numlock OFF)\n\
383 0x10 Digit key returns kp-digit (if numlock OFF)\n\
384 0x20 Digit key returns M-digit (if numlock OFF)\n\
385 0x30 Digit key returns edit key (if numlock OFF)\n\
386 \n\
387 0x00 Grey key returns char (if numlock OFF)\n\
388 0x40 Grey key returns kp-key (if numlock OFF)\n\
389 \n\
390 0x200 ALT-0..ALT-9 in top-row produces shifted codes.");
b3d5621c 391 dos_keypad_mode = 0x75;
5f08dc78
KS
392
393 DEFVAR_INT ("dos-keyboard-layout", &dos_keyboard_layout,
394 "Contains the country code for the current keyboard layout.\n\
395Use msdos-set-keyboard to select another keyboard layout.");
396 dos_keyboard_layout = 1; /* US */
397
398 DEFVAR_INT ("dos-decimal-point", &dos_decimal_point,
399 "If non-zero, it contains the character to be returned when the\n\
400decimal point key in the numeric keypad is pressed when Num Lock is on.\n\
401If zero, the decimal point key returns the country code specific value.");
402 dos_decimal_point = 0;
1b94449f
RS
403}
404#endif /* MSDOS */