diff src/frame-x.c @ 20:859a2309aef8 r19-15b93

Import from CVS: tag r19-15b93
author cvs
date Mon, 13 Aug 2007 08:50:05 +0200
parents 0293115a14e9
children ec9a17fef872
line wrap: on
line diff
--- a/src/frame-x.c	Mon Aug 13 08:49:44 2007 +0200
+++ b/src/frame-x.c	Mon Aug 13 08:50:05 2007 +0200
@@ -486,6 +486,7 @@
   *y = xwa.y;
 }
 
+#if 0
 static void
 x_smash_bastardly_shell_position (Widget shell)
 {
@@ -501,6 +502,7 @@
     x_get_top_level_position (XtDisplay (shell), XtWindow (shell),
 			      &shell->core.x, &shell->core.y);
 }
+#endif /* 0 */
 
 static Lisp_Object
 x_frame_property (struct frame *f, Lisp_Object property)
@@ -512,15 +514,26 @@
 #define FROB(propprop, value) 	\
 do {				\
   if (EQ (property, propprop))	\
-    {				\
-      return (value);		\
-    }				\
+    return (value);		\
 } while (0)
 
+#if 0
   if (EQ (property, Qleft) || EQ (property, Qtop))
     x_smash_bastardly_shell_position (shell);
+#endif
+  if (EQ (property, Qleft) || EQ (property, Qtop))
+    {
+      Position x, y;
+      if (!XtWindow(shell))
+	return make_int (0);
+      x_get_top_level_position (XtDisplay (shell), XtWindow (shell), &x, &y);
+      FROB (Qleft, make_int (x));
+      FROB (Qtop,  make_int (y));
+    }
+#if 0
   FROB (Qleft, make_int (shell->core.x));
   FROB (Qtop, make_int (shell->core.y));
+#endif
   FROB (Qborder_width, make_int (w->core.border_width));
   FROB (Qinternal_border_width,
 	make_int (w->emacs_frame.internal_border_width));
@@ -534,7 +547,7 @@
 	color_to_string (gw, w->emacs_frame.background_toolbar_pixel));
   FROB (Qtoolbar_shadow_thickness,
 	make_int (w->emacs_frame.toolbar_shadow_thickness));
-#endif
+#endif /* HAVE_TOOLBARS */
   FROB (Qinter_line_space, make_int (w->emacs_frame.interline));
   FROB (Qwindow_id, Fx_window_id (make_frame (f)));
 
@@ -546,23 +559,20 @@
 static int
 x_internal_frame_property_p (struct frame *f, Lisp_Object property)
 {
-  if (EQ (property, Qleft)
-      || EQ (property, Qtop)
-      || EQ (property, Qborder_width)
-      || EQ (property, Qinternal_border_width)
-      || EQ (property, Qborder_color)
+  return EQ (property, Qleft)
+    || EQ (property, Qtop)
+    || EQ (property, Qborder_width)
+    || EQ (property, Qinternal_border_width)
+    || EQ (property, Qborder_color)
 #ifdef HAVE_TOOLBARS
-      || EQ (property, Qtop_toolbar_shadow_color)
-      || EQ (property, Qbottom_toolbar_shadow_color)
-      || EQ (property, Qbackground_toolbar_color)
-      || EQ (property, Qtoolbar_shadow_thickness)
+    || EQ (property, Qtop_toolbar_shadow_color)
+    || EQ (property, Qbottom_toolbar_shadow_color)
+    || EQ (property, Qbackground_toolbar_color)
+    || EQ (property, Qtoolbar_shadow_thickness)
 #endif
-      || EQ (property, Qinter_line_space)
-      || EQ (property, Qwindow_id)
-      || STRINGP (property))
-    return 1;
-
-  return 0;
+    || EQ (property, Qinter_line_space)
+    || EQ (property, Qwindow_id)
+    || STRINGP (property);
 }
 
 static Lisp_Object
@@ -572,6 +582,7 @@
   Widget shell = FRAME_X_SHELL_WIDGET (f);
   EmacsFrame w = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
   Widget gw = (Widget) w;
+  Position x, y;
 
 #define FROB(propprop, value)				\
 do {							\
@@ -581,9 +592,19 @@
     result = Fcons (temtem, Fcons (propprop, result));	\
 } while (0)
 
+#if 0
   x_smash_bastardly_shell_position (shell);
   FROB (Qleft, make_int (shell->core.x));
   FROB (Qtop, make_int (shell->core.y));
+#endif
+  if (!XtWindow(shell))
+    x = y = 0;
+  else
+    x_get_top_level_position (XtDisplay (shell), XtWindow (shell), &x, &y);
+  
+  FROB (Qleft, make_int (x));
+  FROB (Qtop,  make_int (y));
+
   FROB (Qborder_width, make_int (w->core.border_width));
   FROB (Qinternal_border_width,
 	make_int (w->emacs_frame.internal_border_width));
@@ -597,7 +618,7 @@
 	color_to_string (gw, w->emacs_frame.background_toolbar_pixel));
   FROB (Qtoolbar_shadow_thickness,
 	make_int (w->emacs_frame.toolbar_shadow_thickness));
-#endif
+#endif /* HAVE_TOOLBARS */
   FROB (Qinter_line_space, make_int (w->emacs_frame.interline));
   FROB (Qwindow_id, Fx_window_id (make_frame (f)));
 
@@ -618,7 +639,6 @@
   Atom encoding = XA_STRING;
   String new_XtValue = (String) value;
   String old_XtValue = NULL;
-  Bufbyte *ptr;
   Arg av[2];
 
   /* ### Caching is device-independent - belongs in update_frame_title. */
@@ -694,7 +714,7 @@
 static void
 x_set_frame_properties (struct frame *f, Lisp_Object plist)
 {
-  int x = 0, y = 0;
+  Position x, y;
   Dimension width = 0, height = 0;
   Bool width_specified_p = False;
   Bool height_specified_p = False;
@@ -781,14 +801,14 @@
 	  if (!strcmp ((char *) XSTRING_DATA (str), "x"))
 	    {
 	      CHECK_INT (val);
-	      x = XINT (val);
+	      x = (Position) XINT (val);
 	      x_position_specified_p = True;
 	      continue;
 	    }
 	  if (!strcmp ((char *) XSTRING_DATA (str), "y"))
 	    {
 	      CHECK_INT (val);
-	      y = XINT (val);
+	      y = (Position) XINT (val);
 	      y_position_specified_p = True;
 	      continue;
 	    }
@@ -837,7 +857,7 @@
 	    {
 	      x_update_frame_scrollbars (f);
 	    }
-#endif
+#endif /* HAVE_SCROLLBARS */
 	}
     }
 
@@ -854,16 +874,26 @@
       height = FRAME_HEIGHT (f);
     
     /* Kludge kludge kludge kludge. */
-    if (!x_position_specified_p)
-      x = (int) (FRAME_X_SHELL_WIDGET (f)->core.x);
-    if (!y_position_specified_p)
-      y = (int) (FRAME_X_SHELL_WIDGET (f)->core.y);
+    if (position_specified_p &&
+	(!x_position_specified_p || !y_position_specified_p))
+      {
+	Position dummy;
+	Widget shell = FRAME_X_SHELL_WIDGET (f);
+	x_get_top_level_position (XtDisplay (shell), XtWindow (shell),
+				  (x_position_specified_p ? &dummy : &x),
+				  (y_position_specified_p ? &dummy : &y));
+#if 0
+	x = (int) (FRAME_X_SHELL_WIDGET (f)->core.x);
+	y = (int) (FRAME_X_SHELL_WIDGET (f)->core.y);
+#endif
+      }
       
     if (!f->init_finished)
       {
 	int flags = (size_specified_p ? WidthValue | HeightValue : 0) |
-	  (position_specified_p ? XValue | YValue : 0) |
-	  (x < 0 ? XNegative : 0) | (y < 0 ? YNegative : 0);
+	  (position_specified_p ?
+	   XValue | YValue | (x < 0 ? XNegative : 0) | (y < 0 ? YNegative : 0)
+	   : 0);
 	if (size_specified_p
 	    || position_specified_p
 	    || internal_border_width_specified)
@@ -937,16 +967,131 @@
 #include <Dt/Dt.h>
 #include <Dt/Dnd.h>
 
+static Widget CurrentDragWidget = NULL;
+
+static void
+x_cde_destroy_callback (Widget widget, XtPointer clientData,
+			XtPointer callData)
+{
+  xfree (clientData);
+  CurrentDragWidget = NULL;
+}
+
+static void
+x_cde_convert_callback (Widget widget, XtPointer clientData,
+			XtPointer callData)
+{
+  DtDndConvertCallbackStruct *convertInfo =
+    (DtDndConvertCallbackStruct *) callData;
+  char *textdata = (char *) clientData;
+
+  if(convertInfo == NULL)
+    {
+      return;
+    }
+
+  if((convertInfo->dragData->protocol != DtDND_BUFFER_TRANSFER) ||
+     (convertInfo->reason != DtCR_DND_CONVERT_DATA))
+    {
+      return;
+    }
+
+  convertInfo->dragData->data.buffers[0].bp = XtNewString(textdata);
+  convertInfo->dragData->data.buffers[0].size = strlen(textdata);
+  convertInfo->dragData->data.buffers[0].name = NULL;
+  convertInfo->dragData->numItems = 1;
+  convertInfo->status = DtDND_SUCCESS;
+}
+
+
+static XtCallbackRec dnd_convert_cb_rec[2];
+static XtCallbackRec dnd_destroy_cb_rec[2];
+static int drag_not_done = 0;
+
+static Lisp_Object
+abort_current_drag(Lisp_Object arg)
+{
+  if(CurrentDragWidget && drag_not_done)
+    {
+      XmDragCancel(CurrentDragWidget);
+      CurrentDragWidget = NULL;
+    }
+  return arg;
+}
+
+DEFUN ("cde-start-drag-internal", Fcde_start_drag_internal, 1, 1, 0, /*
+Start a CDE drag from a buffer.
+*/
+       (text))
+{
+  if (STRINGP (text))
+    {
+      struct frame *f = decode_x_frame (Fselected_frame (Qnil));
+      XEvent event;
+      Widget Wuh = FRAME_X_TEXT_WIDGET (f);
+      char *Ctext;
+      Display *display = XtDisplayOfObject (Wuh);
+      Window root_window, child_window;
+      int root_x, root_y, win_x, win_y;
+      unsigned int keys_and_buttons;
+
+      if (XQueryPointer (display, RootWindow (display, DefaultScreen (display)),
+			 &root_window, &child_window, &root_x, &root_y,
+			 &win_x, &win_y, &keys_and_buttons) == False)
+	return Qnil;
+
+      Ctext = xstrdup ((char *) XSTRING_DATA (text));
+
+      /*
+       * Eek - XEmacs doesn't keep the old X event around so we have to
+       * build a dummy event.  This is a truly gross hack.
+       */
+
+      event.xbutton.type = ButtonPress;
+      event.xbutton.send_event = False;
+      event.xbutton.display = XtDisplayOfObject(Wuh);
+      event.xbutton.window = XtWindowOfObject(Wuh);
+      event.xbutton.root = XRootWindow(event.xkey.display, 0);
+      event.xbutton.subwindow = 0;
+      event.xbutton.time = 0;
+      event.xbutton.x = win_x;
+      event.xbutton.y = win_y;
+      event.xbutton.x_root = root_x;
+      event.xbutton.y_root = root_y;
+      event.xbutton.state = 0;
+      event.xbutton.button = 1;
+      event.xkey.same_screen = True;
+
+      dnd_convert_cb_rec[0].callback = x_cde_convert_callback;
+      dnd_convert_cb_rec[0].closure  = (XtPointer) Ctext;
+      dnd_convert_cb_rec[1].callback = NULL;
+      dnd_convert_cb_rec[1].closure  = NULL;
+      
+      dnd_destroy_cb_rec[0].callback = x_cde_destroy_callback;
+      dnd_destroy_cb_rec[0].closure  = (XtPointer) Ctext;
+      dnd_destroy_cb_rec[1].callback = NULL;
+      dnd_destroy_cb_rec[1].closure  = NULL;
+
+      CurrentDragWidget =
+      DtDndDragStart (Wuh, &event, DtDND_BUFFER_TRANSFER, 1, XmDROP_COPY,
+		      dnd_convert_cb_rec,
+		      dnd_destroy_cb_rec,
+		      NULL, 0);
+      return Qt;
+    }
+  return Qnil;
+}
+
 void
 x_cde_transfer_callback (Widget widget, XtPointer clientData,
 			 XtPointer callData)
 {
   char *filePath, *buf;
   int ii;
-  Lisp_Object data = Qnil;
-  Lisp_Object path = Qnil;
+  Lisp_Object path  = Qnil;
   Lisp_Object frame = Qnil;
-  struct gcpro gcpro1, gcpro2;
+  Lisp_Object data  = Qnil;
+  struct gcpro gcpro1, gcpro2, gcpro3;
     
   DtDndTransferCallbackStruct *transferInfo =
     (DtDndTransferCallbackStruct *) callData;
@@ -954,7 +1099,7 @@
   if (transferInfo == NULL)
     return;
 	
-  GCPRO2 (path, frame);
+  GCPRO3 (path, frame, data);
     
   frame = make_frame ((struct frame *) clientData);
   if (transferInfo->dropData->protocol == DtDND_FILENAME_TRANSFER)
@@ -962,28 +1107,37 @@
       for (ii = 0; ii < transferInfo->dropData->numItems; ii++) 
 	{
 	  filePath = transferInfo->dropData->data.files[ii];
+	  /* ### Mule-izing required */
 	  path = make_string ((Bufbyte *)filePath, strlen (filePath));
 	  va_run_hook_with_args (Qdrag_and_drop_functions, 2, frame, path);
 	}
     }
   else if (transferInfo->dropData->protocol == DtDND_BUFFER_TRANSFER)
     {
+      int speccount = specpdl_depth();
+ 
+      record_unwind_protect(abort_current_drag, Qnil);
+      drag_not_done = 1;
       for (ii = 0; ii < transferInfo->dropData->numItems; ii++)
  	{
  	  filePath = transferInfo->dropData->data.buffers[ii].name;
- 	  path = (filePath != NULL) ?
-            make_string ((Bufbyte *)filePath, strlen (filePath)) : Qnil;
+	  /* ### Mule-izing required */
+	  path = (filePath == NULL) ? Qnil
+	    : make_string ((Bufbyte *)filePath, strlen (filePath));
  	  buf = transferInfo->dropData->data.buffers[ii].bp;
  	  data = make_string ((Bufbyte *)buf,
 			      transferInfo->dropData->data.buffers[ii].size);
- 	  va_run_hook_with_args(Qdrag_and_drop_functions, 3, frame, path, data);
+ 	  va_run_hook_with_args(Qdrag_and_drop_functions, 3, frame, path,
+				data);
  	}
+	drag_not_done = 0;
+	unbind_to(speccount, Qnil);
     }
 
   UNGCPRO;
   return;
 }
-#endif
+#endif /* HAVE_CDE */
 
 #ifdef HAVE_OFFIX_DND
 #include <OffiX/DragAndDrop.h>
@@ -1400,7 +1554,7 @@
                             scrollbar_placement == XtTOP_RIGHT);
     f->scrollbar_y_offset = topbreadth + textbord;
   }
-#endif
+#endif /* HAVE_SCROLLBARS */
 
   /* finally the text area */
   XtConfigureWidget (text, text_x, text_y,
@@ -1423,8 +1577,8 @@
 
   x_get_layout_sizes (f, &topbreadth);
 
-  /* strip away menubar from suggested size, and ask the text widget
-     what size it wants to be */
+  /* Strip away menubar from suggested size, and ask the text widget
+     what size it wants to be.  */
   req.request_mode = mask;
   if (mask & CWWidth)
     req.width = emst->proposed_width - 2*textbord;
@@ -1433,7 +1587,7 @@
   XtQueryGeometry (text, &req, &repl);
 
   /* Now add the menubar back again */
-  emst->proposed_width = repl.width + 2*textbord;
+  emst->proposed_width  = repl.width  + 2*textbord;
   emst->proposed_height = repl.height + topbreadth + 2*textbord;
 }
 
@@ -1527,7 +1681,7 @@
       XtSetArg (av[ac], XtNwindow, window_id); ac++;
     }
   else
-#endif
+#endif /* EXTERNAL_WIDGET */
     {
       XtSetArg (av[ac], XtNinput, True); ac++;
       XtSetArg (av[ac], (String) XtNminWidthCells, 10); ac++;
@@ -1581,7 +1735,7 @@
   
   if (menubar_visible)
     XtManageChild (menubar);
-#endif
+#endif /* HAVE_MENUBARS */
   XtManageChild (text);
   XtManageChild (container);
 }
@@ -1626,7 +1780,7 @@
 /* Does this have to be non-automatic? */
 /* hack frame to respond to dnd messages */
 static XtCallbackRec dnd_transfer_cb_rec[2];
-#endif
+#endif /* HAVE_CDE */
 
 /* create the windows for the specified frame and display them.
    Note that the widgets have already been created, and any
@@ -1681,7 +1835,7 @@
 		     True,                   /* called on non-maskable events? */
 		     _XEditResCheckMessages, /* the handler */
 		     NULL);
-#endif
+#endif /* HACK_EDITRES */
 
 #ifdef HAVE_CDE
   {
@@ -1697,7 +1851,7 @@
 			 DtNpreserveRegistration, False,
 			 NULL);
   }
-#endif
+#endif /* HAVE_CDE */
 
 #ifdef HAVE_OFFIX_DND
   {
@@ -1846,6 +2000,8 @@
   Widget parentwid = 0;
   Arg av[1];
 
+  /* We may be passed a dangling deleted frame */
+  /* I do not know how to test for this. -sb */
   XtSetArg (av[0], XtNtransientFor, &parentwid);
   XtGetValues (FRAME_X_SHELL_WIDGET (f), av, 1);
   /* find the frame whose wid is parentwid */
@@ -1862,14 +2018,13 @@
   return Qnil;
 }
 
-DEFUN ("x-window-id", Fx_window_id, Sx_window_id, 0, 1, 0 /*
+DEFUN ("x-window-id", Fx_window_id, 0, 1, 0, /*
 Get the ID of the X11 window.
 This gives us a chance to manipulate the Emacs window from within a
 different program.  Since the ID is an unsigned long, we return it as
 a string.
-*/ )
-  (frame)
-  Lisp_Object frame;
+*/
+       (frame))
 {
   char str[255];
   struct frame *f = decode_x_frame (frame);
@@ -1888,14 +2043,14 @@
 {
   Widget w = FRAME_X_SHELL_WIDGET (f);
   Display *dpy = XtDisplay (w);
-  Dimension frame_w = DisplayWidth (dpy, DefaultScreen (dpy));
+  Dimension frame_w = DisplayWidth  (dpy, DefaultScreen (dpy));
   Dimension frame_h = DisplayHeight (dpy, DefaultScreen (dpy));
   Dimension shell_w, shell_h, shell_bord;
   int win_gravity;
 
   XtVaGetValues (w,
-		 XtNwidth, &shell_w,
-		 XtNheight, &shell_h,
+		 XtNwidth,       &shell_w,
+		 XtNheight,      &shell_h,
 		 XtNborderWidth, &shell_bord,
 		 0);
 
@@ -1918,24 +2073,21 @@
 		 XtNx, xoff,
 		 XtNy, yoff,
 		 0);
+
   /* Sometimes you will find that
 
      (set-frame-position (selected-frame) -50 -50)
 
-     doesn't put the frame where you expect it to:
-     i.e. it's closer to the lower-right corner than
-     it should be, and it appears that the size of
-     the WM decorations was not taken into account.
-     This is *not* a problem with this function.
-     Both mwm and twm have bugs in handling this
-     situation. (mwm ignores the window gravity
-     and always assumes NorthWest, except the first
-     time you map the window; twm gets things almost
-     right, but forgets to account for the border
-     width of the top-level window.) This function
-     does what it's supposed to according to the ICCCM,
-     and I'm not about to hack around window-manager
-     bugs. */
+     doesn't put the frame where you expect it to: i.e. it's closer to
+     the lower-right corner than it should be, and it appears that the
+     size of the WM decorations was not taken into account.  This is
+     *not* a problem with this function.  Both mwm and twm have bugs
+     in handling this situation. (mwm ignores the window gravity and
+     always assumes NorthWest, except the first time you map the
+     window; twm gets things almost right, but forgets to account for
+     the border width of the top-level window.) This function does
+     what it's supposed to according to the ICCCM, and I'm not about
+     to hack around window-manager bugs. */
 
 #if 0
   /* This is not necessary under either mwm or twm */
@@ -2267,7 +2419,10 @@
   defsymbol (&Qpopup, "popup");
   defsymbol (&Qx_resource_name, "x-resource-name");
 
-  defsubr (&Sx_window_id);
+  DEFSUBR (Fx_window_id);
+#ifdef HAVE_CDE
+  DEFSUBR (Fcde_start_drag_internal);
+#endif
 }
 
 void