(x-long-option-alist): New variable.
[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)
e089dc62 3 Copyright (C) 1991, 1993, 1996, 1997 Free Software Foundation, Inc.
1b94449f
RS
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>
50666766 38#include <dirent.h>
1b94449f 39
1b94449f
RS
40DEFUN ("int86", Fint86, Sint86, 2, 2, 0,
41 "Call specific MSDOS interrupt number INTERRUPT with REGISTERS.\n\
42Return the updated REGISTER vector.\n\
43\n\
44INTERRUPT should be an integer in the range 0 to 255.\n\
45REGISTERS should be a vector produced by `make-register' and\n\
46`set-register-value'.")
e20104ba
EN
47 (interrupt, registers)
48 Lisp_Object interrupt, registers;
1b94449f
RS
49{
50 register int i;
51 int no;
52 union REGS inregs, outregs;
53 Lisp_Object val;
54
e20104ba
EN
55 CHECK_NUMBER (interrupt, 0);
56 no = (unsigned long) XINT (interrupt);
57 CHECK_VECTOR (registers, 1);
58 if (no < 0 || no > 0xff || XVECTOR (registers)-> size != 8)
1b94449f
RS
59 return Qnil;
60 for (i = 0; i < 8; i++)
e20104ba 61 CHECK_NUMBER (XVECTOR (registers)->contents[i], 1);
1b94449f 62
e20104ba
EN
63 inregs.x.ax = (unsigned long) XFASTINT (XVECTOR (registers)->contents[0]);
64 inregs.x.bx = (unsigned long) XFASTINT (XVECTOR (registers)->contents[1]);
65 inregs.x.cx = (unsigned long) XFASTINT (XVECTOR (registers)->contents[2]);
66 inregs.x.dx = (unsigned long) XFASTINT (XVECTOR (registers)->contents[3]);
67 inregs.x.si = (unsigned long) XFASTINT (XVECTOR (registers)->contents[4]);
68 inregs.x.di = (unsigned long) XFASTINT (XVECTOR (registers)->contents[5]);
69 inregs.x.cflag = (unsigned long) XFASTINT (XVECTOR (registers)->contents[6]);
70 inregs.x.flags = (unsigned long) XFASTINT (XVECTOR (registers)->contents[7]);
1b94449f
RS
71
72 int86 (no, &inregs, &outregs);
73
e20104ba
EN
74 XVECTOR (registers)->contents[0] = make_number (outregs.x.ax);
75 XVECTOR (registers)->contents[1] = make_number (outregs.x.bx);
76 XVECTOR (registers)->contents[2] = make_number (outregs.x.cx);
77 XVECTOR (registers)->contents[3] = make_number (outregs.x.dx);
78 XVECTOR (registers)->contents[4] = make_number (outregs.x.si);
79 XVECTOR (registers)->contents[5] = make_number (outregs.x.di);
80 XVECTOR (registers)->contents[6] = make_number (outregs.x.cflag);
81 XVECTOR (registers)->contents[7] = make_number (outregs.x.flags);
1b94449f 82
e20104ba 83 return registers;
1b94449f
RS
84}
85
5f08dc78
KS
86DEFUN ("msdos-memget", Fdos_memget, Sdos_memget, 2, 2, 0,
87 "Read DOS memory at offset ADDRESS into VECTOR.\n\
88Return the updated VECTOR.")
e20104ba
EN
89 (address, vector)
90 Lisp_Object address, vector;
5f08dc78
KS
91{
92 register int i;
93 int offs, len;
94 char *buf;
95 Lisp_Object val;
96
e20104ba
EN
97 CHECK_NUMBER (address, 0);
98 offs = (unsigned long) XINT (address);
99 CHECK_VECTOR (vector, 1);
100 len = XVECTOR (vector)-> size;
101 if (len < 1 || len > 2048 || address < 0 || address > 0xfffff - len)
5f08dc78
KS
102 return Qnil;
103 buf = alloca (len);
104 dosmemget (offs, len, buf);
105
106 for (i = 0; i < len; i++)
e20104ba 107 XVECTOR (vector)->contents[i] = make_number (buf[i]);
5f08dc78 108
e20104ba 109 return vector;
5f08dc78
KS
110}
111
112DEFUN ("msdos-memput", Fdos_memput, Sdos_memput, 2, 2, 0,
113 "Write DOS memory at offset ADDRESS from VECTOR.")
e20104ba
EN
114 (address, vector)
115 Lisp_Object address, vector;
5f08dc78
KS
116{
117 register int i;
118 int offs, len;
119 char *buf;
120 Lisp_Object val;
121
e20104ba
EN
122 CHECK_NUMBER (address, 0);
123 offs = (unsigned long) XINT (address);
124 CHECK_VECTOR (vector, 1);
125 len = XVECTOR (vector)-> size;
126 if (len < 1 || len > 2048 || address < 0 || address > 0xfffff - len)
5f08dc78
KS
127 return Qnil;
128 buf = alloca (len);
129
130 for (i = 0; i < len; i++)
131 {
e20104ba
EN
132 CHECK_NUMBER (XVECTOR (vector)->contents[i], 1);
133 buf[i] = (unsigned char) XFASTINT (XVECTOR (vector)->contents[i]) & 0xFF;
5f08dc78
KS
134 }
135
136 dosmemput (buf, len, offs);
137 return Qt;
138}
139
140DEFUN ("msdos-set-keyboard", Fmsdos_set_keyboard, Smsdos_set_keyboard, 1, 2, 0,
e20104ba 141 "Set keyboard layout according to COUNTRY-CODE.\n\
5f08dc78
KS
142If the optional argument ALLKEYS is non-nil, the keyboard is mapped for\n\
143all keys; otherwise it is only used when the ALT key is pressed.\n\
144The current keyboard layout is available in dos-keyboard-code.")
145 (country_code, allkeys)
146 Lisp_Object country_code;
147{
148 CHECK_NUMBER (country_code, 0);
149 if (!dos_set_keyboard (XINT (country_code), !NILP (allkeys)))
150 return Qnil;
151 return Qt;
152}
153
87485d6f
MW
154#ifndef HAVE_X_WINDOWS
155/* Later we might want to control the mouse interface with this function,
156 e.g., with respect to non-80 column screen modes. */
157
158DEFUN ("msdos-mouse-p", Fmsdos_mouse_p, Smsdos_mouse_p, 0, 0, 0, "\
159Report whether a mouse is present.")
160 ()
161{
162 if (have_mouse)
163 return Qt;
164 else
165 return Qnil;
166}
167
87485d6f
MW
168/* Function to translate colour names to integers. See lisp/term/pc-win.el
169 for its definition. */
170
171Lisp_Object Qmsdos_color_translate;
172#endif
173
ac3b0279
RS
174
175DEFUN ("msdos-mouse-init", Fmsdos_mouse_init, Smsdos_mouse_init, 0, 0, "",
176 "Initialize and enable mouse if available.")
177 ()
178{
5f08dc78
KS
179 if (have_mouse)
180 {
181 have_mouse = 1;
182 mouse_init ();
183 return Qt;
184 }
ac3b0279
RS
185 return Qnil;
186}
187
188DEFUN ("msdos-mouse-enable", Fmsdos_mouse_enable, Smsdos_mouse_enable, 0, 0, "",
189 "Enable mouse if available.")
190 ()
191{
192 if (have_mouse)
193 {
5f08dc78
KS
194 have_mouse = 1;
195 mouse_on ();
ac3b0279
RS
196 }
197 return have_mouse ? Qt : Qnil;
198}
199
200DEFUN ("msdos-mouse-disable", Fmsdos_mouse_disable, Smsdos_mouse_disable, 0, 0, "",
201 "Disable mouse if available.")
202 ()
203{
204 mouse_off ();
205 if (have_mouse) have_mouse = -1;
206 return Qnil;
207}
208
5f08dc78
KS
209DEFUN ("insert-startup-screen", Finsert_startup_screen, Sinsert_startup_screen, 0, 0, "", "\
210Insert copy of screen contents prior to starting emacs.\n\
211Return nil if startup screen is not available.")
212 ()
213{
214 char *s;
215 int rows, cols;
216 int i, j;
217
218 if (!dos_get_saved_screen (&s, &rows, &cols))
219 return Qnil;
220
221 for (i = 0; i < rows; i++)
222 {
223 for (j = 0; j < cols; j++)
224 {
65788bc2 225 insert_char (*s);
5f08dc78
KS
226 s += 2;
227 }
65788bc2 228 insert_char ('\n');
5f08dc78
KS
229 }
230
231 return Qt;
232}
87485d6f 233\f
5f08dc78 234/* country info */
1b94449f
RS
235int dos_country_code;
236int dos_codepage;
5f08dc78
KS
237int dos_timezone_offset;
238int dos_decimal_point;
239int dos_keyboard_layout;
240unsigned char dos_country_info[DOS_COUNTRY_INFO];
e089dc62
RS
241static unsigned char usa_country_info[DOS_COUNTRY_INFO] = {
242 0, 0, /* date format */
243 '$', 0, 0, 0, 0, /* currency string */
244 ',', 0, /* thousands separator */
245 '.', 0, /* decimal separator */
246 '/', 0, /* date separator */
247 ':', 0, /* time separator */
248 0, /* currency format */
249 2, /* digits after decimal in currency */
250 0, /* time format */
251 0, 0, 0, 0, /* address of case map routine, GPF if used */
252 ' ', 0, /* data-list separator (?) */
253 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* reserved */
254};
5f08dc78
KS
255
256int dos_hyper_key;
257int dos_super_key;
258int dos_keypad_mode;
1b94449f 259
5f08dc78
KS
260Lisp_Object Vdos_version;
261Lisp_Object Vdos_display_scancodes;
5f08dc78 262
1b94449f
RS
263void
264init_dosfns ()
265{
266 union REGS regs;
1b94449f 267 _go32_dpmi_registers dpmiregs;
e089dc62 268 unsigned long xbuf = _go32_info_block.linear_address_of_transfer_buffer;
1b94449f 269
87485d6f 270#ifndef SYSTEM_MALLOC
1b94449f 271 get_lim_data (); /* why the hell isn't this called elsewhere? */
87485d6f 272#endif
1b94449f
RS
273
274 regs.x.ax = 0x3000;
275 intdos (&regs, &regs);
276 Vdos_version = Fcons (make_number (regs.h.al), make_number (regs.h.ah));
277
e089dc62
RS
278 /* Obtain the country code via DPMI, use DJGPP transfer buffer. */
279 dpmiregs.x.ax = 0x3800;
280 dpmiregs.x.ds = xbuf;
281 dpmiregs.x.dx = 0;
282 dpmiregs.x.ss = dpmiregs.x.sp = dpmiregs.x.flags = 0;
283 _go32_dpmi_simulate_int (0x21, &dpmiregs);
284 if (dpmiregs.x.flags & 1)
285 {
286 dos_country_code = 1; /* assume USA if 213800 failed */
287 memcpy (dos_country_info, usa_country_info, DOS_COUNTRY_INFO);
288 }
1b94449f
RS
289 else
290 {
1b94449f 291 dos_country_code = dpmiregs.x.bx;
e089dc62 292 dosmemget (xbuf, DOS_COUNTRY_INFO, dos_country_info);
1b94449f 293 }
e089dc62 294
5f08dc78 295 dos_set_keyboard (dos_country_code, 0);
1b94449f
RS
296
297 regs.x.ax = 0x6601;
298 intdos (&regs, &regs);
299 if (regs.x.cflag)
300 /* Estimate code page from country code */
301 switch (dos_country_code)
302 {
303 case 45: /* Denmark */
304 case 47: /* Norway */
305 dos_codepage = 865;
306 break;
307 default:
308 /* US */
309 dos_codepage = 437;
310 }
311 else
312 dos_codepage = regs.x.bx & 0xffff;
50666766
RS
313
314#if __DJGPP__ >= 2
315
459f4042
RS
316 /* Without this, we never see hidden files.
317 Don't OR it with the previous value, so the value recorded at dump
318 time, possibly with `preserve-case' flags set, won't get through. */
319 __opendir_flags = __OPENDIR_FIND_HIDDEN;
320
321#if __DJGPP_MINOR__ == 0
322 /* Under LFN, preserve the case of files as recorded in the directory
323 (in DJGPP 2.01 and later this is automagically done by the library). */
50666766
RS
324 if (!NILP (Fmsdos_long_file_names ()))
325 __opendir_flags |= __OPENDIR_PRESERVE_CASE;
459f4042
RS
326#endif /* __DJGPP_MINOR__ == 0 */
327#endif /* __DJGPP__ >= 2 */
1b94449f
RS
328}
329\f
330/*
331 * Define everything
332 */
333syms_of_dosfns ()
334{
1b94449f 335 defsubr (&Sint86);
5f08dc78
KS
336 defsubr (&Sdos_memget);
337 defsubr (&Sdos_memput);
ac3b0279
RS
338 defsubr (&Smsdos_mouse_init);
339 defsubr (&Smsdos_mouse_enable);
5f08dc78
KS
340 defsubr (&Smsdos_set_keyboard);
341 defsubr (&Sinsert_startup_screen);
ac3b0279 342 defsubr (&Smsdos_mouse_disable);
87485d6f
MW
343#ifndef HAVE_X_WINDOWS
344 defsubr (&Smsdos_mouse_p);
87485d6f
MW
345 Qmsdos_color_translate = intern ("msdos-color-translate");
346 staticpro (&Qmsdos_color_translate);
347#endif
1b94449f
RS
348
349 DEFVAR_INT ("dos-country-code", &dos_country_code,
350 "The country code returned by Dos when Emacs was started.\n\
351Usually this is the international telephone prefix.");
352
353 DEFVAR_INT ("dos-codepage", &dos_codepage,
5f08dc78 354 "The codepage active when Emacs was started.\n\
24ba360b
RS
355The following are known:\n\
356 437 United States\n\
357 850 Multilingual (Latin I)\n\
358 852 Slavic (Latin II)\n\
359 857 Turkish\n\
360 860 Portugal\n\
361 861 Iceland\n\
362 863 Canada (French)\n\
1b94449f
RS
363 865 Norway/Denmark");
364
5f08dc78
KS
365 DEFVAR_INT ("dos-timezone-offset", &dos_timezone_offset,
366 "The current timezone offset to UTC in minutes.
367Implicitly modified when the TZ variable is changed.");
368
1b94449f
RS
369 DEFVAR_LISP ("dos-version", &Vdos_version,
370 "The (MAJOR . MINOR) Dos version (subject to modification with setver).");
5f08dc78
KS
371
372 DEFVAR_LISP ("dos-display-scancodes", &Vdos_display_scancodes,
373 "*When non-nil, the keyboard scan-codes are displayed at the bottom right\n\
374corner of the display (typically at the end of the mode line).\n\
375The output format is: scan code:char code*modifiers.");
376 Vdos_display_scancodes = Qnil;
377
5f08dc78
KS
378 DEFVAR_INT ("dos-hyper-key", &dos_hyper_key,
379 "*If set to 1, use right ALT key as hyper key.\n\
380If set to 2, use right CTRL key as hyper key.");
381 dos_hyper_key = 0;
382
383 DEFVAR_INT ("dos-super-key", &dos_super_key,
384 "*If set to 1, use right ALT key as super key.\n\
385If set to 2, use right CTRL key as super key.");
386 dos_super_key = 0;
387
388 DEFVAR_INT ("dos-keypad-mode", &dos_keypad_mode,
389 "*Controls what key code is returned by a key in the numeric keypad.\n\
390The `numlock ON' action is only taken if no modifier keys are pressed.\n\
391The value is an integer constructed by adding the following bits together:\n\
392 \n\
393 0x00 Digit key returns digit (if numlock ON)\n\
394 0x01 Digit key returns kp-digit (if numlock ON)\n\
395 0x02 Digit key returns M-digit (if numlock ON)\n\
396 0x03 Digit key returns edit key (if numlock ON)\n\
397 \n\
398 0x00 Grey key returns char (if numlock ON)\n\
399 0x04 Grey key returns kp-key (if numlock ON)\n\
400 \n\
401 0x00 Digit key returns digit (if numlock OFF)\n\
402 0x10 Digit key returns kp-digit (if numlock OFF)\n\
403 0x20 Digit key returns M-digit (if numlock OFF)\n\
404 0x30 Digit key returns edit key (if numlock OFF)\n\
405 \n\
406 0x00 Grey key returns char (if numlock OFF)\n\
407 0x40 Grey key returns kp-key (if numlock OFF)\n\
408 \n\
409 0x200 ALT-0..ALT-9 in top-row produces shifted codes.");
b3d5621c 410 dos_keypad_mode = 0x75;
5f08dc78
KS
411
412 DEFVAR_INT ("dos-keyboard-layout", &dos_keyboard_layout,
413 "Contains the country code for the current keyboard layout.\n\
414Use msdos-set-keyboard to select another keyboard layout.");
415 dos_keyboard_layout = 1; /* US */
416
417 DEFVAR_INT ("dos-decimal-point", &dos_decimal_point,
418 "If non-zero, it contains the character to be returned when the\n\
419decimal point key in the numeric keypad is pressed when Num Lock is on.\n\
420If zero, the decimal point key returns the country code specific value.");
421 dos_decimal_point = 0;
1b94449f
RS
422}
423#endif /* MSDOS */