diff lwlib/lwlib-Xlw.c @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children ac2d302a0011
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwlib/lwlib-Xlw.c	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,439 @@
+/* The lwlib interface to "xlwmenu" menus.
+   Copyright (C) 1992, 1994 Lucid, Inc.
+
+This file is part of the Lucid Widget Library.
+
+The Lucid Widget Library is free software; you can redistribute it and/or 
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+The Lucid Widget Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of 
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdlib.h> /* for abort () */
+#include <limits.h>
+
+#include "lwlib-Xlw.h"
+#include <X11/StringDefs.h>
+#include <X11/IntrinsicP.h>
+#include <X11/ObjectP.h>
+#include <X11/CompositeP.h>
+#include <X11/Shell.h>
+#ifdef MENUBARS_LUCID
+#include "xlwmenu.h"
+#endif
+#ifdef SCROLLBARS_LUCID
+#include "xlwscrollbar.h"
+#endif
+
+
+
+#ifdef MENUBARS_LUCID
+
+/* Menu callbacks */
+
+static void
+pre_hook (Widget w, XtPointer client_data, XtPointer call_data)
+{
+  widget_instance* instance = (widget_instance*)client_data;
+  widget_value* val;
+  
+  if (w->core.being_destroyed)
+    return;
+
+  val = lw_get_widget_value_for_widget (instance, w);
+#if 0
+  /* #### - this code used to (for some random back_asswards reason) pass
+  the expression below in the call_data slot.  For incremental menu
+  construction, this needs to go.  I can't even figure out why it was done
+  this way in the first place...it's just a historical wierdism. --Stig */
+  call_data = (val ? val->call_data : NULL);
+#endif 
+  if (val && val->call_data)
+    abort();			/* #### - the call_data for the top_level
+				   "menubar" widget_value used to be passed
+				   back to the pre_hook. */
+
+  if (instance->info->pre_activate_cb)
+    instance->info->pre_activate_cb (w, instance->info->id, call_data);
+}
+
+static void
+pick_hook (Widget w, XtPointer client_data, XtPointer call_data)
+{
+  widget_instance* instance = (widget_instance*)client_data;
+  widget_value* contents_val = (widget_value*)call_data;
+  widget_value* widget_val;
+  XtPointer widget_arg;
+  LWLIB_ID id;
+  lw_callback post_activate_cb;
+
+  if (w->core.being_destroyed)
+    return;
+
+  /* Grab these values before running any functions, in case running
+     the selection_cb causes the widget to be destroyed. */
+  id = instance->info->id;
+  post_activate_cb = instance->info->post_activate_cb;
+
+  widget_val = lw_get_widget_value_for_widget (instance, w);
+  widget_arg = widget_val ? widget_val->call_data : NULL;
+
+  if (instance->info->selection_cb &&
+      contents_val &&
+      contents_val->enabled &&
+      !contents_val->contents)
+    instance->info->selection_cb (w, id, contents_val->call_data);
+
+  if (post_activate_cb)
+    post_activate_cb (w, id, widget_arg);
+}
+
+
+
+/* creation functions */
+static Widget
+xlw_create_menubar (widget_instance* instance)
+{
+  Widget widget =
+    XtVaCreateWidget (instance->info->name, xlwMenuWidgetClass,
+		      instance->parent,
+		      XtNmenu, instance->info->val,
+		      0);
+  XtAddCallback (widget, XtNopen, pre_hook, (XtPointer)instance);
+  XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
+  return widget;
+}
+
+static Widget
+xlw_create_popup_menu (widget_instance* instance)
+{
+  Widget popup_shell =
+    XtCreatePopupShell (instance->info->name, overrideShellWidgetClass,
+			instance->parent, NULL, 0);
+  
+  Widget widget = 
+    XtVaCreateManagedWidget ("popup", xlwMenuWidgetClass,
+			     popup_shell,
+			     XtNmenu, instance->info->val,
+			     XtNhorizontal, False,
+			     0);
+
+  XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
+
+  return popup_shell;
+}
+#endif /* MENUBARS_LUCID */
+
+#ifdef SCROLLBARS_LUCID
+static void
+xlw_scrollbar_callback (Widget widget, XtPointer closure, XtPointer call_data)
+{
+  widget_instance *instance = (widget_instance *) closure;
+  LWLIB_ID id;
+  XlwScrollBarCallbackStruct *data =
+    (XlwScrollBarCallbackStruct *) call_data;
+  scroll_event event_data;
+  scrollbar_values *val =
+    (scrollbar_values *) instance->info->val->scrollbar_data;
+  double percent;
+
+  if (!instance || widget->core.being_destroyed)
+    return;
+
+  id = instance->info->id;
+
+  percent = (double) (data->value - 1) / (double) (INT_MAX - 1);
+  event_data.slider_value =
+    (int) (percent * (double) (val->maximum - val->minimum)) + val->minimum;
+
+  if (event_data.slider_value > (val->maximum - val->slider_size))
+    event_data.slider_value = val->maximum - val->slider_size;
+  else if (event_data.slider_value < val->minimum)
+    event_data.slider_value = val->minimum;
+
+  if (data->event)
+    {
+      switch (data->event->xany.type)
+	{
+	case KeyPress:
+	case KeyRelease:
+	  event_data.time = data->event->xkey.time;
+	  break;
+	case ButtonPress:
+	case ButtonRelease:
+	  event_data.time = data->event->xbutton.time;
+	  break;
+	case MotionNotify:
+	  event_data.time = data->event->xmotion.time;
+	  break;
+	case EnterNotify:
+	case LeaveNotify:
+	  event_data.time = data->event->xcrossing.time;
+	  break;
+	default:
+	  event_data.time = 0;
+	  break;
+	}
+    }
+  else
+    event_data.time = 0;
+
+  switch (data->reason)
+    {
+    case XmCR_DECREMENT:
+      event_data.action = SCROLLBAR_LINE_UP;
+      break;
+    case XmCR_INCREMENT:
+      event_data.action = SCROLLBAR_LINE_DOWN;
+      break;
+    case XmCR_PAGE_DECREMENT:
+      event_data.action = SCROLLBAR_PAGE_UP;
+      break;
+    case XmCR_PAGE_INCREMENT:
+      event_data.action = SCROLLBAR_PAGE_DOWN;
+      break;
+    case XmCR_TO_TOP:
+      event_data.action = SCROLLBAR_TOP;
+      break;
+    case XmCR_TO_BOTTOM:
+      event_data.action = SCROLLBAR_BOTTOM;
+      break;
+    case XmCR_DRAG:
+      event_data.action = SCROLLBAR_DRAG;
+      break;
+    case XmCR_VALUE_CHANGED:
+      event_data.action = SCROLLBAR_CHANGE;
+      break;
+    default:
+      event_data.action = SCROLLBAR_CHANGE;
+      break;
+    }
+
+  if (instance->info->pre_activate_cb)
+    instance->info->pre_activate_cb (widget, id, (XtPointer) &event_data);
+}
+
+/* #### Does not yet support horizontal scrollbars. */
+static Widget
+xlw_create_scrollbar (widget_instance *instance, int vertical)
+{
+  Arg al[20];
+  int ac = 0;
+  Widget scrollbar;
+
+  XtSetArg (al[ac], XmNminimum, 1); ac++;
+  XtSetArg (al[ac], XmNmaximum, INT_MAX); ac++;
+  XtSetArg (al[ac], XmNincrement, 1); ac++;
+  XtSetArg (al[ac], XmNpageIncrement, 1); ac++;
+  if (vertical)
+    {
+      XtSetArg (al[ac], XmNorientation, XmVERTICAL); ac++;
+    }
+  else
+    {
+      XtSetArg (al[ac], XmNorientation, XmHORIZONTAL); ac++;
+    }
+
+  scrollbar =
+    XtCreateWidget (instance->info->name, xlwScrollBarWidgetClass, instance->parent, al, ac);
+
+  XtAddCallback(scrollbar, XmNdecrementCallback, xlw_scrollbar_callback,
+		(XtPointer) instance);
+  XtAddCallback(scrollbar, XmNdragCallback, xlw_scrollbar_callback,
+		(XtPointer) instance);
+  XtAddCallback(scrollbar, XmNincrementCallback, xlw_scrollbar_callback,
+		(XtPointer) instance);
+  XtAddCallback(scrollbar, XmNpageDecrementCallback, xlw_scrollbar_callback,
+		(XtPointer) instance);
+  XtAddCallback(scrollbar, XmNpageIncrementCallback, xlw_scrollbar_callback,
+		(XtPointer) instance);
+  XtAddCallback(scrollbar, XmNtoBottomCallback, xlw_scrollbar_callback,
+		(XtPointer) instance);
+  XtAddCallback(scrollbar, XmNtoTopCallback, xlw_scrollbar_callback,
+		(XtPointer) instance);
+  XtAddCallback(scrollbar, XmNvalueChangedCallback, xlw_scrollbar_callback,
+		(XtPointer) instance);
+
+  return scrollbar;
+}
+
+static Widget
+xlw_create_vertical_scrollbar (widget_instance *instance)
+{
+  return xlw_create_scrollbar (instance, 1);
+}
+
+static Widget
+xlw_create_horizontal_scrollbar (widget_instance *instance)
+{
+  return xlw_create_scrollbar (instance, 0);
+}
+
+static void
+xlw_update_scrollbar (widget_instance *instance, Widget widget,
+		      widget_value *val)
+{
+  if (val->scrollbar_data)
+    {
+      scrollbar_values *data = val->scrollbar_data;
+      int widget_sliderSize, widget_val;
+      int new_sliderSize, new_value;
+      double percent;
+
+      /*
+       * First size and position the scrollbar widget.
+       */
+      XtVaSetValues (widget,
+		     XtNx, data->scrollbar_x,
+		     XtNy, data->scrollbar_y,
+		     XtNwidth, data->scrollbar_width,
+		     XtNheight, data->scrollbar_height,
+		     0);
+
+      /*
+       * Now the size the scrollbar's slider.
+       */
+
+      XtVaGetValues (widget,
+		     XmNsliderSize, &widget_sliderSize,
+		     XmNvalue, &widget_val,
+		     0);
+
+      percent = (double) data->slider_size /
+	(double) (data->maximum - data->minimum);
+      percent = (percent > 1.0 ? 1.0 : percent);
+      new_sliderSize = (int) ((double) (INT_MAX - 1) * percent);
+
+      percent = (double) (data->slider_position - data->minimum) /
+	(double) (data->maximum - data->minimum);
+      percent = (percent > 1.0 ? 1.0 : percent);
+      new_value = (int) ((double) (INT_MAX - 1) * percent);
+
+      if (new_sliderSize > (INT_MAX - 1))
+	new_sliderSize = INT_MAX - 1;
+      if (new_sliderSize < 1)
+	new_sliderSize = 1;
+
+      if (new_value > (INT_MAX - new_sliderSize))
+	new_value = INT_MAX - new_sliderSize;
+      else if (new_value < 1)
+	new_value = 1;
+
+      if (new_sliderSize != widget_sliderSize || new_value != widget_val)
+	XlwScrollBarSetValues (widget, new_value, new_sliderSize, 1, 1, False);
+    }
+}
+
+#endif /* SCROLLBARS_LUCID */
+
+widget_creation_entry 
+xlw_creation_table [] =
+{
+#ifdef MENUBARS_LUCID
+  {"menubar", xlw_create_menubar},
+  {"popup", xlw_create_popup_menu},
+#endif
+#ifdef SCROLLBARS_LUCID
+  {"vertical-scrollbar",	xlw_create_vertical_scrollbar},
+  {"horizontal-scrollbar",	xlw_create_horizontal_scrollbar},
+#endif
+  {NULL, NULL}
+};
+
+Boolean
+lw_lucid_widget_p (Widget widget)
+{
+  WidgetClass the_class = XtClass (widget);
+#ifdef MENUBARS_LUCID
+  if (the_class == xlwMenuWidgetClass)
+    return True;
+#endif
+#ifdef SCROLLBARS_LUCID
+  if (the_class == xlwScrollBarWidgetClass)
+    return True;
+#endif
+#ifdef MENUBARS_LUCID
+  if (the_class == overrideShellWidgetClass)
+    return
+      XtClass (((CompositeWidget)widget)->composite.children [0])
+	== xlwMenuWidgetClass;
+#endif
+  return False;
+}
+
+void
+xlw_update_one_widget (widget_instance* instance, Widget widget,
+		       widget_value* val, Boolean deep_p)
+{
+  WidgetClass class;
+
+  class = XtClass (widget);
+
+  if (0)
+    ;
+#ifdef MENUBARS_LUCID
+  else if (class == xlwMenuWidgetClass)
+    {
+      XlwMenuWidget mw;
+      if (XtIsShell (widget))
+	mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0];
+      else
+	mw = (XlwMenuWidget)widget;
+      XtVaSetValues (widget, XtNmenu, val, 0);
+    }
+#endif
+#ifdef SCROLLBARS_LUCID
+  else if (class == xlwScrollBarWidgetClass)
+    {
+      xlw_update_scrollbar (instance, widget, val);
+    }
+#endif
+}
+
+void
+xlw_update_one_value (widget_instance* instance, Widget widget,
+		      widget_value* val)
+{
+  return;
+}
+
+void
+xlw_pop_instance (widget_instance* instance, Boolean up)
+{
+}
+
+#ifdef MENUBARS_LUCID
+void
+xlw_popup_menu (Widget widget, XEvent *event)
+{
+  XlwMenuWidget mw;
+
+  if (!XtIsShell (widget))
+    return;
+
+  if (event->type == ButtonPress || event->type == ButtonRelease)
+    {
+      mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0];
+      xlw_pop_up_menu (mw, (XButtonPressedEvent *)event);
+    }
+  else
+    abort ();
+}
+#endif
+
+/* Destruction of instances */
+void
+xlw_destroy_instance (widget_instance* instance)
+{
+  if (instance->widget)
+    XtDestroyWidget (instance->widget);
+}
+