]> code.delx.au - gnu-emacs/blobdiff - src/xfns.c
Use #if GLYPH_DEBUG instead of #ifdef GLYPH_DEBUG.
[gnu-emacs] / src / xfns.c
index 930269c738f994327bf20f258124cf80eb402262..6e8931b42d703fe9db7e154f881b09ca7277c4ad 100644 (file)
@@ -124,7 +124,7 @@ extern double atof ();
 
 int gray_bitmap_width = gray_width;
 int gray_bitmap_height = gray_height;
-unsigned char *gray_bitmap_bits = gray_bits;
+char *gray_bitmap_bits = gray_bits;
 
 /* The name we're using in resource queries.  Most often "emacs".  */
 
@@ -255,6 +255,11 @@ extern Lisp_Object Vwindow_system_version;
 
 Lisp_Object Qface_set_after_frame_default;
 
+#if GLYPH_DEBUG
+int image_cache_refcount, dpyinfo_refcount;
+#endif
+
+
 \f
 /* Error if we are not connected to X.  */
 
@@ -746,6 +751,8 @@ struct x_frame_parm_table
   void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
 };
 
+static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
+static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
 static void x_change_window_heights P_ ((Lisp_Object, int));
 static void x_disable_image P_ ((struct frame *, struct image *));
 static void x_create_im P_ ((struct frame *));
@@ -4023,6 +4030,35 @@ x_free_gcs (f)
 }
 
 
+/* Handler for signals raised during x_create_frame and
+   x_create_top_frame.  FRAME is the frame which is partially
+   constructed.  */
+
+static Lisp_Object
+unwind_create_frame (frame)
+     Lisp_Object frame;
+{
+  struct frame *f = XFRAME (frame);
+
+  /* If frame is ``official'', nothing to do.  */
+  if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
+    {
+#if GLYPH_DEBUG
+      struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+#endif
+      
+      x_free_frame_resources (f);
+
+      /* Check that reference counts are indeed correct.  */
+      xassert (dpyinfo->reference_count == dpyinfo_refcount);
+      xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
+      return Qt;
+    }
+  
+  return Qnil;
+}
+
+
 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
        1, 1, 0,
   "Make a new X window, which is called a \"frame\" in Emacs terms.\n\
@@ -4043,7 +4079,7 @@ This function is an internal primitive--use `make-frame' instead.")
   int minibuffer_only = 0;
   long window_prompting = 0;
   int width, height;
-  int count = specpdl_ptr - specpdl;
+  int count = BINDING_STACK_SIZE ();
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   Lisp_Object display;
   struct x_display_info *dpyinfo = NULL;
@@ -4113,6 +4149,7 @@ This function is an internal primitive--use `make-frame' instead.")
   f->output_data.x->fontset = -1;
   f->output_data.x->scroll_bar_foreground_pixel = -1;
   f->output_data.x->scroll_bar_background_pixel = -1;
+  record_unwind_protect (unwind_create_frame, frame);
 
   f->icon_name
     = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
@@ -4121,6 +4158,10 @@ This function is an internal primitive--use `make-frame' instead.")
     f->icon_name = Qnil;
 
   FRAME_X_DISPLAY_INFO (f) = dpyinfo;
+#if GLYPH_DEBUG
+  image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
+  dpyinfo_refcount = dpyinfo->reference_count;
+#endif /* GLYPH_DEBUG */
 #ifdef MULTI_KBOARD
   FRAME_KBOARD (f) = kb;
 #endif
@@ -4409,6 +4450,7 @@ This function is an internal primitive--use `make-frame' instead.")
   return unbind_to (count, frame);
 }
 
+
 /* FRAME is used only to get a handle on the X display.  We don't pass the
    display info directly because we're called from frame.c, which doesn't
    know about that structure.  */
@@ -10226,31 +10268,41 @@ show_busy_cursor (timer)
       BLOCK_INPUT;
   
       FOR_EACH_FRAME (rest, frame)
-       if (FRAME_X_P (XFRAME (frame)))
-         {
-           struct frame *f = XFRAME (frame);
-       
-           f->output_data.x->busy_p = 1;
+       {
+         struct frame *f = XFRAME (frame);
+         
+         if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
+           {
+             Display *dpy = FRAME_X_DISPLAY (f);
+             
+#ifdef USE_X_TOOLKIT
+             if (f->output_data.x->widget)
+#else
+             if (FRAME_OUTER_WINDOW (f))
+#endif
+               {
+                 f->output_data.x->busy_p = 1;
        
-           if (!f->output_data.x->busy_window)
-             {
-               unsigned long mask = CWCursor;
-               XSetWindowAttributes attrs;
+                 if (!f->output_data.x->busy_window)
+                   {
+                     unsigned long mask = CWCursor;
+                     XSetWindowAttributes attrs;
            
-               attrs.cursor = f->output_data.x->busy_cursor;
+                     attrs.cursor = f->output_data.x->busy_cursor;
            
-               f->output_data.x->busy_window
-                 = XCreateWindow (FRAME_X_DISPLAY (f),
-                                  FRAME_OUTER_WINDOW (f),
-                                  0, 0, 32000, 32000, 0, 0,
-                                  InputOnly,
-                                  CopyFromParent,
-                                  mask, &attrs);
-             }
+                     f->output_data.x->busy_window
+                       = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
+                                        0, 0, 32000, 32000, 0, 0,
+                                        InputOnly,
+                                        CopyFromParent,
+                                        mask, &attrs);
+                   }
        
-           XMapRaised (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
-           XFlush (FRAME_X_DISPLAY (f));
-         }
+                 XMapRaised (dpy, f->output_data.x->busy_window);
+                 XFlush (dpy);
+               }
+           }
+       }
 
       busy_cursor_shown_p = 1;
       UNBLOCK_INPUT;
@@ -10308,8 +10360,31 @@ Lisp_Object tip_frame;
 Lisp_Object tip_timer;
 Window tip_window;
 
+
+static Lisp_Object
+unwind_create_tip_frame (frame)
+     Lisp_Object frame;
+{
+  Lisp_Object deleted;
+
+  deleted = unwind_create_frame (frame);
+  if (EQ (deleted, Qt))
+    {
+      tip_window = None;
+      tip_frame = Qnil;
+    }
+  
+  return deleted;
+}
+
+
 /* Create a frame for a tooltip on the display described by DPYINFO.
-   PARMS is a list of frame parameters.  Value is the frame.  */
+   PARMS is a list of frame parameters.  Value is the frame.
+
+   Note that functions called here, esp. x_default_parameter can
+   signal errors, for instance when a specified color name is
+   undefined.  We have to make sure that we're in a consistent state
+   when this happens.  */
 
 static Lisp_Object
 x_create_tip_frame (dpyinfo, parms)
@@ -10321,7 +10396,7 @@ x_create_tip_frame (dpyinfo, parms)
   Lisp_Object name;
   long window_prompting = 0;
   int width, height;
-  int count = specpdl_ptr - specpdl;
+  int count = BINDING_STACK_SIZE ();
   struct gcpro gcpro1, gcpro2, gcpro3;
   struct kboard *kb;
 
@@ -10350,7 +10425,12 @@ x_create_tip_frame (dpyinfo, parms)
   f = make_frame (1);
   XSETFRAME (frame, f);
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
+  record_unwind_protect (unwind_create_tip_frame, frame);
 
+  /* By setting the output method, we're essentially saying that
+     the frame is live, as per FRAME_LIVE_P.  If we get a signal
+     from this point on, x_destroy_window might screw up reference
+     counts etc.  */
   f->output_method = output_x_window;
   f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
   bzero (f->output_data.x, sizeof (struct x_output));
@@ -10360,6 +10440,10 @@ x_create_tip_frame (dpyinfo, parms)
   f->output_data.x->scroll_bar_background_pixel = -1;
   f->icon_name = Qnil;
   FRAME_X_DISPLAY_INFO (f) = dpyinfo;
+#if GLYPH_DEBUG
+  image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
+  dpyinfo_refcount = dpyinfo->reference_count;
+#endif /* GLYPH_DEBUG */
 #ifdef MULTI_KBOARD
   FRAME_KBOARD (f) = kb;
 #endif
@@ -10404,8 +10488,8 @@ x_create_tip_frame (dpyinfo, parms)
       specbind (Qx_resource_name, name);
     }
 
-  /* Extract the window parameters from the supplied values
-     that are needed to determine window geometry.  */
+  /* Extract the window parameters from the supplied values that are
+     needed to determine window geometry.  */
   {
     Lisp_Object font;
 
@@ -10566,6 +10650,7 @@ x_create_tip_frame (dpyinfo, parms)
      its display.  */
   FRAME_X_DISPLAY_INFO (f)->reference_count++;
 
+  /* Discard the unwind_protect.  */
   return unbind_to (count, frame);
 }
 
@@ -10751,39 +10836,29 @@ Value is t is tooltip was open, nil otherwise.")
   ()
 {
   int count;
-  Lisp_Object deleted;
+  Lisp_Object deleted, frame, timer;
+  struct gcpro gcpro1, gcpro2;
 
   /* Return quickly if nothing to do.  */
-  if (NILP (tip_timer) && !FRAMEP (tip_frame))
+  if (NILP (tip_timer) && NILP (tip_frame))
     return Qnil;
   
+  frame = tip_frame;
+  timer = tip_timer;
+  GCPRO2 (frame, timer);
+  tip_frame = tip_timer = deleted = Qnil;
+  
   count = BINDING_STACK_SIZE ();
-  deleted = Qnil;
   specbind (Qinhibit_redisplay, Qt);
   specbind (Qinhibit_quit, Qt);
   
-  if (!NILP (tip_timer))
-    {
-      Lisp_Object tem;
-      struct gcpro gcpro1;
-      tem = tip_timer;
-      GCPRO1 (tem);
-      tip_timer = Qnil;
-      call1 (intern ("cancel-timer"), tem);
-      UNGCPRO;
-    }
+  if (!NILP (timer))
+    call1 (intern ("cancel-timer"), timer);
 
-  if (FRAMEP (tip_frame))
+  if (FRAMEP (frame))
     {
-      Lisp_Object frame;
-      struct gcpro gcpro1;
-
-      frame = tip_frame;
-      GCPRO1 (frame);
-      tip_frame = Qnil;
       Fdelete_frame (frame, Qnil);
       deleted = Qt;
-      UNGCPRO;
 
 #ifdef USE_LUCID
       /* Bloodcurdling hack alert: The Lucid menu bar widget's
@@ -10805,6 +10880,7 @@ Value is t is tooltip was open, nil otherwise.")
 #endif /* USE_LUCID */
     }
 
+  UNGCPRO;
   return unbind_to (count, deleted);
 }
 
@@ -10996,6 +11072,68 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
 #endif /* USE_MOTIF */
 
 
+\f
+/***********************************************************************
+                              Keyboard
+ ***********************************************************************/
+
+#ifdef HAVE_XKBGETKEYBOARD
+#include <X11/XKBlib.h>
+#include <X11/keysym.h>
+#endif
+
+DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
+       Sx_backspace_delete_keys_p, 0, 1, 0,
+  "Check if both Backspace and Delete keys are on the keyboard of FRAME.\n\
+FRAME nil means use the selected frame.\n\
+Value is t if we know that both keys are present, and are mapped to the\n\
+usual X keysyms.")
+  (frame)
+     Lisp_Object frame;
+{
+#ifdef HAVE_XKBGETKEYBOARD
+  XkbDescPtr kb;
+  struct frame *f = check_x_frame (frame);
+  Display *dpy = FRAME_X_DISPLAY (f);
+  Lisp_Object have_keys;
+
+  have_keys = Qnil;
+
+  BLOCK_INPUT;
+  kb = XkbGetKeyboard (dpy, XkbAllComponentsMask, XkbUseCoreKbd);
+  if (kb)
+    {
+      int delete_keycode = 0, backspace_keycode = 0, i;
+      
+      for (i = kb->min_key_code;
+          (i < kb->max_key_code
+           && (delete_keycode == 0 || backspace_keycode == 0));
+          ++i)
+       {
+         /* The XKB symbolic key names can be seen most easily
+            in the PS file generated by `xkbprint -label name $DISPLAY'.  */
+         if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
+           delete_keycode = i;
+         else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
+           backspace_keycode = i;
+       }
+
+      XkbFreeKeyboard (kb, XkbAllComponentsMask, True);
+  
+      if (delete_keycode
+         && backspace_keycode
+         && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
+         && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
+       have_keys = Qt;
+    }
+  UNBLOCK_INPUT;
+  return have_keys;
+#else /* not HAVE_XKBGETKEYBOARD */
+  return Qnil;
+#endif /* not HAVE_XKBGETKEYBOARD */
+}
+
+
 \f
 /***********************************************************************
                            Initialization
@@ -11265,7 +11403,8 @@ meaning don't clear the cache.");
   defsubr (&Sx_display_list);
   defsubr (&Sx_synchronize);
   defsubr (&Sx_focus_frame);
-
+  defsubr (&Sx_backspace_delete_keys_p);
+  
   /* Setting callback functions for fontset handler.  */
   get_font_info_func = x_get_font_info;