]> code.delx.au - gnu-emacs/blobdiff - src/msdos.c
(have_menus_p): Renamed from using_x_p.
[gnu-emacs] / src / msdos.c
index a05149eea333299fefae99e5e8b9b3881a92c33f..a8435d6ec267687f2269fd2ab85cc481ef77d7c7 100644 (file)
@@ -223,7 +223,7 @@ mouse_init ()
   mouse_moveto (0, 0);
   mouse_visible = 0;
 }
-
+\f
 /* ------------------------- Screen control ----------------------
  *
  */
@@ -249,6 +249,7 @@ static int startup_screen_size_X;
 static int startup_screen_size_Y;
 static int startup_pos_X;
 static int startup_pos_Y;
+static unsigned char startup_screen_attrib;
 
 static int term_setup_done;
 
@@ -554,12 +555,14 @@ IT_set_terminal_modes (void)
   
   startup_screen_size_X = screen_size_X;
   startup_screen_size_Y = screen_size_Y;
+  startup_screen_attrib = ScreenAttrib;
 
   ScreenGetCursor (&startup_pos_Y, &startup_pos_X);
   ScreenRetrieve (startup_screen_buffer = xmalloc (screen_size * 2));
 
   if (termscript)
-    fprintf (termscript, "<SCREEN SAVED>\n");
+    fprintf (termscript, "<SCREEN SAVED (dimensions=%dx%d)>\n",
+             screen_size_X, screen_size_Y);
 }
 
 /*
@@ -570,6 +573,15 @@ IT_set_terminal_modes (void)
 static
 IT_reset_terminal_modes (void)
 {
+  int display_row_start = (int) ScreenPrimary;
+  int saved_row_len     = startup_screen_size_X * 2;
+  int update_row_len    = ScreenCols () * 2;
+  int current_rows      = ScreenRows ();
+  int to_next_row       = update_row_len;
+  unsigned char *saved_row = startup_screen_buffer;
+  int cursor_pos_X = ScreenCols () - 1;
+  int cursor_pos_Y = ScreenRows () - 1;
+
   if (termscript)
     fprintf (termscript, "\n<RESET_TERM>");
 
@@ -578,12 +590,45 @@ IT_reset_terminal_modes (void)
   if (!term_setup_done)
     return;
   
-  ScreenUpdate (startup_screen_buffer);
-  ScreenSetCursor (startup_pos_Y, startup_pos_X);
-  xfree (startup_screen_buffer);
+  mouse_off ();
+  /* We have a situation here.
+     We cannot just do ScreenUpdate(startup_screen_buffer) because
+     the luser could have changed screen dimensions inside Emacs
+     and failed (or didn't want) to restore them before killing
+     Emacs.  ScreenUpdate() uses the *current* screen dimensions and
+     thus will happily use memory outside what was allocated for
+     `startup_screen_buffer'.
+     Thus we only restore as much as the current screen dimensions
+     can hold, and clear the rest (if the saved screen is smaller than
+     the current) with the color attribute saved at startup.  The cursor
+     is also restored within the visible dimensions.  */
+
+  ScreenAttrib = startup_screen_attrib;
+  ScreenClear ();
+
+  if (update_row_len > saved_row_len)
+    update_row_len = saved_row_len;
+  if (current_rows > startup_screen_size_Y)
+    current_rows = startup_screen_size_Y;
 
   if (termscript)
-    fprintf (termscript, "<SCREEN RESTORED>\n");
+    fprintf (termscript, "<SCREEN RESTORED (dimensions=%dx%d)>\n",
+             update_row_len / 2, current_rows);
+
+  while (current_rows--)
+    {
+      dosmemput (saved_row, update_row_len, display_row_start);
+      saved_row         += saved_row_len;
+      display_row_start += to_next_row;
+    }
+  if (startup_pos_X < cursor_pos_X)
+    cursor_pos_X = startup_pos_X;
+  if (startup_pos_Y < cursor_pos_Y)
+    cursor_pos_Y = startup_pos_Y;
+
+  ScreenSetCursor (cursor_pos_Y, cursor_pos_X);
+  xfree (startup_screen_buffer);
 
   term_setup_done = 0;
 }
@@ -731,8 +776,6 @@ dos_get_saved_screen (screen, rows, cols)
   return 0;
 #endif  
 }
-
-
 \f
 /* ----------------------- Keyboard control ----------------------
  *
@@ -1574,9 +1617,17 @@ IT_menu_display (XMenu *menu, int y, int x, int *faces)
   IT_cursor_to (row, col);
   xfree (text);
 }
-
+\f
 /* --------------------------- X Menu emulation ---------------------- */
 
+/* Report availability of menus.  */
+
+int
+have_menus_p ()
+{
+  return 1;
+}
+
 /* Create a brand new menu structure.  */
 
 XMenu *
@@ -1634,11 +1685,7 @@ void
 XMenuLocate (Display *foo0, XMenu *menu, int foo1, int foo2, int x, int y,
             int *ulx, int *uly, int *width, int *height)
 {
-  if (menu->count == 1 && menu->submenu[0])
-      /* Special case: the menu consists of only one pane.  */
-    IT_menu_calc_size (menu->submenu[0], width, height);
-  else
-    IT_menu_calc_size (menu, width, height);
+  IT_menu_calc_size (menu, width, height);
   *ulx = x + 1;
   *uly = y;
   *width += 2;
@@ -1665,6 +1712,7 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
   int screensize;
   int faces[4], selectface;
   int leave, result, onepane;
+  int title_faces[4];          /* face to display the menu title */
 
   /* Just in case we got here without a mouse present...  */
   if (have_mouse <= 0)
@@ -1689,10 +1737,17 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
   faces[2] = compute_glyph_face (&the_only_frame, selectface, faces[0]);
   faces[3] = compute_glyph_face (&the_only_frame, selectface, faces[1]);
 
+  /* Make sure the menu title is always displayed with
+     `msdos-menu-active-face', no matter where the mouse pointer is.  */
+  for (i = 0; i < 4; i++)
+    title_faces[i] = faces[3];
+
   statecount = 1;
   state[0].menu = menu;
   mouse_off ();
   ScreenRetrieve (state[0].screen_behind = xmalloc (screensize));
+
+  IT_menu_display (menu, y0 - 1, x0 - 1, title_faces); /* display menu title */
   if ((onepane = menu->count == 1 && menu->submenu[0]))
     {
       menu->width = menu->submenu[0]->width;
@@ -1810,8 +1865,7 @@ x_pixel_height (struct frame *f)
   return FRAME_HEIGHT (f);
 }
 #endif /* !HAVE_X_WINDOWS */
-
-
+\f
 /* ----------------------- DOS / UNIX conversion --------------------- */
 
 /* Destructively turn backslashes into slashes.  */
@@ -2153,12 +2207,13 @@ dos_ttcooked ()
 
 \f
 /* Run command as specified by ARGV in directory DIR.
-   The command is run with input from TEMPIN and output to file TEMPOUT.  */
+   The command is run with input from TEMPIN, output to
+   file TEMPOUT and stderr to TEMPERR.  */
 int
-run_msdos_command (argv, dir, tempin, tempout)
+run_msdos_command (argv, dir, tempin, tempout, temperr)
      unsigned char **argv;
      Lisp_Object dir;
-     int tempin, tempout;
+     int tempin, tempout, temperr;
 {
   char *saveargv1, *saveargv2, **envv;
   char oldwd[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS.  */
@@ -2229,7 +2284,7 @@ run_msdos_command (argv, dir, tempin, tempout)
   
   dup2 (tempin, 0);
   dup2 (tempout, 1);
-  dup2 (tempout, 2);
+  dup2 (temperr, 2);
 
   result = spawnve (P_WAIT, argv[0], argv, envv);
   
@@ -2264,8 +2319,7 @@ croak (badfunc)
   reset_sys_modes ();
   exit (1);
 }
-
-
+\f
 /* ------------------------- Compatibility functions -------------------
  *     gethostname
  *     gettimeofday
@@ -2343,66 +2397,66 @@ setpriority (x,y,z) int x,y,z; { return 0; }
 sigsetmask (x) int x; { return 0; }
 unrequest_sigio () {}
 
-int run_dos_timer_hooks = 0;
-
 #ifndef HAVE_SELECT
 #include "sysselect.h"
 
-static int last_ti_sec = -1;
-static int dos_menubar_clock_displayed = 0;
+static struct time last_time  = {120, 120, 120, 120};
+static int modeline_time_displayed = 0;
+
+Lisp_Object Vdos_display_time;
 
 static void
 check_timer (t)
   struct time *t;
 {
+  int sec, min, hour, hund;
+
   gettime (t);
-  
-  if (t->ti_sec == last_ti_sec)
+  sec  = t->ti_sec;
+  hund = t->ti_hund;
+  hour = t->ti_hour;
+  min  = t->ti_min;
+
+  /* Any chance of not getting here 24 hours or more since last time? */
+  if (hour == last_time.ti_hour
+      && min == last_time.ti_min
+      && sec == last_time.ti_sec)
     return;
-  last_ti_sec = t->ti_sec;
 
-  if (!NILP (Vdos_menubar_clock))
+  if (!NILP (Vdos_display_time))
     {
-      char clock_str[16];
-      int len;
-      int min = t->ti_min;
-      int hour = t->ti_hour;
-
-      if (dos_timezone_offset)
-       {
-         int tz = dos_timezone_offset;
-         min -= tz % 60;
-         if (min < 0)
-           min += 60, hour--;
-         else
-           if (min >= 60)
-             min -= 60, hour++;
-         
-         if ((hour -= (tz / 60)) < 0)
-           hour += 24;
-         else
-           hour %= 24;
-       }
-      
-      if ((dos_country_info[0x11] & 0x01) == 0) /* 12 hour clock */
-       {
-         hour %= 12;
-         if (hour == 0) hour = 12;
-       }
-
-      len = sprintf (clock_str, "%2d.%02d.%02d", hour, min, t->ti_sec);
-      dos_direct_output (0, screen_size_X - len - 1, clock_str, len);
-      dos_menubar_clock_displayed = 1;
+      int interval;
+      Lisp_Object dti = XSYMBOL (Fintern_soft (build_string ("display-time-interval"), Qnil))->value;
+      int delta_time  = ((hour - last_time.ti_hour) * 3600
+                        + (min  - last_time.ti_min) * 60
+                        + (sec  - last_time.ti_sec));
+
+      /* Who knows what the user may put into `display-time-interval'?  */
+      if (!INTEGERP (dti) || (interval = XINT (dti)) <= 0)
+       interval = 60;
+
+      /* When it's time to renew the display, fake a `wakeup' call.  */
+      if (!modeline_time_displayed     /* first time */
+         || delta_time >= interval     /* or if we were busy for a long time */
+         || interval == 1              /* and every `interval' seconds hence */
+         || interval == 60 && sec == 0 /* (usual cases first) */
+         || (hour * 3600 + min * 60 + sec) % interval == 0)
+       call2 (intern ("display-time-filter"), Qnil,
+              build_string ("Wake up!\n"));
+
+      modeline_time_displayed = 1;
     }
-  else if (dos_menubar_clock_displayed)
+  else if (modeline_time_displayed)
     {
-      /* Erase last displayed time.  */
-      dos_direct_output (0, screen_size_X - 9, "        ", 8);
-      dos_menubar_clock_displayed = 0;
+      modeline_time_displayed = 0;
+      Fset (intern ("display-time-string"), build_string (""));
+
+      /* Force immediate redisplay of modelines.  */
+      update_mode_lines++;
+      redisplay_preserve_echo_area ();
     }
   
-  if (!NILP (Vdos_timer_hooks))
-    run_dos_timer_hooks++;
+  last_time  = *t;
 }
 
 /* Only event queue is checked.  */
@@ -2540,6 +2594,15 @@ dos_abort (file, line)
   ScreenSetCursor (2, 0);
   abort ();
 }
+#else
+void
+abort ()
+{
+  dos_ttcooked ();
+  ScreenSetCursor (10, 0);
+  cputs ("\r\n\nEmacs aborted!\r\n");
+  exit (2);
+}
 #endif
 
 syms_of_msdos ()
@@ -2548,6 +2611,10 @@ syms_of_msdos ()
   staticpro (&recent_doskeys);
 
   defsubr (&Srecent_doskeys);
+
+  DEFVAR_LISP ("dos-display-time", &Vdos_display_time,
+    "*When non-nil, `display-time' is in effect on DOS systems.");
+  Vdos_display_time = Qnil;
 }
 
 #endif /* MSDOS */