* README: Add a note about ranges in copyright years.
[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)
0b5538bd 3 Copyright (C) 1991, 1993, 1996, 1997, 1998, 2001, 2002, 2003, 2004,
5df4f04c 4 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
1b94449f
RS
5
6This file is part of GNU Emacs.
7
9ec0b715 8GNU Emacs is free software: you can redistribute it and/or modify
1b94449f 9it under the terms of the GNU General Public License as published by
9ec0b715
GM
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
1b94449f
RS
12
13GNU Emacs is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
9ec0b715 19along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
1b94449f 20
48984716 21#include <config.h>
1b94449f
RS
22
23#ifdef MSDOS
24/* The entire file is within this conditional */
25
26#include <stdio.h>
27#include <dos.h>
d7306fe6 28#include <setjmp.h>
1b94449f
RS
29#include "lisp.h"
30#include "buffer.h"
31#include "termchar.h"
1b94449f 32#include "frame.h"
c06981c0 33#include "termhooks.h"
838a94b8
EZ
34#include "blockinput.h"
35#include "window.h"
1b94449f
RS
36#include "dosfns.h"
37#include "msdos.h"
e4441df0 38#include "dispextern.h"
83be827a 39#include "character.h"
76a76a57 40#include "coding.h"
e5c9f94c 41#include "process.h"
838a94b8 42#include <dpmi.h>
5f08dc78 43#include <go32.h>
50666766 44#include <dirent.h>
76a76a57 45#include <sys/vfs.h>
e5c9f94c
EZ
46#include <unistd.h>
47#include <grp.h>
48#include <crt0.h>
1b94449f 49
1b94449f 50DEFUN ("int86", Fint86, Sint86, 2, 2, 0,
8fc29035 51 doc: /* Call specific MS-DOS interrupt number INTERRUPT with REGISTERS.
7363986a
PJ
52Return the updated REGISTER vector.
53
54INTERRUPT should be an integer in the range 0 to 255.
55REGISTERS should be a vector produced by `make-register' and
56`set-register-value'. */)
5842a27b 57 (Lisp_Object interrupt, Lisp_Object registers)
1b94449f
RS
58{
59 register int i;
60 int no;
61 union REGS inregs, outregs;
1b94449f 62
b7826503 63 CHECK_NUMBER (interrupt);
e20104ba 64 no = (unsigned long) XINT (interrupt);
b7826503 65 CHECK_VECTOR (registers);
b058cb36 66 if (no < 0 || no > 0xff || XVECTOR (registers)-> size != 8)
1b94449f
RS
67 return Qnil;
68 for (i = 0; i < 8; i++)
b7826503 69 CHECK_NUMBER (XVECTOR (registers)->contents[i]);
1b94449f 70
e20104ba
EN
71 inregs.x.ax = (unsigned long) XFASTINT (XVECTOR (registers)->contents[0]);
72 inregs.x.bx = (unsigned long) XFASTINT (XVECTOR (registers)->contents[1]);
73 inregs.x.cx = (unsigned long) XFASTINT (XVECTOR (registers)->contents[2]);
74 inregs.x.dx = (unsigned long) XFASTINT (XVECTOR (registers)->contents[3]);
75 inregs.x.si = (unsigned long) XFASTINT (XVECTOR (registers)->contents[4]);
76 inregs.x.di = (unsigned long) XFASTINT (XVECTOR (registers)->contents[5]);
77 inregs.x.cflag = (unsigned long) XFASTINT (XVECTOR (registers)->contents[6]);
78 inregs.x.flags = (unsigned long) XFASTINT (XVECTOR (registers)->contents[7]);
1b94449f
RS
79
80 int86 (no, &inregs, &outregs);
81
e20104ba
EN
82 XVECTOR (registers)->contents[0] = make_number (outregs.x.ax);
83 XVECTOR (registers)->contents[1] = make_number (outregs.x.bx);
84 XVECTOR (registers)->contents[2] = make_number (outregs.x.cx);
85 XVECTOR (registers)->contents[3] = make_number (outregs.x.dx);
86 XVECTOR (registers)->contents[4] = make_number (outregs.x.si);
87 XVECTOR (registers)->contents[5] = make_number (outregs.x.di);
88 XVECTOR (registers)->contents[6] = make_number (outregs.x.cflag);
89 XVECTOR (registers)->contents[7] = make_number (outregs.x.flags);
1b94449f 90
e20104ba 91 return registers;
1b94449f
RS
92}
93
5f08dc78 94DEFUN ("msdos-memget", Fdos_memget, Sdos_memget, 2, 2, 0,
7363986a
PJ
95 doc: /* Read DOS memory at offset ADDRESS into VECTOR.
96Return the updated VECTOR. */)
5842a27b 97 (Lisp_Object address, Lisp_Object vector)
5f08dc78
KS
98{
99 register int i;
100 int offs, len;
101 char *buf;
5f08dc78 102
b7826503 103 CHECK_NUMBER (address);
e20104ba 104 offs = (unsigned long) XINT (address);
b7826503 105 CHECK_VECTOR (vector);
e20104ba 106 len = XVECTOR (vector)-> size;
238a44a8 107 if (len < 1 || len > 2048 || offs < 0 || offs > 0xfffff - len)
5f08dc78
KS
108 return Qnil;
109 buf = alloca (len);
110 dosmemget (offs, len, buf);
b058cb36 111
5f08dc78 112 for (i = 0; i < len; i++)
e20104ba 113 XVECTOR (vector)->contents[i] = make_number (buf[i]);
5f08dc78 114
e20104ba 115 return vector;
5f08dc78
KS
116}
117
118DEFUN ("msdos-memput", Fdos_memput, Sdos_memput, 2, 2, 0,
7363986a 119 doc: /* Write DOS memory at offset ADDRESS from VECTOR. */)
5842a27b 120 (Lisp_Object address, Lisp_Object vector)
5f08dc78
KS
121{
122 register int i;
123 int offs, len;
124 char *buf;
5f08dc78 125
b7826503 126 CHECK_NUMBER (address);
e20104ba 127 offs = (unsigned long) XINT (address);
b7826503 128 CHECK_VECTOR (vector);
e20104ba 129 len = XVECTOR (vector)-> size;
238a44a8 130 if (len < 1 || len > 2048 || offs < 0 || offs > 0xfffff - len)
5f08dc78
KS
131 return Qnil;
132 buf = alloca (len);
133
134 for (i = 0; i < len; i++)
135 {
b7826503 136 CHECK_NUMBER (XVECTOR (vector)->contents[i]);
e20104ba 137 buf[i] = (unsigned char) XFASTINT (XVECTOR (vector)->contents[i]) & 0xFF;
5f08dc78
KS
138 }
139
140 dosmemput (buf, len, offs);
141 return Qt;
142}
143
144DEFUN ("msdos-set-keyboard", Fmsdos_set_keyboard, Smsdos_set_keyboard, 1, 2, 0,
7363986a
PJ
145 doc: /* Set keyboard layout according to COUNTRY-CODE.
146If the optional argument ALLKEYS is non-nil, the keyboard is mapped for
147all keys; otherwise it is only used when the ALT key is pressed.
148The current keyboard layout is available in dos-keyboard-code. */)
5842a27b 149 (Lisp_Object country_code, Lisp_Object allkeys)
5f08dc78 150{
b7826503 151 CHECK_NUMBER (country_code);
5f08dc78
KS
152 if (!dos_set_keyboard (XINT (country_code), !NILP (allkeys)))
153 return Qnil;
154 return Qt;
155}
156
87485d6f
MW
157#ifndef HAVE_X_WINDOWS
158/* Later we might want to control the mouse interface with this function,
159 e.g., with respect to non-80 column screen modes. */
160
7363986a
PJ
161DEFUN ("msdos-mouse-p", Fmsdos_mouse_p, Smsdos_mouse_p, 0, 0, 0,
162 doc: /* Report whether a mouse is present. */)
5842a27b 163 (void)
87485d6f
MW
164{
165 if (have_mouse)
166 return Qt;
167 else
168 return Qnil;
169}
87485d6f
MW
170#endif
171
ac3b0279 172DEFUN ("msdos-mouse-init", Fmsdos_mouse_init, Smsdos_mouse_init, 0, 0, "",
7363986a 173 doc: /* Initialize and enable mouse if available. */)
5842a27b 174 (void)
ac3b0279 175{
5f08dc78
KS
176 if (have_mouse)
177 {
178 have_mouse = 1;
179 mouse_init ();
180 return Qt;
181 }
ac3b0279
RS
182 return Qnil;
183}
184
185DEFUN ("msdos-mouse-enable", Fmsdos_mouse_enable, Smsdos_mouse_enable, 0, 0, "",
7363986a 186 doc: /* Enable mouse if available. */)
5842a27b 187 (void)
ac3b0279
RS
188{
189 if (have_mouse)
190 {
5f08dc78
KS
191 have_mouse = 1;
192 mouse_on ();
ac3b0279
RS
193 }
194 return have_mouse ? Qt : Qnil;
195}
196
197DEFUN ("msdos-mouse-disable", Fmsdos_mouse_disable, Smsdos_mouse_disable, 0, 0, "",
7363986a 198 doc: /* Disable mouse if available. */)
5842a27b 199 (void)
ac3b0279
RS
200{
201 mouse_off ();
202 if (have_mouse) have_mouse = -1;
203 return Qnil;
204}
205
7363986a 206DEFUN ("insert-startup-screen", Finsert_startup_screen, Sinsert_startup_screen, 0, 0, "",
cd53fb50 207 doc: /* Insert copy of screen contents prior to starting Emacs.
7363986a 208Return nil if startup screen is not available. */)
5842a27b 209 (void)
5f08dc78
KS
210{
211 char *s;
b058cb36
EZ
212 int rows, cols, i, j;
213
5f08dc78
KS
214 if (!dos_get_saved_screen (&s, &rows, &cols))
215 return Qnil;
b058cb36 216
5f08dc78
KS
217 for (i = 0; i < rows; i++)
218 {
219 for (j = 0; j < cols; j++)
220 {
65788bc2 221 insert_char (*s);
5f08dc78
KS
222 s += 2;
223 }
65788bc2 224 insert_char ('\n');
5f08dc78
KS
225 }
226
227 return Qt;
228}
87485d6f 229\f
5f08dc78 230unsigned char dos_country_info[DOS_COUNTRY_INFO];
e089dc62
RS
231static unsigned char usa_country_info[DOS_COUNTRY_INFO] = {
232 0, 0, /* date format */
233 '$', 0, 0, 0, 0, /* currency string */
234 ',', 0, /* thousands separator */
235 '.', 0, /* decimal separator */
236 '/', 0, /* date separator */
237 ':', 0, /* time separator */
238 0, /* currency format */
239 2, /* digits after decimal in currency */
240 0, /* time format */
241 0, 0, 0, 0, /* address of case map routine, GPF if used */
242 ' ', 0, /* data-list separator (?) */
243 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* reserved */
244};
5f08dc78 245
838a94b8
EZ
246#ifndef HAVE_X_WINDOWS
247static unsigned dos_windows_version;
838a94b8
EZ
248char parent_vm_title[50]; /* Ralf Brown says 30 is enough */
249int w95_set_virtual_machine_title (const char *);
250
251void
252restore_parent_vm_title (void)
253{
254 if (NILP (Vdos_windows_version))
255 return;
256 if ((dos_windows_version & 0xff) >= 4 && parent_vm_title[0])
257 w95_set_virtual_machine_title (parent_vm_title);
258 delay (50);
259}
260#endif /* !HAVE_X_WINDOWS */
b058cb36 261
1b94449f 262void
3a8ce822 263init_dosfns (void)
1b94449f
RS
264{
265 union REGS regs;
1b94449f 266 _go32_dpmi_registers dpmiregs;
e089dc62 267 unsigned long xbuf = _go32_info_block.linear_address_of_transfer_buffer;
1b94449f 268
87485d6f 269#ifndef SYSTEM_MALLOC
891ef8f7
EZ
270 extern void get_lim_data (void);
271
1b94449f 272 get_lim_data (); /* why the hell isn't this called elsewhere? */
87485d6f 273#endif
1b94449f
RS
274
275 regs.x.ax = 0x3000;
276 intdos (&regs, &regs);
277 Vdos_version = Fcons (make_number (regs.h.al), make_number (regs.h.ah));
278
e089dc62
RS
279 /* Obtain the country code via DPMI, use DJGPP transfer buffer. */
280 dpmiregs.x.ax = 0x3800;
7a2fd369 281 dpmiregs.x.ds = xbuf >> 4;
e089dc62
RS
282 dpmiregs.x.dx = 0;
283 dpmiregs.x.ss = dpmiregs.x.sp = dpmiregs.x.flags = 0;
284 _go32_dpmi_simulate_int (0x21, &dpmiregs);
285 if (dpmiregs.x.flags & 1)
286 {
287 dos_country_code = 1; /* assume USA if 213800 failed */
288 memcpy (dos_country_info, usa_country_info, DOS_COUNTRY_INFO);
289 }
1b94449f
RS
290 else
291 {
1b94449f 292 dos_country_code = dpmiregs.x.bx;
e089dc62 293 dosmemget (xbuf, DOS_COUNTRY_INFO, dos_country_info);
1b94449f 294 }
e089dc62 295
5f08dc78 296 dos_set_keyboard (dos_country_code, 0);
1b94449f
RS
297
298 regs.x.ax = 0x6601;
299 intdos (&regs, &regs);
300 if (regs.x.cflag)
301 /* Estimate code page from country code */
b058cb36 302 switch (dos_country_code)
1b94449f
RS
303 {
304 case 45: /* Denmark */
305 case 47: /* Norway */
306 dos_codepage = 865;
307 break;
308 default:
309 /* US */
310 dos_codepage = 437;
311 }
312 else
313 dos_codepage = regs.x.bx & 0xffff;
50666766 314
838a94b8
EZ
315#ifndef HAVE_X_WINDOWS
316 parent_vm_title[0] = '\0';
317
318 /* If we are running from DOS box on MS-Windows, get Windows version. */
319 dpmiregs.x.ax = 0x1600; /* enhanced mode installation check */
320 dpmiregs.x.ss = dpmiregs.x.sp = dpmiregs.x.flags = 0;
321 _go32_dpmi_simulate_int (0x2f, &dpmiregs);
322 /* We only support Windows-specific features when we run on Windows 9X
323 or on Windows 3.X/enhanced mode.
324
325 Int 2Fh/AX=1600h returns:
326
327 AL = 00: no Windows at all;
328 AL = 01: Windows/386 2.x;
329 AL = 80h: Windows 3.x in mode other than enhanced;
330 AL = FFh: Windows/386 2.x
331
332 We also check AH > 0 (Windows 3.1 or later), in case AL tricks us. */
333 if (dpmiregs.h.al > 2 && dpmiregs.h.al != 0x80 && dpmiregs.h.al != 0xff
334 && (dpmiregs.h.al > 3 || dpmiregs.h.ah > 0))
335 {
336 dos_windows_version = dpmiregs.x.ax;
337 Vdos_windows_version =
338 Fcons (make_number (dpmiregs.h.al), make_number (dpmiregs.h.ah));
339
340 /* Save the current title of this virtual machine, so we can restore
341 it before exiting. Otherwise, Windows 95 will continue to use
342 the title we set even after we are history, stupido... */
343 if (dpmiregs.h.al >= 4)
344 {
345 dpmiregs.x.ax = 0x168e;
346 dpmiregs.x.dx = 3; /* get VM title */
347 dpmiregs.x.cx = sizeof(parent_vm_title) - 1;
348 dpmiregs.x.es = __tb >> 4;
349 dpmiregs.x.di = __tb & 15;
350 dpmiregs.x.sp = dpmiregs.x.ss = dpmiregs.x.flags = 0;
351 _go32_dpmi_simulate_int (0x2f, &dpmiregs);
352 if (dpmiregs.x.ax == 1)
353 dosmemget (__tb, sizeof(parent_vm_title), parent_vm_title);
354 }
355 }
356 else
357 {
358 dos_windows_version = 0;
359 Vdos_windows_version = Qnil;
360 }
361#endif /* !HAVE_X_WINDOWS */
362
459f4042
RS
363 /* Without this, we never see hidden files.
364 Don't OR it with the previous value, so the value recorded at dump
365 time, possibly with `preserve-case' flags set, won't get through. */
366 __opendir_flags = __OPENDIR_FIND_HIDDEN;
367
368#if __DJGPP_MINOR__ == 0
369 /* Under LFN, preserve the case of files as recorded in the directory
370 (in DJGPP 2.01 and later this is automagically done by the library). */
50666766
RS
371 if (!NILP (Fmsdos_long_file_names ()))
372 __opendir_flags |= __OPENDIR_PRESERVE_CASE;
459f4042 373#endif /* __DJGPP_MINOR__ == 0 */
1b94449f
RS
374}
375\f
838a94b8 376#ifndef HAVE_X_WINDOWS
e4441df0
EZ
377
378/* Emulation of some X window features from xfns.c and xfaces.c. */
379
380/* Standard VGA colors, in the order of their standard numbering
381 in the default VGA palette. */
382static char *vga_colors[16] = {
383 "black", "blue", "green", "cyan", "red", "magenta", "brown",
384 "lightgray", "darkgray", "lightblue", "lightgreen", "lightcyan",
385 "lightred", "lightmagenta", "yellow", "white"
386};
387
388/* Given a color name, return its index, or -1 if not found. Note
389 that this only performs case-insensitive comparison against the
390 standard names. For anything more sophisticated, like matching
391 "gray" with "grey" or translating X color names into their MSDOS
2d764c78
EZ
392 equivalents, call the Lisp function Qtty_color_desc (defined
393 on lisp/term/tty-colors.el). */
e4441df0
EZ
394int
395msdos_stdcolor_idx (const char *name)
396{
397 int i;
398
399 for (i = 0; i < sizeof (vga_colors) / sizeof (vga_colors[0]); i++)
05131107 400 if (xstrcasecmp (name, vga_colors[i]) == 0)
e4441df0
EZ
401 return i;
402
f9d2fdc4 403 return
24480d5b
EZ
404 strcmp (name, unspecified_fg) == 0 ? FACE_TTY_DEFAULT_FG_COLOR
405 : strcmp (name, unspecified_bg) == 0 ? FACE_TTY_DEFAULT_BG_COLOR
f9d2fdc4 406 : FACE_TTY_DEFAULT_COLOR;
e4441df0
EZ
407}
408
409/* Given a color index, return its standard name. */
2d764c78 410Lisp_Object
e4441df0
EZ
411msdos_stdcolor_name (int idx)
412{
24480d5b
EZ
413 extern Lisp_Object Qunspecified;
414
415 if (idx == FACE_TTY_DEFAULT_FG_COLOR)
416 return build_string (unspecified_fg);
417 else if (idx == FACE_TTY_DEFAULT_BG_COLOR)
418 return build_string (unspecified_bg);
419 else if (idx >= 0 && idx < sizeof (vga_colors) / sizeof (vga_colors[0]))
420 return build_string (vga_colors[idx]);
421 else
422 return Qunspecified; /* meaning the default */
e4441df0
EZ
423}
424
838a94b8
EZ
425/* Support for features that are available when we run in a DOS box
426 on MS-Windows. */
427int
428ms_windows_version (void)
429{
430 return dos_windows_version;
431}
432
433/* Set the title of the current virtual machine, to appear on
434 the caption bar of that machine's window. */
435
436int
437w95_set_virtual_machine_title (const char *title_string)
438{
439 /* Only Windows 9X (version 4 and higher) support this function. */
440 if (!NILP (Vdos_windows_version)
441 && (dos_windows_version & 0xff) >= 4)
442 {
443 _go32_dpmi_registers regs;
444 dosmemput (title_string, strlen (title_string) + 1, __tb);
445 regs.x.ax = 0x168e;
446 regs.x.dx = 1;
447 regs.x.es = __tb >> 4;
448 regs.x.di = __tb & 15;
449 regs.x.sp = regs.x.ss = regs.x.flags = 0;
450 _go32_dpmi_simulate_int (0x2f, &regs);
451 return regs.x.ax == 1;
452 }
453 return 0;
454}
455
456/* Change the title of frame F to NAME.
457 If NAME is nil, use the frame name as the title.
458
459 If Emacs is not run from a DOS box on Windows 9X, this only
460 sets the name in the frame struct, but has no other effects. */
461
462void
3a8ce822 463x_set_title (struct frame *f, Lisp_Object name)
838a94b8
EZ
464{
465 /* Don't change the title if it's already NAME. */
466 if (EQ (name, f->title))
467 return;
468
469 update_mode_lines = 1;
470
471 f->title = name;
472
473 if (NILP (name))
474 name = f->name;
475
476 if (FRAME_MSDOS_P (f))
477 {
478 BLOCK_INPUT;
d5db4077 479 w95_set_virtual_machine_title (SDATA (name));
838a94b8
EZ
480 UNBLOCK_INPUT;
481 }
482}
483#endif /* !HAVE_X_WINDOWS */
484\f
76a76a57 485DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0,
7363986a
PJ
486 doc: /* Return storage information about the file system FILENAME is on.
487Value is a list of floats (TOTAL FREE AVAIL), where TOTAL is the total
488storage of the file system, FREE is the free storage, and AVAIL is the
489storage available to a non-superuser. All 3 numbers are in bytes.
490If the underlying system call fails, value is nil. */)
5842a27b 491 (Lisp_Object filename)
76a76a57
EZ
492{
493 struct statfs stfs;
494 Lisp_Object encoded, value;
495
b7826503 496 CHECK_STRING (filename);
76a76a57
EZ
497 filename = Fexpand_file_name (filename, Qnil);
498 encoded = ENCODE_FILE (filename);
499
d5db4077 500 if (statfs (SDATA (encoded), &stfs))
76a76a57
EZ
501 value = Qnil;
502 else
503 value = list3 (make_float ((double) stfs.f_bsize * stfs.f_blocks),
504 make_float ((double) stfs.f_bsize * stfs.f_bfree),
505 make_float ((double) stfs.f_bsize * stfs.f_bavail));
506
507 return value;
508}
509\f
e5c9f94c
EZ
510/* System depended enumeration of and access to system processes a-la
511 ps(1). Here, we only return info about the running Emacs process.
512 (There are no other processes on DOS, right?) */
513
514Lisp_Object
3a8ce822 515list_system_processes (void)
e5c9f94c
EZ
516{
517 Lisp_Object proclist = Qnil;
518
519 proclist = Fcons (make_fixnum_or_float (getpid ()), proclist);
520
521 return proclist;
522}
523
524Lisp_Object
525system_process_attributes (Lisp_Object pid)
526{
527 int proc_id;
528 Lisp_Object attrs = Qnil;
529
530 CHECK_NUMBER_OR_FLOAT (pid);
531 proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
532
533 if (proc_id == getpid ())
534 {
535 EMACS_INT uid, gid;
536 char *usr;
537 struct group *gr;
538 char cmd[FILENAME_MAX];
539 char *cmdline = NULL, *p, *q;
540 size_t cmdline_size = 0;
541 int i;
542 Lisp_Object cmd_str, decoded_cmd, tem;
543 double pmem;
891ef8f7 544 EXFUN (Fget_internal_run_time, 0);
693a2698 545#ifndef SYSTEM_MALLOC
e5c9f94c 546 extern unsigned long ret_lim_data ();
693a2698 547#endif
e5c9f94c
EZ
548
549 uid = getuid ();
550 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
551 usr = getlogin ();
552 if (usr)
553 attrs = Fcons (Fcons (Quser, build_string (usr)), attrs);
554 gid = getgid ();
555 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid)), attrs);
556 gr = getgrgid (gid);
557 if (gr)
558 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
559 strcpy (cmd, basename (__crt0_argv[0]));
560 /* Command name is encoded in locale-coding-system; decode it. */
561 cmd_str = make_unibyte_string (cmd, strlen (cmd));
562 decoded_cmd = code_convert_string_norecord (cmd_str,
563 Vlocale_coding_system, 0);
564 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
565 /* Pretend we have 0 as PPID. */
566 attrs = Fcons (Fcons (Qppid, make_number (0)), attrs);
567 attrs = Fcons (Fcons (Qpgrp, pid), attrs);
568 attrs = Fcons (Fcons (Qttname, build_string ("/dev/tty")), attrs);
569 /* We are never idle! */
570 tem = Fget_internal_run_time ();
571 attrs = Fcons (Fcons (Qtime, tem), attrs);
572 attrs = Fcons (Fcons (Qthcount, make_number (1)), attrs);
573 attrs = Fcons (Fcons (Qstart,
574 Fsymbol_value (intern ("before-init-time"))),
575 attrs);
576 attrs = Fcons (Fcons (Qvsize,
577 make_fixnum_or_float ((unsigned long)sbrk(0)/1024)),
578 attrs);
579 attrs = Fcons (Fcons (Qetime, tem), attrs);
693a2698
EZ
580#ifndef SYSTEM_MALLOC
581 /* ret_lim_data is on vm-limit.c, which is not compiled in under
582 SYSTEM_MALLOC. */
e5c9f94c
EZ
583 pmem = (double)((unsigned long) sbrk (0)) / ret_lim_data () * 100.0;
584 if (pmem > 100)
693a2698 585#endif
e5c9f94c
EZ
586 pmem = 100;
587 attrs = Fcons (Fcons (Qpmem, make_float (pmem)), attrs);
588 /* Pass 1: Count how much storage we need. */
589 for (i = 0; i < __crt0_argc; i++)
590 {
591 cmdline_size += strlen (__crt0_argv[i]) + 1; /* +1 for blank delim */
592 if (strpbrk (__crt0_argv[i], " \t\n\r\v\f"))
593 {
594 cmdline_size += 2;
595 for (p = __crt0_argv[i]; *p; p++)
596 {
597 if (*p == '"')
598 cmdline_size++;
599 }
600 }
601 }
602 /* Pass 2: Allocate storage and concatenate argv[]. */
603 cmdline = xmalloc (cmdline_size + 1);
604 for (i = 0, q = cmdline; i < __crt0_argc; i++)
605 {
606 if (strpbrk (__crt0_argv[i], " \t\n\r\v\f"))
607 {
608 *q++ = '"';
609 for (p = __crt0_argv[i]; *p; p++)
610 {
611 if (*p == '\"')
612 *q++ = '\\';
613 *q++ = *p;
614 }
615 *q++ = '"';
616 }
617 else
618 {
619 strcpy (q, __crt0_argv[i]);
620 q += strlen (__crt0_argv[i]);
621 }
622 *q++ = ' ';
623 }
624 /* Remove the trailing blank. */
625 if (q > cmdline)
626 q[-1] = '\0';
627
628 /* Command line is encoded in locale-coding-system; decode it. */
629 cmd_str = make_unibyte_string (cmdline, strlen (cmdline));
630 decoded_cmd = code_convert_string_norecord (cmd_str,
631 Vlocale_coding_system, 0);
632 xfree (cmdline);
633 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
634 }
635
636 return attrs;
637}
638\f
838a94b8
EZ
639void
640dos_cleanup (void)
641{
c06981c0
EZ
642 struct tty_display_info *tty;
643
838a94b8
EZ
644#ifndef HAVE_X_WINDOWS
645 restore_parent_vm_title ();
646#endif
6f855d64
EZ
647 /* Make sure the termscript file is committed, in case we are
648 crashing and some vital info was written there. */
c06981c0 649 if (FRAMEP (selected_frame))
6f855d64 650 {
c06981c0
EZ
651 struct frame *sf = XFRAME (selected_frame);
652
653 if (FRAME_LIVE_P (sf)
654 && (FRAME_MSDOS_P (sf) || FRAME_TERMCAP_P (sf)))
655 {
656 tty = CURTTY ();
657 if (tty->termscript)
658 {
659 fflush (tty->termscript);
660 fsync (fileno (tty->termscript));
661 }
662 }
6f855d64 663 }
838a94b8
EZ
664}
665
1b94449f
RS
666/*
667 * Define everything
668 */
3a8ce822
EZ
669void
670syms_of_dosfns (void)
1b94449f 671{
1b94449f 672 defsubr (&Sint86);
5f08dc78
KS
673 defsubr (&Sdos_memget);
674 defsubr (&Sdos_memput);
ac3b0279
RS
675 defsubr (&Smsdos_mouse_init);
676 defsubr (&Smsdos_mouse_enable);
5f08dc78
KS
677 defsubr (&Smsdos_set_keyboard);
678 defsubr (&Sinsert_startup_screen);
ac3b0279 679 defsubr (&Smsdos_mouse_disable);
76a76a57 680 defsubr (&Sfile_system_info);
87485d6f
MW
681#ifndef HAVE_X_WINDOWS
682 defsubr (&Smsdos_mouse_p);
87485d6f 683#endif
1b94449f 684
29208e82 685 DEFVAR_INT ("dos-country-code", dos_country_code,
7363986a
PJ
686 doc: /* The country code returned by Dos when Emacs was started.
687Usually this is the international telephone prefix. */);
1b94449f 688
29208e82 689 DEFVAR_INT ("dos-codepage", dos_codepage,
7363986a
PJ
690 doc: /* The codepage active when Emacs was started.
691The following are known:
692 437 United States
693 850 Multilingual (Latin I)
694 852 Slavic (Latin II)
695 857 Turkish
696 860 Portugal
697 861 Iceland
698 863 Canada (French)
699 865 Norway/Denmark */);
1b94449f 700
29208e82 701 DEFVAR_INT ("dos-timezone-offset", dos_timezone_offset,
7363986a
PJ
702 doc: /* The current timezone offset to UTC in minutes.
703Implicitly modified when the TZ variable is changed. */);
b058cb36 704
29208e82 705 DEFVAR_LISP ("dos-version", Vdos_version,
7363986a 706 doc: /* The (MAJOR . MINOR) Dos version (subject to modification with setver). */);
5f08dc78 707
838a94b8 708#ifndef HAVE_X_WINDOWS
29208e82 709 DEFVAR_LISP ("dos-windows-version", Vdos_windows_version,
7363986a 710 doc: /* The (MAJOR . MINOR) Windows version for DOS session on MS-Windows. */);
838a94b8
EZ
711#endif
712
29208e82 713 DEFVAR_LISP ("dos-display-scancodes", Vdos_display_scancodes,
7363986a
PJ
714 doc: /* *Controls whether DOS raw keyboard events are displayed as you type.
715When non-nil, the keyboard scan-codes are displayed at the bottom right
716corner of the display (typically at the end of the mode line).
717The output format is: scan code:char code*modifiers. */);
718
5f08dc78 719 Vdos_display_scancodes = Qnil;
b058cb36 720
29208e82 721 DEFVAR_INT ("dos-hyper-key", dos_hyper_key,
7363986a
PJ
722 doc: /* *If set to 1, use right ALT key as hyper key.
723If set to 2, use right CTRL key as hyper key. */);
5f08dc78 724 dos_hyper_key = 0;
b058cb36 725
29208e82 726 DEFVAR_INT ("dos-super-key", dos_super_key,
7363986a
PJ
727 doc: /* *If set to 1, use right ALT key as super key.
728If set to 2, use right CTRL key as super key. */);
5f08dc78 729 dos_super_key = 0;
b058cb36 730
29208e82 731 DEFVAR_INT ("dos-keypad-mode", dos_keypad_mode,
7363986a
PJ
732 doc: /* *Controls what key code is returned by a key in the numeric keypad.
733The `numlock ON' action is only taken if no modifier keys are pressed.
734The value is an integer constructed by adding the following bits together:
735
736 0x00 Digit key returns digit (if numlock ON)
737 0x01 Digit key returns kp-digit (if numlock ON)
738 0x02 Digit key returns M-digit (if numlock ON)
739 0x03 Digit key returns edit key (if numlock ON)
740
741 0x00 Grey key returns char (if numlock ON)
742 0x04 Grey key returns kp-key (if numlock ON)
743
744 0x00 Digit key returns digit (if numlock OFF)
745 0x10 Digit key returns kp-digit (if numlock OFF)
746 0x20 Digit key returns M-digit (if numlock OFF)
747 0x30 Digit key returns edit key (if numlock OFF)
748
749 0x00 Grey key returns char (if numlock OFF)
750 0x40 Grey key returns kp-key (if numlock OFF)
751
752 0x200 ALT-0..ALT-9 in top-row produces shifted codes. */);
b3d5621c 753 dos_keypad_mode = 0x75;
b058cb36 754
29208e82 755 DEFVAR_INT ("dos-keyboard-layout", dos_keyboard_layout,
7363986a
PJ
756 doc: /* Contains the country code for the current keyboard layout.
757Use msdos-set-keyboard to select another keyboard layout. */);
5f08dc78 758 dos_keyboard_layout = 1; /* US */
b058cb36 759
29208e82 760 DEFVAR_INT ("dos-decimal-point", dos_decimal_point,
7363986a
PJ
761 doc: /* The character to produce when kp-decimal key is pressed.
762If non-zero, this variable contains the character to be returned when the
763decimal point key in the numeric keypad is pressed when Num Lock is on.
764If zero, the decimal point key returns the country code specific value. */);
5f08dc78 765 dos_decimal_point = 0;
1b94449f
RS
766}
767#endif /* MSDOS */
6b61353c 768