(Fmsdos_long_file_names): New function.
[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}
ac3b0279 243
fb859603
RS
244DEFUN ("msdos-long-file-names", Fmsdos_long_file_names, Smsdos_long_file_names,
245 0, 0, 0,
246 "Return non-nil if long file names are supported. on MSDOS.")
247 ()
248{
249#if __DJGPP__ >= 2
250 return (! NILP (Fgetenv ("LFN")) ? Qt : Qnil);
251#else
252 return Qnil;
253#endif
254}
255
87485d6f 256\f
5f08dc78 257/* country info */
1b94449f
RS
258int dos_country_code;
259int dos_codepage;
5f08dc78
KS
260int dos_timezone_offset;
261int dos_decimal_point;
262int dos_keyboard_layout;
263unsigned char dos_country_info[DOS_COUNTRY_INFO];
264
265int dos_hyper_key;
266int dos_super_key;
267int dos_keypad_mode;
1b94449f 268
5f08dc78
KS
269Lisp_Object Vdos_version;
270Lisp_Object Vdos_display_scancodes;
5f08dc78 271
1b94449f
RS
272void
273init_dosfns ()
274{
275 union REGS regs;
276 _go32_dpmi_seginfo info;
277 _go32_dpmi_registers dpmiregs;
278
87485d6f 279#ifndef SYSTEM_MALLOC
1b94449f 280 get_lim_data (); /* why the hell isn't this called elsewhere? */
87485d6f 281#endif
1b94449f
RS
282
283 regs.x.ax = 0x3000;
284 intdos (&regs, &regs);
285 Vdos_version = Fcons (make_number (regs.h.al), make_number (regs.h.ah));
286
287 /* Obtain the country code by calling Dos via Dpmi. Don't rely on GO32. */
5f08dc78 288 info.size = (sizeof(dos_country_info) + 15) / 16;
1b94449f
RS
289 if (_go32_dpmi_allocate_dos_memory (&info))
290 dos_country_code = 1;
291 else
292 {
293 dpmiregs.x.ax = 0x3800;
294 dpmiregs.x.ds = info.rm_segment;
295 dpmiregs.x.dx = 0;
296 dpmiregs.x.ss = dpmiregs.x.sp = 0;
297 _go32_dpmi_simulate_int (0x21, &dpmiregs);
298 dos_country_code = dpmiregs.x.bx;
5f08dc78 299 dosmemget (info.rm_segment * 16, DOS_COUNTRY_INFO, dos_country_info);
1b94449f
RS
300 _go32_dpmi_free_dos_memory (&info);
301 }
5f08dc78 302 dos_set_keyboard (dos_country_code, 0);
1b94449f
RS
303
304 regs.x.ax = 0x6601;
305 intdos (&regs, &regs);
306 if (regs.x.cflag)
307 /* Estimate code page from country code */
308 switch (dos_country_code)
309 {
310 case 45: /* Denmark */
311 case 47: /* Norway */
312 dos_codepage = 865;
313 break;
314 default:
315 /* US */
316 dos_codepage = 437;
317 }
318 else
319 dos_codepage = regs.x.bx & 0xffff;
320}
321\f
322/*
323 * Define everything
324 */
325syms_of_dosfns ()
326{
1b94449f 327 defsubr (&Sint86);
5f08dc78
KS
328 defsubr (&Sdos_memget);
329 defsubr (&Sdos_memput);
ac3b0279
RS
330 defsubr (&Smsdos_mouse_init);
331 defsubr (&Smsdos_mouse_enable);
5f08dc78
KS
332 defsubr (&Smsdos_set_keyboard);
333 defsubr (&Sinsert_startup_screen);
ac3b0279 334 defsubr (&Smsdos_mouse_disable);
fb859603 335 defsubr (&Smsdos_long_file_names);
87485d6f
MW
336#ifndef HAVE_X_WINDOWS
337 defsubr (&Smsdos_mouse_p);
338 defsubr (&Sset_mouse_position);
339
340 Qmsdos_color_translate = intern ("msdos-color-translate");
341 staticpro (&Qmsdos_color_translate);
342#endif
1b94449f
RS
343
344 DEFVAR_INT ("dos-country-code", &dos_country_code,
345 "The country code returned by Dos when Emacs was started.\n\
346Usually this is the international telephone prefix.");
347
348 DEFVAR_INT ("dos-codepage", &dos_codepage,
5f08dc78 349 "The codepage active when Emacs was started.\n\
24ba360b
RS
350The following are known:\n\
351 437 United States\n\
352 850 Multilingual (Latin I)\n\
353 852 Slavic (Latin II)\n\
354 857 Turkish\n\
355 860 Portugal\n\
356 861 Iceland\n\
357 863 Canada (French)\n\
1b94449f
RS
358 865 Norway/Denmark");
359
5f08dc78
KS
360 DEFVAR_INT ("dos-timezone-offset", &dos_timezone_offset,
361 "The current timezone offset to UTC in minutes.
362Implicitly modified when the TZ variable is changed.");
363
1b94449f
RS
364 DEFVAR_LISP ("dos-version", &Vdos_version,
365 "The (MAJOR . MINOR) Dos version (subject to modification with setver).");
5f08dc78
KS
366
367 DEFVAR_LISP ("dos-display-scancodes", &Vdos_display_scancodes,
368 "*When non-nil, the keyboard scan-codes are displayed at the bottom right\n\
369corner of the display (typically at the end of the mode line).\n\
370The output format is: scan code:char code*modifiers.");
371 Vdos_display_scancodes = Qnil;
372
5f08dc78
KS
373 DEFVAR_INT ("dos-hyper-key", &dos_hyper_key,
374 "*If set to 1, use right ALT key as hyper key.\n\
375If set to 2, use right CTRL key as hyper key.");
376 dos_hyper_key = 0;
377
378 DEFVAR_INT ("dos-super-key", &dos_super_key,
379 "*If set to 1, use right ALT key as super key.\n\
380If set to 2, use right CTRL key as super key.");
381 dos_super_key = 0;
382
383 DEFVAR_INT ("dos-keypad-mode", &dos_keypad_mode,
384 "*Controls what key code is returned by a key in the numeric keypad.\n\
385The `numlock ON' action is only taken if no modifier keys are pressed.\n\
386The value is an integer constructed by adding the following bits together:\n\
387 \n\
388 0x00 Digit key returns digit (if numlock ON)\n\
389 0x01 Digit key returns kp-digit (if numlock ON)\n\
390 0x02 Digit key returns M-digit (if numlock ON)\n\
391 0x03 Digit key returns edit key (if numlock ON)\n\
392 \n\
393 0x00 Grey key returns char (if numlock ON)\n\
394 0x04 Grey key returns kp-key (if numlock ON)\n\
395 \n\
396 0x00 Digit key returns digit (if numlock OFF)\n\
397 0x10 Digit key returns kp-digit (if numlock OFF)\n\
398 0x20 Digit key returns M-digit (if numlock OFF)\n\
399 0x30 Digit key returns edit key (if numlock OFF)\n\
400 \n\
401 0x00 Grey key returns char (if numlock OFF)\n\
402 0x40 Grey key returns kp-key (if numlock OFF)\n\
403 \n\
404 0x200 ALT-0..ALT-9 in top-row produces shifted codes.");
b3d5621c 405 dos_keypad_mode = 0x75;
5f08dc78
KS
406
407 DEFVAR_INT ("dos-keyboard-layout", &dos_keyboard_layout,
408 "Contains the country code for the current keyboard layout.\n\
409Use msdos-set-keyboard to select another keyboard layout.");
410 dos_keyboard_layout = 1; /* US */
411
412 DEFVAR_INT ("dos-decimal-point", &dos_decimal_point,
413 "If non-zero, it contains the character to be returned when the\n\
414decimal point key in the numeric keypad is pressed when Num Lock is on.\n\
415If zero, the decimal point key returns the country code specific value.");
416 dos_decimal_point = 0;
1b94449f
RS
417}
418#endif /* MSDOS */