Fix the MSDOS build.
[bpt/emacs.git] / src / msdos.c
index 5174bc4..010a0a3 100644 (file)
@@ -1,6 +1,6 @@
-/* MS-DOS specific C utilities.          -*- coding: raw-text -*-
+/* MS-DOS specific C utilities.          -*- coding: cp850 -*-
 
-Copyright (C) 1993-1997, 1999-2013 Free Software Foundation, Inc.
+Copyright (C) 1993-1997, 1999-2014 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -20,6 +20,13 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 /* Contributed by Morten Welinder */
 /* New display, keyboard, and mouse control by Kim F. Storm */
 
+/* Note: This file MUST use a unibyte encoding, to both display the
+   keys on the non-US keyboard layout as their respective labels, and
+   provide the correct byte values for the keyboard input to inject
+   into Emacs.  See 'struct dos_keyboard_map' below.  As long as there
+   are only European keyboard layouts here, we are OK with DOS
+   codepage 850 encoding.  */
+
 /* Note: some of the stuff here was taken from end of sysdep.c in demacs. */
 
 #include <config.h>
@@ -43,6 +50,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <unistd.h>     /* for chdir, dup, dup2, etc. */
 #include <dir.h>        /* for getdisk */
 #pragma pack(0)                 /* dir.h does a pack(4), which isn't GCC's default */
+#undef opendir
+#include <dirent.h>     /* for opendir */
 #include <fcntl.h>
 #include <io.h>                 /* for setmode */
 #include <dpmi.h>       /* for __dpmi_xxx stuff */
@@ -291,7 +300,7 @@ mouse_button_depressed (int b, int *xp, int *yp)
 }
 
 void
-mouse_get_pos (FRAME_PTR *f, int insist, Lisp_Object *bar_window,
+mouse_get_pos (struct frame **f, int insist, Lisp_Object *bar_window,
               enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
               Time *time)
 {
@@ -401,7 +410,7 @@ static int term_setup_done;
 
 static unsigned short outside_cursor;
 
-/* Similar to the_only_frame.  */
+/* The only display since MS-DOS does not support multiple ones.  */
 struct tty_display_info the_only_display_info;
 
 /* Support for DOS/V (allows Japanese characters to be displayed on
@@ -595,11 +604,7 @@ dos_set_window_size (int *rows, int *cols)
       Lisp_Object window = hlinfo->mouse_face_window;
 
       if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
-       {
-         hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
-         hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
-         hlinfo->mouse_face_window = Qnil;
-       }
+       reset_mouse_highlight (hlinfo);
     }
 
   /* Enable bright background colors.  */
@@ -943,9 +948,6 @@ IT_write_glyphs (struct frame *f, struct glyph *str, int str_len)
                          Mouse Highlight (and friends..)
  ************************************************************************/
 
-/* Last window where we saw the mouse.  Used by mouse-autoselect-window.  */
-static Lisp_Object last_mouse_window;
-
 static int mouse_preempted = 0;        /* non-zero when XMenu gobbles mouse events */
 
 int
@@ -1151,7 +1153,7 @@ IT_display_cursor (int on)
    to put the cursor at the end of the text displayed there.  */
 
 static void
-IT_cmgoto (FRAME_PTR f)
+IT_cmgoto (struct frame *f)
 {
   /* Only set the cursor to where it should be if the display is
      already in sync with the window contents.  */
@@ -1222,7 +1224,7 @@ IT_cmgoto (FRAME_PTR f)
 static void
 IT_update_begin (struct frame *f)
 {
-  struct tty_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
+  struct tty_display_info *display_info = FRAME_DISPLAY_INFO (f);
   Mouse_HLInfo *hlinfo = &display_info->mouse_highlight;
   struct frame *mouse_face_frame = hlinfo->mouse_face_mouse_frame;
 
@@ -1254,7 +1256,7 @@ IT_update_begin (struct frame *f)
          /* If the mouse highlight is in the window that was deleted
             (e.g., if it was popped by completion), clear highlight
             unconditionally.  */
-         if (NILP (w->buffer))
+         if (NILP (w->contents))
            hlinfo->mouse_face_window = Qnil;
          else
            {
@@ -1264,19 +1266,14 @@ IT_update_begin (struct frame *f)
                  break;
            }
 
-         if (NILP (w->buffer) || i < w->desired_matrix->nrows)
+         if (NILP (w->contents) || i < w->desired_matrix->nrows)
            clear_mouse_face (hlinfo);
        }
     }
   else if (mouse_face_frame && !FRAME_LIVE_P (mouse_face_frame))
-    {
-      /* If the frame with mouse highlight was deleted, invalidate the
-        highlight info.  */
-      hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
-      hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
-      hlinfo->mouse_face_window = Qnil;
-      hlinfo->mouse_face_mouse_frame = NULL;
-    }
+    /* If the frame with mouse highlight was deleted, invalidate the
+       highlight info.  */
+    reset_mouse_highlight (hlinfo);
 
   unblock_input ();
 }
@@ -1284,7 +1281,7 @@ IT_update_begin (struct frame *f)
 static void
 IT_update_end (struct frame *f)
 {
-  struct tty_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct tty_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
 
   if (dpyinfo->termscript)
     fprintf (dpyinfo->termscript, "\n<UPDATE_END\n");
@@ -1314,7 +1311,7 @@ IT_frame_up_to_date (struct frame *f)
     new_cursor = frame_desired_cursor;
   else
     {
-      struct buffer *b = XBUFFER (sw->buffer);
+      struct buffer *b = XBUFFER (sw->contents);
 
       if (EQ (BVAR (b,cursor_type), Qt))
        new_cursor = frame_desired_cursor;
@@ -1384,13 +1381,6 @@ IT_delete_glyphs (struct frame *f, int n)
   emacs_abort ();
 }
 
-/* set-window-configuration on window.c needs this.  */
-void
-x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
-{
-  set_menu_bar_lines (f, value, oldval);
-}
-
 /* This was copied from xfaces.c  */
 
 extern Lisp_Object Qbackground_color;
@@ -1548,11 +1538,6 @@ IT_reset_terminal_modes (struct terminal *term)
   term_setup_done = 0;
 }
 
-static void
-IT_set_terminal_window (struct frame *f, int foo)
-{
-}
-
 /* Remember the screen colors of the current frame, to serve as the
    default colors for newly-created frames.  */
 DEFUN ("msdos-remember-default-colors", Fmsdos_remember_default_colors,
@@ -1753,7 +1738,7 @@ IT_set_frame_parameters (struct frame *f, Lisp_Object alist)
     }
 }
 
-extern void init_frame_faces (FRAME_PTR);
+extern void init_frame_faces (struct frame *);
 
 #endif /* !HAVE_X_WINDOWS */
 
@@ -1836,17 +1821,8 @@ internal_terminal_init (void)
          if (colors[1] >= 0 && colors[1] < 16)
            FRAME_BACKGROUND_PIXEL (SELECTED_FRAME ()) = colors[1];
        }
-      the_only_display_info.mouse_highlight.mouse_face_mouse_frame = NULL;
-      the_only_display_info.mouse_highlight.mouse_face_beg_row =
-       the_only_display_info.mouse_highlight.mouse_face_beg_col = -1;
-      the_only_display_info.mouse_highlight.mouse_face_end_row =
-       the_only_display_info.mouse_highlight.mouse_face_end_col = -1;
-      the_only_display_info.mouse_highlight.mouse_face_face_id = DEFAULT_FACE_ID;
-      the_only_display_info.mouse_highlight.mouse_face_window = Qnil;
-      the_only_display_info.mouse_highlight.mouse_face_mouse_x =
-       the_only_display_info.mouse_highlight.mouse_face_mouse_y = 0;
-      the_only_display_info.mouse_highlight.mouse_face_defer = 0;
-      the_only_display_info.mouse_highlight.mouse_face_hidden = 0;
+
+      reset_mouse_highlight (&the_only_display_info.mouse_highlight);
 
       if (have_mouse)  /* detected in dos_ttraw, which see */
        {
@@ -1882,7 +1858,7 @@ initialize_msdos_display (struct terminal *term)
   term->ring_bell_hook = IT_ring_bell;
   term->reset_terminal_modes_hook = IT_reset_terminal_modes;
   term->set_terminal_modes_hook = IT_set_terminal_modes;
-  term->set_terminal_window_hook = IT_set_terminal_window;
+  term->set_terminal_window_hook = NULL;
   term->update_begin_hook = IT_update_begin;
   term->update_end_hook = IT_update_end;
   term->frame_up_to_date_hook = IT_frame_up_to_date;
@@ -1909,18 +1885,6 @@ dos_get_saved_screen (char **screen, int *rows, int *cols)
 #endif
 }
 
-#ifndef HAVE_X_WINDOWS
-
-/* We are not X, but we can emulate it well enough for our needs... */
-void
-check_x (void)
-{
-  if (! FRAME_MSDOS_P (SELECTED_FRAME ()))
-    error ("Not running under a window system");
-}
-
-#endif
-
 \f
 /* ----------------------- Keyboard control ----------------------
  *
@@ -1965,10 +1929,10 @@ struct dos_keyboard_map
 
 static struct dos_keyboard_map us_keyboard = {
 /* 0         1         2         3         4         5      */
-/* 01234567890123456789012345678901234567890 12345678901234 */
-  "`1234567890-=  qwertyuiop[]   asdfghjkl;'\\   zxcvbnm,./  ",
+/* 01234567890123456789012345678901234567890 123 45678901234 */
+  "`1234567890-=  qwertyuiop[]   asdfghjkl;'\\  \\zxcvbnm,./  ",
 /* 0123456789012345678901234567890123456789 012345678901234 */
-  "~!@#$%^&*()_+  QWERTYUIOP{}   ASDFGHJKL:\"|   ZXCVBNM<>?  ",
+  "~!@#$%^&*()_+  QWERTYUIOP{}   ASDFGHJKL:\"|  |ZXCVBNM<>?  ",
   0,                           /* no Alt-Gr key */
   0                            /* no translate table */
 };
@@ -1976,9 +1940,9 @@ static struct dos_keyboard_map us_keyboard = {
 static struct dos_keyboard_map fr_keyboard = {
 /* 0         1         2         3         4         5      */
 /* 012 3456789012345678901234567890123456789012345678901234 */
-  "ý&\82\",(-\8a_\80\85)=  azertyuiop^$   qsdfghjklm\97*   wxcvbnm;:!  ",
+  "ý&\82\"'(-\8a_\80\85)=  azertyuiop^$   qsdfghjklm\97*  <wxcvbn,;:!  ",
 /* 0123456789012345678901234567890123456789012345678901234 */
-  " 1234567890ø+  AZERTYUIOPù\9c   QSDFGHJKLM%æ   WXCVBN?./õ  ",
+  " 1234567890ø+  AZERTYUIOPù\9c   QSDFGHJKLM%æ  >WXCVBN?./õ  ",
 /* 01234567 89012345678901234567890123456789012345678901234 */
   "  ~#{[|`\\^@]}             Ï                              ",
   0                            /* no translate table */
@@ -2000,9 +1964,9 @@ static struct kbd_translate it_kbd_translate_table[] = {
 static struct dos_keyboard_map it_keyboard = {
 /* 0          1         2         3         4         5     */
 /* 0 123456789012345678901234567890123456789012345678901234 */
-  "\\1234567890'\8d< qwertyuiop\8a+>  asdfghjkl\95\85\97   zxcvbnm,.-  ",
+  "\\1234567890'\8d< qwertyuiop\8a+>  asdfghjkl\95\85\97  <zxcvbnm,.-  ",
 /* 01 23456789012345678901234567890123456789012345678901234 */
-  "|!\"\9c$%&/()=?^> QWERTYUIOP\82*   ASDFGHJKL\87øõ   ZXCVBNM;:_  ",
+  "|!\"\9c$%&/()=?^> QWERTYUIOP\82*   ASDFGHJKL\87øõ  >ZXCVBNM;:_  ",
 /* 0123456789012345678901234567890123456789012345678901234 */
   "        {}~`             []             @#               ",
   it_kbd_translate_table
@@ -2011,9 +1975,9 @@ static struct dos_keyboard_map it_keyboard = {
 static struct dos_keyboard_map dk_keyboard = {
 /* 0         1         2         3         4         5      */
 /* 0123456789012345678901234567890123456789012345678901234 */
-  "«1234567890+|  qwertyuiop\86~   asdfghjkl\91\9b'   zxcvbnm,.-  ",
+  "«1234567890+|  qwertyuiop\86~   asdfghjkl\91\9b'  <zxcvbnm,.-  ",
 /* 01 23456789012345678901234567890123456789012345678901234 */
-  "õ!\"#$%&/()=?`  QWERTYUIOP\8f^   ASDFGHJKL\92\9d*   ZXCVBNM;:_  ",
+  "õ!\"#$%&/()=?`  QWERTYUIOP\8f^   ASDFGHJKL\92\9d*  >ZXCVBNM;:_  ",
 /* 0123456789012345678901234567890123456789012345678901234 */
   "  @\9c$  {[]} |                                             ",
   0                            /* no translate table */
@@ -2684,10 +2648,10 @@ dos_rawgetc (void)
          /* Generate SELECT_WINDOW_EVENTs when needed.  */
          if (!NILP (Vmouse_autoselect_window))
            {
-             mouse_window = window_from_coordinates (SELECTED_FRAME (),
-                                                     mouse_last_x,
-                                                     mouse_last_y,
-                                                     0, 0);
+             static Lisp_Object last_mouse_window;
+
+             mouse_window = window_from_coordinates
+               (SELECTED_FRAME (), mouse_last_x, mouse_last_y, 0, 0);
              /* A window will be selected only when it is not
                 selected now, and the last mouse movement event was
                 not in it.  A minibuffer window will be selected iff
@@ -2702,10 +2666,9 @@ dos_rawgetc (void)
                  event.timestamp = event_timestamp ();
                  kbd_buffer_store_event (&event);
                }
+             /* Remember the last window where we saw the mouse.  */
              last_mouse_window = mouse_window;
            }
-         else
-           last_mouse_window = Qnil;
 
          previous_help_echo_string = help_echo_string;
          help_echo_string = help_echo_object = help_echo_window = Qnil;
@@ -2976,11 +2939,6 @@ IT_menu_display (XMenu *menu, int y, int x, int pn, int *faces, int disp_help)
 \f
 /* --------------------------- X Menu emulation ---------------------- */
 
-/* Report availability of menus.  */
-
-int
-have_menus_p (void) {  return 1; }
-
 /* Create a brand new menu structure.  */
 
 XMenu *
@@ -3281,10 +3239,10 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
      erasing it works correctly...  */
   if (! NILP (saved_echo_area_message))
     message_with_string ("%s", saved_echo_area_message, 0);
-  message (0);
+  message1 (0);
   while (statecount--)
     xfree (state[statecount].screen_behind);
-  IT_display_cursor (1);       /* turn cursor back on */
+  IT_display_cursor (1);       /* Turn cursor back on.  */
   /* Clean up any mouse events that are waiting inside Emacs event queue.
      These events are likely to be generated before the menu was even
      displayed, probably because the user pressed and released the button
@@ -3318,18 +3276,6 @@ XMenuDestroy (Display *foo, XMenu *menu)
   xfree (menu);
   menu_help_message = prev_menu_help_message = NULL;
 }
-
-int
-x_pixel_width (struct frame *f)
-{
-  return FRAME_COLS (f);
-}
-
-int
-x_pixel_height (struct frame *f)
-{
-  return FRAME_LINES (f);
-}
 #endif /* !HAVE_X_WINDOWS */
 \f
 /* ----------------------- DOS / UNIX conversion --------------------- */
@@ -3919,6 +3865,9 @@ int setpgid (int pid, int pgid) { return 0; }
 int setpriority (int x, int y, int z) { return 0; }
 pid_t setsid (void) { return 0; }
 
+\f
+/* Gnulib support and emulation.  */
+
 #if __DJGPP__ == 2 && __DJGPP_MINOR__ < 4
 ssize_t
 readlink (const char *name, char *dummy1, size_t dummy2)
@@ -3930,6 +3879,38 @@ readlink (const char *name, char *dummy1, size_t dummy2)
 }
 #endif
 
+/* dir_pathname is set by sys_opendir and used in readlinkat and in
+   fstatat, when they get a special FD of zero, which means use the
+   last directory opened by opendir.  */
+static char dir_pathname[MAXPATHLEN];
+DIR *
+sys_opendir (const char *dirname)
+{
+  _fixpath (dirname, dir_pathname);
+  return opendir (dirname);
+}
+
+ssize_t
+readlinkat (int fd, char const *name, char *buffer, size_t buffer_size)
+{
+  /* Rely on a hack: an open directory is modeled as file descriptor 0,
+     as in fstatat.  FIXME: Add proper support for readlinkat.  */
+  char fullname[MAXPATHLEN];
+
+  if (fd != AT_FDCWD)
+    {
+      if (strlen (dir_pathname) + strlen (name) + 1 >= MAXPATHLEN)
+       {
+         errno = ENAMETOOLONG;
+         return -1;
+       }
+      sprintf (fullname, "%s/%s", dir_pathname, name);
+      name = fullname;
+    }
+
+  return readlink (name, buffer, buffer_size);
+}
+
 char *
 careadlinkat (int fd, char const *filename,
               char *buffer, size_t buffer_size,
@@ -3957,13 +3938,81 @@ careadlinkat (int fd, char const *filename,
   return buffer;
 }
 
-ssize_t
-careadlinkatcwd (int fd, char const *filename, char *buffer,
-                 size_t buffer_size)
+/* Emulate faccessat(2).  */
+int
+faccessat (int dirfd, const char * path, int mode, int flags)
+{
+  /* We silently ignore FLAGS.  */
+  flags = flags;
+
+  if (dirfd != AT_FDCWD
+      && !(IS_DIRECTORY_SEP (path[0])
+          || IS_DEVICE_SEP (path[1])))
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  return access (path, mode);
+}
+
+/* Emulate fstatat.  */
+int
+fstatat (int fd, char const *name, struct stat *st, int flags)
+{
+  /* Rely on a hack: an open directory is modeled as file descriptor 0.
+     This is good enough for the current usage in Emacs, but is fragile.
+
+     FIXME: Add proper support for fdopendir, fstatat, readlinkat.
+     Gnulib does this and can serve as a model.  */
+  char fullname[MAXPATHLEN];
+
+  flags = flags;
+
+  if (fd != AT_FDCWD)
+    {
+      char lastc = dir_pathname[strlen (dir_pathname) - 1];
+
+      if (strlen (dir_pathname) + strlen (name) + IS_DIRECTORY_SEP (lastc)
+         >= MAXPATHLEN)
+       {
+         errno = ENAMETOOLONG;
+         return -1;
+       }
+
+      sprintf (fullname, "%s%s%s",
+              dir_pathname, IS_DIRECTORY_SEP (lastc) ? "" : "/", name);
+      name = fullname;
+    }
+
+#if __DJGPP__ > 2 || __DJGPP_MINOR__ > 3
+  return (flags & AT_SYMLINK_NOFOLLOW) ? lstat (name, st) : stat (name, st);
+#else
+  return stat (name, st);
+#endif
+}
+
+#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 4
+/* Emulate the Posix unsetenv.  DJGPP v2.04 has this in the library.  */
+int
+unsetenv (const char *name)
 {
-  (void) fd;
-  return readlink (filename, buffer, buffer_size);
+  char *var;
+  size_t name_len;
+  int retval;
+
+  if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  /* DJGPP's 'putenv' deletes the entry if it doesn't include '='.  */
+  putenv (name);
+
+  return 0;
 }
+#endif
 
 \f
 #if __DJGPP__ == 2 && __DJGPP_MINOR__ < 2
@@ -4090,8 +4139,8 @@ dos_yield_time_slice (void)
 /* We don't have to call timer_check here
    because wait_reading_process_output takes care of that.  */
 int
-sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
-           EMACS_TIME *timeout, void *ignored)
+sys_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds,
+           struct timespec *timeout, void *ignored)
 {
   int check_input;
   struct timespec t;
@@ -4121,20 +4170,20 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
     }
   else
     {
-      EMACS_TIME clnow, cllast, cldiff;
+      struct timespec clnow, cllast, cldiff;
 
       gettime (&t);
-      cllast = make_emacs_time (t.tv_sec, t.tv_nsec);
+      cllast = make_timespec (t.tv_sec, t.tv_nsec);
 
       while (!check_input || !detect_input_pending ())
        {
          gettime (&t);
-         clnow = make_emacs_time (t.tv_sec, t.tv_nsec);
-         cldiff = sub_emacs_time (clnow, cllast);
-         *timeout = sub_emacs_time (*timeout, cldiff);
+         clnow = make_timespec (t.tv_sec, t.tv_nsec);
+         cldiff = timespec_sub (clnow, cllast);
+         *timeout = timespec_sub (*timeout, cldiff);
 
          /* Stop when timeout value crosses zero.  */
-         if (EMACS_TIME_SIGN (*timeout) <= 0)
+         if (timespec_sign (*timeout) <= 0)
            return 0;
          cllast = clnow;
          dos_yield_time_slice ();