XEmacs 21.4.17 "Jumbo Shrimp".
[chise/xemacs-chise.git.1] / src / frame-x.c
index 2aa7d59..780367d 100644 (file)
@@ -23,6 +23,8 @@ Boston, MA 02111-1307, USA.  */
 
 /* Substantially rewritten for XEmacs.  */
 
+/* 7-8-00 !!#### This file needs definite Mule review. */
+
 #include <config.h>
 #include "lisp.h"
 
@@ -50,6 +52,7 @@ Boston, MA 02111-1307, USA.  */
 #include "faces.h"
 #include "frame.h"
 #include "window.h"
+#include "gutter.h"
 
 #ifdef HAVE_DRAGNDROP
 #include "dragdrop.h"
@@ -103,19 +106,34 @@ x_window_to_frame (struct device *d, Window wdesc)
 struct frame *
 x_any_window_to_frame (struct device *d, Window wdesc)
 {
-  Lisp_Object tail, frame;
-  struct frame *f;
-
+  Widget w;
   assert (DEVICE_X_P (d));
 
+  w = XtWindowToWidget (DEVICE_X_DISPLAY (d), wdesc);
+
+  if (!w)
+    return 0;
+
+  /* We used to map over all frames here and then map over all widgets
+     belonging to that frame. However it turns out that this was very fragile
+     as it requires our display structures to be in sync _and_ that the
+     loop is told about every new widget somebody adds. Therefore we
+     now let Xt find it for us (which does a bottom-up search which
+     could even be faster) */
+  return  x_any_widget_or_parent_to_frame (d, w);
+}
+
+static struct frame *
+x_find_frame_for_window (struct device *d, Window wdesc)
+{
+  Lisp_Object tail, frame;
+  struct frame *f;
   /* This function was previously written to accept only a window argument
      (and to loop over all devices looking for a matching window), but
      that is incorrect because window ID's are not unique across displays. */
 
   for (tail = DEVICE_FRAME_LIST (d); CONSP (tail); tail = XCDR (tail))
     {
-      int i;
-
       frame = XCAR (tail);
       f = XFRAME (frame);
       /* This frame matches if the window is any of its widgets. */
@@ -138,18 +156,18 @@ x_any_window_to_frame (struct device *d, Window wdesc)
         would incorrectly get sucked away by Emacs if this function matched
         on psheet widgets. */
 
-      for (i = 0; i < FRAME_X_NUM_TOP_WIDGETS (f); i++)
-       {
-         Widget wid = FRAME_X_TOP_WIDGETS (f)[i];
-         if (wid && XtIsManaged (wid) && wdesc == XtWindow (wid))
-           return f;
-       }
-
-#ifdef HAVE_SCROLLBARS
-      /* Match if the window is one of this frame's scrollbars. */
-      if (x_window_is_scrollbar (f, wdesc))
-       return f;
-#endif
+      /* Note: that this called only from
+         x_any_widget_or_parent_to_frame it is unnecessary to iterate
+         over the top level widgets. */
+
+      /* Note:  we use to special case scrollbars but this turns out to be a bad idea
+         because
+         1. We sometimes get events for _unmapped_ scrollbars and our
+         callers don't want us to fail.
+         2. Starting with the 21.2 widget stuff there are now loads of
+         widgets to check and it is easy to forget adding them in a loop here.
+         See x_any_window_to_frame
+         3. We pick up all widgets now anyway. */
     }
 
   return 0;
@@ -160,7 +178,7 @@ x_any_widget_or_parent_to_frame (struct device *d, Widget widget)
 {
   while (widget)
     {
-      struct frame *f = x_any_window_to_frame (d, XtWindow (widget));
+      struct frame *f = x_find_frame_for_window (d, XtWindow (widget));
       if (f)
        return f;
       widget = XtParent (widget);
@@ -192,14 +210,14 @@ decode_x_frame (Lisp_Object frame)
 void
 x_wm_mark_shell_size_user_specified (Widget wmshell)
 {
-  if (! XtIsWMShell (wmshell)) abort ();
+  if (! XtIsWMShell (wmshell)) ABORT ();
   EmacsShellSetSizeUserSpecified (wmshell);
 }
 
 void
 x_wm_mark_shell_position_user_specified (Widget wmshell)
 {
-  if (! XtIsWMShell (wmshell)) abort ();
+  if (! XtIsWMShell (wmshell)) ABORT ();
   EmacsShellSetPositionUserSpecified (wmshell);
 }
 
@@ -208,7 +226,7 @@ x_wm_mark_shell_position_user_specified (Widget wmshell)
 void
 x_wm_set_shell_iconic_p (Widget shell, int iconic_p)
 {
-  if (! XtIsWMShell (shell)) abort ();
+  if (! XtIsWMShell (shell)) ABORT ();
 
   /* Because of questionable logic in Shell.c, this sequence can't work:
 
@@ -238,9 +256,9 @@ x_wm_set_cell_size (Widget wmshell, int cw, int ch)
   Arg al [2];
 
   if (!XtIsWMShell (wmshell))
-    abort ();
+    ABORT ();
   if (cw <= 0 || ch <= 0)
-    abort ();
+    ABORT ();
 
   XtSetArg (al [0], XtNwidthInc,  cw);
   XtSetArg (al [1], XtNheightInc, ch);
@@ -253,7 +271,7 @@ x_wm_set_variable_size (Widget wmshell, int width, int height)
   Arg al [2];
 
   if (!XtIsWMShell (wmshell))
-    abort ();
+    ABORT ();
 #ifdef DEBUG_GEOMETRY_MANAGEMENT
   /* See comment in EmacsShell.c */
   printf ("x_wm_set_variable_size: %d %d\n", width, height);
@@ -320,7 +338,7 @@ x_wm_store_class_hints (Widget shell, char *frame_name)
   XClassHint classhint;
 
   if (!XtIsWMShell (shell))
-    abort ();
+    ABORT ();
 
   XtGetApplicationNameAndClass (dpy, &app_name, &app_class);
   classhint.res_name = frame_name;
@@ -336,7 +354,7 @@ x_wm_maybe_store_wm_command (struct frame *f)
   struct device *d = XDEVICE (FRAME_DEVICE (f));
 
   if (!XtIsWMShell (w))
-    abort ();
+    ABORT ();
 
   if (NILP (DEVICE_X_WM_COMMAND_FRAME (d)))
     {
@@ -421,9 +439,9 @@ static void
 init_x_prop_symbols (void)
 {
 #define def(sym, rsrc) \
-   pure_put (sym, Qx_resource_name, build_string (rsrc))
+   Fput (sym, Qx_resource_name, build_string (rsrc))
 #define defi(sym,rsrc) \
-   def (sym, rsrc); pure_put (sym, Qintegerp, Qt)
+   def (sym, rsrc); Fput (sym, Qintegerp, Qt)
 
 #if 0 /* this interferes with things. #### fix this right */
   def (Qminibuffer, XtNminibuffer);
@@ -644,15 +662,15 @@ x_set_frame_text_value (struct frame *f, Bufbyte *value,
   for (ptr = value; *ptr; ptr++)
     if (!BYTE_ASCII_P (*ptr))
       {
-        CONST char * tmp;
+        const char * tmp;
         encoding = DEVICE_XATOM_COMPOUND_TEXT (XDEVICE (FRAME_DEVICE (f)));
-        GET_C_CHARPTR_EXT_CTEXT_DATA_ALLOCA ((CONST char *) value, tmp);
+       C_STRING_TO_EXTERNAL (value, tmp, Qctext);
         new_XtValue = (String) tmp;
         break;
       }
 #endif /* MULE */
 
-  /* ### Caching is device-independent - belongs in update_frame_title. */
+  /* #### Caching is device-independent - belongs in update_frame_title. */
   Xt_GET_VALUE (FRAME_X_SHELL_WIDGET (f), Xt_resource_name, &old_XtValue);
   if (!old_XtValue || strcmp (new_XtValue, old_XtValue))
     {
@@ -743,18 +761,20 @@ x_set_frame_properties (struct frame *f, Lisp_Object plist)
 
       if (STRINGP (prop))
        {
-         CONST char *extprop;
+         const char *extprop;
 
          if (XSTRING_LENGTH (prop) == 0)
            continue;
 
-         GET_C_STRING_CTEXT_DATA_ALLOCA (prop, extprop);
+         LISP_STRING_TO_EXTERNAL (prop, extprop, Qctext);
          if (STRINGP (val))
            {
-             CONST Extbyte *extval;
+             const Extbyte *extval;
              Extcount extvallen;
 
-             GET_STRING_CTEXT_DATA_ALLOCA (val, extval, extvallen);
+             TO_EXTERNAL_FORMAT (LISP_STRING, val,
+                                 ALLOCA, (extval, extvallen),
+                                 Qctext);
              XtVaSetValues (w, XtVaTypedArg, extprop,
                             XtRString, extval, extvallen + 1,
                             (XtArgVal) NULL);
@@ -1088,7 +1108,7 @@ WARNING: can only handle plain/text and file: transfers!
       unsigned int modifier = 0, state = 0;
       char *Ctext;
       int numItems = 0, textlen = 0, pos = 0;
-      struct Lisp_Event *lisp_event = XEVENT(event);
+      Lisp_Event *lisp_event = XEVENT (event);
       Lisp_Object item = Qnil;
       struct gcpro gcpro1;
 
@@ -1125,12 +1145,12 @@ WARNING: can only handle plain/text and file: transfers!
          x_event.xbutton.y_root = lisp_event->event.button.y;
        }
       modifier = lisp_event->event.button.modifiers;
-      if (modifier & MOD_SHIFT)   state |= ShiftMask;
-      if (modifier & MOD_CONTROL) state |= ControlMask;
-      if (modifier & MOD_META)    state |= xd->MetaMask;
-      if (modifier & MOD_SUPER)   state |= xd->SuperMask;
-      if (modifier & MOD_HYPER)   state |= xd->HyperMask;
-      if (modifier & MOD_ALT)     state |= xd->AltMask;
+      if (modifier & XEMACS_MOD_SHIFT)   state |= ShiftMask;
+      if (modifier & XEMACS_MOD_CONTROL) state |= ControlMask;
+      if (modifier & XEMACS_MOD_META)    state |= xd->MetaMask;
+      if (modifier & XEMACS_MOD_SUPER)   state |= xd->SuperMask;
+      if (modifier & XEMACS_MOD_HYPER)   state |= xd->HyperMask;
+      if (modifier & XEMACS_MOD_ALT)     state |= xd->AltMask;
       state |= Button1Mask << (lisp_event->event.button.button-1);
 
       x_event.xbutton.state = state;
@@ -1170,7 +1190,7 @@ WARNING: can only handle plain/text and file: transfers!
                  Ctext=NULL;
                  break;
                }
-             strcpy (Ctext+pos, (CONST char *)XSTRING_DATA (XCAR (item)));
+             strcpy (Ctext+pos, (const char *)XSTRING_DATA (XCAR (item)));
              pos += XSTRING_LENGTH (XCAR (item)) + 1;
              item = XCDR (item);
            }
@@ -1240,7 +1260,7 @@ x_cde_transfer_callback (Widget widget, XtPointer clientData,
        {
          filePath = transferInfo->dropData->data.files[ii];
          hurl = dnd_url_hexify_string ((char *)filePath, "file:");
-          /* ### Mule-izing required */
+          /* #### Mule-izing required */
          l_data = Fcons (make_string ((Bufbyte* )hurl,
                                       strlen (hurl)),
                          l_data);
@@ -1315,7 +1335,7 @@ The type defaults to DndText (4).
       char *dnd_data = NULL;
       unsigned long dnd_len = 0;
       int dnd_typ = DndText, dnd_dealloc = 0;
-      struct Lisp_Event *lisp_event = XEVENT(event);
+      Lisp_Event *lisp_event = XEVENT (event);
 
       /* only drag if this is really a press */
       if (EVENT_TYPE(lisp_event) != button_press_event)
@@ -1346,7 +1366,7 @@ The type defaults to DndText (4).
                }
              len = XSTRING_LENGTH (XCAR (run)) + 1;
              dnd_data = (char *) xrealloc (dnd_data, dnd_len + len);
-             strcpy (dnd_data + dnd_len - 1, (CONST char *)XSTRING_DATA (XCAR (run)));
+             strcpy (dnd_data + dnd_len - 1, (const char *)XSTRING_DATA (XCAR (run)));
              dnd_len += len;
              run = XCDR (run);
            }
@@ -1391,12 +1411,12 @@ The type defaults to DndText (4).
        }
 
       modifier = lisp_event->event.button.modifiers;
-      if (modifier & MOD_SHIFT)   state |= ShiftMask;
-      if (modifier & MOD_CONTROL) state |= ControlMask;
-      if (modifier & MOD_META)    state |= xd->MetaMask;
-      if (modifier & MOD_SUPER)   state |= xd->SuperMask;
-      if (modifier & MOD_HYPER)   state |= xd->HyperMask;
-      if (modifier & MOD_ALT)     state |= xd->AltMask;
+      if (modifier & XEMACS_MOD_SHIFT)   state |= ShiftMask;
+      if (modifier & XEMACS_MOD_CONTROL) state |= ControlMask;
+      if (modifier & XEMACS_MOD_META)    state |= xd->MetaMask;
+      if (modifier & XEMACS_MOD_SUPER)   state |= xd->SuperMask;
+      if (modifier & XEMACS_MOD_HYPER)   state |= xd->HyperMask;
+      if (modifier & XEMACS_MOD_ALT)     state |= xd->AltMask;
       state |= Button1Mask << (lisp_event->event.button.button-1);
 
       x_event.xbutton.state = state;
@@ -1529,13 +1549,16 @@ x_initialize_frame_size (struct frame *f)
   {
     struct window *win = XWINDOW (f->root_window);
 
-    WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
-    WINDOW_TOP (win) = FRAME_TOP_BORDER_END (f);
+    WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f)
+      + FRAME_LEFT_GUTTER_BOUNDS (f);
+    WINDOW_TOP (win) = FRAME_TOP_BORDER_END (f)
+      + FRAME_TOP_GUTTER_BOUNDS (f);
 
     if (!NILP (f->minibuffer_window))
       {
        win = XWINDOW (f->minibuffer_window);
-       WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
+       WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f)
+         + FRAME_LEFT_GUTTER_BOUNDS (f);
       }
   }
 
@@ -1614,7 +1637,7 @@ x_initialize_frame_size (struct frame *f)
   /* OK, we're a top-level shell. */
 
   if (!XtIsWMShell (wmshell))
-    abort ();
+    ABORT ();
 
   /* If the EmacsFrame doesn't have a geometry but the shell does,
      treat that as the geometry of the frame.
@@ -1788,10 +1811,14 @@ x_layout_widgets (Widget w, XtPointer client_data, XtPointer call_data)
 #endif
 
   /* finally the text area */
-  XtConfigureWidget (text, text_x, text_y,
-                    width - 2*textbord,
-                    height - text_y - 2*textbord,
-                    textbord);
+  {
+    Dimension nw = width - 2*textbord;
+    Dimension nh = height - text_y - 2*textbord;
+
+    if (nh != f->pixheight || nw != f->pixwidth)
+      MARK_FRAME_SIZE_SLIPPED (f);
+    XtConfigureWidget (text, text_x, text_y, nw, nh, textbord);
+  }
 }
 
 static void
@@ -1840,7 +1867,7 @@ x_create_widgets (struct frame *f, Lisp_Object lisp_window_id,
 #ifdef EXTERNAL_WIDGET
   Window window_id = 0;
 #endif
-  CONST char *name;
+  const char *name;
   Arg al [25];
   int ac = 0;
   Widget text, container, shell;
@@ -1851,7 +1878,7 @@ x_create_widgets (struct frame *f, Lisp_Object lisp_window_id,
 #endif
 
   if (STRINGP (f->name))
-    GET_C_STRING_CTEXT_DATA_ALLOCA (f->name, name);
+    LISP_STRING_TO_EXTERNAL (f->name, name, Qctext);
   else
     name = "emacs";
 
@@ -1880,7 +1907,7 @@ x_create_widgets (struct frame *f, Lisp_Object lisp_window_id,
       char *string;
 
       CHECK_STRING (lisp_window_id);
-      string = (char *) (XSTRING_DATA (lisp_window_id));
+      string = (char *) XSTRING_DATA (lisp_window_id);
       if (string[0] == '0' && (string[1] == 'x' || string[1] == 'X'))
        sscanf (string+2, "%lxu", &window_id);
 #if 0
@@ -2190,10 +2217,10 @@ x_init_frame_3 (struct frame *f)
 }
 
 static void
-x_mark_frame (struct frame *f, void (*markobj) (Lisp_Object))
+x_mark_frame (struct frame *f)
 {
-  markobj (FRAME_X_ICON_PIXMAP (f));
-  markobj (FRAME_X_ICON_PIXMAP_MASK (f));
+  mark_object (FRAME_X_ICON_PIXMAP (f));
+  mark_object (FRAME_X_ICON_PIXMAP_MASK (f));
 }
 
 static void
@@ -2463,6 +2490,18 @@ x_lower_frame (struct frame *f)
     }
 }
 
+static void
+x_enable_frame (struct frame *f)
+{
+  XtSetSensitive (FRAME_X_SHELL_WIDGET (f), True);
+}
+
+static void
+x_disable_frame (struct frame *f)
+{
+  XtSetSensitive (FRAME_X_SHELL_WIDGET (f), False);
+}
+
 /* Change from withdrawn state to mapped state. */
 static void
 x_make_frame_visible (struct frame *f)
@@ -2619,7 +2658,7 @@ x_focus_on_frame (struct frame *f)
   XFlush (XtDisplay (shell_widget)); /* hey, I'd like to DEBUG this... */
 }
 
-/* Destroy the X window of frame S.  */
+/* Destroy the X window of frame F.  */
 static void
 x_delete_frame (struct frame *f)
 {
@@ -2638,18 +2677,18 @@ x_delete_frame (struct frame *f)
   dpy = XtDisplay (FRAME_X_SHELL_WIDGET (f));
 
 #ifdef EXTERNAL_WIDGET
-  expect_x_error (XtDisplay (FRAME_X_SHELL_WIDGET (f)));
+  expect_x_error (dpy);
   /* for obscure reasons having (I think) to do with the internal
      window-to-widget hierarchy maintained by Xt, we have to call
      XtUnrealizeWidget() here.  Xt can really suck. */
   if (f->being_deleted)
     XtUnrealizeWidget (FRAME_X_SHELL_WIDGET (f));
   XtDestroyWidget (FRAME_X_SHELL_WIDGET (f));
-  x_error_occurred_p (XtDisplay (FRAME_X_SHELL_WIDGET (f)));
+  x_error_occurred_p (dpy);
 #else
   XtDestroyWidget (FRAME_X_SHELL_WIDGET (f));
   /* make sure the windows are really gone! */
-  /* ### Is this REALLY necessary? */
+  /* #### Is this REALLY necessary? */
   XFlush (dpy);
 #endif /* EXTERNAL_WIDGET */
 
@@ -2709,12 +2748,14 @@ x_update_frame_external_traits (struct frame* frm, Lisp_Object name)
      Lisp_Object font = FACE_FONT (Vdefault_face, frame, Vcharset_ascii);
 
      if (!EQ (font, Vthe_null_font_instance))
-       XtSetArg (al[ac], XtNfont,
-                (void *) FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font)));
-     ac++;
+       {
+        XtSetArg (al[ac], XtNfont,
+                  (void *) FONT_INSTANCE_X_FONT (XFONT_INSTANCE (font)));
+        ac++;
+       }
    }
   else
-   abort ();
+   ABORT ();
 
   XtSetValues (FRAME_X_TEXT_WIDGET (frm), al, ac);
 
@@ -2766,6 +2807,8 @@ console_type_create_frame_x (void)
   CONSOLE_HAS_METHOD (x, set_mouse_position);
   CONSOLE_HAS_METHOD (x, raise_frame);
   CONSOLE_HAS_METHOD (x, lower_frame);
+  CONSOLE_HAS_METHOD (x, enable_frame);
+  CONSOLE_HAS_METHOD (x, disable_frame);
   CONSOLE_HAS_METHOD (x, make_frame_visible);
   CONSOLE_HAS_METHOD (x, make_frame_invisible);
   CONSOLE_HAS_METHOD (x, iconify_frame);