root/src/dosfns.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. DEFUN
  2. DEFUN
  3. DEFUN
  4. DEFUN
  5. DEFUN
  6. restore_parent_vm_title
  7. init_dosfns
  8. msdos_stdcolor_idx
  9. msdos_stdcolor_name
  10. ms_windows_version
  11. w95_set_virtual_machine_title
  12. x_set_title
  13. DEFUN
  14. list_system_processes
  15. system_process_attributes
  16. dos_memory_info
  17. dos_cleanup
  18. syms_of_dosfns

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

/* [<][>][^][v][top][bottom][index][help] */