summaryrefslogtreecommitdiff
path: root/iup/src/mot
diff options
context:
space:
mode:
Diffstat (limited to 'iup/src/mot')
-rwxr-xr-xiup/src/mot/iupmot_button.c301
-rwxr-xr-xiup/src/mot/iupmot_canvas.c639
-rwxr-xr-xiup/src/mot/iupmot_clipboard.c208
-rwxr-xr-xiup/src/mot/iupmot_color.c380
-rwxr-xr-xiup/src/mot/iupmot_color.h36
-rwxr-xr-xiup/src/mot/iupmot_colordlg.c31
-rwxr-xr-xiup/src/mot/iupmot_common.c630
-rwxr-xr-xiup/src/mot/iupmot_dialog.c1069
-rwxr-xr-xiup/src/mot/iupmot_drv.h75
-rwxr-xr-xiup/src/mot/iupmot_filedlg.c578
-rwxr-xr-xiup/src/mot/iupmot_focus.c35
-rwxr-xr-xiup/src/mot/iupmot_font.c443
-rwxr-xr-xiup/src/mot/iupmot_fontdlg.c31
-rwxr-xr-xiup/src/mot/iupmot_frame.c257
-rwxr-xr-xiup/src/mot/iupmot_globalattrib.c155
-rwxr-xr-xiup/src/mot/iupmot_image.c397
-rwxr-xr-xiup/src/mot/iupmot_key.c425
-rwxr-xr-xiup/src/mot/iupmot_label.c256
-rwxr-xr-xiup/src/mot/iupmot_list.c1404
-rwxr-xr-xiup/src/mot/iupmot_loop.c108
-rwxr-xr-xiup/src/mot/iupmot_menu.c457
-rwxr-xr-xiup/src/mot/iupmot_messagedlg.c191
-rwxr-xr-xiup/src/mot/iupmot_open.c141
-rwxr-xr-xiup/src/mot/iupmot_progressbar.c165
-rwxr-xr-xiup/src/mot/iupmot_tabs.c593
-rwxr-xr-xiup/src/mot/iupmot_text.c1165
-rwxr-xr-xiup/src/mot/iupmot_timer.c70
-rwxr-xr-xiup/src/mot/iupmot_tips.c226
-rwxr-xr-xiup/src/mot/iupmot_toggle.c469
-rwxr-xr-xiup/src/mot/iupmot_tree.c2848
-rwxr-xr-xiup/src/mot/iupmot_val.c488
-rwxr-xr-xiup/src/mot/iupunix_help.c44
-rwxr-xr-xiup/src/mot/iupunix_info.c305
33 files changed, 14620 insertions, 0 deletions
diff --git a/iup/src/mot/iupmot_button.c b/iup/src/mot/iupmot_button.c
new file mode 100755
index 0000000..2d93588
--- /dev/null
+++ b/iup/src/mot/iupmot_button.c
@@ -0,0 +1,301 @@
+/** \file
+ * \brief Button Control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+#include <Xm/PushB.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdarg.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_object.h"
+#include "iup_childtree.h"
+#include "iup_attrib.h"
+#include "iup_dialog.h"
+#include "iup_str.h"
+#include "iup_button.h"
+#include "iup_drv.h"
+#include "iup_image.h"
+#include "iup_key.h"
+
+#include "iupmot_drv.h"
+
+
+void iupdrvButtonAddBorders(int *x, int *y)
+{
+ int border_size = 2*5;
+ (*x) += border_size;
+ (*y) += border_size;
+}
+
+static int motButtonSetTitleAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->type == IUP_BUTTON_TEXT)
+ {
+ iupmotSetMnemonicTitle(ih, value);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int motButtonSetAlignmentAttrib(Ihandle* ih, const char* value)
+{
+ unsigned char align;
+ char value1[30]="", value2[30]="";
+
+ iupStrToStrStr(value, value1, value2, ':'); /* value2 is ignored, NOT supported in Motif */
+
+ if (iupStrEqualNoCase(value1, "ARIGHT"))
+ align = XmALIGNMENT_END;
+ else if (iupStrEqualNoCase(value1, "ACENTER"))
+ align = XmALIGNMENT_CENTER;
+ else /* "ALEFT" */
+ align = XmALIGNMENT_BEGINNING;
+
+ XtVaSetValues (ih->handle, XmNalignment, align, NULL);
+ return 1;
+}
+
+static int motButtonSetImageAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->type == IUP_BUTTON_IMAGE)
+ {
+ iupmotSetPixmap(ih, value, XmNlabelPixmap, 0);
+
+ if (!iupAttribGet(ih, "IMINACTIVE"))
+ {
+ /* if not active and IMINACTIVE is not defined
+ then automaticaly create one based on IMAGE */
+ iupmotSetPixmap(ih, value, XmNlabelInsensitivePixmap, 1); /* make_inactive */
+ }
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static int motButtonSetImInactiveAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->type == IUP_BUTTON_IMAGE)
+ {
+ iupmotSetPixmap(ih, value, XmNlabelInsensitivePixmap, 0);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static int motButtonSetImPressAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->type == IUP_BUTTON_IMAGE)
+ {
+ iupmotSetPixmap(ih, value, XmNarmPixmap, 0);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static int motButtonSetPaddingAttrib(Ihandle* ih, const char* value)
+{
+ iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
+ if (ih->handle)
+ {
+ XtVaSetValues(ih->handle, XmNmarginHeight, ih->data->vert_padding,
+ XmNmarginWidth, ih->data->horiz_padding, NULL);
+ }
+ return 0;
+}
+
+static int motButtonSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ if (iupAttribGet(ih, "IMPRESS") || iupAttribGetBoolean(ih, "FLAT"))
+ {
+ /* ignore given value, must use only from parent */
+ value = iupBaseNativeParentGetBgColor(ih);
+
+ if (iupdrvBaseSetBgColorAttrib(ih, value))
+ return 1;
+ }
+
+ return iupdrvBaseSetBgColorAttrib(ih, value);
+}
+
+static int motButtonSetBackgroundAttrib(Ihandle* ih, const char* value)
+{
+ if (iupAttribGet(ih, "IMPRESS") || iupAttribGetBoolean(ih, "FLAT"))
+ {
+ /* ignore given value, must use only from parent */
+ value = iupAttribGetInheritNativeParent(ih, "BACKGROUND");
+
+ if (iupdrvBaseSetBgColorAttrib(ih, value))
+ return 1;
+ else
+ {
+ Pixmap pixmap = (Pixmap)iupImageGetImage(value, ih, 0);
+ if (pixmap)
+ {
+ XtVaSetValues(ih->handle, XmNbackgroundPixmap, pixmap, NULL);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static void motButtonActivateCallback(Widget w, Ihandle* ih, XtPointer call_data)
+{
+ Icallback cb;
+
+ /* Must manually hide the tip if the button is pressed. */
+ iupmotTipLeaveNotify();
+
+ cb = IupGetCallback(ih, "ACTION");
+ if (cb)
+ {
+ if (cb(ih) == IUP_CLOSE)
+ IupExitLoop();
+ }
+ (void)w;
+ (void)call_data;
+}
+
+static void motButtonEnterLeaveWindowEvent(Widget w, Ihandle* ih, XEvent *evt, Boolean *cont)
+{
+ iupmotEnterLeaveWindowEvent(w, ih, evt, cont);
+
+ if (evt->type == EnterNotify)
+ XtVaSetValues(ih->handle, XmNshadowThickness, 2, NULL);
+ else if (evt->type == LeaveNotify)
+ XtVaSetValues(ih->handle, XmNshadowThickness, 0, NULL);
+}
+
+static int motButtonMapMethod(Ihandle* ih)
+{
+ char* value;
+ int num_args = 0;
+ Arg args[30];
+
+ value = iupAttribGet(ih, "IMAGE");
+ if (value)
+ {
+ ih->data->type = IUP_BUTTON_IMAGE;
+ iupmotSetArg(args, num_args, XmNlabelType, XmPIXMAP);
+ }
+ else
+ {
+ ih->data->type = IUP_BUTTON_TEXT;
+ iupmotSetArg(args, num_args, XmNlabelType, XmSTRING);
+ }
+
+ /* Core */
+ iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+ iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+ iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ /* Label */
+ iupmotSetArg(args, num_args, XmNrecomputeSize, False); /* no automatic resize from text */
+ iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
+ iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+ iupmotSetArg(args, num_args, XmNmarginTop, 0); /* no extra margins */
+ iupmotSetArg(args, num_args, XmNmarginLeft, 0);
+ iupmotSetArg(args, num_args, XmNmarginBottom, 0);
+ iupmotSetArg(args, num_args, XmNmarginRight, 0);
+ /* PushButton */
+ iupmotSetArg(args, num_args, XmNfillOnArm, False);
+
+ /* Primitive */
+ if (iupAttribGetBoolean(ih, "FOCUSONCLICK"))
+ {
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+ iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ else
+ iupmotSetArg(args, num_args, XmNtraversalOn, False);
+ }
+ else
+ iupmotSetArg(args, num_args, XmNtraversalOn, False);
+ iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
+ iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+
+ ih->handle = XtCreateManagedWidget(
+ iupDialogGetChildIdStr(ih), /* child identifier */
+ xmPushButtonWidgetClass, /* widget class */
+ iupChildTreeGetNativeParentHandle(ih), /* widget parent */
+ args, num_args);
+
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ ih->serial = iupDialogGetChildId(ih); /* must be after using the string */
+
+ XtAddCallback(ih->handle, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih);
+
+ value = iupAttribGet(ih, "IMPRESS");
+ if (iupAttribGetBoolean(ih, "FLAT") && !value)
+ {
+ XtVaSetValues(ih->handle, XmNshadowThickness, 0, NULL);
+ XtAddEventHandler(ih->handle, EnterWindowMask, False, (XtEventHandler)motButtonEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, LeaveWindowMask, False, (XtEventHandler)motButtonEnterLeaveWindowEvent, (XtPointer)ih);
+ }
+ else
+ {
+ if (value && !iupAttribGetStr(ih, "IMPRESSBORDER"))
+ XtVaSetValues(ih->handle, XmNshadowThickness, 0, NULL);
+ else
+ XtVaSetValues(ih->handle, XmNshadowThickness, 2, NULL);
+ XtAddEventHandler(ih->handle, EnterWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, LeaveWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ }
+
+ XtAddEventHandler(ih->handle, FocusChangeMask, False, (XtEventHandler)iupmotFocusChangeEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, KeyPressMask, False, (XtEventHandler)iupmotKeyPressEvent, (XtPointer)ih);
+
+ XtAddCallback(ih->handle, XmNactivateCallback, (XtCallbackProc)motButtonActivateCallback, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, ButtonPressMask|ButtonReleaseMask, False, (XtEventHandler)iupmotButtonPressReleaseEvent, (XtPointer)ih);
+
+ /* Disable Drag Source */
+ iupmotDisableDragSource(ih->handle);
+
+ /* initialize the widget */
+ XtRealizeWidget(ih->handle);
+
+ if (ih->data->type == IUP_BUTTON_TEXT)
+ iupmotSetString(ih->handle, XmNlabelString, "");
+
+ return IUP_NOERROR;
+}
+
+void iupdrvButtonInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class functions */
+ ic->Map = motButtonMapMethod;
+
+ /* Driver Dependent Attribute functions */
+
+ /* Visual */
+ iupClassRegisterAttribute(ic, "BGCOLOR", iupmotGetBgColorAttrib, motButtonSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BACKGROUND", NULL, motButtonSetBackgroundAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+
+ /* Special */
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, iupdrvBaseSetFgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGFGCOLOR", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "TITLE", NULL, motButtonSetTitleAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+
+ /* IupButton only */
+ iupClassRegisterAttribute(ic, "ALIGNMENT", NULL, motButtonSetAlignmentAttrib, "ACENTER:ACENTER", NULL, IUPAF_NO_INHERIT); /* force new default value */
+ iupClassRegisterAttribute(ic, "IMAGE", NULL, motButtonSetImageAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "IMINACTIVE", NULL, motButtonSetImInactiveAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "IMPRESS", NULL, motButtonSetImPressAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "FOCUSONCLICK", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute(ic, "PADDING", iupButtonGetPaddingAttrib, motButtonSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
+}
diff --git a/iup/src/mot/iupmot_canvas.c b/iup/src/mot/iupmot_canvas.c
new file mode 100755
index 0000000..7777cf3
--- /dev/null
+++ b/iup/src/mot/iupmot_canvas.c
@@ -0,0 +1,639 @@
+/** \file
+ * \brief Canvas Control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+#include <Xm/ScrolledW.h>
+#include <Xm/DrawingA.h>
+#include <Xm/ScrollBar.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdarg.h>
+#include <limits.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_object.h"
+#include "iup_childtree.h"
+#include "iup_attrib.h"
+#include "iup_dialog.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_drvfont.h"
+#include "iup_canvas.h"
+#include "iup_key.h"
+
+#include "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+
+static void motDialogScrollbarCallback(Widget w, XtPointer client_data, XtPointer call_data)
+{
+ int op = (int)client_data, ipage, ipos;
+ Ihandle *ih;
+ IFniff cb;
+ double posx, posy;
+ (void)call_data;
+
+ XtVaGetValues(w, XmNuserData, &ih, NULL);
+ if (!ih) return;
+
+ XtVaGetValues(w,
+ XmNvalue, &ipos,
+ XmNpageIncrement, &ipage,
+ NULL);
+
+ if (op > IUP_SBDRAGV)
+ {
+ iupCanvasCalcScrollRealPos(iupAttribGetFloat(ih,"XMIN"), iupAttribGetFloat(ih,"XMAX"), &posx,
+ IUP_SB_MIN, IUP_SB_MAX, ipage, &ipos);
+ ih->data->posx = (float)posx;
+ posy = ih->data->posy;
+ }
+ else
+ {
+ iupCanvasCalcScrollRealPos(iupAttribGetFloat(ih,"YMIN"), iupAttribGetFloat(ih,"YMAX"), &posy,
+ IUP_SB_MIN, IUP_SB_MAX, ipage, &ipos);
+ ih->data->posy = (float)posy;
+ posx = ih->data->posx;
+ }
+
+ cb = (IFniff)IupGetCallback(ih,"SCROLL_CB");
+ if (cb)
+ cb(ih, op, (float)posx, (float)posy);
+ else
+ {
+ IFnff cb = (IFnff)IupGetCallback(ih,"ACTION");
+ if (cb)
+ cb (ih, (float)posx, (float)posy);
+ }
+}
+
+static void motCanvasResizeCallback(Widget w, Ihandle *ih, XtPointer call_data)
+{
+ Dimension width, height;
+ IFnii cb;
+ (void)call_data;
+
+ if (!XtWindow(w) || !ih) return;
+
+ /* client size */
+ XtVaGetValues(w, XmNwidth, &width,
+ XmNheight, &height,
+ NULL);
+
+ cb = (IFnii)IupGetCallback(ih,"RESIZE_CB");
+ if (cb)
+ cb(ih,width,height);
+}
+
+static int motCanvasSetBgColorAttrib(Ihandle* ih, const char* value);
+
+static void motCanvasExposeCallback(Widget w, Ihandle *ih, XtPointer call_data)
+{
+ IFnff cb;
+ (void)call_data;
+
+ if (!XtWindow(w) || !ih) return;
+
+ cb = (IFnff)IupGetCallback(ih,"ACTION");
+ if (cb)
+ {
+ if (!iupAttribGet(ih, "_IUPMOT_NO_BGCOLOR"))
+ motCanvasSetBgColorAttrib(ih, iupAttribGetStr(ih, "BGCOLOR")); /* reset to update window attributes */
+
+ cb (ih, ih->data->posx, ih->data->posy);
+ }
+}
+
+static void motCanvasInputCallback(Widget w, Ihandle *ih, XtPointer call_data)
+{
+ XEvent *evt = ((XmDrawingAreaCallbackStruct*)call_data)->event;
+
+ if (!XtWindow(w) || !ih) return;
+
+ switch (evt->type)
+ {
+ case ButtonPress:
+ /* Force focus on canvas click */
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+ XmProcessTraversal(w, XmTRAVERSE_CURRENT);
+ /* break missing on purpose... */
+ case ButtonRelease:
+ {
+ XButtonEvent *but_evt = (XButtonEvent*)evt;
+ Boolean cont = True;
+ iupmotButtonPressReleaseEvent(w, ih, evt, &cont);
+ if (cont == False)
+ return;
+
+ if ((evt->type==ButtonPress) && (but_evt->button==Button4 || but_evt->button==Button5))
+ {
+ IFnfiis wcb = (IFnfiis)IupGetCallback(ih, "WHEEL_CB");
+ if (wcb)
+ {
+ char status[IUPKEY_STATUS_SIZE] = IUPKEY_STATUS_INIT;
+ int delta = but_evt->button==Button4? 1: -1;
+ iupmotButtonKeySetStatus(but_evt->state, but_evt->button, status, 0);
+
+ wcb(ih, (float)delta, but_evt->x, but_evt->y, status);
+ }
+ else
+ {
+ IFniff scb = (IFniff)IupGetCallback(ih,"SCROLL_CB");
+ float posy = ih->data->posy;
+ int delta = but_evt->button==Button4? 1: -1;
+ int op = but_evt->button==Button4? IUP_SBUP: IUP_SBDN;
+ posy -= delta*iupAttribGetFloat(ih, "DY")/10.0f;
+ IupSetfAttribute(ih, "POSY", "%g", posy);
+ if (scb)
+ scb(ih,op,ih->data->posx,ih->data->posy);
+ }
+ }
+ }
+ break;
+ }
+}
+
+static void motCanvasSetScrollInfo(Widget sb, int imin, int imax, int ipos, int ipage, int iline)
+{
+ XtVaSetValues(sb,
+ XmNminimum, imin,
+ XmNmaximum, imax,
+ XmNvalue, ipos,
+ XmNincrement, iline,
+ XmNpageIncrement, ipage,
+ XmNsliderSize, ipage, /* to make the thumb proportional */
+ NULL);
+}
+
+static int motCanvasSetDXAttrib(Ihandle* ih, const char *value)
+{
+ if (ih->data->sb & IUP_SB_HORIZ)
+ {
+ double posx, xmin, xmax, linex;
+ float dx;
+ int iposx, ipagex, ilinex;
+ Widget sb_horiz, sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ XtVaGetValues(sb_win, XmNhorizontalScrollBar, &sb_horiz, NULL);
+ if (!sb_horiz) return 1;
+
+ if (!iupStrToFloat(value, &dx))
+ return 1;
+
+ xmin = iupAttribGetFloat(ih, "XMIN");
+ xmax = iupAttribGetFloat(ih, "XMAX");
+ posx = ih->data->posx;
+
+ iupCanvasCalcScrollIntPos(xmin, xmax, dx, posx,
+ IUP_SB_MIN, IUP_SB_MAX, &ipagex, &iposx);
+
+ if (!iupAttribGet(ih,"LINEX"))
+ {
+ ilinex = ipagex/10;
+ if (!ilinex)
+ ilinex = 1;
+ }
+ else
+ {
+ /* line and page convertions are the same */
+ linex = iupAttribGetFloat(ih,"LINEX");
+ iupCanvasCalcScrollIntPos(xmin, xmax, linex, 0,
+ IUP_SB_MIN, IUP_SB_MAX, &ilinex, NULL);
+ }
+
+ if (dx >= (xmax-xmin))
+ {
+ if (iupAttribGetBoolean(ih, "XAUTOHIDE"))
+ XtUnmanageChild(sb_horiz);
+ else
+ XtSetSensitive(sb_horiz, 0);
+ return 1;
+ }
+ else
+ {
+ if (!XtIsManaged(sb_horiz))
+ XtManageChild(sb_horiz);
+ XtSetSensitive(sb_horiz, 1);
+ }
+
+ motCanvasSetScrollInfo(sb_horiz, IUP_SB_MIN, IUP_SB_MAX, iposx, ipagex, ilinex);
+
+ /* update position because it could be corrected */
+ iupCanvasCalcScrollRealPos(xmin, xmax, &posx,
+ IUP_SB_MIN, IUP_SB_MAX, ipagex, &iposx);
+
+ ih->data->posx = (float)posx;
+ }
+ return 1;
+}
+
+static int motCanvasSetPosXAttrib(Ihandle* ih, const char *value)
+{
+ if (ih->data->sb & IUP_SB_HORIZ)
+ {
+ double xmin, xmax, dx;
+ float posx;
+ int iposx, ipagex;
+ Widget sb_horiz, sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ XtVaGetValues(sb_win, XmNhorizontalScrollBar, &sb_horiz, NULL);
+ if (!sb_horiz) return 1;
+
+ if (!iupStrToFloat(value, &posx))
+ return 1;
+
+ xmin = iupAttribGetFloat(ih, "XMIN");
+ xmax = iupAttribGetFloat(ih, "XMAX");
+ dx = iupAttribGetFloat(ih, "DX");
+
+ if (posx < xmin) posx = (float)xmin;
+ if (posx > (xmax - dx)) posx = (float)(xmax - dx);
+ ih->data->posx = posx;
+
+ iupCanvasCalcScrollIntPos(xmin, xmax, dx, posx,
+ IUP_SB_MIN, IUP_SB_MAX, &ipagex, &iposx);
+
+ XtVaSetValues(sb_horiz, XmNvalue, iposx, NULL);
+ }
+ return 1;
+}
+
+static int motCanvasSetDYAttrib(Ihandle* ih, const char *value)
+{
+ if (ih->data->sb & IUP_SB_VERT)
+ {
+ double posy, ymin, ymax, liney;
+ float dy;
+ int iposy, ipagey, iliney;
+ Widget sb_vert, sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ XtVaGetValues(sb_win, XmNverticalScrollBar, &sb_vert, NULL);
+ if (!sb_vert) return 1;
+
+ if (!iupStrToFloat(value, &dy))
+ return 1;
+
+ ymin = iupAttribGetFloat(ih, "YMIN");
+ ymax = iupAttribGetFloat(ih, "YMAX");
+ posy = ih->data->posy;
+
+ iupCanvasCalcScrollIntPos(ymin, ymax, dy, posy,
+ IUP_SB_MIN, IUP_SB_MAX, &ipagey, &iposy);
+
+ if (!iupAttribGet(ih,"LINEY"))
+ {
+ iliney = ipagey/10;
+ if (!iliney)
+ iliney = 1;
+ }
+ else
+ {
+ /* line and page convertions are the same */
+ liney = iupAttribGetFloat(ih,"LINEY");
+ iupCanvasCalcScrollIntPos(ymin, ymax, liney, 0,
+ IUP_SB_MIN, IUP_SB_MAX, &iliney, NULL);
+ }
+
+ if (dy >= (ymax-ymin))
+ {
+ if (iupAttribGetBoolean(ih, "YAUTOHIDE"))
+ XtUnmanageChild(sb_vert);
+ else
+ XtSetSensitive(sb_vert, 0);
+ return 1;
+ }
+ else
+ {
+ if (!XtIsManaged(sb_vert))
+ XtManageChild(sb_vert);
+ XtSetSensitive(sb_vert, 1);
+ }
+
+ motCanvasSetScrollInfo(sb_vert, IUP_SB_MIN, IUP_SB_MAX, iposy, ipagey, iliney);
+
+ /* update position because it could be corrected */
+ iupCanvasCalcScrollRealPos(ymin, ymax, &posy,
+ IUP_SB_MIN, IUP_SB_MAX, ipagey, &iposy);
+
+ ih->data->posy = (float)posy;
+ }
+ return 1;
+}
+
+static int motCanvasSetPosYAttrib(Ihandle* ih, const char *value)
+{
+ if (ih->data->sb & IUP_SB_VERT)
+ {
+ double ymin, ymax, dy;
+ float posy;
+ int iposy, ipagey;
+ Widget sb_vert, sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ XtVaGetValues(sb_win, XmNverticalScrollBar, &sb_vert, NULL);
+ if (!sb_vert) return 1;
+
+ if (!iupStrToFloat(value, &posy))
+ return 1;
+
+ ymin = iupAttribGetFloat(ih, "YMIN");
+ ymax = iupAttribGetFloat(ih, "YMAX");
+ dy = iupAttribGetFloat(ih, "DY");
+
+ if (posy < ymin) posy = (float)ymin;
+ if (posy > (ymax - dy)) posy = (float)(ymax - dy);
+ ih->data->posy = posy;
+
+ iupCanvasCalcScrollIntPos(ymin, ymax, dy, posy,
+ IUP_SB_MIN, IUP_SB_MAX, &ipagey, &iposy);
+
+ XtVaSetValues(sb_vert, XmNvalue, iposy, NULL);
+ }
+ return 1;
+}
+
+static char* motCanvasGetXDisplayAttrib(Ihandle *ih)
+{
+ (void)ih;
+ return (char*)iupmot_display;
+}
+
+static char* motCanvasGetXScreenAttrib(Ihandle *ih)
+{
+ (void)ih;
+ return (char*)iupmot_screen;
+}
+
+static char* motCanvasGetXWindowAttrib(Ihandle *ih)
+{
+ return (char*)XtWindow(ih->handle);
+}
+
+static char* motCanvasGetClientSizeAttrib(Ihandle *ih)
+{
+ char* str = iupStrGetMemory(20);
+
+ Dimension width, height;
+ XtVaGetValues(ih->handle, XmNwidth, &width,
+ XmNheight, &height,
+ NULL);
+
+ sprintf(str, "%dx%d", (int)width, (int)height);
+ return str;
+}
+
+static int motCanvasSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ Pixel color;
+
+ /* ignore given value, must use only from parent for the scrollbars */
+ char* parent_value = iupBaseNativeParentGetBgColor(ih);
+
+ color = iupmotColorGetPixelStr(parent_value);
+ if (color != (Pixel)-1)
+ {
+ Widget sb;
+ Widget sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+
+ iupmotSetBgColor(sb_win, color);
+
+ XtVaGetValues(sb_win, XmNverticalScrollBar, &sb, NULL);
+ if (sb) iupmotSetBgColor(sb, color);
+
+ XtVaGetValues(sb_win, XmNhorizontalScrollBar, &sb, NULL);
+ if (sb) iupmotSetBgColor(sb, color);
+ }
+
+ if (!IupGetCallback(ih, "ACTION"))
+ iupdrvBaseSetBgColorAttrib(ih, value); /* Use the given value only here */
+ else
+ {
+ XSetWindowAttributes attrs;
+ attrs.background_pixmap = None;
+ XChangeWindowAttributes(iupmot_display, XtWindow(ih->handle), CWBackPixmap, &attrs);
+ iupAttribSetStr(ih, "_IUPMOT_NO_BGCOLOR", "1");
+ }
+
+ return 1;
+}
+
+static void motCanvasLayoutUpdateMethod(Ihandle *ih)
+{
+ Widget sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ Dimension border;
+
+ /* IMPORTANT:
+ The ScrolledWindow border, added by the Core, is NOT included in the Motif size.
+ So when setting the size, we must compensate the border,
+ so the actual size will be the size we expect.
+ */
+
+ XtVaGetValues(sb_win, XmNborderWidth, &border, NULL);
+
+ XtVaSetValues(sb_win,
+ XmNx, (XtArgVal)ih->x,
+ XmNy, (XtArgVal)ih->y,
+ XmNwidth, (XtArgVal)(ih->currentwidth-2*border),
+ XmNheight, (XtArgVal)(ih->currentheight-2*border),
+ NULL);
+}
+
+static int motCanvasMapMethod(Ihandle* ih)
+{
+ Widget sb_win;
+ char *visual;
+ int num_args = 0;
+ Arg args[20];
+
+ if (!ih->parent)
+ return IUP_ERROR;
+
+ ih->data->sb = iupBaseGetScrollbar(ih);
+
+ /******************************/
+ /* Create the scrolled window */
+ /******************************/
+
+ iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupmotSetArg(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED);
+ iupmotSetArg(args, num_args, XmNvisualPolicy, XmVARIABLE);
+ iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between scrollbars and draw area */
+ iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+
+ if (iupAttribGetBoolean(ih, "BORDER"))
+ {
+ iupmotSetArg(args, num_args, XmNborderWidth, 1);
+ iupmotSetArg(args, num_args, XmNborderColor, iupmotColorGetPixelStr("0 0 0"));
+ }
+ else
+ iupmotSetArg(args, num_args, XmNborderWidth, 0);
+
+ sb_win = XtCreateManagedWidget(
+ iupDialogGetChildIdStr(ih), /* child identifier */
+ xmScrolledWindowWidgetClass, /* widget class */
+ iupChildTreeGetNativeParentHandle(ih), /* widget parent */
+ args, num_args);
+
+ if (!sb_win)
+ return IUP_ERROR;
+
+ ih->serial = iupDialogGetChildId(ih); /* must be after using the string */
+
+ /****************************/
+ /* Create the drawing area */
+ /****************************/
+
+ num_args = 0;
+ iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* no shadow margins */
+ iupmotSetArg(args, num_args, XmNmarginWidth, 0); /* no shadow margins */
+ iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+ iupmotSetArg(args, num_args, XmNresizePolicy, XmRESIZE_NONE); /* no automatic resize of children */
+ if (ih->iclass->is_interactive)
+ {
+ iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP); /* include in navigation */
+
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+ iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ else
+ iupmotSetArg(args, num_args, XmNtraversalOn, False);
+ }
+ else
+ {
+ iupmotSetArg(args, num_args, XmNnavigationType, XmNONE);
+ iupmotSetArg(args, num_args, XmNtraversalOn, False);
+ }
+
+ iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+ iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+ iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+
+ visual = IupGetAttribute(ih, "VISUAL"); /* defined by the OpenGL Canvas or NULL */
+ if (visual)
+ {
+ Colormap colormap = (Colormap)iupAttribGet(ih, "COLORMAP");
+ if (colormap)
+ iupmotSetArg(args, num_args, XmNcolormap,colormap);
+
+ iupmotDialogSetVisual(ih, visual);
+ }
+
+ ih->handle = XtCreateManagedWidget(
+ "draw_area", /* child identifier */
+ xmDrawingAreaWidgetClass, /* widget class */
+ sb_win, /* widget parent */
+ args, num_args);
+
+ if (!ih->handle)
+ {
+ XtDestroyWidget(sb_win);
+ return IUP_ERROR;
+ }
+
+ if (visual)
+ iupmotDialogResetVisual(ih);
+
+ iupAttribSetStr(ih, "_IUP_EXTRAPARENT", (char*)sb_win);
+ XtVaSetValues(sb_win, XmNworkWindow, ih->handle, NULL);
+
+ {
+ XSetWindowAttributes attrs;
+ attrs.bit_gravity = ForgetGravity; /* For the DrawingArea widget gets Expose events when you resize it to be smaller. */
+
+ if (iupAttribGetBoolean(ih, "BACKINGSTORE"))
+ attrs.backing_store = WhenMapped;
+ else
+ attrs.backing_store = NotUseful;
+
+ XChangeWindowAttributes(iupmot_display, XtWindow(ih->handle), CWBitGravity|CWBackingStore, &attrs);
+ }
+
+ if (ih->data->sb & IUP_SB_HORIZ)
+ {
+ Widget sb_horiz = XtVaCreateManagedWidget("sb_horiz",
+ xmScrollBarWidgetClass, sb_win,
+ XmNorientation, XmHORIZONTAL,
+ XmNsliderMark, XmTHUMB_MARK,
+ XmNuserData, ih,
+ NULL);
+
+ XtAddCallback(sb_horiz, XmNvalueChangedCallback, motDialogScrollbarCallback, (void*)IUP_SBPOSH);
+ XtAddCallback(sb_horiz, XmNdragCallback, motDialogScrollbarCallback, (void*)IUP_SBDRAGH);
+ XtAddCallback(sb_horiz, XmNdecrementCallback, motDialogScrollbarCallback, (void*)IUP_SBLEFT);
+ XtAddCallback(sb_horiz, XmNincrementCallback, motDialogScrollbarCallback, (void*)IUP_SBRIGHT);
+ XtAddCallback(sb_horiz, XmNpageDecrementCallback, motDialogScrollbarCallback, (void*)IUP_SBPGLEFT);
+ XtAddCallback(sb_horiz, XmNpageIncrementCallback, motDialogScrollbarCallback, (void*)IUP_SBPGRIGHT);
+
+ XtVaSetValues(sb_win, XmNhorizontalScrollBar, sb_horiz, NULL);
+ }
+
+ if (ih->data->sb & IUP_SB_VERT)
+ {
+ Widget sb_vert = XtVaCreateManagedWidget("sb_vert",
+ xmScrollBarWidgetClass, sb_win,
+ XmNorientation, XmVERTICAL,
+ XmNsliderMark, XmTHUMB_MARK,
+ XmNuserData, ih,
+ NULL);
+
+ XtAddCallback(sb_vert, XmNvalueChangedCallback, motDialogScrollbarCallback, (void*)IUP_SBPOSV);
+ XtAddCallback(sb_vert, XmNdragCallback, motDialogScrollbarCallback, (void*)IUP_SBDRAGV);
+ XtAddCallback(sb_vert, XmNdecrementCallback, motDialogScrollbarCallback, (void*)IUP_SBUP);
+ XtAddCallback(sb_vert, XmNincrementCallback, motDialogScrollbarCallback, (void*)IUP_SBDN);
+ XtAddCallback(sb_vert, XmNpageDecrementCallback, motDialogScrollbarCallback, (void*)IUP_SBPGUP);
+ XtAddCallback(sb_vert, XmNpageIncrementCallback, motDialogScrollbarCallback, (void*)IUP_SBPGDN);
+
+ XtVaSetValues(sb_win, XmNverticalScrollBar, sb_vert, NULL);
+ }
+
+ XtAddCallback(ih->handle, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih);
+ XtAddCallback(ih->handle, XmNexposeCallback, (XtCallbackProc)motCanvasExposeCallback, (XtPointer)ih);
+ XtAddCallback(ih->handle, XmNresizeCallback, (XtCallbackProc)motCanvasResizeCallback, (XtPointer)ih);
+ XtAddCallback(ih->handle, XmNinputCallback, (XtCallbackProc)motCanvasInputCallback, (XtPointer)ih);
+
+ XtAddEventHandler(ih->handle, EnterWindowMask, False,(XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, LeaveWindowMask, False,(XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+
+ XtAddEventHandler(ih->handle, FocusChangeMask, False,(XtEventHandler)iupmotFocusChangeEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, KeyPressMask, False, (XtEventHandler)iupmotKeyPressEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, KeyReleaseMask, False, (XtEventHandler)iupmotCanvasKeyReleaseEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, PointerMotionMask, False, (XtEventHandler)iupmotPointerMotionEvent, (XtPointer)ih);
+
+ /* initialize the widget */
+ XtRealizeWidget(sb_win);
+
+ return IUP_NOERROR;
+}
+
+void iupdrvCanvasInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class functions */
+ ic->Map = motCanvasMapMethod;
+ ic->LayoutUpdate = motCanvasLayoutUpdateMethod;
+
+ /* Driver Dependent Attribute functions */
+
+ /* Visual */
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, motCanvasSetBgColorAttrib, "255 255 255", NULL, IUPAF_DEFAULT); /* force new default value */
+
+ /* IupCanvas only */
+ iupClassRegisterAttribute(ic, "DRAWSIZE", motCanvasGetClientSizeAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "CURSOR", NULL, iupdrvBaseSetCursorAttrib, IUPAF_SAMEASSYSTEM, "ARROW", IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute(ic, "DX", NULL, motCanvasSetDXAttrib, "0.1", NULL, IUPAF_NO_INHERIT); /* force new default value */
+ iupClassRegisterAttribute(ic, "DY", NULL, motCanvasSetDYAttrib, "0.1", NULL, IUPAF_NO_INHERIT); /* force new default value */
+ iupClassRegisterAttribute(ic, "POSX", iupCanvasGetPosXAttrib, motCanvasSetPosXAttrib, "0.0", NULL, IUPAF_NO_INHERIT); /* force new default value */
+ iupClassRegisterAttribute(ic, "POSY", iupCanvasGetPosYAttrib, motCanvasSetPosYAttrib, "0.0", NULL, IUPAF_NO_INHERIT); /* force new default value */
+ iupClassRegisterAttribute(ic, "YAUTOHIDE", NULL, NULL, "YES", NULL, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "XAUTOHIDE", NULL, NULL, "YES", NULL, IUPAF_NOT_MAPPED);
+
+ /* IupCanvas X only */
+ iupClassRegisterAttribute(ic, "XWINDOW", motCanvasGetXWindowAttrib, NULL, NULL, NULL, IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+ iupClassRegisterAttribute(ic, "XDISPLAY", motCanvasGetXDisplayAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+ iupClassRegisterAttribute(ic, "XSCREEN", motCanvasGetXScreenAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+ iupClassRegisterAttribute(ic, "BACKINGSTORE", NULL, NULL, "YES", NULL, IUPAF_NOT_MAPPED);
+}
diff --git a/iup/src/mot/iupmot_clipboard.c b/iup/src/mot/iupmot_clipboard.c
new file mode 100755
index 0000000..43a0087
--- /dev/null
+++ b/iup/src/mot/iupmot_clipboard.c
@@ -0,0 +1,208 @@
+/** \file
+ * \brief Clipboard for the Motif Driver.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <Xm/Xm.h>
+#include <Xm/CutPaste.h>
+
+#include "iup.h"
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_image.h"
+
+#include "iupmot_drv.h"
+
+
+static Window motClipboardGetWindow(void)
+{
+ Ihandle* focus = IupGetFocus();
+ Ihandle* dlg;
+ if (!focus) return (Window)NULL;
+ dlg = IupGetDialog(focus);
+ if (dlg)
+ return XtWindow(dlg->handle);
+ else
+ return (Window)NULL;
+}
+
+static int motClipboardSetTextAttrib(Ihandle *ih, const char *value)
+{
+ long item_id = 0;
+ Window window = motClipboardGetWindow();
+ XmString clip_label = XmStringCreateLocalized ("IupClipboard");
+ (void)ih;
+
+ if (XmClipboardStartCopy(iupmot_display, window, clip_label, CurrentTime, NULL, NULL, &item_id)!=ClipboardSuccess)
+ {
+ XmStringFree(clip_label);
+ return 0;
+ }
+
+ XmStringFree(clip_label);
+
+ XmClipboardCopy(iupmot_display, window, item_id, "STRING", (char*)value, (long)strlen(value)+1, 0, NULL);
+ XmClipboardEndCopy(iupmot_display, window, item_id);
+ return 0;
+}
+
+static char* motClipboardGetTextAttrib(Ihandle *ih)
+{
+ unsigned long size;
+ char* str;
+ Window window = motClipboardGetWindow();
+ (void)ih;
+
+ if (XmClipboardInquireLength(iupmot_display, window, "STRING", &size)!=ClipboardSuccess)
+ return NULL;
+
+ str = iupStrGetMemory(size+1);
+
+ if (XmClipboardRetrieve(iupmot_display, window, "STRING", str, size+1, NULL, NULL)!=ClipboardSuccess)
+ return NULL;
+
+ return str;
+}
+
+static int motClipboardSetImageAttrib(Ihandle *ih, const char *value)
+{
+ Pixmap pixmap;
+ long item_id = 0;
+ Window window = motClipboardGetWindow();
+ XmString clip_label = XmStringCreateLocalized ("IupClipboard");
+
+ if (XmClipboardStartCopy(iupmot_display, window, clip_label, CurrentTime, NULL, NULL, &item_id)!=ClipboardSuccess)
+ {
+ XmStringFree(clip_label);
+ return 0;
+ }
+
+ XmStringFree(clip_label);
+
+ pixmap = (Pixmap)iupImageGetImage(value, ih, 0);
+
+ XmClipboardCopy(iupmot_display, window, item_id, "PIXMAP", (char*)&pixmap, sizeof(Pixmap), 0, NULL);
+ XmClipboardEndCopy(iupmot_display, window, item_id);
+
+ (void)ih;
+ return 0;
+}
+
+static int motClipboardSetNativeImageAttrib(Ihandle *ih, const char *value)
+{
+ long item_id = 0;
+ Window window = motClipboardGetWindow();
+ XmString clip_label = XmStringCreateLocalized ("IupClipboard");
+ Pixmap pixmap = (Pixmap)value;
+
+ if (XmClipboardStartCopy(iupmot_display, window, clip_label, CurrentTime, NULL, NULL, &item_id)!=ClipboardSuccess)
+ {
+ XmStringFree(clip_label);
+ return 0;
+ }
+
+ XmStringFree(clip_label);
+
+ XmClipboardCopy(iupmot_display, window, item_id, "PIXMAP", (char*)&pixmap, sizeof(Pixmap), 0, NULL);
+ XmClipboardEndCopy(iupmot_display, window, item_id);
+
+ (void)ih;
+ return 0;
+}
+
+static char* motClipboardGetNativeImageAttrib(Ihandle *ih)
+{
+ unsigned long size;
+ void* data;
+ Pixmap pixmap;
+ Window window = motClipboardGetWindow();
+ (void)ih;
+
+ if (XmClipboardInquireLength(iupmot_display, window, "PIXMAP", &size)!=ClipboardSuccess)
+ return NULL;
+
+ data = XtMalloc(size);
+
+ if (XmClipboardRetrieve(iupmot_display, window, "PIXMAP", data, size, NULL, NULL)!=ClipboardSuccess)
+ return NULL;
+
+ pixmap = *((Pixmap*)data);
+ XtFree(data);
+ return (char*)pixmap;
+}
+
+static int motClipboardIsAvailable(const char* format_name)
+{
+ Window window = motClipboardGetWindow();
+ int count, i;
+ unsigned long max_length, length;
+ char* str;
+
+ if (XmClipboardInquireCount(iupmot_display, window, &count, &max_length) != ClipboardSuccess)
+ return 0;
+
+ str = iupStrGetMemory(max_length+1);
+
+ for (i = 1; i<=count; i++)
+ {
+ if (XmClipboardInquireFormat(iupmot_display, window, i, str, max_length+1, &length)==ClipboardSuccess)
+ {
+ if (iupStrEqualNoCase(str, format_name))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static char* motClipboardGetTextAvailableAttrib(Ihandle *ih)
+{
+ (void)ih;
+ if (motClipboardIsAvailable("STRING"))
+ return "YES";
+ else
+ return "NO";
+}
+
+static char* motClipboardGetImageAvailableAttrib(Ihandle *ih)
+{
+ (void)ih;
+ if (motClipboardIsAvailable("PIXMAP"))
+ return "YES";
+ else
+ return "NO";
+}
+
+/******************************************************************************/
+
+Ihandle* IupClipboard(void)
+{
+ return IupCreate("clipboard");
+}
+
+Iclass* iupClipboardGetClass(void)
+{
+ Iclass* ic = iupClassNew(NULL);
+
+ ic->name = "clipboard";
+ ic->format = NULL; /* no parameters */
+ ic->nativetype = IUP_TYPECONTROL;
+ ic->childtype = IUP_CHILDNONE;
+ ic->is_interactive = 0;
+
+ /* Attribute functions */
+ iupClassRegisterAttribute(ic, "TEXT", motClipboardGetTextAttrib, motClipboardSetTextAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NATIVEIMAGE", motClipboardGetNativeImageAttrib, motClipboardSetNativeImageAttrib, NULL, NULL, IUPAF_NO_STRING|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "IMAGE", NULL, motClipboardSetImageAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "TEXTAVAILABLE", motClipboardGetTextAvailableAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "IMAGEAVAILABLE", motClipboardGetImageAvailableAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ return ic;
+}
diff --git a/iup/src/mot/iupmot_color.c b/iup/src/mot/iupmot_color.c
new file mode 100755
index 0000000..276bccc
--- /dev/null
+++ b/iup/src/mot/iupmot_color.c
@@ -0,0 +1,380 @@
+/** \file
+ * \brief Motif Driver color management
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <Xm/Xm.h>
+#include <X11/Xproto.h>
+
+#include "iup.h"
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drvinfo.h"
+
+#include "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+
+/* local variables */
+
+typedef struct _Icolor
+{
+ Colormap colormap; /* colormap for all canvas, dialogs and menus */
+ XColor color_table[256]; /* colormap colors */
+ int num_colors; /* number of colors in colormap */
+
+ int rshift; /* red shift for truecolor */
+ int gshift; /* green shift for truecolor */
+ int bshift; /* blue shift for truecolor */
+
+ int direct_conv[256]; /* used with directColor visuals */
+} Icolor;
+
+static Icolor mot_color;
+
+
+/*******************************************
+ NOT TrueColor Functions
+*******************************************/
+
+static int motColor8BppErrorHandler(Display* dpy, XErrorEvent *err)
+{
+ char msg[80];
+
+ /* BadAcess in XFreeColors is OK */
+ if (err->request_code==X_FreeColors && err->error_code==BadAccess)
+ return 0;
+
+ XGetErrorText(dpy, err->error_code, msg, 80 );
+ fprintf(stderr,"IUP Motif error handler: Xlib request %d: %s\n", err->request_code, msg);
+
+ return 0;
+}
+
+static unsigned long motColorNearestRGB(XColor* xc1)
+{
+ static int nearest_try = 0;
+
+ int pos = 0, i;
+ unsigned long min_dist = ULONG_MAX, this_dist;
+ int dr, dg, db;
+ XColor* xc2;
+
+ for (i=0; i<mot_color.num_colors; i++)
+ {
+ xc2 = &(mot_color.color_table[i]);
+
+ dr = (xc1->red - xc2->red) / 850; /* 0.30 / 255 */
+ dg = (xc1->green - xc2->green) / 432; /* 0.59 / 255 */
+ db = (xc1->blue - xc2->blue) / 2318; /* 0.11 / 255 */
+
+ this_dist = dr*dr + dg*dg + db*db;
+
+ if (this_dist < min_dist)
+ {
+ min_dist = this_dist;
+ pos = i;
+ }
+ }
+
+ /* verifico se a cor ainda esta alocada */
+ /* Try to allocate the closest match color. This should only
+ fail if the cell is read/write. Otherwise, we're incrementing
+ the cell's reference count. (comentario extraido da biblioteca Mesa) */
+ if (!XAllocColor(iupmot_display, mot_color.colormap,
+ &(mot_color.color_table[pos])))
+ {
+ /* nao esta, preciso atualizar a tabela e procurar novamente */
+ /* isto acontece porque a cor encontrada pode ter sido de uma aplicacao que nao existe mais */
+ /* uma vez atualizada, o problema nao ocorrera' na nova procura */
+ /* ou a celula e' read write */
+
+ if (nearest_try == 1)
+ {
+ nearest_try = 0;
+ return mot_color.color_table[pos].pixel;
+ }
+
+ XQueryColors(iupmot_display, mot_color.colormap, mot_color.color_table, mot_color.num_colors);
+
+ nearest_try = 1; /* garante que so' vai tentar isso uma vez */
+ return motColorNearestRGB(xc1);
+ }
+
+ return mot_color.color_table[pos].pixel;
+}
+
+static unsigned long motColorGetPixel_NotTrueColor(unsigned char cr, unsigned char cg, unsigned char cb)
+{
+ unsigned long pixel;
+ XColor xc;
+ xc.red = iupCOLOR8TO16(cr);
+ xc.green = iupCOLOR8TO16(cg);
+ xc.blue = iupCOLOR8TO16(cb);
+ xc.flags = DoRed | DoGreen | DoBlue;
+
+ /* verificamos se a nova cor ja' esta' disponivel */
+ if (!XAllocColor(iupmot_display, mot_color.colormap, &xc))
+ {
+ /* nao estava disponivel, procuro pela mais proxima na tabela de cores */
+ pixel = motColorNearestRGB(&xc);
+ }
+ else
+ {
+ /* ja' estava disponivel */
+ /* atualizo a tabela de cores */
+ mot_color.color_table[xc.pixel] = xc;
+ pixel = xc.pixel;
+ }
+
+ return pixel;
+}
+
+static void motColorGetRGB_NotTrueColor(unsigned long pixel, unsigned char* red, unsigned char* green, unsigned char* blue)
+{
+ XColor xc;
+ xc.pixel = pixel;
+ XQueryColor(iupmot_display, mot_color.colormap, &xc);
+ *red = (unsigned char)xc.red;
+ *green = (unsigned char)xc.green;
+ *blue = (unsigned char)xc.blue;
+}
+
+static void motColorReserveColors(void)
+{
+ unsigned char r, g, b;
+ unsigned long background, foreground, shadow, highlight, selection;
+ XtVaGetValues(iupmot_appshell, XmNbackground, &background, NULL);
+ XmGetColors(DefaultScreenOfDisplay(iupmot_display), mot_color.colormap,
+ background, &foreground, &highlight, &shadow, &selection);
+ motColorGetRGB_NotTrueColor(background, &r, &g, &b);
+ motColorGetPixel_NotTrueColor(r, g, b);
+ motColorGetRGB_NotTrueColor(foreground, &r, &g, &b);
+ motColorGetPixel_NotTrueColor(r, g, b);
+ motColorGetRGB_NotTrueColor(shadow, &r, &g, &b);
+ motColorGetPixel_NotTrueColor(r, g, b);
+ motColorGetRGB_NotTrueColor(highlight, &r, &g, &b);
+ motColorGetPixel_NotTrueColor(r, g, b);
+ motColorGetRGB_NotTrueColor(selection, &r, &g, &b);
+ motColorGetPixel_NotTrueColor(r, g, b);
+}
+
+
+/*******************************************
+ TrueColor Functions
+*******************************************/
+
+
+static void motColorGetRGB_TrueColor(unsigned long pixel, unsigned char* red, unsigned char* green, unsigned char* blue)
+{
+ unsigned long r = pixel & iupmot_visual->red_mask;
+ unsigned long g = pixel & iupmot_visual->green_mask;
+ unsigned long b = pixel & iupmot_visual->blue_mask;
+ if (mot_color.rshift<0) r = r >> (-mot_color.rshift);
+ else r = r << mot_color.rshift;
+ if (mot_color.gshift<0) g = g >> (-mot_color.gshift);
+ else g = g << mot_color.gshift;
+ if (mot_color.bshift<0) b = b >> (-mot_color.bshift);
+ else b = b << mot_color.bshift;
+ *red = iupCOLOR16TO8(r);
+ *green = iupCOLOR16TO8(g);
+ *blue = iupCOLOR16TO8(b);
+}
+
+static unsigned long motColorGetPixel_TrueColor(unsigned char cr, unsigned char cg, unsigned char cb)
+{
+ unsigned long r = iupCOLOR8TO16(cr);
+ unsigned long g = iupCOLOR8TO16(cg);
+ unsigned long b = iupCOLOR8TO16(cb);
+
+ if (mot_color.rshift<0)
+ r = r << (-mot_color.rshift);
+ else
+ r = r >> mot_color.rshift;
+
+ if (mot_color.gshift<0)
+ g = g << (-mot_color.gshift);
+ else
+ g = g >> mot_color.gshift;
+
+ if (mot_color.bshift<0)
+ b = b << (-mot_color.bshift);
+ else
+ b = b >> mot_color.bshift;
+
+ r = r & iupmot_visual->red_mask;
+ g = g & iupmot_visual->green_mask;
+ b = b & iupmot_visual->blue_mask;
+
+ return r | g | b;
+}
+
+static int motColorHighBit(unsigned long ul)
+{
+/* returns position of highest set bit in 'ul' as an integer (0-31),
+ or -1 if none */
+ int i; unsigned long hb;
+
+ hb = 0x80; hb = hb << 24; /* hb = 0x80000000UL */
+ for (i=31; ((ul & hb) == 0) && i>=0; i--, ul<<=1);
+ return i;
+}
+
+static void motColorMakeDirectCmap(Colormap cmap)
+{
+ int i, cmaplen, numgot;
+ unsigned char origgot[256];
+ XColor c;
+ unsigned long rmask, gmask, bmask;
+ int rshift, gshift, bshift;
+
+ rmask = iupmot_visual->red_mask;
+ gmask = iupmot_visual->green_mask;
+ bmask = iupmot_visual->blue_mask;
+
+ rshift = motColorHighBit(rmask) - 15;
+ gshift = motColorHighBit(gmask) - 15;
+ bshift = motColorHighBit(bmask) - 15;
+
+ if (rshift<0) rmask = rmask << (-rshift);
+ else rmask = rmask >> rshift;
+
+ if (gshift<0) gmask = gmask << (-gshift);
+ else gmask = gmask >> gshift;
+
+ if (bshift<0) bmask = bmask << (-bshift);
+ else bmask = bmask >> bshift;
+
+ cmaplen = iupmot_visual->map_entries;
+ if (cmaplen>256) cmaplen=256;
+
+ /* try to alloc a 'cmaplen' long grayscale colormap. May not get all
+ entries for whatever reason. Build table 'mot_color.direct_conv[]' that
+ maps range [0..(cmaplen-1)] into set of colors we did get */
+
+ for (i=0; i<256; i++) { origgot[i] = 0; mot_color.direct_conv[i] = i; }
+
+ for (i=numgot=0; i<cmaplen; i++)
+ {
+ c.red = c.green = c.blue = (unsigned short)((i * 0xffff) / (cmaplen - 1));
+ c.red = (unsigned short)(c.red & rmask);
+ c.green = (unsigned short)(c.green & gmask);
+ c.blue = (unsigned short)(c.blue & bmask);
+ c.flags = DoRed | DoGreen | DoBlue;
+
+ if (XAllocColor(iupmot_display, cmap, &c))
+ {
+ origgot[i] = 1;
+ numgot++;
+ }
+ }
+
+ if (numgot == 0)
+ return;
+
+ /* mot_color.direct_conv may or may not have holes in it. */
+ for (i=0; i<cmaplen; i++)
+ {
+ if (!origgot[i])
+ {
+ int numbak, numfwd;
+ numbak = numfwd = 0;
+ while ((i - numbak) >= 0 && !origgot[i-numbak]) numbak++;
+ while ((i + numfwd) < cmaplen && !origgot[i+numfwd]) numfwd++;
+
+ if (i-numbak<0 || !origgot[i-numbak]) numbak = 999;
+ if (i+numfwd>=cmaplen || !origgot[i+numfwd]) numfwd = 999;
+
+ if (numbak<numfwd) mot_color.direct_conv[i] = mot_color.direct_conv[i-numbak];
+ else if (numfwd<999) mot_color.direct_conv[i] = mot_color.direct_conv[i+numfwd];
+ }
+ }
+}
+
+
+/*******************************************
+ Exported Functions
+*******************************************/
+
+unsigned long (* iupmotColorGetPixel)(unsigned char r, unsigned char g, unsigned char b) = 0;
+void (* iupmotColorGetRGB)(unsigned long pixel, unsigned char* red, unsigned char* green, unsigned char* blue) = 0;
+
+void iupmotColorInit(void)
+{
+ int depth = iupdrvGetScreenDepth();
+
+ if (depth > 8)
+ {
+ iupmotColorGetRGB = motColorGetRGB_TrueColor;
+ iupmotColorGetPixel = motColorGetPixel_TrueColor;
+
+ /* make linear colormap for DirectColor visual */
+ if (iupmot_visual->class == DirectColor)
+ motColorMakeDirectCmap(DefaultColormap(iupmot_display, iupmot_screen));
+
+ mot_color.rshift = 15 - motColorHighBit(iupmot_visual->red_mask);
+ mot_color.gshift = 15 - motColorHighBit(iupmot_visual->green_mask);
+ mot_color.bshift = 15 - motColorHighBit(iupmot_visual->blue_mask);
+
+ mot_color.num_colors = 0;
+ mot_color.colormap = 0;
+ }
+ else
+ {
+ int i;
+ iupmotColorGetRGB = motColorGetRGB_NotTrueColor;
+ iupmotColorGetPixel = motColorGetPixel_NotTrueColor;
+
+ mot_color.colormap = DefaultColormap(iupmot_display, iupmot_screen);
+ mot_color.num_colors = 1L << depth;
+
+ for (i=0; i<mot_color.num_colors; i++)
+ mot_color.color_table[i].pixel = i;
+
+ XQueryColors(iupmot_display, mot_color.colormap, mot_color.color_table, mot_color.num_colors);
+ XSetErrorHandler(motColor8BppErrorHandler);
+
+ motColorReserveColors();
+ }
+}
+
+void iupmotColorFinish(void)
+{
+ if (mot_color.colormap)
+ {
+ unsigned long pixels[256];
+ int i;
+
+ /* release colors */
+ for (i = 0; i < mot_color.num_colors; i++)
+ pixels[i] = mot_color.color_table[i].pixel;
+
+ XFreeColors(iupmot_display, mot_color.colormap, pixels, mot_color.num_colors, 0);
+
+ /* release palette */
+ if (mot_color.colormap != DefaultColormap(iupmot_display, iupmot_screen))
+ XFreeColormap(iupmot_display, mot_color.colormap);
+ }
+}
+
+Colormap iupmotColorMap(void)
+{
+ return mot_color.colormap;
+}
+
+unsigned long iupmotColorGetPixelStr(const char* color)
+{
+ unsigned char r, g, b;
+ if (!iupStrToRGB(color, &r, &g, &b))
+ return (unsigned long)-1;
+
+ return iupmotColorGetPixel(r, g, b);
+}
diff --git a/iup/src/mot/iupmot_color.h b/iup/src/mot/iupmot_color.h
new file mode 100755
index 0000000..a306fd3
--- /dev/null
+++ b/iup/src/mot/iupmot_color.h
@@ -0,0 +1,36 @@
+/** \file
+ * \brief Motif Color Management
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMOT_COLOR_H
+#define __IUPMOT_COLOR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Returns a pixel value from a RGB triple. */
+extern unsigned long (* iupmotColorGetPixel)(unsigned char r, unsigned char g, unsigned char b);
+
+/* Returns a RGB triple from a pixel value. */
+extern void (* iupmotColorGetRGB)(unsigned long pixel, unsigned char *r, unsigned char *g, unsigned char *b);
+
+/* initialize the toplevel colormap and the iupmotColorGet* functions */
+void iupmotColorInit(void);
+void iupmotColorFinish(void);
+
+/* returns the toplevel colormap */
+Colormap iupmotColorMap(void);
+
+/* Returns a pixel value from a IUP color description. */
+unsigned long iupmotColorGetPixelStr(const char* color);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/src/mot/iupmot_colordlg.c b/iup/src/mot/iupmot_colordlg.c
new file mode 100755
index 0000000..7a949bf
--- /dev/null
+++ b/iup/src/mot/iupmot_colordlg.c
@@ -0,0 +1,31 @@
+/** \file
+ * \brief IupColorDlg pre-defined dialog
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+
+#include "iup.h"
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drvinfo.h"
+#include "iup_dialog.h"
+
+#include "iupmot_drv.h"
+
+
+static int motColorDlgPopup(Ihandle* ih, int x, int y)
+{
+ (void)ih;
+ (void)x;
+ (void)y;
+ return IUP_ERROR;
+}
+
+void iupdrvColorDlgInitClass(Iclass* ic)
+{
+ ic->DlgPopup = motColorDlgPopup;
+}
diff --git a/iup/src/mot/iupmot_common.c b/iup/src/mot/iupmot_common.c
new file mode 100755
index 0000000..7b3f8b7
--- /dev/null
+++ b/iup/src/mot/iupmot_common.c
@@ -0,0 +1,630 @@
+/** \file
+ * \brief Motif Base Functions
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <Xm/Xm.h>
+#include <Xm/ScrollBar.h>
+#include <X11/cursorfont.h>
+
+#include "iup.h"
+#include "iupkey.h"
+#include "iupcbs.h"
+
+#include "iup_object.h"
+#include "iup_childtree.h"
+#include "iup_key.h"
+#include "iup_str.h"
+#include "iup_class.h"
+#include "iup_attrib.h"
+#include "iup_focus.h"
+#include "iup_key.h"
+#include "iup_drv.h"
+#include "iup_image.h"
+#include "iup_drv.h"
+
+#include "iupmot_color.h"
+#include "iupmot_drv.h"
+
+
+
+void iupdrvActivate(Ihandle* ih)
+{
+ if (iupStrEqual(ih->iclass->name, "text") || iupStrEqual(ih->iclass->name, "multiline"))
+ XmProcessTraversal(ih->handle, XmTRAVERSE_CURRENT);
+ else
+ XtCallActionProc(ih->handle, "ArmAndActivate", 0, 0, 0 );
+}
+
+static int motActivateMnemonic(Ihandle *dialog, int c)
+{
+ Ihandle *ih;
+ char attrib[19] = "_IUPMOT_MNEMONIC_ ";
+ attrib[17] = (char)c;
+ ih = (Ihandle*)iupAttribGet(dialog, attrib);
+ if (iupObjectCheck(ih))
+ {
+ iupdrvActivate(ih);
+ return IUP_IGNORE;
+ }
+ return IUP_CONTINUE;
+}
+
+void iupmotSetMnemonicTitle(Ihandle *ih, const char* value)
+{
+ char c;
+ char* str;
+
+ if (!value)
+ value = "";
+
+ str = iupStrProcessMnemonic(value, &c, -1); /* remove & and return in c */
+ if (str != value)
+ {
+ KeySym keysym = iupmotKeyCharToKeySym(c);
+ XtVaSetValues(ih->handle, XmNmnemonic, keysym, NULL); /* works only for menus, but underlines the letter */
+
+ if (ih->iclass->nativetype != IUP_TYPEMENU)
+ {
+ Ihandle* dialog = IupGetDialog(ih);
+ char attrib[22] = "_IUPMOT_MNEMONIC_ \0CB";
+ attrib[17] = (char)toupper(c);
+
+ /* used by motActivateMnemonic */
+ if (iupStrEqual(ih->iclass->name, "label"))
+ iupAttribSetStr(dialog, attrib, (char*)iupFocusNextInteractive(ih));
+ else
+ iupAttribSetStr(dialog, attrib, (char*)ih);
+
+ /* used by iupmotKeyPressEvent */
+ attrib[18] = '_';
+ IupSetCallback(dialog, attrib, (Icallback)motActivateMnemonic);
+ }
+
+ iupmotSetString(ih->handle, XmNlabelString, str);
+ free(str);
+ }
+ else
+ {
+ XtVaSetValues (ih->handle, XmNmnemonic, NULL, NULL);
+ iupmotSetString(ih->handle, XmNlabelString, str);
+ }
+}
+
+void iupmotSetString(Widget w, const char *resource, const char* value)
+{
+ XmString xm_str = XmStringCreateLocalized((String)value);
+ XtVaSetValues(w, resource, xm_str, NULL);
+ XmStringFree(xm_str);
+}
+
+char* iupmotConvertString(XmString str)
+{
+ char* text = (char*)XmStringUnparse(str, NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
+ char* buf = iupStrGetMemoryCopy(text);
+ XtFree(text);
+ return buf;
+}
+
+#ifdef OLD_CONVERT
+char* iupmotConvertString(XmString str)
+{
+ XmStringContext context;
+ char *text, *p, *buf;
+ unsigned int length;
+ XmStringComponentType type;
+
+ if (!XmStringInitContext (&context, str))
+ return NULL;
+
+ buf = iupStrGetMemory(XmStringLength(str)); /* always greatter than strlen */
+
+ /* p keeps a running pointer through buf as text is read */
+ p = buf;
+ while ((type = XmStringGetNextTriple(context, &length, (XtPointer)&text)) != XmSTRING_COMPONENT_END)
+ {
+ switch (type)
+ {
+ case XmSTRING_COMPONENT_TEXT:
+ memcpy(p, text, length);
+ p += length;
+ *p = 0;
+ break;
+ case XmSTRING_COMPONENT_TAB:
+ *p++ = '\t';
+ *p = 0;
+ break;
+ case XmSTRING_COMPONENT_SEPARATOR:
+ *p++ = '\n';
+ *p = 0;
+ break;
+ }
+ XtFree(text);
+ }
+
+ XmStringFreeContext(context);
+
+ return buf;
+}
+#endif
+
+void iupdrvReparent(Ihandle* ih)
+{
+ Widget native_parent = iupChildTreeGetNativeParentHandle(ih);
+ Widget widget = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (!widget) widget = ih->handle;
+ XReparentWindow(iupmot_display, XtWindow(widget), XtWindow(native_parent), 0, 0);
+}
+
+void iupdrvBaseLayoutUpdateMethod(Ihandle *ih)
+{
+ Widget widget = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (!widget) widget = ih->handle;
+
+ XtVaSetValues(widget,
+ XmNx, (XtArgVal)ih->x,
+ XmNy, (XtArgVal)ih->y,
+ XmNwidth, (XtArgVal)ih->currentwidth,
+ XmNheight, (XtArgVal)ih->currentheight,
+ NULL);
+}
+
+void iupdrvBaseUnMapMethod(Ihandle* ih)
+{
+ Widget widget = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (!widget) widget = ih->handle;
+
+ XtUnrealizeWidget(widget); /* To match the call to XtRealizeWidget */
+ XtDestroyWidget(widget); /* To match the call to XtCreateManagedWidget */
+}
+
+void iupdrvDisplayUpdate(Ihandle *ih)
+{
+ XExposeEvent evt;
+ Dimension w, h;
+
+ XtVaGetValues(ih->handle, XmNwidth, &w,
+ XmNheight, &h,
+ NULL);
+
+ evt.type = Expose;
+ evt.display = iupmot_display;
+ evt.send_event = True;
+ evt.window = XtWindow(ih->handle);
+
+ evt.x = 0;
+ evt.y = 0;
+ evt.width = w;
+ evt.height = h;
+
+ evt.count = 0;
+
+ /* POST a Redraw */
+ XSendEvent(iupmot_display, XtWindow(ih->handle), False, ExposureMask, (XEvent*)&evt);
+}
+
+void iupdrvDisplayRedraw(Ihandle *ih)
+{
+ Widget w;
+
+ /* POST a Redraw */
+ iupdrvDisplayUpdate(ih);
+
+ /* if this element has an inner native parent (like IupTabs),
+ then redraw that native parent if different from the element. */
+ w = (Widget)iupClassObjectGetInnerNativeContainerHandle(ih, (Ihandle*)IupGetAttribute(ih, "VALUE_HANDLE"));
+ if (w && w != ih->handle)
+ {
+ Widget handle = ih->handle;
+ ih->handle = w;
+ iupdrvDisplayUpdate(ih);
+ ih->handle = handle;
+ }
+
+ /* flush exposure events. */
+ XmUpdateDisplay(ih->handle);
+}
+
+void iupdrvScreenToClient(Ihandle* ih, int *x, int *y)
+{
+ Window child;
+ XTranslateCoordinates(iupmot_display, RootWindow(iupmot_display, iupmot_screen),
+ XtWindow(ih->handle),
+ *x, *y, x, y, &child);
+}
+
+void iupmotHelpCallback(Widget w, Ihandle *ih, XtPointer call_data)
+{
+ Icallback cb = IupGetCallback(ih, "HELP_CB");
+ if (cb && cb(ih) == IUP_CLOSE)
+ IupExitLoop();
+
+ (void)call_data;
+ (void)w;
+}
+
+void iupmotEnterLeaveWindowEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont)
+{
+ Icallback cb = NULL;
+ (void)cont;
+ (void)w;
+
+ if (evt->type == EnterNotify)
+ {
+ iupmotTipEnterNotify(ih);
+
+ cb = IupGetCallback(ih, "ENTERWINDOW_CB");
+ }
+ else if (evt->type == LeaveNotify)
+ {
+ iupmotTipLeaveNotify();
+
+ cb = IupGetCallback(ih, "LEAVEWINDOW_CB");
+ }
+
+ if (cb)
+ cb(ih);
+}
+
+int iupdrvBaseSetZorderAttrib(Ihandle* ih, const char* value)
+{
+ if (iupdrvIsVisible(ih))
+ {
+ if (iupStrEqualNoCase(value, "TOP"))
+ XRaiseWindow(iupmot_display, XtWindow(ih->handle));
+ else
+ XLowerWindow(iupmot_display, XtWindow(ih->handle));
+ }
+
+ return 0;
+}
+
+void iupdrvSetVisible(Ihandle* ih, int visible)
+{
+ Widget widget = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (!widget) widget = ih->handle;
+
+ if (visible)
+ XtMapWidget(widget);
+ else
+ XtUnmapWidget(widget);
+}
+
+int iupdrvIsVisible(Ihandle* ih)
+{
+ XWindowAttributes wa;
+ XGetWindowAttributes(iupmot_display, XtWindow(ih->handle), &wa);
+ return (wa.map_state == IsViewable);
+}
+
+int iupdrvIsActive(Ihandle* ih)
+{
+ return XtIsSensitive(ih->handle);
+}
+
+void iupdrvSetActive(Ihandle* ih, int enable)
+{
+ Widget widget = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (!widget) widget = ih->handle;
+
+ XtSetSensitive(widget, enable);
+}
+
+char* iupmotGetXWindowAttrib(Ihandle *ih)
+{
+ return (char*)XtWindow(ih->handle);
+}
+
+char* iupdrvBaseGetXAttrib(Ihandle *ih)
+{
+ int x, y;
+ Window child;
+ char* str = iupStrGetMemory(20);
+ Widget widget = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (!widget) widget = ih->handle;
+
+ /* Translating to absolute screen coordinates */
+ /* source destination */
+ XTranslateCoordinates(iupmot_display,
+ XtWindow(widget), RootWindow(iupmot_display, iupmot_screen),
+ 0, 0, &x, &y,
+ &child);
+
+ sprintf(str, "%d", x);
+ return str;
+}
+
+char* iupdrvBaseGetYAttrib(Ihandle *ih)
+{
+ int x, y;
+ Window child;
+ char* str = iupStrGetMemory(20);
+ Widget widget = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (!widget) widget = ih->handle;
+
+ /* Translating to absolute screen coordinates */
+ /* source destination */
+ XTranslateCoordinates(iupmot_display,
+ XtWindow(widget), RootWindow(iupmot_display, iupmot_screen),
+ 0, 0, &x, &y,
+ &child);
+
+ sprintf(str, "%d", y);
+ return str;
+}
+
+void iupmotSetBgColor(Widget w, Pixel color)
+{
+ Pixel fgcolor;
+ XtVaGetValues(w, XmNforeground, &fgcolor, NULL);
+ XmChangeColor(w, color);
+ /* XmChangeColor also sets the XmNforeground color, so we must reset to the previous one. */
+ XtVaSetValues(w, XmNforeground, fgcolor, NULL);
+ XtVaSetValues(w, XmNbackgroundPixmap, XmUNSPECIFIED_PIXMAP, NULL);
+}
+
+int iupdrvBaseSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ Pixel color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ {
+ iupmotSetBgColor(ih->handle, color);
+
+ /* update internal image cache for controls that have the IMAGE attribute */
+ iupImageUpdateParent(ih);
+ }
+ return 1;
+}
+
+char* iupmotGetBgColorAttrib(Ihandle* ih)
+{
+ unsigned char r, g, b;
+ Pixel color;
+ char* str = iupStrGetMemory(20);
+ XtVaGetValues(ih->handle, XmNbackground, &color, NULL);
+ iupmotColorGetRGB(color, &r, &g, &b);
+ sprintf(str, "%d %d %d", (int)r, (int)g, (int)b);
+ return str;
+}
+
+int iupdrvBaseSetFgColorAttrib(Ihandle* ih, const char* value)
+{
+ Pixel color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ XtVaSetValues(ih->handle, XmNforeground, color, NULL);
+ return 1;
+}
+
+void iupmotGetWindowSize(Ihandle *ih, int *width, int *height)
+{
+ Dimension w, h;
+ XtVaGetValues(ih->handle, XmNwidth, &w,
+ XmNheight, &h,
+ NULL);
+ *width = w;
+ *height = h;
+}
+
+static Cursor motEmptyCursor(Ihandle* ih)
+{
+ /* creates an empty cursor */
+ XColor cursor_color = {0L,0,0,0,0,0};
+ char bitsnull[1] = {0x00};
+ Pixmap pixmapnull;
+ Cursor cur;
+
+ pixmapnull = XCreateBitmapFromData(iupmot_display,
+ XtWindow(ih->handle),
+ bitsnull,
+ 1,1);
+
+ cur = XCreatePixmapCursor(iupmot_display,
+ pixmapnull,
+ pixmapnull,
+ &cursor_color,
+ &cursor_color,
+ 0,0);
+
+ XFreePixmap(iupmot_display, pixmapnull);
+
+ return cur;
+}
+
+static Cursor motGetCursor(Ihandle* ih, const char* name)
+{
+ static struct {
+ const char* iupname;
+ int sysname;
+ } table[] = {
+ { "NONE", 0},
+ { "NULL", 0},
+ { "ARROW", XC_left_ptr},
+ { "BUSY", XC_watch},
+ { "CROSS", XC_crosshair},
+ { "HAND", XC_hand2},
+ { "HELP", XC_question_arrow},
+ { "IUP", XC_question_arrow},
+ { "MOVE", XC_fleur},
+ { "PEN", XC_pencil},
+ { "RESIZE_N", XC_top_side},
+ { "RESIZE_S", XC_bottom_side},
+ { "RESIZE_NS", XC_sb_v_double_arrow},
+ { "RESIZE_W", XC_left_side},
+ { "RESIZE_E", XC_right_side},
+ { "RESIZE_WE", XC_sb_h_double_arrow},
+ { "RESIZE_NE", XC_top_right_corner},
+ { "RESIZE_SE", XC_bottom_right_corner},
+ { "RESIZE_NW", XC_top_left_corner},
+ { "RESIZE_SW", XC_bottom_left_corner},
+ { "TEXT", XC_xterm},
+ { "UPARROW", XC_center_ptr}
+ };
+
+ Cursor cur;
+ char str[50];
+ int i, count = sizeof(table)/sizeof(table[0]);
+
+ /* check the cursor cache first (per control)*/
+ sprintf(str, "_IUPMOT_CURSOR_%s", name);
+ cur = (Cursor)iupAttribGet(ih, str);
+ if (cur)
+ return cur;
+
+ /* check the pre-defined IUP names first */
+ for (i = 0; i < count; i++)
+ {
+ if (iupStrEqualNoCase(name, table[i].iupname))
+ {
+ if (table[i].sysname)
+ cur = XCreateFontCursor(iupmot_display, table[i].sysname);
+ else
+ cur = motEmptyCursor(ih);
+
+ break;
+ }
+ }
+
+ if (i == count)
+ {
+ /* check for a name defined cursor */
+ cur = (Cursor)iupImageGetCursor(name);
+ }
+
+ iupAttribSetStr(ih, str, (char*)cur);
+ return cur;
+}
+
+int iupdrvBaseSetCursorAttrib(Ihandle* ih, const char* value)
+{
+ Cursor cur = motGetCursor(ih, value);
+ if (cur)
+ {
+ XDefineCursor(iupmot_display, XtWindow(ih->handle), cur);
+ return 1;
+ }
+ return 0;
+}
+
+#include <Xm/XmP.h>
+#include <Xm/DrawP.h>
+
+void iupdrvDrawFocusRect(Ihandle* ih, void* _gc, int x, int y, int w, int h)
+{
+ Drawable wnd = (Drawable)IupGetAttribute(ih, "XWINDOW"); /* Use IupGetAttribute to consult the native implemetation */
+ GC gc = (GC)_gc;
+ XmeDrawHighlight(iupmot_display, wnd, gc, x, y, w, h, 1);
+}
+
+void iupdrvBaseRegisterCommonAttrib(Iclass* ic)
+{
+ iupClassRegisterAttribute(ic, "XMFONTLIST", iupmotGetFontListAttrib, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+ iupClassRegisterAttribute(ic, "XFONTSTRUCT", iupmotGetFontStructAttrib, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+ iupClassRegisterAttribute(ic, "XFONTID", iupmotGetFontIdAttrib, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+}
+
+static void motDoNothing(Widget w, XEvent* evt, String* params, Cardinal* num_params)
+{
+ (void)w;
+ (void)evt;
+ (void)params;
+ (void)num_params;
+}
+
+void iupmotDisableDragSource(Widget w)
+{
+ char dragTranslations[] = "#override <Btn2Down>: iupDoNothing()";
+ static int do_nothing_rec = 0;
+ if (!do_nothing_rec)
+ {
+ XtActionsRec rec = {"iupDoNothing", (XtActionProc)motDoNothing};
+ XtAppAddActions(iupmot_appcontext, &rec, 1);
+ do_nothing_rec = 1;
+ }
+ XtOverrideTranslations(w, XtParseTranslationTable(dragTranslations));
+}
+
+int iupdrvGetScrollbarSize(void)
+{
+ return 15;
+}
+
+void iupmotSetPixmap(Ihandle* ih, const char* name, const char* prop, int make_inactive)
+{
+ if (name)
+ {
+ Pixmap old_pixmap;
+ Pixmap pixmap = (Pixmap)iupImageGetImage(name, ih, make_inactive);
+ if (!pixmap)
+ pixmap = XmUNSPECIFIED_PIXMAP;
+ XtVaGetValues(ih->handle, prop, &old_pixmap, NULL);
+ if (pixmap != old_pixmap)
+ XtVaSetValues(ih->handle, prop, pixmap, NULL);
+ return;
+ }
+
+ /* if not defined */
+ XtVaSetValues(ih->handle, prop, XmUNSPECIFIED_PIXMAP, NULL);
+}
+
+void iupmotButtonPressReleaseEvent(Widget w, Ihandle* ih, XEvent* evt, Boolean* cont)
+{
+ unsigned long elapsed;
+ static Time last = 0;
+ char status[IUPKEY_STATUS_SIZE] = IUPKEY_STATUS_INIT;
+ IFniiiis cb;
+
+ XButtonEvent *but_evt = (XButtonEvent*)evt;
+ if (but_evt->button!=Button1 &&
+ but_evt->button!=Button2 &&
+ but_evt->button!=Button3 &&
+ but_evt->button!=Button4 &&
+ but_evt->button!=Button5)
+ return;
+
+ cb = (IFniiiis) IupGetCallback(ih,"BUTTON_CB");
+ if (cb)
+ {
+ int ret, doubleclick = 0;
+ int b = IUP_BUTTON1+(but_evt->button-1);
+
+ /* Double/Single Click */
+ if (but_evt->type==ButtonPress)
+ {
+ elapsed = but_evt->time - last;
+ last = but_evt->time;
+ if ((int)elapsed <= XtGetMultiClickTime(iupmot_display))
+ doubleclick = 1;
+ }
+
+ iupmotButtonKeySetStatus(but_evt->state, but_evt->button, status, doubleclick);
+
+ ret = cb(ih, b, (but_evt->type==ButtonPress), but_evt->x, but_evt->y, status);
+ if (ret==IUP_CLOSE)
+ IupExitLoop();
+ else if (ret==IUP_IGNORE)
+ *cont=False;
+ }
+
+ (void)w;
+}
+
+void iupmotPointerMotionEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont)
+{
+ IFniis cb = (IFniis)IupGetCallback(ih,"MOTION_CB");
+ if (cb)
+ {
+ XMotionEvent *motion_evt = (XMotionEvent*)evt;
+ char status[IUPKEY_STATUS_SIZE] = IUPKEY_STATUS_INIT;
+ iupmotButtonKeySetStatus(motion_evt->state, 0, status, 0);
+ cb(ih, motion_evt->x, motion_evt->y, status);
+ }
+
+ (void)w;
+ (void)cont;
+}
diff --git a/iup/src/mot/iupmot_dialog.c b/iup/src/mot/iupmot_dialog.c
new file mode 100755
index 0000000..4eeb834
--- /dev/null
+++ b/iup/src/mot/iupmot_dialog.c
@@ -0,0 +1,1069 @@
+/** \file
+ * \brief IupDialog class
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+#include <Xm/BulletinB.h>
+#include <Xm/MwmUtil.h>
+#include <Xm/AtomMgr.h>
+#include <Xm/Protocols.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdarg.h>
+#include <limits.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_class.h"
+#include "iup_object.h"
+#include "iup_childtree.h"
+#include "iup_dlglist.h"
+#include "iup_attrib.h"
+#include "iup_drv.h"
+#include "iup_drvfont.h"
+#include "iup_drvinfo.h"
+#include "iup_focus.h"
+#include "iup_str.h"
+#define _IUPDLG_PRIVATE
+#include "iup_dialog.h"
+#include "iup_image.h"
+
+#include "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+Atom iupmot_wm_deletewindow = 0; /* used also by IupMessageDlg */
+
+static int motDialogSetBgColorAttrib(Ihandle* ih, const char* value);
+
+/****************************************************************
+ Utilities
+****************************************************************/
+
+
+int iupdrvDialogIsVisible(Ihandle* ih)
+{
+ return iupdrvIsVisible(ih) || ih->data->show_state == IUP_MINIMIZE;
+}
+
+void iupdrvDialogUpdateSize(Ihandle* ih)
+{
+ Dimension width, height;
+ XtVaGetValues(ih->handle, XmNwidth, &width, XmNheight, &height, NULL);
+ ih->currentwidth = width;
+ ih->currentheight = height;
+}
+
+void iupdrvDialogGetSize(InativeHandle* handle, int *w, int *h)
+{
+ Dimension width, height;
+ XtVaGetValues(handle, XmNwidth, &width, XmNheight, &height, NULL);
+ if (w) *w = width;
+ if (h) *h = height;
+}
+
+void iupmotDialogSetVisual(Ihandle* ih, void* visual)
+{
+ Ihandle *dialog = IupGetDialog(ih);
+ XtVaSetValues(dialog->handle, XmNvisual, visual, NULL);
+}
+
+void iupmotDialogResetVisual(Ihandle* ih)
+{
+ Ihandle *dialog = IupGetDialog(ih);
+ XtVaSetValues(dialog->handle, XmNvisual, iupmot_visual, NULL);
+}
+
+void iupdrvDialogSetVisible(Ihandle* ih, int visible)
+{
+ if (visible)
+ {
+ XtMapWidget(ih->handle);
+ XRaiseWindow(iupmot_display, XtWindow(ih->handle));
+ while (!iupdrvDialogIsVisible(ih)); /* waits until window get mapped */
+ }
+ else
+ {
+ /* if iupdrvIsVisible reports hidden, then it should be minimized */
+ if (!iupdrvIsVisible(ih)) /* can NOT hide a minimized window, so map it first. */
+ {
+ XtMapWidget(ih->handle);
+ XRaiseWindow(iupmot_display, XtWindow(ih->handle));
+ while (!iupdrvDialogIsVisible(ih)); /* waits until window get mapped */
+ }
+
+ XtUnmapWidget(ih->handle);
+ while (iupdrvDialogIsVisible(ih)); /* waits until window gets unmapped */
+ }
+}
+
+void iupdrvDialogGetPosition(InativeHandle* handle, int *x, int *y)
+{
+ Dimension cur_x, cur_y;
+ XtVaGetValues(handle, XmNx, &cur_x,
+ XmNy, &cur_y,
+ NULL);
+ if (x) *x = cur_x;
+ if (y) *y = cur_y;
+}
+
+void iupdrvDialogSetPosition(Ihandle *ih, int x, int y)
+{
+ XtVaSetValues(ih->handle,
+ XmNx, (XtArgVal)x,
+ XmNy, (XtArgVal)y,
+ NULL);
+}
+
+static int motDialogGetMenuSize(Ihandle* ih)
+{
+ if (ih->data->menu)
+ return iupdrvMenuGetMenuBarSize(ih->data->menu);
+ else
+ return 0;
+}
+
+void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu)
+{
+ static int native_border = 0;
+ static int native_caption = 0;
+
+ int has_caption = iupAttribGetBoolean(ih, "MAXBOX") ||
+ iupAttribGetBoolean(ih, "MINBOX") ||
+ iupAttribGetBoolean(ih, "MENUBOX") ||
+ IupGetAttribute(ih, "TITLE"); /* must use IupGetAttribute to check from the native implementation */
+
+ int has_border = has_caption ||
+ iupAttribGetBoolean(ih, "RESIZE") ||
+ iupAttribGetBoolean(ih, "BORDER");
+
+ *menu = motDialogGetMenuSize(ih);
+
+ if (ih->handle && iupdrvDialogIsVisible(ih))
+ {
+ int win_border, win_caption;
+ if (iupdrvGetWindowDecor((void*)XtWindow(ih->handle), &win_border, &win_caption))
+ {
+ *border = 0;
+ if (has_border)
+ *border = win_border;
+
+ *caption = 0;
+ if (has_caption)
+ *caption = win_caption;
+
+ if (!native_border && *border)
+ native_border = win_border;
+
+ if (!native_caption && *caption)
+ native_caption = win_caption;
+
+ return;
+ }
+ }
+
+ /* I could not set the size of the window including the decorations when the dialog is hidden */
+ /* So we have to estimate the size of borders and caption when the dialog is hidden */
+
+ *border = 0;
+ if (has_border)
+ {
+ if (native_border)
+ *border = native_border;
+ else
+ *border = 5;
+ }
+
+ *caption = 0;
+ if (has_caption)
+ {
+ if (native_caption)
+ *caption = native_caption;
+ else
+ *caption = 20;
+ }
+}
+
+static int motDialogQueryWMspecSupport(Atom feature)
+{
+ static Atom netsuppport = 0;
+ Atom type;
+ Atom *atoms;
+ int format;
+ unsigned long after, natoms, i;
+
+ if (!netsuppport)
+ netsuppport = XmInternAtom(iupmot_display, "_NET_SUPPORTED", False);
+
+ /* get all the features */
+ XGetWindowProperty(iupmot_display, RootWindow(iupmot_display, iupmot_screen),
+ netsuppport, 0, LONG_MAX, False, XA_ATOM, &type, &format, &natoms,
+ &after, (unsigned char **)&atoms);
+ if (type != XA_ATOM || atoms == NULL)
+ {
+ if (atoms) XFree(atoms);
+ return 0;
+ }
+
+ /* Lookup the feature we want */
+ for (i = 0; i < natoms; i++)
+ {
+ if (atoms[i] == feature)
+ {
+ XFree(atoms);
+ return 1;
+ }
+ }
+
+ XFree(atoms);
+ return 0;
+}
+
+static void motDialogSetWindowManagerStyle(Ihandle* ih)
+{
+ MwmHints hints;
+ static Atom xwmhint = 0;
+ if (!xwmhint)
+ xwmhint = XmInternAtom(iupmot_display, "_MOTIF_WM_HINTS", False);
+
+ hints.flags = (MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS);
+ hints.functions = 0;
+ hints.decorations = 0;
+ hints.input_mode = 0;
+ hints.status = 0;
+
+ if (IupGetAttribute(ih, "TITLE")) { /* must use IupGetAttribute to check from the native implementation */
+ hints.functions |= MWM_FUNC_MOVE;
+ hints.decorations |= MWM_DECOR_TITLE;
+ }
+
+ if (iupAttribGetBoolean(ih, "MENUBOX")) {
+ hints.functions |= MWM_FUNC_CLOSE;
+ hints.decorations |= MWM_DECOR_MENU;
+ }
+
+ if (iupAttribGetBoolean(ih, "MINBOX")) {
+ hints.functions |= MWM_FUNC_MINIMIZE;
+ hints.decorations |= MWM_DECOR_MINIMIZE;
+ }
+
+ if (iupAttribGetBoolean(ih, "MAXBOX")) {
+ hints.functions |= MWM_FUNC_MAXIMIZE;
+ hints.decorations |= MWM_DECOR_MAXIMIZE;
+ }
+
+ if (iupAttribGetBoolean(ih, "RESIZE")) {
+ hints.functions |= MWM_FUNC_RESIZE;
+ hints.decorations |= MWM_DECOR_RESIZEH;
+ }
+
+ if (iupAttribGetBoolean(ih, "BORDER"))
+ hints.decorations |= MWM_DECOR_BORDER;
+
+ XChangeProperty(iupmot_display, XtWindow(ih->handle),
+ xwmhint, xwmhint,
+ 32, PropModeReplace,
+ (const unsigned char *) &hints,
+ PROP_MOTIF_WM_HINTS_ELEMENTS);
+}
+
+static void motDialogChangeWMState(Ihandle* ih, Atom state1, Atom state2, int operation)
+{
+ static Atom wmstate = 0;
+ if (!wmstate)
+ wmstate = XmInternAtom(iupmot_display, "_NET_WM_STATE", False);
+
+ if (iupdrvDialogIsVisible(ih))
+ {
+ XEvent evt;
+ evt.type = ClientMessage;
+ evt.xclient.type = ClientMessage;
+ evt.xclient.serial = 0;
+ evt.xclient.send_event = True;
+ evt.xclient.display = iupmot_display;
+ evt.xclient.window = XtWindow(ih->handle);
+ evt.xclient.message_type = wmstate;
+ evt.xclient.format = 32;
+ evt.xclient.data.l[0] = operation;
+ evt.xclient.data.l[1] = state1;
+ evt.xclient.data.l[2] = state2;
+ evt.xclient.data.l[3] = 0;
+ evt.xclient.data.l[4] = 0;
+
+ XSendEvent(iupmot_display, RootWindow(iupmot_display, iupmot_screen), False,
+ SubstructureRedirectMask | SubstructureNotifyMask, &evt);
+ }
+ else
+ {
+ if (operation)
+ {
+ if (state1 && state2)
+ {
+ Atom atoms[2];
+ atoms[0] = state1;
+ atoms[0] = state2;
+
+ XChangeProperty(iupmot_display, XtWindow(ih->handle),
+ wmstate, XA_ATOM,
+ 32, PropModeReplace,
+ (const unsigned char *)&atoms, 2);
+ }
+ else
+ {
+ XChangeProperty(iupmot_display, XtWindow(ih->handle),
+ wmstate, XA_ATOM,
+ 32, PropModeReplace,
+ (const unsigned char *)&state1, 1);
+ }
+ }
+ else
+ {
+ /* TODO: This is not working. The property is not correctly removed. */
+ /* XDeleteProperty(iupmot_display, XtWindow(ih->handle), wmstate); */
+
+ /* Maybe the right way to do it is to retrieve all the atoms */
+ /* and change again with all atoms except the one to remove */
+ }
+ }
+}
+
+static int motDialogSetFullScreen(Ihandle* ih, int fullscreen)
+{
+ static int support_fullscreen = -1; /* WARNING: The WM can be changed dinamically */
+
+ static Atom xwmfs = 0;
+ if (!xwmfs)
+ xwmfs = XmInternAtom(iupmot_display, "_NET_WM_STATE_FULLSCREEN", False);
+
+ if (support_fullscreen == -1)
+ support_fullscreen = motDialogQueryWMspecSupport(xwmfs);
+
+ if (support_fullscreen)
+ {
+ motDialogChangeWMState(ih, xwmfs, 0, fullscreen);
+ return 1;
+ }
+
+ return 0;
+}
+
+int iupdrvDialogSetPlacement(Ihandle* ih)
+{
+ char* placement;
+ ih->data->show_state = IUP_SHOW;
+
+ if (iupAttribGetBoolean(ih, "FULLSCREEN"))
+ return 1;
+
+ placement = iupAttribGet(ih, "PLACEMENT");
+ if (!placement)
+ return 0;
+
+ if (iupStrEqualNoCase(placement, "MINIMIZED"))
+ {
+ if (iupdrvDialogIsVisible(ih))
+ XIconifyWindow(iupmot_display, XtWindow(ih->handle), iupmot_screen);
+ else
+ {
+ /* TODO: This is not working, so force a minimize after visible. */
+ /*XWMHints wm_hints; */
+ /*wm_hints.flags = StateHint; */
+ /*wm_hints.initial_state = IconicState; */
+ /*XSetWMHints(iupmot_display, XtWindow(ih->handle), &wm_hints); */
+
+ XtMapWidget(ih->handle);
+ XIconifyWindow(iupmot_display, XtWindow(ih->handle), iupmot_screen);
+ }
+ }
+ else if (iupStrEqualNoCase(placement, "MAXIMIZED"))
+ {
+ static Atom maxatoms[2] = {0, 0};
+ if (!(maxatoms[0]))
+ {
+ maxatoms[0] = XmInternAtom(iupmot_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
+ maxatoms[1] = XmInternAtom(iupmot_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
+ }
+
+ motDialogChangeWMState(ih, maxatoms[0], maxatoms[1], 1);
+ }
+ else if (iupStrEqualNoCase(placement, "FULL"))
+ {
+ int width, height, x, y;
+ int border, caption, menu;
+ iupdrvDialogGetDecoration(ih, &border, &caption, &menu);
+
+ /* position the decoration outside the screen */
+ x = -(border);
+ y = -(border+caption+menu);
+
+ /* the dialog client area will cover the task bar */
+ iupdrvGetFullSize(&width, &height);
+
+ height += menu; /* the menu is included in the client area size in Motif. */
+
+ /* set the new size and position */
+ /* The resize event will update the layout */
+ XtVaSetValues(ih->handle,
+ XmNx, (XtArgVal)x, /* outside border */
+ XmNy, (XtArgVal)y,
+ XmNwidth, (XtArgVal)width, /* client size */
+ XmNheight, (XtArgVal)height,
+ NULL);
+ }
+
+ iupAttribSetStr(ih, "PLACEMENT", NULL); /* reset to NORMAL */
+
+ return 1;
+}
+
+/****************************************************************************
+ Attributes
+****************************************************************************/
+
+
+static int motDialogSetMinSizeAttrib(Ihandle* ih, const char* value)
+{
+ int decorwidth = 0, decorheight = 0;
+ int min_w = 1, min_h = 1; /* MINSIZE default value */
+ iupStrToIntInt(value, &min_w, &min_h, 'x');
+
+ /* The minmax size restricts the client area */
+ iupDialogGetDecorSize(ih, &decorwidth, &decorheight);
+
+ if (min_w > decorwidth)
+ XtVaSetValues(ih->handle, XmNminWidth, min_w-decorwidth, NULL);
+ if (min_h > decorheight)
+ XtVaSetValues(ih->handle, XmNminHeight, min_h-decorheight, NULL);
+
+ return 1;
+}
+
+static int motDialogSetMaxSizeAttrib(Ihandle* ih, const char* value)
+{
+ int decorwidth = 0, decorheight = 0;
+ int max_w = 65535, max_h = 65535; /* MAXSIZE default value */
+ iupStrToIntInt(value, &max_w, &max_h, 'x');
+
+ /* The minmax size restricts the client area */
+ iupDialogGetDecorSize(ih, &decorwidth, &decorheight);
+
+ if (max_w > decorwidth)
+ XtVaSetValues(ih->handle, XmNmaxWidth, max_w-decorwidth, NULL);
+ if (max_h > decorheight)
+ XtVaSetValues(ih->handle, XmNmaxHeight, max_h-decorheight, NULL);
+
+ return 1;
+}
+
+static char* motDialogGetXAttrib(Ihandle *ih)
+{
+ char* str = iupStrGetMemory(20);
+
+ int x;
+ iupdrvDialogGetPosition(ih->handle, &x, NULL);
+
+ sprintf(str, "%d", x);
+ return str;
+}
+
+static char* motDialogGetYAttrib(Ihandle *ih)
+{
+ char* str = iupStrGetMemory(20);
+
+ int y;
+ iupdrvDialogGetPosition(ih->handle, &y, NULL);
+
+ sprintf(str, "%d", y);
+ return str;
+}
+
+static int motDialogSetTitleAttrib(Ihandle* ih, const char* value)
+{
+ if (!value)
+ value = "";
+
+ XtVaSetValues(ih->handle, XmNtitle, value,
+ XmNiconName, value,
+ NULL);
+ return 0;
+}
+
+static char* motDialogGetTitleAttrib(Ihandle* ih)
+{
+ char* title;
+ XtVaGetValues(ih->handle, XmNtitle, &title, NULL);
+
+ if (!title || title[0] == 0)
+ return NULL;
+ else
+ {
+ char* str = iupStrGetMemory(200);
+ strcpy(str, title);
+ return str;
+ }
+}
+
+static char* motDialogGetClientSizeAttrib(Ihandle *ih)
+{
+ char* str = iupStrGetMemory(20);
+
+ Dimension manager_width, manager_height;
+ Widget dialog_manager = XtNameToWidget(ih->handle, "*dialog_manager");
+ XtVaGetValues(dialog_manager, XmNwidth, &manager_width,
+ XmNheight, &manager_height,
+ NULL);
+
+ sprintf(str, "%dx%d", (int)manager_width, (int)manager_height - motDialogGetMenuSize(ih));
+ return str;
+}
+
+static int motDialogSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ Pixel color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ {
+ Widget dialog_manager = XtNameToWidget(ih->handle, "*dialog_manager");
+ XtVaSetValues(dialog_manager, XmNbackground, color, NULL);
+ XtVaSetValues(dialog_manager, XmNbackgroundPixmap, XmUNSPECIFIED_PIXMAP, NULL);
+ return 1;
+ }
+ return 0;
+}
+
+static int motDialogSetBackgroundAttrib(Ihandle* ih, const char* value)
+{
+ if (motDialogSetBgColorAttrib(ih, value))
+ return 1;
+ else
+ {
+ Pixmap pixmap = (Pixmap)iupImageGetImage(value, ih, 0);
+ if (pixmap)
+ {
+ Widget dialog_manager = XtNameToWidget(ih->handle, "*dialog_manager");
+ XtVaSetValues(dialog_manager, XmNbackgroundPixmap, pixmap, NULL);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int motDialogSetFullScreenAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrBoolean(value))
+ {
+ if (!iupAttribGet(ih, "_IUPMOT_FS_STYLE"))
+ {
+ int visible = iupdrvDialogIsVisible(ih);
+ if (visible)
+ iupAttribSetStr(ih, "_IUPMOT_FS_STYLE", "VISIBLE");
+ else
+ iupAttribSetStr(ih, "_IUPMOT_FS_STYLE", "HIDDEN");
+
+ /* save the previous decoration attributes */
+ /* during fullscreen these attributes can be consulted by the application */
+ iupAttribStoreStr(ih, "_IUPMOT_FS_MAXBOX", iupAttribGet(ih, "MAXBOX"));
+ iupAttribStoreStr(ih, "_IUPMOT_FS_MINBOX", iupAttribGet(ih, "MINBOX"));
+ iupAttribStoreStr(ih, "_IUPMOT_FS_MENUBOX",iupAttribGet(ih, "MENUBOX"));
+ iupAttribStoreStr(ih, "_IUPMOT_FS_RESIZE", iupAttribGet(ih, "RESIZE"));
+ iupAttribStoreStr(ih, "_IUPMOT_FS_BORDER", iupAttribGet(ih, "BORDER"));
+ iupAttribStoreStr(ih, "_IUPMOT_FS_TITLE", IupGetAttribute(ih, "TITLE")); /* must use IupGetAttribute to check from the native implementation */
+
+ /* remove the decorations attributes */
+ iupAttribSetStr(ih, "MAXBOX", "NO");
+ iupAttribSetStr(ih, "MINBOX", "NO");
+ iupAttribSetStr(ih, "MENUBOX", "NO");
+ IupSetAttribute(ih, "TITLE", NULL); iupAttribSetStr(ih, "TITLE", NULL); /* remove from the hash table if we are during IupMap */
+ iupAttribSetStr(ih, "RESIZE", "NO");
+ iupAttribSetStr(ih, "BORDER", "NO");
+
+ /* use WM fullscreen support */
+ if (!motDialogSetFullScreen(ih, 1))
+ {
+ /* or configure fullscreen manually */
+ int decor;
+ int width, height;
+
+ /* hide before changing decorations */
+ if (visible)
+ {
+ iupAttribSetStr(ih, "_IUPMOT_SHOW_STATE", NULL); /* To avoid a SHOW_CB notification */
+ XtUnmapWidget(ih->handle);
+ }
+
+ /* save the previous position and size */
+ iupAttribStoreStr(ih, "_IUPMOT_FS_X", IupGetAttribute(ih, "X")); /* must use IupGetAttribute to check from the native implementation */
+ iupAttribStoreStr(ih, "_IUPMOT_FS_Y", IupGetAttribute(ih, "Y"));
+ iupAttribStoreStr(ih, "_IUPMOT_FS_SIZE", IupGetAttribute(ih, "RASTERSIZE"));
+
+ /* save the previous decoration */
+ XtVaGetValues(ih->handle, XmNmwmDecorations, &decor, NULL);
+ iupAttribSetStr(ih, "_IUPMOT_FS_DECOR", (char*)decor);
+
+ /* remove the decorations */
+ XtVaSetValues(ih->handle, XmNmwmDecorations, (XtArgVal)0, NULL);
+ motDialogSetWindowManagerStyle(ih);
+
+ /* get full screen size */
+ iupdrvGetFullSize(&width, &height);
+
+ /* set position and size */
+ XtVaSetValues(ih->handle, XmNwidth, (XtArgVal)width,
+ XmNheight, (XtArgVal)height,
+ XmNx, (XtArgVal)0,
+ XmNy, (XtArgVal)0,
+ NULL);
+
+ /* layout will be updated in motDialogConfigureNotify */
+ if (visible)
+ XtMapWidget(ih->handle);
+ }
+ }
+ }
+ else
+ {
+ char* fs_style = iupAttribGet(ih, "_IUPMOT_FS_STYLE");
+ if (fs_style)
+ {
+ /* can only switch back from full screen if window was visible */
+ /* when fullscreen was set */
+ if (iupStrEqualNoCase(fs_style, "VISIBLE"))
+ {
+ iupAttribSetStr(ih, "_IUPMOT_FS_STYLE", NULL);
+
+ /* restore the decorations attributes */
+ iupAttribStoreStr(ih, "MAXBOX", iupAttribGet(ih, "_IUPMOT_FS_MAXBOX"));
+ iupAttribStoreStr(ih, "MINBOX", iupAttribGet(ih, "_IUPMOT_FS_MINBOX"));
+ iupAttribStoreStr(ih, "MENUBOX",iupAttribGet(ih, "_IUPMOT_FS_MENUBOX"));
+ IupSetAttribute(ih, "TITLE", iupAttribGet(ih, "_IUPMOT_FS_TITLE")); /* TITLE is not stored in the HashTable */
+ iupAttribStoreStr(ih, "RESIZE", iupAttribGet(ih, "_IUPMOT_FS_RESIZE"));
+ iupAttribStoreStr(ih, "BORDER", iupAttribGet(ih, "_IUPMOT_FS_BORDER"));
+
+ if (!motDialogSetFullScreen(ih, 0))
+ {
+ int border, caption, menu, x, y;
+ int visible = iupdrvDialogIsVisible(ih);
+ if (visible)
+ XtUnmapWidget(ih->handle);
+
+ /* restore the decorations */
+ XtVaSetValues(ih->handle, XmNmwmDecorations, (XtArgVal)(int)iupAttribGet(ih, "_IUPMOT_FS_DECOR"), NULL);
+ motDialogSetWindowManagerStyle(ih);
+
+ /* the dialog decoration will not be considered yet in the next XtVaSetValues */
+ /* so compensate the decoration when restoring the position and size */
+ iupdrvDialogGetDecoration(ih, &border, &caption, &menu);
+ x = iupAttribGetInt(ih, "_IUPMOT_FS_X") - (border);
+ y = iupAttribGetInt(ih, "_IUPMOT_FS_Y") - (border+caption+menu);
+
+ /* restore position and size */
+ XtVaSetValues(ih->handle,
+ XmNx, (XtArgVal)x,
+ XmNy, (XtArgVal)y,
+ XmNwidth, (XtArgVal)(IupGetInt(ih, "_IUPMOT_FS_SIZE") - (2*border)),
+ XmNheight, (XtArgVal)(IupGetInt2(ih, "_IUPMOT_FS_SIZE") - (2*border+caption)),
+ NULL);
+
+ /* layout will be updated in motDialogConfigureNotify */
+ if (visible)
+ XtMapWidget(ih->handle);
+
+ /* remove auxiliar attributes */
+ iupAttribSetStr(ih, "_IUPMOT_FS_X", NULL);
+ iupAttribSetStr(ih, "_IUPMOT_FS_Y", NULL);
+ iupAttribSetStr(ih, "_IUPMOT_FS_SIZE", NULL);
+ iupAttribSetStr(ih, "_IUPMOT_FS_DECOR", NULL);
+ }
+
+ /* remove auxiliar attributes */
+ iupAttribSetStr(ih, "_IUPMOT_FS_MAXBOX", NULL);
+ iupAttribSetStr(ih, "_IUPMOT_FS_MINBOX", NULL);
+ iupAttribSetStr(ih, "_IUPMOT_FS_MENUBOX",NULL);
+ iupAttribSetStr(ih, "_IUPMOT_FS_RESIZE", NULL);
+ iupAttribSetStr(ih, "_IUPMOT_FS_BORDER", NULL);
+ iupAttribSetStr(ih, "_IUPMOT_FS_TITLE", NULL);
+ }
+ }
+ }
+ return 1;
+}
+
+static int motDialogSetIconAttrib(Ihandle* ih, const char *value)
+{
+ if (!value)
+ XtVaSetValues(ih->handle, XmNiconPixmap, NULL, NULL);
+ else
+ {
+ Pixmap icon = (Pixmap)iupImageGetIcon(value);
+ Pixmap icon_mask = (Pixmap)iupImageGetMask(value);
+ if (icon)
+ XtVaSetValues(ih->handle, XmNiconPixmap, icon, NULL);
+ if (icon_mask)
+ XtVaSetValues(ih->handle, XmNiconMask, icon, NULL);
+ }
+ return 1;
+}
+
+/****************************************************************
+ Callbacks and Events
+****************************************************************/
+
+
+static void motDialogCBclose(Widget w, XtPointer client_data, XtPointer call_data)
+{
+ Icallback cb;
+ Ihandle *ih = (Ihandle*)client_data;
+ if (!ih) return;
+ (void)call_data;
+ (void)w;
+
+ /* even when ACTIVE=NO the dialog gets this event */
+ if (!iupdrvIsActive(ih))
+ return;
+
+ cb = IupGetCallback(ih, "CLOSE_CB");
+ if (cb)
+ {
+ int ret = cb(ih);
+ if (ret == IUP_IGNORE)
+ return;
+ if (ret == IUP_CLOSE)
+ IupExitLoop();
+ }
+
+ IupHide(ih); /* default: close the window */
+}
+
+static void motDialogConfigureNotify(Widget w, XEvent *evt, String* s, Cardinal *card)
+{
+ IFnii cb;
+ int border, caption, menu;
+ XConfigureEvent *cevent = (XConfigureEvent *)evt;
+ Ihandle* ih;
+ (void)s;
+ (void)card;
+
+ XtVaGetValues(w, XmNuserData, &ih, NULL);
+ if (!ih) return;
+
+ if (ih->data->menu && ih->data->menu->handle)
+ {
+ XtVaSetValues(ih->data->menu->handle,
+ XmNwidth, (XtArgVal)(cevent->width),
+ NULL);
+ }
+
+ if (ih->data->ignore_resize) return;
+
+ iupdrvDialogGetDecoration(ih, &border, &caption, &menu);
+
+ /* update dialog size */
+ ih->currentwidth = cevent->width + 2*border;
+ ih->currentheight = cevent->height + 2*border + caption; /* menu is inside the dialog_manager */
+
+ cb = (IFnii)IupGetCallback(ih, "RESIZE_CB");
+ if (!cb || cb(ih, cevent->width, cevent->height - menu)!=IUP_IGNORE) /* width and height here are for the client area */
+ {
+ ih->data->ignore_resize = 1;
+ IupRefresh(ih);
+ ih->data->ignore_resize = 0;
+ }
+}
+
+static void motDialogCBStructureNotifyEvent(Widget w, XtPointer data, XEvent *evt, Boolean *cont)
+{
+ Ihandle *ih = (Ihandle*)data;
+ int state = -1;
+ (void)cont;
+ (void)w;
+
+ switch(evt->type)
+ {
+ case MapNotify:
+ {
+ if (ih->data->show_state == IUP_MINIMIZE) /* it is a RESTORE. */
+ state = IUP_RESTORE;
+ break;
+ }
+ case UnmapNotify:
+ {
+ if (ih->data->show_state != IUP_HIDE) /* it is a MINIMIZE. */
+ state = IUP_MINIMIZE;
+ break;
+ }
+ }
+
+ if (state < 0)
+ return;
+
+ if (ih->data->show_state != state)
+ {
+ IFni cb;
+ ih->data->show_state = state;
+
+ cb = (IFni)IupGetCallback(ih, "SHOW_CB");
+ if (cb && cb(ih, state) == IUP_CLOSE)
+ IupExitLoop();
+ }
+}
+
+static void motDialogDestroyCallback(Widget w, Ihandle *ih, XtPointer call_data)
+{
+ /* If the IUP dialog was not destroyed, destroy it here. */
+ if (iupObjectCheck(ih))
+ IupDestroy(ih);
+
+ /* this callback is usefull to destroy children dialogs when the parent is destroyed. */
+ /* The application is responsable for destroying the children before this happen. */
+ (void)w;
+ (void)call_data;
+}
+
+
+/****************************************************************
+ Idialog
+****************************************************************/
+
+/* replace the common dialog SetChildrenPosition method because of
+ the menu that it is inside the dialog. */
+static void motDialogSetChildrenPositionMethod(Ihandle* ih, int x, int y)
+{
+ int menu_h = motDialogGetMenuSize(ih);
+ (void)x;
+ (void)y;
+
+ /* Child coordinates are relative to client left-top corner. */
+ iupBaseSetPosition(ih->firstchild, 0, menu_h);
+}
+
+static void* motDialogGetInnerNativeContainerHandleMethod(Ihandle* ih, Ihandle* child)
+{
+ (void)child;
+ return XtNameToWidget(ih->handle, "*dialog_manager");
+}
+
+static int motDialogMapMethod(Ihandle* ih)
+{
+ Widget dialog_manager;
+ InativeHandle* parent;
+ int mwm_decor = 0;
+ int num_args = 0;
+ Arg args[20];
+
+ if (iupAttribGetBoolean(ih, "DIALOGFRAME"))
+ {
+ iupAttribSetStr(ih, "RESIZE", "NO");
+ iupAttribSetStr(ih, "MAXBOX", "NO");
+ iupAttribSetStr(ih, "MINBOX", "NO");
+ }
+
+ /****************************/
+ /* Create the dialog shell */
+ /****************************/
+
+ if (iupAttribGet(ih, "TITLE"))
+ mwm_decor |= MWM_DECOR_TITLE;
+ if (iupAttribGetBoolean(ih, "MENUBOX"))
+ mwm_decor |= MWM_DECOR_MENU;
+ if (iupAttribGetBoolean(ih, "MINBOX"))
+ mwm_decor |= MWM_DECOR_MINIMIZE;
+ if (iupAttribGetBoolean(ih, "MAXBOX"))
+ mwm_decor |= MWM_DECOR_MAXIMIZE;
+ if (iupAttribGetBoolean(ih, "RESIZE"))
+ mwm_decor |= MWM_DECOR_RESIZEH;
+ if (iupAttribGetBoolean(ih, "BORDER"))
+ mwm_decor |= MWM_DECOR_BORDER;
+
+ iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* so XtRealizeWidget will not show the dialog */
+ iupmotSetArg(args, num_args, XmNdeleteResponse, XmDO_NOTHING);
+ iupmotSetArg(args, num_args, XmNallowShellResize, True); /* Used so the BulletinBoard can control the shell size */
+ iupmotSetArg(args, num_args, XmNtitle, "");
+ iupmotSetArg(args, num_args, XmNvisual, iupmot_visual);
+
+ if (iupmotColorMap())
+ iupmotSetArg(args, num_args, XmNcolormap, iupmotColorMap());
+
+ if (mwm_decor != 0x7E)
+ iupmotSetArg(args, num_args, XmNmwmDecorations, mwm_decor);
+
+ if (iupAttribGetBoolean(ih, "SAVEUNDER"))
+ iupmotSetArg(args, num_args, XmNsaveUnder, True);
+
+ parent = iupDialogGetNativeParent(ih);
+ if (parent)
+ ih->handle = XtCreatePopupShell(NULL, topLevelShellWidgetClass, (Widget)parent, args, num_args);
+ else
+ ih->handle = XtAppCreateShell(NULL, "dialog", topLevelShellWidgetClass, iupmot_display, args, num_args);
+
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ XmAddWMProtocolCallback(ih->handle, iupmot_wm_deletewindow, motDialogCBclose, (XtPointer)ih);
+
+ XtAddEventHandler(ih->handle, FocusChangeMask, False, (XtEventHandler)iupmotFocusChangeEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, EnterWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, LeaveWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, StructureNotifyMask, False, (XtEventHandler)motDialogCBStructureNotifyEvent, (XtPointer)ih);
+
+ XtAddCallback(ih->handle, XmNdestroyCallback, (XtCallbackProc)motDialogDestroyCallback, (XtPointer)ih);
+
+ /*****************************/
+ /* Create the dialog manager */
+ /*****************************/
+
+ dialog_manager = XtVaCreateManagedWidget(
+ "dialog_manager",
+ xmBulletinBoardWidgetClass,
+ ih->handle,
+ XmNmarginWidth, 0,
+ XmNmarginHeight, 0,
+ XmNwidth, 100, /* set this to avoid size calculation problems */
+ XmNheight, 100,
+ XmNborderWidth, 0,
+ XmNshadowThickness, 0,
+ XmNnoResize, iupAttribGetBoolean(ih, "RESIZE")? False: True,
+ XmNresizePolicy, XmRESIZE_NONE, /* no automatic resize of children */
+ XmNuserData, ih, /* used only in motDialogConfigureNotify */
+ XmNnavigationType, XmTAB_GROUP,
+ NULL);
+
+ XtOverrideTranslations(dialog_manager, XtParseTranslationTable("<Configure>: iupDialogConfigure()"));
+ XtAddCallback(dialog_manager, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih);
+ XtAddEventHandler(dialog_manager, KeyPressMask, False,(XtEventHandler)iupmotKeyPressEvent, (XtPointer)ih);
+
+ /* initialize the widget */
+ XtRealizeWidget(ih->handle);
+
+ /* child dialogs must be always on top of the parent */
+ if (parent)
+ XSetTransientForHint(iupmot_display, XtWindow(ih->handle), XtWindow(parent));
+
+ if (mwm_decor != 0x7E) /* some decoration was changed */
+ motDialogSetWindowManagerStyle(ih);
+
+ /* Ignore VISIBLE before mapping */
+ iupAttribSetStr(ih, "VISIBLE", NULL);
+
+ if (IupGetGlobal("_IUP_RESET_DLGBGCOLOR"))
+ {
+ iupmotSetGlobalColorAttrib(dialog_manager, XmNbackground, "DLGBGCOLOR");
+ iupmotSetGlobalColorAttrib(dialog_manager, XmNforeground, "DLGFGCOLOR");
+ IupSetGlobal("_IUP_RESET_DLGBGCOLOR", NULL);
+ }
+
+ return IUP_NOERROR;
+}
+
+static void motDialogUnMapMethod(Ihandle* ih)
+{
+ Widget dialog_manager;
+ if (ih->data->menu)
+ {
+ ih->data->menu->handle = NULL; /* the dialog will destroy the native menu */
+ IupDestroy(ih->data->menu);
+ }
+
+ dialog_manager = XtNameToWidget(ih->handle, "*dialog_manager");
+ XtVaSetValues(dialog_manager, XmNuserData, NULL, NULL);
+
+ XtRemoveEventHandler(ih->handle, FocusChangeMask, False, (XtEventHandler)iupmotFocusChangeEvent, (XtPointer)ih);
+ XtRemoveEventHandler(ih->handle, KeyPressMask, False, (XtEventHandler)iupmotKeyPressEvent, (XtPointer)ih);
+ XtRemoveEventHandler(ih->handle, StructureNotifyMask, False, (XtEventHandler)motDialogCBStructureNotifyEvent, (XtPointer)ih);
+ XtRemoveCallback(ih->handle, XmNdestroyCallback, (XtCallbackProc)motDialogDestroyCallback, (XtPointer)ih);
+
+ XtRemoveEventHandler(dialog_manager, KeyPressMask, False, (XtEventHandler)iupmotKeyPressEvent, (XtPointer)ih);
+ XtRemoveCallback(dialog_manager, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih);
+
+ iupdrvBaseUnMapMethod(ih);
+}
+
+static void motDialogLayoutUpdateMethod(Ihandle *ih)
+{
+ int border, caption, menu;
+
+ if (ih->data->ignore_resize ||
+ iupAttribGet(ih, "_IUPMOT_FS_STYLE"))
+ return;
+
+ /* for dialogs the position is not updated here */
+ ih->data->ignore_resize = 1;
+
+ iupdrvDialogGetDecoration(ih, &border, &caption, &menu);
+
+ if (!iupAttribGetBoolean(ih, "RESIZE"))
+ {
+ int width = ih->currentwidth - 2*border;
+ int height = ih->currentheight - 2*border - caption;
+ XtVaSetValues(ih->handle,
+ XmNwidth, width,
+ XmNheight, height,
+ XmNminWidth, width,
+ XmNminHeight, height,
+ XmNmaxWidth, width,
+ XmNmaxHeight, height,
+ NULL);
+ }
+ else
+ {
+ XtVaSetValues(ih->handle,
+ XmNwidth, (XtArgVal)(ih->currentwidth - 2*border), /* excluding the border */
+ XmNheight, (XtArgVal)(ih->currentheight - 2*border - caption),
+ NULL);
+ }
+
+ ih->data->ignore_resize = 0;
+}
+
+/***************************************************************/
+
+void iupdrvDialogInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class methods */
+ ic->Map = motDialogMapMethod;
+ ic->UnMap = motDialogUnMapMethod;
+ ic->LayoutUpdate = motDialogLayoutUpdateMethod;
+ ic->SetChildrenPosition = motDialogSetChildrenPositionMethod;
+ ic->GetInnerNativeContainerHandle = motDialogGetInnerNativeContainerHandleMethod;
+
+ if (!iupmot_wm_deletewindow)
+ {
+ /* Set up a translation table that captures "Resize" events
+ (also called ConfigureNotify or Configure events). */
+ XtActionsRec rec = {"iupDialogConfigure", motDialogConfigureNotify};
+ XtAppAddActions(iupmot_appcontext, &rec, 1);
+
+ /* register atom to intercept the close button in the window frame */
+ iupmot_wm_deletewindow = XmInternAtom(iupmot_display, "WM_DELETE_WINDOW", False);
+ }
+
+ /* Driver Dependent Attribute functions */
+
+ /* Visual */
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, motDialogSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+
+ /* Overwrite Visual */
+ iupClassRegisterAttribute(ic, "X", motDialogGetXAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "Y", motDialogGetYAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT);
+
+ /* Base Container */
+ iupClassRegisterAttribute(ic, "CLIENTSIZE", motDialogGetClientSizeAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT);
+
+ /* Special */
+ iupClassRegisterAttribute(ic, "TITLE", motDialogGetTitleAttrib, motDialogSetTitleAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+
+ /* IupDialog only */
+ iupClassRegisterAttribute(ic, "BACKGROUND", NULL, motDialogSetBackgroundAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "ICON", NULL, motDialogSetIconAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "FULLSCREEN", NULL, motDialogSetFullScreenAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MINSIZE", NULL, motDialogSetMinSizeAttrib, IUPAF_SAMEASSYSTEM, "1x1", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MAXSIZE", NULL, motDialogSetMaxSizeAttrib, IUPAF_SAMEASSYSTEM, "65535x65535", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SAVEUNDER", NULL, NULL, "YES", NULL, IUPAF_NO_INHERIT);
+
+ /* IupDialog X Only */
+ iupClassRegisterAttribute(ic, "XWINDOW", iupmotGetXWindowAttrib, NULL, NULL, NULL, IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+}
diff --git a/iup/src/mot/iupmot_drv.h b/iup/src/mot/iupmot_drv.h
new file mode 100755
index 0000000..8a536ef
--- /dev/null
+++ b/iup/src/mot/iupmot_drv.h
@@ -0,0 +1,75 @@
+/** \file
+ * \brief Motif Driver
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMOT_DRV_H
+#define __IUPMOT_DRV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* global variables, declared in iupmot_open.c */
+extern Widget iupmot_appshell;
+extern Display* iupmot_display;
+extern int iupmot_screen;
+extern XtAppContext iupmot_appcontext;
+extern Visual* iupmot_visual;
+extern Atom iupmot_wm_deletewindow;
+
+/* dialog */
+void iupmotDialogSetVisual(Ihandle* ih, void* visual);
+void iupmotDialogResetVisual(Ihandle* ih);
+
+/* focus */
+void iupmotFocusChangeEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont);
+
+/* key */
+void iupmotCanvasKeyReleaseEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont);
+void iupmotKeyPressEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont);
+KeySym iupmotKeyCharToKeySym(char c);
+void iupmotButtonKeySetStatus(unsigned int state, unsigned int but, char* status, int doubleclick);
+void iupmotKeyEncode(int key, unsigned int *keyval, unsigned int *state);
+
+/* font */
+char* iupmotGetFontListAttrib(Ihandle *ih);
+XmFontList iupmotGetFontList(const char* foundry, const char* value);
+char* iupmotFindFontList(XmFontList fontlist);
+char* iupmotGetFontStructAttrib(Ihandle *ih);
+char* iupmotGetFontIdAttrib(Ihandle *ih);
+
+/* tips */
+/* called from Enter/Leave events to check if a TIP is present. */
+void iupmotTipEnterNotify(Ihandle* ih);
+void iupmotTipLeaveNotify(void);
+void iupmotTipsFinish(void);
+
+/* common */
+void iupmotPointerMotionEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont);
+void iupmotButtonPressReleaseEvent(Widget w, Ihandle* ih, XEvent* evt, Boolean* cont);
+void iupmotEnterLeaveWindowEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont);
+void iupmotHelpCallback(Widget w, Ihandle *ih, XtPointer call_data);
+void iupmotSetString(Widget w, const char *resource, const char* value);
+char* iupmotConvertString(XmString str);
+void iupmotSetMnemonicTitle(Ihandle *ih, const char* value);
+void iupmotDisableDragSource(Widget w);
+void iupmotSetPixmap(Ihandle* ih, const char* name, const char* prop, int make_inactive);
+void iupmotSetGlobalColorAttrib(Widget w, const char* xmname, const char* name);
+void iupmotSetBgColor(Widget w, Pixel color);
+char* iupmotGetBgColorAttrib(Ihandle* ih);
+
+void iupmotGetWindowSize(Ihandle *ih, int *width, int *height);
+
+char* iupmotGetXWindowAttrib(Ihandle *ih);
+
+#define iupmotSetArg(_a, _i, _n, _d) ((_a)[(_i)].name = (_n), (_a)[(_i)].value = (XtArgVal)(_d), (_i)++)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/src/mot/iupmot_filedlg.c b/iup/src/mot/iupmot_filedlg.c
new file mode 100755
index 0000000..768dd2b
--- /dev/null
+++ b/iup/src/mot/iupmot_filedlg.c
@@ -0,0 +1,578 @@
+/** \file
+ * \brief Motif IupFileDlg pre-defined dialog
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <Xm/Xm.h>
+#include <Xm/MwmUtil.h>
+#include <Xm/FileSB.h>
+#include <Xm/Protocols.h>
+#include <Xm/SelectioB.h>
+#include <Xm/MessageB.h>
+#include <Xm/DrawingA.h>
+#include <Xm/PushB.h>
+#include <Xm/Frame.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drvinfo.h"
+#include "iup_dialog.h"
+#include "iup_strmessage.h"
+#include "iup_drvinfo.h"
+
+#include "iupmot_drv.h"
+
+
+enum {IUP_DIALOGOPEN, IUP_DIALOGSAVE, IUP_DIALOGDIR};
+
+static void motFileDlgAskUserCallback(Widget w, int* ret_code, XmSelectionBoxCallbackStruct* cbs)
+{
+ if (cbs->reason == XmCR_OK)
+ *ret_code = 1;
+ else
+ *ret_code = -1;
+ XtDestroyWidget(XtParent(w));
+}
+
+static int motFileDlgAskUser(Widget parent, const char* message)
+{
+ Widget questionbox;
+ Arg args[3];
+ int ret_code = 0;
+ XmString title;
+
+ XtSetArg(args[0], XmNautoUnmanage, False);
+ XtSetArg(args[1], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
+ XtSetArg(args[2], XmNnoResize, True);
+ questionbox = XmCreateQuestionDialog(parent, "filedlg_question", args, 3);
+ iupmotSetString(questionbox, XmNmessageString, message);
+ XtVaGetValues(parent, XmNdialogTitle, &title, NULL);
+ XtVaSetValues(questionbox, XmNdialogTitle, title, NULL);
+
+ XtAddCallback(questionbox, XmNokCallback, (XtCallbackProc)motFileDlgAskUserCallback, (XtPointer)&ret_code);
+ XtAddCallback(questionbox, XmNcancelCallback, (XtCallbackProc)motFileDlgAskUserCallback, (XtPointer)&ret_code);
+ XtUnmanageChild(XmMessageBoxGetChild(questionbox, XmDIALOG_HELP_BUTTON));
+ XtManageChild(questionbox);
+
+ while (ret_code == 0)
+ XtAppProcessEvent(iupmot_appcontext, XtIMAll);
+
+ XtUnmanageChild(questionbox);
+
+ if (ret_code == 1)
+ return 1;
+ else
+ return 0;
+}
+
+static int motFileDlgCheckValue(Ihandle* ih, Widget w)
+{
+ char* value = iupAttribGet(ih, "VALUE");
+ int dialogtype = iupAttribGetInt(ih, "_IUPDLG_DIALOGTYPE");
+
+ if (dialogtype == IUP_DIALOGDIR)
+ {
+ if (!iupdrvIsDirectory(value)) /* if does not exist or not a directory */
+ {
+ iupStrMessageShowError(ih, "IUP_INVALIDDIR");
+ return 0;
+ }
+ }
+ else
+ {
+ if (iupdrvIsDirectory(value)) /* selected a directory */
+ {
+ iupStrMessageShowError(ih, "IUP_INVALIDDIR");
+ return 0;
+ }
+ else if (!iupdrvIsFile(value)) /* new file */
+ {
+ value = iupAttribGet(ih, "ALLOWNEW");
+ if (!value)
+ {
+ if (dialogtype == IUP_DIALOGSAVE)
+ value = "YES";
+ else
+ value = "NO";
+ }
+
+ if (!iupStrBoolean(value))
+ {
+ iupStrMessageShowError(ih, "IUP_FILENOTEXIST");
+ return 0;
+ }
+ }
+ else if (dialogtype == IUP_DIALOGSAVE && !iupAttribGetInt(ih, "NOOVERWRITEPROMPT"))
+ {
+ if (!motFileDlgAskUser(w, iupStrMessageGet("IUP_FILEOVERWRITE")))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void motFileDlgCBclose(Widget w, XtPointer client_data, XtPointer call_data)
+{
+ Ihandle *ih = (Ihandle*)client_data;
+ if (!ih) return;
+ (void)call_data;
+ (void)w;
+ iupAttribSetStr(ih, "VALUE", NULL);
+ iupAttribSetStr(ih, "STATUS", "-1");
+ iupAttribSetStr(ih, "_IUP_WM_DELETE", "1");
+}
+
+static void motFileDlgCallback(Widget w, Ihandle* ih, XmFileSelectionBoxCallbackStruct* call_data)
+{
+ (void)w;
+ if (call_data->reason == XmCR_OK)
+ {
+ int dialogtype = iupAttribGetInt(ih, "_IUPDLG_DIALOGTYPE");
+ char* filename;
+ XmStringGetLtoR(call_data->value, XmSTRING_DEFAULT_CHARSET, &filename);
+ iupAttribStoreStr(ih, "VALUE", filename);
+ XtFree(filename);
+
+ if (!motFileDlgCheckValue(ih, w))
+ return;
+
+ if (dialogtype == IUP_DIALOGDIR)
+ {
+ iupAttribSetStr(ih, "STATUS", "0");
+ iupAttribSetStr(ih, "FILEEXIST", NULL);
+ }
+ else
+ {
+ IFnss file_cb = (IFnss)IupGetCallback(ih, "FILE_CB");
+ if (file_cb && file_cb(ih, iupAttribGet(ih, "VALUE"), "OK") == IUP_IGNORE)
+ return;
+
+ if (iupdrvIsFile(iupAttribGet(ih, "VALUE"))) /* check if file exists */
+ {
+ iupAttribSetStr(ih, "FILEEXIST", "YES");
+ iupAttribSetStr(ih, "STATUS", "0");
+ }
+ else
+ {
+ iupAttribSetStr(ih, "FILEEXIST", "NO");
+ iupAttribSetStr(ih, "STATUS", "1");
+ }
+ }
+
+ if (!iupAttribGetBoolean(ih, "NOCHANGEDIR")) /* do change the current directory */
+ {
+ /* XmFileSelection does not change the current directory */
+ XmString xm_dir;
+ char* dir;
+ XtVaGetValues(w, XmNdirectory, &xm_dir, NULL);
+ XmStringGetLtoR(xm_dir, XmSTRING_DEFAULT_CHARSET, &dir);
+ iupdrvSetCurrentDirectory(dir);
+ XtFree(dir);
+ }
+ }
+ else if (call_data->reason == XmCR_CANCEL)
+ {
+ iupAttribSetStr(ih, "VALUE", NULL);
+ iupAttribSetStr(ih, "FILEEXIST", NULL);
+ iupAttribSetStr(ih, "STATUS", "-1");
+ }
+}
+
+static void motFileDlgHelpCallback(Widget w, XtPointer client_data, XtPointer call_data)
+{
+ Ihandle *ih = (Ihandle*)client_data;
+ Icallback cb = IupGetCallback(ih, "HELP_CB");
+ if (cb && cb(ih) == IUP_CLOSE)
+ {
+ iupAttribSetStr(ih, "VALUE", NULL);
+ iupAttribSetStr(ih, "FILEEXIST", NULL);
+ iupAttribSetStr(ih, "STATUS", "-1");
+ }
+
+ (void)call_data;
+ (void)w;
+}
+
+typedef struct _ImotPromt
+{
+ XmString xm_dir;
+ int ret_code;
+} ImotPromt;
+
+static void motFileDlgPromptCallback(Widget w, ImotPromt* prompt, XmSelectionBoxCallbackStruct* cbs)
+{
+ if (cbs->reason == XmCR_OK)
+ prompt->xm_dir = XmStringCopy(cbs->value);
+
+ prompt->ret_code = 1;
+ XtDestroyWidget(XtParent(w));
+}
+
+static XmString motFileDlgPrompt(Widget parent, const char* message)
+{
+ Widget promptbox;
+ Arg args[2];
+ ImotPromt prompt;
+ XmString title;
+
+ XtSetArg(args[0], XmNautoUnmanage, False);
+ XtSetArg(args[1], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
+ promptbox = XmCreatePromptDialog(parent, "filedlg_prompt", args, 2);
+ iupmotSetString(promptbox, XmNselectionLabelString, message);
+ XtVaGetValues(parent, XmNdialogTitle, &title, NULL);
+ XtVaSetValues(promptbox, XmNdialogTitle, title, NULL);
+
+ prompt.ret_code = 0;
+ prompt.xm_dir = NULL;
+
+ XtAddCallback(promptbox, XmNokCallback, (XtCallbackProc)motFileDlgPromptCallback, (XtPointer)&prompt);
+ XtAddCallback(promptbox, XmNcancelCallback, (XtCallbackProc)motFileDlgPromptCallback, (XtPointer)&prompt);
+ XtUnmanageChild(XmSelectionBoxGetChild(promptbox, XmDIALOG_HELP_BUTTON));
+ XtManageChild(promptbox);
+
+ while (prompt.ret_code == 0)
+ XtAppProcessEvent(iupmot_appcontext, XtIMAll);
+
+ XtUnmanageChild(promptbox);
+
+ return prompt.xm_dir;
+}
+
+static void motFileDlgNewFolderCallback(Widget w, Widget filebox, XtPointer call_data)
+{
+ XmString xm_new_dir = motFileDlgPrompt(filebox, iupStrMessageGet("IUP_NAMENEWFOLDER"));
+ if (xm_new_dir)
+ {
+ XmString xm_dir;
+ XtVaGetValues(filebox, XmNdirectory, &xm_dir, NULL);
+ xm_dir = XmStringConcat(xm_dir, xm_new_dir);
+
+ {
+ char* dir;
+ XmStringGetLtoR(xm_dir, XmSTRING_DEFAULT_CHARSET, &dir);
+ iupdrvMakeDirectory(dir);
+ XtFree(dir);
+ }
+
+ XtVaSetValues(filebox, XmNdirectory, xm_dir, NULL);
+
+ XmStringFree(xm_dir);
+ XmStringFree(xm_new_dir);
+ }
+
+ (void)call_data;
+ (void)w;
+}
+
+static void motFileDlgPreviewCanvasResizeCallback(Widget w, Ihandle *ih, XtPointer call_data)
+{
+ Dimension width, height;
+ XtVaGetValues(w, XmNwidth, &width,
+ XmNheight, &height,
+ NULL);
+
+ iupAttribSetInt(ih, "PREVIEWWIDTH", width);
+ iupAttribSetInt(ih, "PREVIEWHEIGHT", height);
+
+ (void)call_data;
+}
+
+static void motFileDlgUpdatePreviewGLCanvas(Ihandle* ih)
+{
+ Ihandle* glcanvas = IupGetAttributeHandle(ih, "PREVIEWGLCANVAS");
+ if (glcanvas)
+ {
+ iupAttribSetStr(glcanvas, "XWINDOW", iupAttribGet(ih, "XWINDOW"));
+ glcanvas->iclass->Map(glcanvas);
+ }
+}
+
+static void motFileDlgPreviewCanvasInit(Ihandle *ih, Widget w)
+{
+ XSetWindowAttributes attrs;
+ GC gc = XCreateGC(iupmot_display, XtWindow(w), 0, NULL);
+ iupAttribSetStr(ih, "PREVIEWDC", (char*)gc);
+ iupAttribSetStr(ih, "WID", (char*)w);
+
+ iupAttribSetStr(ih, "XWINDOW", (char*)XtWindow(w));
+ iupAttribSetStr(ih, "XDISPLAY", (char*)iupmot_display);
+ motFileDlgUpdatePreviewGLCanvas(ih);
+
+ attrs.bit_gravity = ForgetGravity; /* For the DrawingArea widget gets Expose events when you resize it to be smaller. */
+ attrs.background_pixmap = None;
+ XChangeWindowAttributes(iupmot_display, XtWindow(w), CWBitGravity|CWBackPixmap, &attrs);
+}
+
+static void motFileDlgPreviewCanvasExposeCallback(Widget w, Ihandle *ih, XtPointer call_data)
+{
+ Widget filebox = (Widget)iupAttribGet(ih, "_IUPDLG_FILEBOX");
+ char* filename;
+ XmString xm_file;
+ IFnss cb;
+
+ if (!iupAttribGet(ih, "PREVIEWDC"))
+ motFileDlgPreviewCanvasInit(ih, w);
+
+ XtVaGetValues(filebox, XmNdirSpec, &xm_file, NULL);
+ XmStringGetLtoR(xm_file, XmSTRING_DEFAULT_CHARSET, &filename);
+
+ cb = (IFnss)IupGetCallback(ih, "FILE_CB");
+ if (iupdrvIsFile(filename))
+ cb(ih, filename, "PAINT");
+ else
+ cb(ih, NULL, "PAINT");
+
+ XtFree(filename);
+ (void)call_data;
+ (void)w;
+}
+
+static void motFileDlgBrowseSelectionCallback(Widget w, Ihandle* ih, XmListCallbackStruct* list_data)
+{
+ char* filename;
+
+ XmStringGetLtoR(list_data->item, XmSTRING_DEFAULT_CHARSET, &filename);
+
+ if (iupdrvIsFile(filename))
+ {
+ IFnss cb = (IFnss)IupGetCallback(ih, "FILE_CB");
+ cb(ih, filename, "SELECT");
+ }
+
+ XtFree(filename);
+ (void)w;
+}
+
+static int motFileDlgPopup(Ihandle* ih, int x, int y)
+{
+ InativeHandle* parent = iupDialogGetNativeParent(ih);
+ Widget filebox, dialog;
+ int dialogtype, style = XmDIALOG_FULL_APPLICATION_MODAL;
+ IFnss file_cb = NULL;
+ Widget preview_canvas = NULL;
+ char* value;
+
+ iupAttribSetInt(ih, "_IUPDLG_X", x); /* used in iupDialogUpdatePosition */
+ iupAttribSetInt(ih, "_IUPDLG_Y", y);
+
+ value = iupAttribGetStr(ih, "DIALOGTYPE");
+ if (iupStrEqualNoCase(value, "SAVE"))
+ dialogtype = IUP_DIALOGSAVE;
+ else if (iupStrEqualNoCase(value, "DIR"))
+ dialogtype = IUP_DIALOGDIR;
+ else
+ dialogtype = IUP_DIALOGOPEN;
+ iupAttribSetInt(ih, "_IUPDLG_DIALOGTYPE", dialogtype);
+
+ if (parent)
+ {
+ filebox = XmCreateFileSelectionDialog(parent, "filedialog", NULL, 0);
+ dialog = XtParent(filebox);
+ }
+ else
+ {
+ dialog = XtAppCreateShell(NULL, "filedialog", topLevelShellWidgetClass, iupmot_display, NULL, 0);
+ filebox = XmCreateFileSelectionBox(dialog, "filebox", NULL, 0);
+ style = XmDIALOG_MODELESS;
+ XtVaSetValues(dialog,
+ XmNmwmInputMode, MWM_INPUT_FULL_APPLICATION_MODAL,
+ XmNmappedWhenManaged, False,
+ XmNsaveUnder, True,
+ NULL);
+ }
+ if (!filebox)
+ return IUP_NOERROR;
+
+ if (!iupAttribGetBoolean(ih, "SHOWHIDDEN"))
+ XtVaSetValues(filebox, XmNfileFilterStyle, XmFILTER_HIDDEN_FILES, NULL);
+
+ value = iupAttribGet(ih, "TITLE");
+ if (!value)
+ {
+ if (dialogtype == IUP_DIALOGSAVE)
+ value = "IUP_SAVEAS";
+ else if (dialogtype == IUP_DIALOGOPEN)
+ value = "IUP_OPEN";
+ else
+ value = "IUP_SELECTDIR";
+ iupAttribSetStr(ih, "TITLE", iupStrMessageGet(value));
+ }
+ iupmotSetString(filebox, XmNdialogTitle, value);
+
+ XtVaSetValues(filebox,
+ XmNdialogStyle, style,
+ XmNautoUnmanage, False,
+ NULL);
+
+ if (dialogtype == IUP_DIALOGDIR)
+ XtVaSetValues(filebox, XmNfileTypeMask, XmFILE_DIRECTORY, NULL);
+
+ /* just check for the path inside FILE */
+ value = iupAttribGet(ih, "FILE");
+ if (value && value[0] == '/')
+ {
+ char* dir = iupStrFileGetPath(value);
+ iupAttribStoreStr(ih, "DIRECTORY", dir);
+ free(dir);
+ }
+
+ /* set XmNdirectory before XmNpattern and before XmNdirSpec */
+
+ value = iupAttribGet(ih, "DIRECTORY");
+ if (value)
+ iupmotSetString(filebox, XmNdirectory, value);
+
+ value = iupAttribGet(ih, "FILTER");
+ if (value)
+ {
+ char *filter = value;
+ char *p = strchr(value, ';');
+ if (p)
+ {
+ int size = p-value;
+ filter = (char*)malloc(size+1);
+ memcpy(filter, value, size);
+ filter[size] = 0;
+ }
+
+ iupmotSetString(filebox, XmNpattern, filter);
+
+ if (filter != value)
+ free(filter);
+ }
+
+ value = iupAttribGet(ih, "FILE");
+ if (value)
+ {
+ char* file = value;
+
+ if (value[0] != '/') /* if does not contains a full path, then add the directory */
+ {
+ char* cur_dir = NULL;
+ char* dir = iupAttribGet(ih, "DIRECTORY");
+ if (!dir)
+ {
+ cur_dir = iupdrvGetCurrentDirectory();
+ dir = cur_dir;
+ }
+
+ file = iupStrFileMakeFileName(dir, value);
+
+ if (cur_dir)
+ free(cur_dir);
+ }
+
+ /* clear value before setting. Do not know why we have to do this,
+ but if not cleared it will fail to set the XmNdirSpec value. */
+ iupmotSetString(filebox, XmNdirSpec, "");
+ iupmotSetString(filebox, XmNdirSpec, file);
+
+ if (file != value)
+ free(file);
+ }
+
+ if (!IupGetCallback(ih, "HELP_CB"))
+ XtUnmanageChild(XmFileSelectionBoxGetChild(filebox, XmDIALOG_HELP_BUTTON));
+
+ XtAddCallback(filebox, XmNokCallback, (XtCallbackProc)motFileDlgCallback, (XtPointer)ih);
+ XtAddCallback(filebox, XmNcancelCallback, (XtCallbackProc)motFileDlgCallback, (XtPointer)ih);
+ XtAddCallback(filebox, XmNhelpCallback, (XtCallbackProc)motFileDlgHelpCallback, (XtPointer)ih);
+
+ if (dialogtype == IUP_DIALOGDIR)
+ {
+ Widget new_folder = XtVaCreateManagedWidget("new_folder", xmPushButtonWidgetClass, filebox,
+ XmNlabelType, XmSTRING,
+ NULL);
+ iupmotSetString(new_folder, XmNlabelString, iupStrMessageGet("IUP_CREATEFOLDER"));
+ XtAddCallback(new_folder, XmNactivateCallback, (XtCallbackProc)motFileDlgNewFolderCallback, (XtPointer)filebox);
+ }
+ else
+ {
+ file_cb = (IFnss)IupGetCallback(ih, "FILE_CB");
+ if (file_cb)
+ {
+ Widget file_list = XmFileSelectionBoxGetChild(filebox, XmDIALOG_LIST);
+ XtAddCallback(file_list, XmNbrowseSelectionCallback, (XtCallbackProc)motFileDlgBrowseSelectionCallback, (XtPointer)ih);
+
+ if (iupAttribGetBoolean(ih, "SHOWPREVIEW"))
+ {
+ Widget frame = XtVaCreateManagedWidget("preview_canvas", xmFrameWidgetClass, filebox,
+ XmNshadowType, XmSHADOW_ETCHED_IN,
+ NULL);
+
+ preview_canvas = XtVaCreateManagedWidget("preview_canvas", xmDrawingAreaWidgetClass, frame,
+ XmNwidth, 180,
+ XmNheight, 150,
+ XmNresizePolicy, XmRESIZE_GROW,
+ NULL);
+
+ XtAddCallback(preview_canvas, XmNexposeCallback, (XtCallbackProc)motFileDlgPreviewCanvasExposeCallback, (XtPointer)ih);
+ XtAddCallback(preview_canvas, XmNresizeCallback, (XtCallbackProc)motFileDlgPreviewCanvasResizeCallback, (XtPointer)ih);
+
+ iupAttribSetStr(ih, "_IUPDLG_FILEBOX", (char*)filebox);
+ }
+ }
+ }
+
+ XmAddWMProtocolCallback(dialog, iupmot_wm_deletewindow, motFileDlgCBclose, (XtPointer)ih);
+ XtManageChild(filebox);
+
+ XtRealizeWidget(dialog);
+ ih->handle = dialog;
+ iupDialogUpdatePosition(ih);
+ ih->handle = NULL; /* reset handle */
+
+ if (file_cb)
+ {
+ if (preview_canvas)
+ motFileDlgPreviewCanvasInit(ih, preview_canvas);
+
+ file_cb(ih, NULL, "INIT");
+ }
+
+ if (style == XmDIALOG_MODELESS)
+ XtPopup(dialog, XtGrabExclusive);
+
+ /* while the user hasn't provided an answer, simulate main loop.
+ ** The answer changes as soon as the user selects one of the
+ ** buttons and the callback routine changes its value. */
+ iupAttribSetStr(ih, "STATUS", NULL);
+ while (iupAttribGet(ih, "STATUS") == NULL)
+ XtAppProcessEvent(iupmot_appcontext, XtIMAll);
+
+ if (file_cb)
+ {
+ if (preview_canvas)
+ XFreeGC(iupmot_display, (GC)iupAttribGet(ih, "PREVIEWDC"));
+
+ file_cb(ih, NULL, "FINISH");
+ }
+
+ if (!iupAttribGet(ih, "_IUP_WM_DELETE"))
+ {
+ XtUnmanageChild(filebox);
+
+ if (style == XmDIALOG_MODELESS)
+ {
+ XtPopdown(dialog);
+ XtDestroyWidget(dialog);
+ }
+ }
+
+ return IUP_NOERROR;
+}
+
+void iupdrvFileDlgInitClass(Iclass* ic)
+{
+ ic->DlgPopup = motFileDlgPopup;
+}
diff --git a/iup/src/mot/iupmot_focus.c b/iup/src/mot/iupmot_focus.c
new file mode 100755
index 0000000..5b09bd9
--- /dev/null
+++ b/iup/src/mot/iupmot_focus.c
@@ -0,0 +1,35 @@
+/** \file
+ * \brief Motif Focus
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+
+#include <stdio.h>
+
+#include "iup.h"
+
+#include "iup_object.h"
+#include "iup_focus.h"
+#include "iup_attrib.h"
+#include "iup_assert.h"
+#include "iup_drv.h"
+
+#include "iupmot_drv.h"
+
+void iupdrvSetFocus(Ihandle *ih)
+{
+ XmProcessTraversal(ih->handle, XmTRAVERSE_CURRENT);
+}
+
+void iupmotFocusChangeEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont)
+{
+ (void)w;
+ (void)cont;
+
+ if (evt->type == FocusIn)
+ iupCallGetFocusCb(ih);
+ else if (evt->type == FocusOut)
+ iupCallKillFocusCb(ih);
+}
diff --git a/iup/src/mot/iupmot_font.c b/iup/src/mot/iupmot_font.c
new file mode 100755
index 0000000..8da06dd
--- /dev/null
+++ b/iup/src/mot/iupmot_font.c
@@ -0,0 +1,443 @@
+/** \file
+ * \brief Motif Font mapping
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <Xm/Xm.h>
+#include <Xm/XmP.h>
+
+#include "iup.h"
+
+#include "iup_str.h"
+#include "iup_attrib.h"
+#include "iup_array.h"
+#include "iup_object.h"
+#include "iup_drv.h"
+#include "iup_drvfont.h"
+#include "iup_assert.h"
+
+#include "iupmot_drv.h"
+
+
+typedef struct _ImotFont
+{
+ char standardfont[1024];
+ char xlfd[1024]; /* X-Windows Font Description */
+ XmFontList fontlist; /* same as XmRenderTable */
+ XFontStruct *fontstruct;
+ int charwidth, charheight;
+} ImotFont;
+
+static Iarray* mot_fonts = NULL;
+
+static int motGetFontSize(char* font_name)
+{
+ int i = 0;
+ while (i < 8)
+ {
+ font_name = strchr(font_name, '-')+1;
+ i++;
+ }
+
+ *(strchr(font_name, '-')) = 0;
+ return atoi(font_name);
+}
+
+static XFontStruct* motLoadFont(const char* foundry, const char *typeface, int size, int bold, int italic, char *xlfd)
+{
+ XFontStruct* fontstruct;
+ char font_name[1024];
+ char **font_names_list;
+ char *weight, *slant;
+ int i, num_fonts, font_size, near_size;
+
+ /* no underline or strikeout support */
+
+ if (iupStrEqualNoCase(typeface, "System"))
+ typeface = "fixed";
+
+ if (!foundry) foundry = "*";
+
+ if (iupStrEqualNoCase(typeface, "fixed"))
+ foundry = "misc";
+
+ if (bold)
+ weight = "bold";
+ else
+ weight = "medium";
+
+ if (italic)
+ slant = "i";
+ else
+ slant = "r";
+
+ sprintf(font_name,"-%s-%s-%s-%s-*-*-*-*-*-*-*-*-*-*", foundry, typeface, weight, slant);
+
+ font_names_list = XListFonts(iupmot_display, font_name, 32767, &num_fonts);
+ if (!num_fonts)
+ {
+ /* try changing 'i' to 'o', for italic */
+ if (italic)
+ {
+ slant = "o";
+ strstr(font_name, "-i-")[1] = 'o';
+ font_names_list = XListFonts(iupmot_display, font_name, 32767, &num_fonts);
+ }
+
+ if (!num_fonts)
+ return NULL;
+ }
+
+ if (size < 0) /* if in pixels convert to points */
+ {
+ double res = ((double)DisplayWidth(iupmot_display, iupmot_screen) / (double)DisplayWidthMM(iupmot_display, iupmot_screen)); /* pixels/mm */
+ /* 1 point = 1/72 inch 1 inch = 25.4 mm */
+ /* pixel = ((point/72)*25.4)*pixel/mm */
+ size = (int)((-size/res)*2.83464567 + 0.5); /* from pixels to points */
+ }
+
+ size *= 10; /* convert to deci-points */
+
+ near_size = -1000;
+ for (i=0; i<num_fonts; i++)
+ {
+ font_size = motGetFontSize(font_names_list[i]);
+
+ if (font_size == size)
+ {
+ near_size = font_size;
+ break;
+ }
+
+ if (abs(font_size-size) < abs(near_size-size))
+ near_size = font_size;
+ }
+
+ XFreeFontNames(font_names_list);
+
+ sprintf(font_name,"-%s-%s-%s-%s-*-*-*-%d-*-*-*-*-*-*", foundry, typeface, weight, slant, near_size);
+ fontstruct = XLoadQueryFont(iupmot_display, font_name);
+
+ if (fontstruct)
+ strcpy(xlfd, font_name);
+
+ return fontstruct;
+}
+
+static XmFontList motFontCreateRenderTable(XFontStruct* fontstruct, int is_underline, int is_strikeout)
+{
+ XmFontList fontlist;
+ XmRendition rendition;
+ Arg args[10];
+ int num_args = 0;
+
+ iupmotSetArg(args, num_args, XmNfontType, XmFONT_IS_FONT);
+ iupmotSetArg(args, num_args, XmNfont, (XtPointer)fontstruct);
+ iupmotSetArg(args, num_args, XmNloadModel, XmLOAD_IMMEDIATE);
+
+ if (is_underline)
+ iupmotSetArg(args, num_args, XmNunderlineType, XmSINGLE_LINE);
+ else
+ iupmotSetArg(args, num_args, XmNunderlineType, XmNO_LINE);
+
+ if (is_strikeout)
+ iupmotSetArg(args, num_args, XmNstrikethruType, XmSINGLE_LINE);
+ else
+ iupmotSetArg(args, num_args, XmNstrikethruType, XmNO_LINE);
+
+ rendition = XmRenditionCreate(NULL, "", args, num_args);
+
+ fontlist = XmRenderTableAddRenditions(NULL, &rendition, 1, XmDUPLICATE);
+
+ XmRenditionFree(rendition);
+
+ return fontlist;
+}
+
+static int motFontCalcCharWidth(XFontStruct *fontstruct)
+{
+ if (fontstruct->per_char)
+ {
+ int i, all=0;
+ int first = fontstruct->min_char_or_byte2;
+ int last = fontstruct->max_char_or_byte2;
+ if (first < 32) first = 32; /* space */
+ if (last > 126) last = 126; /* tilde */
+ for (i=first; i<=last; i++)
+ all += fontstruct->per_char[i].width;
+ return all/(last-first + 1); /* average character width */
+ }
+ else
+ return fontstruct->max_bounds.width;
+}
+
+static ImotFont* motFindFont(const char* foundry, const char *standardfont)
+{
+ char xlfd[1024];
+ XFontStruct* fontstruct;
+ int i, count = iupArrayCount(mot_fonts);
+ int is_underline = 0, is_strikeout = 0;
+
+ ImotFont* fonts = (ImotFont*)iupArrayGetData(mot_fonts);
+
+ /* Check if the standardfont already exists in cache */
+ for (i = 0; i < count; i++)
+ {
+ if (iupStrEqualNoCase(standardfont, fonts[i].standardfont))
+ return &fonts[i];
+ }
+
+ /* not found, create a new one */
+ if (standardfont[0] == '-')
+ {
+ fontstruct = XLoadQueryFont(iupmot_display, standardfont);
+ if (!fontstruct) return NULL;
+ strcpy(xlfd, standardfont);
+ }
+ else
+ {
+ int size = 0,
+ is_bold = 0,
+ is_italic = 0;
+ char typeface[1024];
+ const char* mapped_name;
+
+ if (!iupFontParsePango(standardfont, typeface, &size, &is_bold, &is_italic, &is_underline, &is_strikeout))
+ return NULL;
+
+ mapped_name = iupFontGetXName(typeface);
+ if (mapped_name)
+ strcpy(typeface, mapped_name);
+
+ fontstruct = motLoadFont(foundry, typeface, size, is_bold, is_italic, xlfd);
+ if (!fontstruct) return NULL;
+ }
+
+ /* create room in the array */
+ fonts = (ImotFont*)iupArrayInc(mot_fonts);
+
+ strcpy(fonts[i].standardfont, standardfont);
+ strcpy(fonts[i].xlfd, xlfd);
+ fonts[i].fontstruct = fontstruct;
+ fonts[i].fontlist = motFontCreateRenderTable(fontstruct, is_underline, is_strikeout);
+ fonts[i].charwidth = motFontCalcCharWidth(fontstruct);
+ fonts[i].charheight = fontstruct->ascent + fontstruct->descent;
+
+ return &fonts[i];
+}
+
+char* iupdrvGetSystemFont(void)
+{
+ static char systemfont[200] = "";
+ ImotFont* motfont = NULL;
+ char* font = XGetDefault(iupmot_display, "Iup", "fontList");
+ if (font)
+ motfont = motFindFont(NULL, font);
+
+ if (!motfont)
+ {
+ font = "Fixed, 11";
+ motfont = motFindFont("misc", font);
+ }
+
+ strcpy(systemfont, font);
+ return systemfont;
+}
+
+char* iupmotFindFontList(XmFontList fontlist)
+{
+ int i, count = iupArrayCount(mot_fonts);
+ ImotFont* fonts = (ImotFont*)iupArrayGetData(mot_fonts);
+
+ /* Check if the standardfont already exists in cache */
+ for (i = 0; i < count; i++)
+ {
+ if (fontlist == fonts[i].fontlist)
+ return fonts[i].standardfont;
+ }
+
+ return NULL;
+}
+
+XmFontList iupmotGetFontList(const char* foundry, const char* value)
+{
+ ImotFont *motfont = motFindFont(foundry, value);
+ if (!motfont)
+ {
+ iupERROR1("Failed to create Font: %s", value);
+ return NULL;
+ }
+
+ return motfont->fontlist;
+}
+
+static ImotFont* motFontCreateNativeFont(Ihandle* ih, const char* value)
+{
+ ImotFont *motfont = motFindFont(iupAttribGet(ih, "FOUNDRY"), value);
+ if (!motfont)
+ {
+ iupERROR1("Failed to create Font: %s", value);
+ return NULL;
+ }
+
+ iupAttribSetStr(ih, "_IUPMOT_FONT", (char*)motfont);
+ iupAttribSetStr(ih, "XLFD", motfont->xlfd);
+ return motfont;
+}
+
+static ImotFont* motGetFont(Ihandle *ih)
+{
+ ImotFont* motfont = (ImotFont*)iupAttribGet(ih, "_IUPMOT_FONT");
+ if (!motfont)
+ motfont = motFontCreateNativeFont(ih, iupGetFontAttrib(ih));
+ return motfont;
+}
+
+char* iupmotGetFontListAttrib(Ihandle *ih)
+{
+ ImotFont* motfont = motGetFont(ih);
+ if (!motfont)
+ return NULL;
+ else
+ return (char*)motfont->fontlist;
+}
+
+char* iupmotGetFontStructAttrib(Ihandle *ih)
+{
+ ImotFont* motfont = motGetFont(ih);
+ if (!motfont)
+ return NULL;
+ else
+ return (char*)motfont->fontstruct;
+}
+
+char* iupmotGetFontIdAttrib(Ihandle *ih)
+{
+ ImotFont* motfont = motGetFont(ih);
+ if (!motfont)
+ return NULL;
+ else
+ return (char*)motfont->fontstruct->fid;
+}
+
+int iupdrvSetStandardFontAttrib(Ihandle* ih, const char* value)
+{
+ ImotFont *motfont = motFontCreateNativeFont(ih, value);
+ if (!motfont)
+ return 1;
+
+ /* If FONT is changed, must update the SIZE attribute */
+ iupBaseUpdateSizeFromFont(ih);
+
+ /* FONT attribute must be able to be set before mapping,
+ so the font is enable for size calculation. */
+ if (ih->handle && (ih->iclass->nativetype != IUP_TYPEVOID))
+ XtVaSetValues(ih->handle, XmNrenderTable, motfont->fontlist, NULL);
+
+ return 1;
+}
+
+int iupdrvFontGetStringWidth(Ihandle* ih, const char* str)
+{
+ XFontStruct* fontstruct;
+ int len;
+ char* line_end;
+
+ if (!str || str[0]==0)
+ return 0;
+
+ fontstruct = (XFontStruct*)iupmotGetFontStructAttrib(ih);
+ if (!fontstruct)
+ return 0;
+
+ line_end = strchr(str, '\n');
+ if (line_end)
+ len = line_end-str;
+ else
+ len = strlen(str);
+
+ return XTextWidth(fontstruct, str, len);
+}
+
+void iupdrvFontGetMultiLineStringSize(Ihandle* ih, const char* str, int *w, int *h)
+{
+ int num_lin, max_w;
+
+ ImotFont* motfont = motGetFont(ih);
+ if (!motfont)
+ {
+ if (w) *w = 0;
+ if (h) *h = 0;
+ return;
+ }
+
+ if (!str)
+ {
+ if (w) *w = 0;
+ if (h) *h = motfont->charheight * 1;
+ return;
+ }
+
+ max_w = 0;
+ num_lin = 1;
+ if (str[0])
+ {
+ int len, lw;
+ const char *nextstr;
+ const char *curstr = str;
+ do
+ {
+ nextstr = iupStrNextLine(curstr, &len);
+ lw = XTextWidth(motfont->fontstruct, curstr, len);
+ max_w = iupMAX(max_w, lw);
+
+ curstr = nextstr;
+ if (*nextstr)
+ num_lin++;
+ } while(*nextstr);
+ }
+
+ if (w) *w = max_w;
+ if (h) *h = motfont->charheight * num_lin;
+}
+
+
+void iupdrvFontGetCharSize(Ihandle* ih, int *charwidth, int *charheight)
+{
+ ImotFont* motfont = motGetFont(ih);
+ if (!motfont)
+ {
+ if (charwidth) *charwidth = 0;
+ if (charheight) *charheight = 0;
+ return;
+ }
+
+ if (charheight)
+ *charheight = motfont->charheight;
+
+ if (charwidth)
+ *charwidth = motfont->charwidth;
+}
+
+void iupdrvFontInit(void)
+{
+ mot_fonts = iupArrayCreate(50, sizeof(ImotFont));
+}
+
+void iupdrvFontFinish(void)
+{
+ int i, count = iupArrayCount(mot_fonts);
+ ImotFont* fonts = (ImotFont*)iupArrayGetData(mot_fonts);
+ for (i = 0; i < count; i++)
+ {
+ XmFontListFree(fonts[i].fontlist);
+ fonts[i].fontlist = NULL;
+ XFreeFont(iupmot_display, fonts[i].fontstruct);
+ fonts[i].fontstruct = NULL;
+ }
+ iupArrayDestroy(mot_fonts);
+}
diff --git a/iup/src/mot/iupmot_fontdlg.c b/iup/src/mot/iupmot_fontdlg.c
new file mode 100755
index 0000000..42767b2
--- /dev/null
+++ b/iup/src/mot/iupmot_fontdlg.c
@@ -0,0 +1,31 @@
+/** \file
+ * \brief IupFontDlg pre-defined dialog
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+
+#include "iup.h"
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drvinfo.h"
+#include "iup_dialog.h"
+
+#include "iupmot_drv.h"
+
+
+static int motFontDlgPopup(Ihandle* ih, int x, int y)
+{
+ (void)ih;
+ (void)x;
+ (void)y;
+ return IUP_ERROR;
+}
+
+void iupdrvFontDlgInitClass(Iclass* ic)
+{
+ ic->DlgPopup = motFontDlgPopup;
+}
diff --git a/iup/src/mot/iupmot_frame.c b/iup/src/mot/iupmot_frame.c
new file mode 100755
index 0000000..39de5d8
--- /dev/null
+++ b/iup/src/mot/iupmot_frame.c
@@ -0,0 +1,257 @@
+/** \file
+ * \brief Frame Control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+#include <Xm/Frame.h>
+#include <Xm/Label.h>
+#include <Xm/BulletinB.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdarg.h>
+
+#include "iup.h"
+
+#include "iup_object.h"
+#include "iup_childtree.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_dialog.h"
+#include "iup_image.h"
+#include "iup_drv.h"
+#include "iup_drvfont.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+void iupdrvFrameGetDecorOffset(Ihandle* ih, int *x, int *y)
+{
+ (void)ih;
+ *x = 0;
+ *y = 0;
+}
+
+static int motFrameSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ Pixel color;
+
+ /* ignore given value, must use only from parent */
+ value = iupBaseNativeParentGetBgColor(ih);
+
+ color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ {
+ Widget title_label, child_manager;
+
+ iupmotSetBgColor(ih->handle, color);
+
+ child_manager = XtNameToWidget(ih->handle, "*child_manager");
+ iupmotSetBgColor(child_manager, color);
+
+ title_label = XtNameToWidget(ih->handle, "*title_label");
+ if (!title_label) return 1;
+ iupmotSetBgColor(title_label, color);
+
+ return 1;
+ }
+ return 0;
+}
+
+static int motFrameSetBackgroundAttrib(Ihandle* ih, const char* value)
+{
+ Pixel color;
+
+ /* ignore given value, must use only from parent */
+ value = iupAttribGetInheritNativeParent(ih, "BACKGROUND");
+
+ color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ {
+ Widget title_label, child_manager;
+
+ iupmotSetBgColor(ih->handle, color);
+
+ child_manager = XtNameToWidget(ih->handle, "*child_manager");
+ iupmotSetBgColor(child_manager, color);
+
+ title_label = XtNameToWidget(ih->handle, "*title_label");
+ if (!title_label) return 1;
+ iupmotSetBgColor(title_label, color);
+
+ return 1;
+ }
+ else
+ {
+ Pixmap pixmap = (Pixmap)iupImageGetImage(value, ih, 0);
+ if (pixmap)
+ {
+ Widget child_manager = XtNameToWidget(ih->handle, "*child_manager");
+ Widget title_label = XtNameToWidget(ih->handle, "*title_label");
+
+ XtVaSetValues(child_manager, XmNbackgroundPixmap, pixmap, NULL);
+ if (title_label)
+ XtVaSetValues(title_label, XmNbackgroundPixmap, pixmap, NULL);
+
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int motFrameSetFgColorAttrib(Ihandle* ih, const char* value)
+{
+ Pixel color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ {
+ Widget title_label = XtNameToWidget(ih->handle, "*title_label");
+ if (!title_label) return 0;
+ XtVaSetValues(title_label, XmNforeground, color, NULL);
+ return 1;
+ }
+ return 0;
+}
+
+static int motFrameSetStandardFontAttrib(Ihandle* ih, const char* value)
+{
+ iupdrvSetStandardFontAttrib(ih, value);
+
+ if (ih->handle)
+ {
+ XmFontList fontlist;
+ Widget title_label = XtNameToWidget(ih->handle, "*title_label");
+ if (!title_label) return 1;
+
+ fontlist = (XmFontList)iupmotGetFontListAttrib(ih);
+ XtVaSetValues(title_label, XmNrenderTable, fontlist, NULL);
+ }
+
+ return 1;
+}
+
+static int motFrameSetTitleAttrib(Ihandle* ih, const char* value)
+{
+ Widget title_label = XtNameToWidget(ih->handle, "*title_label");
+ if (title_label)
+ {
+ if (!value) value = "";
+ iupmotSetString(title_label, XmNlabelString, value);
+ return 1;
+ }
+ return 0;
+}
+
+static void* motFrameGetInnerNativeContainerHandleMethod(Ihandle* ih, Ihandle* child)
+{
+ (void)child;
+ return XtNameToWidget(ih->handle, "*child_manager");
+}
+
+static int motFrameMapMethod(Ihandle* ih)
+{
+ char *title;
+ int num_args = 0;
+ Arg args[20];
+ Widget child_manager;
+
+ if (!ih->parent)
+ return IUP_ERROR;
+
+ title = iupAttribGet(ih, "TITLE");
+
+ if (title)
+ iupAttribSetStr(ih, "_IUPFRAME_HAS_TITLE", "1");
+ else
+ {
+ char* value = iupAttribGetStr(ih, "SUNKEN");
+ if (iupStrBoolean(value))
+ iupmotSetArg(args, num_args, XmNshadowType, XmSHADOW_IN);
+ else
+ iupmotSetArg(args, num_args, XmNshadowType, XmSHADOW_ETCHED_IN);
+ }
+
+ /* Core */
+ iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+ iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+ iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ /* Manager */
+ iupmotSetArg(args, num_args, XmNshadowThickness, 2);
+ /* Frame */
+ iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* no shadow margins */
+ iupmotSetArg(args, num_args, XmNmarginWidth, 0); /* no shadow margins */
+
+ ih->handle = XtCreateManagedWidget(
+ iupDialogGetChildIdStr(ih), /* child identifier */
+ xmFrameWidgetClass, /* widget class */
+ iupChildTreeGetNativeParentHandle(ih), /* widget parent */
+ args, num_args);
+
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ ih->serial = iupDialogGetChildId(ih); /* must be after using the string */
+
+ if (title)
+ {
+ Widget title_label;
+ num_args = 0;
+ /* Label */
+ iupmotSetArg(args, num_args, XmNlabelType, XmSTRING);
+ iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
+ iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+ /* Frame Constraint */
+ iupmotSetArg(args, num_args, XmNchildType, XmFRAME_TITLE_CHILD);
+ title_label = XtCreateManagedWidget("title_label", xmLabelWidgetClass, ih->handle, args, num_args);
+ iupmotSetString(title_label, XmNlabelString, title);
+ }
+
+ child_manager = XtVaCreateManagedWidget(
+ "child_manager",
+ xmBulletinBoardWidgetClass,
+ ih->handle,
+ /* Core */
+ XmNborderWidth, 0,
+ /* Manager */
+ XmNshadowThickness, 0,
+ XmNnavigationType, XmTAB_GROUP,
+ /* BulletinBoard */
+ XmNmarginWidth, 0,
+ XmNmarginHeight, 0,
+ XmNresizePolicy, XmRESIZE_NONE, /* no automatic resize of children */
+ /* Frame Constraint */
+ XmNchildType, XmFRAME_WORKAREA_CHILD,
+ NULL);
+
+ /* initialize the widget */
+ XtRealizeWidget(ih->handle);
+
+ return IUP_NOERROR;
+}
+
+void iupdrvFrameInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class functions */
+ ic->Map = motFrameMapMethod;
+ ic->GetInnerNativeContainerHandle = motFrameGetInnerNativeContainerHandleMethod;
+
+ /* Driver Dependent Attribute functions */
+
+ /* Overwrite Common */
+ iupClassRegisterAttribute(ic, "STANDARDFONT", NULL, motFrameSetStandardFontAttrib, IUPAF_SAMEASSYSTEM, "DEFAULTFONT", IUPAF_NOT_MAPPED);
+
+ /* Visual */
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, motFrameSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BACKGROUND", NULL, motFrameSetBackgroundAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+
+ /* Special */
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, motFrameSetFgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGFGCOLOR", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "TITLE", NULL, motFrameSetTitleAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+}
diff --git a/iup/src/mot/iupmot_globalattrib.c b/iup/src/mot/iupmot_globalattrib.c
new file mode 100755
index 0000000..9567cf5
--- /dev/null
+++ b/iup/src/mot/iupmot_globalattrib.c
@@ -0,0 +1,155 @@
+/** \file
+ * \brief Motif Driver implementation of iupdrvSetGlobal
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+
+#include <stdio.h>
+
+#include "iup.h"
+
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_drvinfo.h"
+#include "iup_strmessage.h"
+
+#include "iupmot_drv.h"
+
+
+static void motGlobalSendKey(int key, int press)
+{
+ Window focus;
+ int revert_to;
+ XKeyEvent evt;
+ memset(&evt, 0, sizeof(XKeyEvent));
+ evt.display = iupmot_display;
+ evt.send_event = True;
+ evt.root = DefaultRootWindow(iupmot_display);
+
+ XGetInputFocus(iupmot_display, &focus, &revert_to);
+ evt.window = focus;
+
+ iupmotKeyEncode(key, &evt.keycode, &evt.state);
+ if (!evt.keycode)
+ return;
+
+ if (press & 0x01)
+ {
+ evt.type = KeyPress;
+ XSendEvent(iupmot_display, (Window)InputFocus, False, KeyPressMask, (XEvent*)&evt);
+ }
+
+ if (press & 0x02)
+ {
+ evt.type = KeyRelease;
+ XSendEvent(iupmot_display, (Window)InputFocus, False, KeyReleaseMask, (XEvent*)&evt);
+ }
+}
+
+int iupdrvSetGlobal(const char *name, const char *value)
+{
+ if (iupStrEqual(name, "LANGUAGE"))
+ {
+ iupStrMessageUpdateLanguage(value);
+ return 1;
+ }
+ if (iupStrEqual(name, "AUTOREPEAT"))
+ {
+ XKeyboardControl values;
+ if (iupStrBoolean(value))
+ values.auto_repeat_mode = 1;
+ else
+ values.auto_repeat_mode = 0;
+ XChangeKeyboardControl(iupmot_display, KBAutoRepeatMode, &values);
+ return 0;
+ }
+ if (iupStrEqual(name, "CURSORPOS"))
+ {
+ int x, y;
+ if (iupStrToIntInt(value, &x, &y, 'x') == 2)
+ XWarpPointer(iupmot_display,None,RootWindow(iupmot_display, iupmot_screen),0,0,0,0,x,y);
+ return 0;
+ }
+ if (iupStrEqual(name, "KEYPRESS"))
+ {
+ int key;
+ if (iupStrToInt(value, &key))
+ motGlobalSendKey(key, 0x01);
+ return 0;
+ }
+ if (iupStrEqual(name, "KEYRELEASE"))
+ {
+ int key;
+ if (iupStrToInt(value, &key))
+ motGlobalSendKey(key, 0x02);
+ return 0;
+ }
+ if (iupStrEqual(name, "KEY"))
+ {
+ int key;
+ if (iupStrToInt(value, &key))
+ motGlobalSendKey(key, 0x03);
+ return 0;
+ }
+ return 1;
+}
+
+char* iupdrvGetGlobal(const char *name)
+{
+ if (iupStrEqual(name, "CURSORPOS"))
+ {
+ int x, y;
+ char* str = iupStrGetMemory(50);
+ iupdrvGetCursorPos(&x, &y);
+ sprintf(str, "%dx%d", x, y);
+ return str;
+ }
+ if (iupStrEqual(name, "SHIFTKEY"))
+ {
+ char key[5];
+ iupdrvGetKeyState(key);
+ if (key[0] == 'S')
+ return "ON";
+ return "OFF";
+ }
+ if (iupStrEqual(name, "CONTROLKEY"))
+ {
+ char key[5];
+ iupdrvGetKeyState(key);
+ if (key[1] == 'C')
+ return "ON";
+ return "OFF";
+ }
+ if (iupStrEqual(name, "MODKEYSTATE"))
+ {
+ char *str = iupStrGetMemory(5);
+ iupdrvGetKeyState(str);
+ return str;
+ }
+ if (iupStrEqual(name, "SCREENSIZE"))
+ {
+ char *str = iupStrGetMemory(50);
+ int w, h;
+ iupdrvGetScreenSize(&w, &h);
+ sprintf(str, "%dx%d", w, h);
+ return str;
+ }
+ if (iupStrEqual(name, "FULLSIZE"))
+ {
+ char *str = iupStrGetMemory(50);
+ int w, h;
+ iupdrvGetFullSize(&w, &h);
+ sprintf(str, "%dx%d", w, h);
+ return str;
+ }
+ if (iupStrEqual(name, "SCREENDEPTH"))
+ {
+ char *str = iupStrGetMemory(50);
+ int bpp = iupdrvGetScreenDepth();
+ sprintf(str, "%d", bpp);
+ return str;
+ }
+ return NULL;
+}
diff --git a/iup/src/mot/iupmot_image.c b/iup/src/mot/iupmot_image.c
new file mode 100755
index 0000000..b0078d5
--- /dev/null
+++ b/iup/src/mot/iupmot_image.c
@@ -0,0 +1,397 @@
+/** \file
+ * \brief Image Resource.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+
+#include <stdio.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <memory.h>
+
+#include "iup.h"
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_image.h"
+#include "iup_drvinfo.h"
+
+#include "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+void iupdrvImageGetRawData(void* handle, unsigned char* imgdata)
+{
+ Pixmap pixmap = (Pixmap)handle;
+ int w, h, y, x, bpp;
+ XImage *xi;
+
+ if (!iupdrvImageGetInfo(handle, &w, &h, &bpp))
+ return;
+
+ if (bpp==8)
+ return;
+
+ xi = XGetImage(iupmot_display, pixmap, 0, 0, w, h, ULONG_MAX, ZPixmap);
+ if (xi)
+ {
+ /* planes are separated in imgdata */
+ int planesize = w*h;
+ unsigned char *r = imgdata,
+ *g = imgdata+planesize,
+ *b = imgdata+2*planesize;
+ for (y=0; y<h; y++)
+ {
+ int lineoffset = (h-1 - y)*w; /* imgdata is bottom up */
+ for (x=0; x<w; x++)
+ {
+ iupmotColorGetRGB(XGetPixel(xi, x, y), r + lineoffset+x, g + lineoffset+x, b + lineoffset+x);
+ }
+ }
+
+ XDestroyImage(xi);
+ }
+}
+
+void* iupdrvImageCreateImageRaw(int width, int height, int bpp, iupColor* colors, int colors_count, unsigned char *imgdata)
+{
+ int y, x;
+ Pixmap pixmap;
+ GC gc;
+
+ pixmap = XCreatePixmap(iupmot_display,
+ RootWindow(iupmot_display,iupmot_screen),
+ width, height, iupdrvGetScreenDepth());
+ if (!pixmap)
+ return NULL;
+
+ gc = XCreateGC(iupmot_display,pixmap,0,NULL);
+
+ /* Pixmap is top-bottom */
+ /* imgdata is bottom up */
+
+ if (bpp == 8)
+ {
+ Pixel color2pixel[256];
+ int i;
+ for (i=0;i<colors_count;i++)
+ color2pixel[i] = iupmotColorGetPixel(colors[i].r, colors[i].g, colors[i].b);
+
+ for (y=0;y<height;y++)
+ {
+ int lineoffset = (height-1 - y)*width; /* imgdata is bottom up */
+ for(x=0;x<width;x++)
+ {
+ unsigned long p = color2pixel[imgdata[lineoffset+x]];
+ XSetForeground(iupmot_display,gc,p);
+ XDrawPoint(iupmot_display,pixmap,gc,x,y);
+ }
+ }
+ }
+ else
+ {
+ /* planes are separated in imgdata */
+ int planesize = width*height;
+ unsigned char *r = imgdata,
+ *g = imgdata+planesize,
+ *b = imgdata+2*planesize;
+ for (y=0;y<height;y++)
+ {
+ int lineoffset = (height-1 - y)*width; /* imgdata is bottom up */
+ for(x=0;x<width;x++)
+ {
+ unsigned long p = iupmotColorGetPixel(r[lineoffset+x], g[lineoffset+x], b[lineoffset+x]);
+ XSetForeground(iupmot_display,gc,p);
+ XDrawPoint(iupmot_display,pixmap,gc,x,y);
+ }
+ }
+ }
+
+ XFreeGC(iupmot_display,gc);
+
+ return (void*)pixmap;
+}
+
+void* iupdrvImageCreateImage(Ihandle *ih, const char* bgcolor, int make_inactive)
+{
+ int y, x, bpp, bgcolor_depend = 0,
+ width = ih->currentwidth,
+ height = ih->currentheight;
+ unsigned char *imgdata = (unsigned char*)iupAttribGetStr(ih, "WID");
+ Pixmap pixmap;
+ unsigned char bg_r=0, bg_g=0, bg_b=0;
+ GC gc;
+ Pixel color2pixel[256];
+
+ bpp = iupAttribGetInt(ih, "BPP");
+
+ iupStrToRGB(bgcolor, &bg_r, &bg_g, &bg_b);
+
+ if (bpp == 8)
+ {
+ int i, colors_count = 0;
+ iupColor colors[256];
+
+ iupImageInitColorTable(ih, colors, &colors_count);
+
+ for (i=0;i<colors_count;i++)
+ {
+ if (colors[i].a == 0)
+ {
+ colors[i].r = bg_r;
+ colors[i].g = bg_g;
+ colors[i].b = bg_b;
+ colors[i].a = 255;
+ bgcolor_depend = 1;
+ }
+
+ if (make_inactive)
+ iupImageColorMakeInactive(&(colors[i].r), &(colors[i].g), &(colors[i].b),
+ bg_r, bg_g, bg_b);
+
+ color2pixel[i] = iupmotColorGetPixel(colors[i].r, colors[i].g, colors[i].b);
+ }
+ }
+
+ pixmap = XCreatePixmap(iupmot_display,
+ RootWindow(iupmot_display,iupmot_screen),
+ width, height, iupdrvGetScreenDepth());
+ if (!pixmap)
+ return NULL;
+
+ gc = XCreateGC(iupmot_display,pixmap,0,NULL);
+ for (y=0;y<height;y++)
+ {
+ for(x=0;x<width;x++)
+ {
+ unsigned long p;
+ if (bpp == 8)
+ p = color2pixel[imgdata[y*width+x]];
+ else
+ {
+ int channels = (bpp==24)? 3: 4;
+ unsigned char *pixel_data = imgdata + y*width*channels + x*channels;
+ unsigned char r = *(pixel_data),
+ g = *(pixel_data+1),
+ b = *(pixel_data+2);
+
+ if (bpp == 32)
+ {
+ unsigned char a = *(pixel_data+3);
+ if (a != 255)
+ {
+ r = iupALPHABLEND(r, bg_r, a);
+ g = iupALPHABLEND(g, bg_g, a);
+ b = iupALPHABLEND(b, bg_b, a);
+ bgcolor_depend = 1;
+ }
+ }
+
+ if (make_inactive)
+ iupImageColorMakeInactive(&r, &g, &b, bg_r, bg_g, bg_b);
+
+ p = iupmotColorGetPixel(r, g, b);
+ }
+
+ XSetForeground(iupmot_display,gc,p);
+ XDrawPoint(iupmot_display,pixmap,gc,x,y);
+ }
+ }
+ XFreeGC(iupmot_display,gc);
+
+ if (bgcolor_depend || make_inactive)
+ iupAttribSetStr(ih, "_IUP_BGCOLOR_DEPEND", "1");
+
+ return (void*)pixmap;
+}
+
+void* iupdrvImageCreateIcon(Ihandle *ih)
+{
+ return iupdrvImageCreateImage(ih, NULL, 0);
+}
+
+void* iupdrvImageCreateCursor(Ihandle *ih)
+{
+ int bpp,y,x,hx,hy,
+ width = ih->currentwidth,
+ height = ih->currentheight,
+ line_size = (width+7)/8,
+ size_bytes = line_size*height;
+ unsigned char *imgdata = (unsigned char*)iupAttribGetStr(ih, "WID");
+ char *sbits, *mbits, *sb, *mb;
+ Pixmap source, mask;
+ XColor fg, bg;
+ unsigned char r, g, b;
+ Cursor cursor;
+
+ bpp = iupAttribGetInt(ih, "BPP");
+ if (bpp > 8)
+ return NULL;
+
+ sbits = (char*)malloc(2*size_bytes);
+ if (!sbits) return NULL;
+ memset(sbits, 0, 2*size_bytes);
+ mbits = sbits + size_bytes;
+
+ sb = sbits;
+ mb = mbits;
+ for (y=0; y<height; y++)
+ {
+ for (x=0; x<width; x++)
+ {
+ int byte = x/8;
+ int bit = x%8;
+ int index = (int)imgdata[y*width+x];
+ /* index==0 is transparent */
+ if (index == 1)
+ sb[byte] = (char)(sb[byte] | (1<<bit));
+ if (index != 0)
+ mb[byte] = (char)(mb[byte] | (1<<bit));
+ }
+
+ sb += line_size;
+ mb += line_size;
+ }
+
+ r = 255; g = 255; b = 255;
+ iupStrToRGB(iupAttribGet(ih, "1"), &r, &g, &b );
+ fg.red = iupCOLOR8TO16(r);
+ fg.green = iupCOLOR8TO16(g);
+ fg.blue = iupCOLOR8TO16(b);
+ fg.flags = DoRed | DoGreen | DoBlue;
+
+ r = 0; g = 0; b = 0;
+ iupStrToRGB(iupAttribGet(ih, "2"), &r, &g, &b );
+ bg.red = iupCOLOR8TO16(r);
+ bg.green = iupCOLOR8TO16(g);
+ bg.blue = iupCOLOR8TO16(b);
+ bg.flags = DoRed | DoGreen | DoBlue;
+
+ hx=0; hy=0;
+ iupStrToIntInt(iupAttribGet(ih, "HOTSPOT"), &hx, &hy, ':');
+
+ source = XCreateBitmapFromData(iupmot_display,
+ RootWindow(iupmot_display,iupmot_screen),
+ sbits, width, height);
+ mask = XCreateBitmapFromData(iupmot_display,
+ RootWindow(iupmot_display,iupmot_screen),
+ mbits, width, height);
+
+ cursor = XCreatePixmapCursor(iupmot_display, source, mask, &fg, &bg, hx, hy);
+
+ free(sbits);
+ return (void*)cursor;
+}
+
+void* iupdrvImageCreateMask(Ihandle *ih)
+{
+ int bpp,y,x,
+ width = ih->currentwidth,
+ height = ih->currentheight,
+ line_size = (width+7)/8,
+ size_bytes = line_size*height;
+ unsigned char *imgdata = (unsigned char*)iupAttribGetStr(ih, "WID");
+ char *bits, *sb;
+ Pixmap mask;
+ unsigned char colors[256];
+
+ bpp = iupAttribGetInt(ih, "BPP");
+ if (bpp > 8)
+ return NULL;
+
+ bits = (char*)malloc(size_bytes);
+ if (!bits) return NULL;
+ memset(bits, 0, size_bytes);
+
+ iupImageInitNonBgColors(ih, colors);
+
+ sb = bits;
+ for (y=0; y<height; y++)
+ {
+ for (x=0; x<width; x++)
+ {
+ int byte = x/8;
+ int bit = x%8;
+ int index = (int)imgdata[y*width+x];
+ if (colors[index])
+ sb[byte] = (char)(sb[byte] | (1<<bit));
+ }
+
+ sb += line_size;
+ }
+
+ mask = XCreateBitmapFromData(iupmot_display,
+ RootWindow(iupmot_display,iupmot_screen),
+ bits, width, height);
+
+ free(bits);
+ return (void*)mask;
+}
+
+void* iupdrvImageLoad(const char* name, int type)
+{
+ if (type == IUPIMAGE_CURSOR)
+ {
+ Cursor cursor = 0;
+ int id;
+ if (iupStrToInt(name, &id))
+ cursor = XCreateFontCursor(iupmot_display, id);
+ return (void*)cursor;
+ }
+ else /* IUPIMAGE_IMAGE or IUPIMAGE_ICON */
+ {
+ Screen* screen = ScreenOfDisplay(iupmot_display, iupmot_screen);
+ Pixmap pixmap = XmGetPixmap(screen, (char*)name, BlackPixelOfScreen(screen), WhitePixelOfScreen(screen));
+ if (pixmap == XmUNSPECIFIED_PIXMAP)
+ {
+ unsigned int width, height;
+ int hotx, hoty;
+ pixmap = 0;
+ XReadBitmapFile(iupmot_display, RootWindow(iupmot_display,iupmot_screen), name, &width, &height, &pixmap, &hotx, &hoty);
+ }
+ return (void*)pixmap;
+ }
+}
+
+int iupdrvImageGetInfo(void* handle, int *w, int *h, int *bpp)
+{
+ Pixmap pixmap = (Pixmap)handle;
+ Window root;
+ int x, y;
+ unsigned int width, height, b, depth;
+ if (!XGetGeometry(iupmot_display, pixmap, &root, &x, &y, &width, &height, &b, &depth))
+ {
+ if (w) *w = 0;
+ if (h) *h = 0;
+ if (bpp) *bpp = 0;
+ return 0;
+ }
+ if (w) *w = width;
+ if (h) *h = height;
+ if (bpp) *bpp = iupImageNormBpp(depth);
+ return 1;
+}
+
+int iupdrvImageGetRawInfo(void* handle, int *w, int *h, int *bpp, iupColor* colors, int *colors_count)
+{
+ /* How to get the pallete? */
+ (void)colors;
+ (void)colors_count;
+ return iupdrvImageGetInfo(handle, w, h, bpp);
+}
+
+void iupdrvImageDestroy(void* handle, int type)
+{
+ if (type == IUPIMAGE_CURSOR)
+ XFreeCursor(iupmot_display, (Cursor)handle);
+ else
+ {
+ Screen* screen = ScreenOfDisplay(iupmot_display, iupmot_screen);
+ if (!XmDestroyPixmap(screen, (Pixmap)handle))
+ XFreePixmap(iupmot_display, (Pixmap)handle);
+ }
+}
+
diff --git a/iup/src/mot/iupmot_key.c b/iup/src/mot/iupmot_key.c
new file mode 100755
index 0000000..835b5d7
--- /dev/null
+++ b/iup/src/mot/iupmot_key.c
@@ -0,0 +1,425 @@
+/** \file
+ * \brief Motif Driver keyboard mapping
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+#include <X11/keysym.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iupkey.h"
+
+#include "iup_object.h"
+#include "iup_key.h"
+#include "iup_str.h"
+
+#include "iupmot_drv.h"
+
+typedef struct Imot2iupkey
+{
+ KeySym motcode;
+ int iupcode;
+ int s_iupcode;
+ int c_iupcode;
+ int m_iupcode;
+ int y_iupcode;
+} Imot2iupkey;
+
+static Imot2iupkey motkey_map[] = {
+
+{ XK_Escape, K_ESC, K_sESC, K_cESC, K_mESC ,K_yESC },
+{ XK_Pause, K_PAUSE, K_sPAUSE, K_cPAUSE, K_mPAUSE ,K_yPAUSE },
+{ XK_Print, K_Print, K_sPrint, K_cPrint, K_mPrint ,K_yPrint },
+{ XK_Menu, K_Menu, K_sMenu, K_cMenu, K_mMenu ,K_yMenu },
+
+{ XK_Home, K_HOME, K_sHOME, K_cHOME, K_mHOME ,K_yHOME },
+{ XK_Up, K_UP, K_sUP, K_cUP, K_mUP ,K_yUP },
+{ XK_Prior, K_PGUP, K_sPGUP, K_cPGUP, K_mPGUP ,K_yPGUP },
+{ XK_Left, K_LEFT, K_sLEFT, K_cLEFT, K_mLEFT ,K_yLEFT },
+{ XK_Begin, K_MIDDLE,K_sMIDDLE, K_cMIDDLE,K_mMIDDLE,K_yMIDDLE},
+{ XK_Right, K_RIGHT, K_sRIGHT, K_cRIGHT, K_mRIGHT ,K_yRIGHT },
+{ XK_End, K_END, K_sEND, K_cEND, K_mEND ,K_yEND },
+{ XK_Down, K_DOWN, K_sDOWN, K_cDOWN, K_mDOWN ,K_yDOWN },
+{ XK_Next, K_PGDN, K_sPGDN, K_cPGDN, K_mPGDN ,K_yPGDN },
+{ XK_Insert, K_INS, K_sINS, K_cINS, K_mINS ,K_yINS },
+{ XK_Delete, K_DEL, K_sDEL, K_cDEL, K_mDEL ,K_yDEL },
+{ XK_space, K_SP, K_sSP, K_cSP, K_mSP ,K_ySP },
+{ XK_Tab, K_TAB, K_sTAB, K_cTAB, K_mTAB ,K_yTAB },
+{ XK_Return, K_CR, K_sCR, K_cCR, K_mCR ,K_yCR },
+{ XK_BackSpace, K_BS, K_sBS, K_cBS, K_mBS ,K_yBS },
+
+{ XK_1, K_1, K_exclam, K_c1, K_m1, K_y1 },
+{ XK_2, K_2, K_at, K_c2, K_m2, K_y2 },
+{ XK_3, K_3, K_numbersign, K_c3, K_m3, K_y3 },
+{ XK_4, K_4, K_dollar, K_c4, K_m4, K_y4 },
+{ XK_5, K_5, K_percent, K_c5, K_m5, K_y5 },
+{ XK_6, K_6, K_circum, K_c6, K_m6, K_y6 },
+{ XK_7, K_7, K_ampersand, K_c7, K_m7, K_y7 },
+{ XK_8, K_8, K_asterisk, K_c8, K_m8, K_y8 },
+{ XK_9, K_9, K_parentleft, K_c9, K_m9, K_y9 },
+{ XK_0, K_0, K_parentright, K_c0, K_m0, K_y0 },
+
+{ XK_a, K_a, K_A, K_cA, K_mA, K_yA },
+{ XK_b, K_b, K_B, K_cB, K_mB, K_yB },
+{ XK_c, K_c, K_C, K_cC, K_mC, K_yC },
+{ XK_d, K_d, K_D, K_cD, K_mD, K_yD },
+{ XK_e, K_e, K_E, K_cE, K_mE, K_yE },
+{ XK_f, K_f, K_F, K_cF, K_mF, K_yF },
+{ XK_g, K_g, K_G, K_cG, K_mG, K_yG },
+{ XK_h, K_h, K_H, K_cH, K_mH, K_yH },
+{ XK_i, K_i, K_I, K_cI, K_mI, K_yI },
+{ XK_j, K_j, K_J, K_cJ, K_mJ, K_yJ },
+{ XK_k, K_k, K_K, K_cK, K_mK, K_yK },
+{ XK_l, K_l, K_L, K_cL, K_mL, K_yL },
+{ XK_m, K_m, K_M, K_cM, K_mM, K_yM },
+{ XK_n, K_n, K_N, K_cN, K_mN, K_yN },
+{ XK_o, K_o, K_O, K_cO, K_mO, K_yO },
+{ XK_p, K_p, K_P, K_cP, K_mP, K_yP },
+{ XK_q, K_q, K_Q, K_cQ, K_mQ, K_yQ },
+{ XK_r, K_r, K_R, K_cR, K_mR, K_yR },
+{ XK_s, K_s, K_S, K_cS, K_mS, K_yS },
+{ XK_t, K_t, K_T, K_cT, K_mT, K_yT },
+{ XK_u, K_u, K_U, K_cU, K_mU, K_yU },
+{ XK_v, K_v, K_V, K_cV, K_mV, K_yV },
+{ XK_w, K_w, K_W, K_cW, K_mW, K_yW },
+{ XK_x, K_x, K_X, K_cX, K_mX, K_yX },
+{ XK_y, K_y, K_Y, K_cY, K_mY, K_yY },
+{ XK_z, K_z, K_Z, K_cZ, K_mZ, K_yZ },
+
+{ XK_F1, K_F1, K_sF1, K_cF1, K_mF1, K_yF1 },
+{ XK_F2, K_F2, K_sF2, K_cF2, K_mF2, K_yF2 },
+{ XK_F3, K_F3, K_sF3, K_cF3, K_mF3, K_yF3 },
+{ XK_F4, K_F4, K_sF4, K_cF4, K_mF4, K_yF4 },
+{ XK_F5, K_F5, K_sF5, K_cF5, K_mF5, K_yF5 },
+{ XK_F6, K_F6, K_sF6, K_cF6, K_mF6, K_yF6 },
+{ XK_F7, K_F7, K_sF7, K_cF7, K_mF7, K_yF7 },
+{ XK_F8, K_F8, K_sF8, K_cF8, K_mF8, K_yF8 },
+{ XK_F9, K_F9, K_sF9, K_cF9, K_mF9, K_yF9 },
+{ XK_F10, K_F10, K_sF10, K_cF10, K_mF10, K_yF10 },
+{ XK_F11, K_F11, K_sF11, K_cF11, K_mF11, K_yF11 },
+{ XK_F12, K_F12, K_sF12, K_cF12, K_mF12, K_yF12 },
+
+{ XK_semicolon, K_semicolon, K_colon, K_cSemicolon, K_mSemicolon, K_ySemicolon },
+{ XK_equal, K_equal, K_plus, K_cEqual, K_mEqual, K_yEqual },
+{ XK_comma, K_comma, K_less, K_cComma, K_mComma, K_yComma },
+{ XK_minus, K_minus, K_underscore, K_cMinus, K_mMinus, K_yMinus },
+{ XK_period, K_period, K_greater, K_cPeriod, K_mPeriod, K_yPeriod },
+{ XK_slash, K_slash, K_question, K_cSlash, K_mSlash, K_ySlash },
+{ XK_grave, K_grave, K_tilde, 0, 0, 0 },
+{ XK_bracketleft, K_bracketleft, K_braceleft, K_cBracketleft, K_mBracketleft, K_yBracketleft },
+{ XK_backslash, K_backslash, K_bar, K_cBackslash, K_mBackslash, K_yBackslash },
+{ XK_bracketright,K_bracketright, K_braceright, K_cBracketright,K_mBracketright,K_yBracketright },
+{ XK_apostrophe, K_apostrophe, K_quotedbl, 0, 0, 0 },
+
+{ XK_KP_0, K_0, K_0, K_c0, K_m0, K_y0 },
+{ XK_KP_1, K_1, K_1, K_c1, K_m1, K_y1 },
+{ XK_KP_2, K_2, K_2, K_c2, K_m2, K_y2 },
+{ XK_KP_3, K_3, K_3, K_c3, K_m3, K_y3 },
+{ XK_KP_4, K_4, K_4, K_c4, K_m4, K_y4 },
+{ XK_KP_5, K_5, K_5, K_c5, K_m5, K_y5 },
+{ XK_KP_6, K_6, K_6, K_c6, K_m6, K_y6 },
+{ XK_KP_7, K_7, K_7, K_c7, K_m7, K_y7 },
+{ XK_KP_8, K_8, K_8, K_c8, K_m8, K_y8 },
+{ XK_KP_9, K_9, K_9, K_c9, K_m9, K_y9 },
+{ XK_KP_Multiply, K_asterisk, K_sAsterisk, K_cAsterisk, K_mAsterisk, K_yAsterisk },
+{ XK_KP_Add, K_plus, K_sPlus, K_cPlus, K_mPlus, K_yPlus },
+{ XK_KP_Subtract, K_minus, K_sMinus, K_cMinus, K_mMinus, K_yMinus },
+{ XK_KP_Decimal, K_period, K_sPeriod, K_cPeriod, K_mPeriod, K_yPeriod },
+{ XK_KP_Divide, K_slash, K_sSlash, K_cSlash, K_mSlash, K_ySlash },
+{ XK_KP_Separator, K_comma, K_sComma, K_cComma, K_mComma, K_yComma },
+
+{ XK_ccedilla, K_ccedilla, K_Ccedilla, K_cCcedilla, K_mCcedilla, K_yCcedilla },
+
+{ XK_dead_tilde, K_tilde, K_circum, 0, 0, 0 },
+{ XK_dead_acute, K_acute, K_grave, 0, 0, 0 },
+{ XK_dead_grave, K_grave, K_tilde, 0, 0, 0 },
+
+{ XK_KP_F1, K_F1, K_sF1, K_cF1, K_mF1, K_yF1 },
+{ XK_KP_F2, K_F2, K_sF2, K_cF2, K_mF2, K_yF2 },
+{ XK_KP_F3, K_F3, K_sF3, K_cF3, K_mF3, K_yF3 },
+{ XK_KP_F4, K_F4, K_sF4, K_cF4, K_mF4, K_yF4 },
+{ XK_KP_Space, K_SP, K_sSP, K_cSP, K_mSP ,K_ySP },
+{ XK_KP_Tab, K_TAB, K_sTAB, K_cTAB, K_mTAB ,K_yTAB },
+{ XK_KP_Equal, K_equal, 0, K_cEqual, K_mEqual, K_yEqual },
+
+{ XK_KP_Enter, K_CR, K_sCR, K_cCR, K_mCR, K_yCR },
+{ XK_KP_Home, K_HOME, K_sHOME, K_cHOME, K_mHOME, K_yHOME },
+{ XK_KP_Up, K_UP, K_sUP, K_cUP, K_mUP, K_yUP },
+{ XK_KP_Page_Up, K_PGUP, K_sPGUP, K_cPGUP, K_mPGUP, K_yPGUP },
+{ XK_KP_Left, K_LEFT, K_sLEFT, K_cLEFT, K_mLEFT, K_yLEFT },
+{ XK_KP_Begin, K_MIDDLE,K_sMIDDLE, K_cMIDDLE,K_mMIDDLE,K_yMIDDLE},
+{ XK_KP_Right, K_RIGHT, K_sRIGHT, K_cRIGHT, K_mRIGHT, K_yRIGHT },
+{ XK_KP_End, K_END, K_sEND, K_cEND, K_mEND, K_yEND },
+{ XK_KP_Down, K_DOWN, K_sDOWN, K_cDOWN, K_mDOWN, K_yDOWN },
+{ XK_KP_Page_Down, K_PGDN, K_sPGDN, K_cPGDN, K_mPGDN, K_yPGDN },
+{ XK_KP_Insert, K_INS, K_sINS, K_cINS, K_mINS, K_yINS },
+{ XK_KP_Delete, K_DEL, K_sDEL, K_cDEL, K_mDEL, K_yDEL }
+
+};
+
+void iupmotKeyEncode(int key, unsigned int *keyval, unsigned int *state)
+{
+ int i, iupcode = key & 0xFF; /* 0-255 interval */
+ int count = sizeof(motkey_map)/sizeof(motkey_map[0]);
+ for (i = 0; i < count; i++)
+ {
+ Imot2iupkey* key_map = &(motkey_map[i]);
+ if (key_map->iupcode == iupcode)
+ {
+ *keyval = XKeysymToKeycode(iupmot_display, key_map->motcode);
+ *state = 0;
+
+ if (iupcode != key)
+ {
+ if (key_map->c_iupcode == key)
+ *state = ControlMask;
+ else if (key_map->m_iupcode == key)
+ *state = Mod1Mask;
+ else if (key_map->y_iupcode == key)
+ *state = Mod4Mask;
+ else if (key_map->s_iupcode == key)
+ *state = ShiftMask;
+ }
+ return;
+ }
+ else if (key_map->s_iupcode == key) /* There are Shift keys bellow 256 */
+ {
+ *keyval = XKeysymToKeycode(iupmot_display, key_map->motcode);
+ *state = ShiftMask;
+ return;
+ }
+ }
+}
+
+static int motKeyMap2Iup(unsigned int state, int i)
+{
+ int code = 0;
+ if (state & ControlMask) /* Ctrl */
+ code = motkey_map[i].c_iupcode;
+ else if (state & Mod1Mask ||
+ state & Mod5Mask) /* Alt */
+ code = motkey_map[i].m_iupcode;
+ else if (state & Mod4Mask) /* Apple/Win */
+ code = motkey_map[i].y_iupcode;
+ else if (state & LockMask) /* CapsLock */
+ {
+ if ((state & ShiftMask) || !iupKeyCanCaps(motkey_map[i].iupcode))
+ return motkey_map[i].iupcode;
+ else
+ code = motkey_map[i].s_iupcode;
+ }
+ else if (state & ShiftMask) /* Shift */
+ code = motkey_map[i].s_iupcode;
+ else
+ return motkey_map[i].iupcode;
+
+ if (!code)
+ code = motkey_map[i].iupcode;
+
+ return code;
+}
+
+static int motKeyDecode(XKeyEvent *evt)
+{
+ int i;
+ KeySym motcode = XKeycodeToKeysym(iupmot_display, evt->keycode, 0);
+ int count = sizeof(motkey_map)/sizeof(motkey_map[0]);
+
+ if ((evt->state & Mod2Mask) && /* NumLock */
+ (motcode >= XK_KP_Home) &&
+ (motcode <= XK_KP_Delete))
+ {
+ /* remap to numeric keys */
+ KeySym remap_numkey[] = {XK_KP_7, XK_KP_4, XK_KP_8, XK_KP_6, XK_KP_2, XK_KP_9, XK_KP_3, XK_KP_1, XK_KP_5, XK_KP_0, XK_KP_Decimal};
+ motcode = remap_numkey[motcode-XK_KP_Home];
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ if (motkey_map[i].motcode == motcode)
+ return motKeyMap2Iup(evt->state, i);
+ }
+
+ return 0;
+}
+
+KeySym iupmotKeyCharToKeySym(char c)
+{
+ int i;
+ int count = sizeof(motkey_map)/sizeof(motkey_map[0]);
+
+ for (i = 0; i < count; i++)
+ {
+ if (motkey_map[i].iupcode == c)
+ return motkey_map[i].motcode;
+ if (motkey_map[i].s_iupcode == c)
+ {
+ if (motkey_map[i].motcode >= XK_a &&
+ motkey_map[i].motcode <= XK_z)
+ return motkey_map[i].motcode - (XK_a-XK_A);
+ }
+ }
+
+ return 0;
+}
+
+/* Discards keyrepeat by removing the keypress event from the queue.
+ * The pair keyrelease/keypress is always put together in the queue,
+ * by removing the keypress, we only worry about keyrelease. In case
+ * of a keyrelease, we ignore it if the next event is a keypress (which
+ * means repetition. Otherwise it is a real keyrelease.
+ *
+ * Returns 1 if the keypress is found in the queue and 0 otherwise.
+ */
+static int motKeyDiscardKeypressRepeat(XEvent *evt)
+{
+ XEvent ahead;
+ if (XEventsQueued(iupmot_display, QueuedAfterReading))
+ {
+ XPeekEvent(iupmot_display, &ahead);
+ if (ahead.type == KeyPress && ahead.xkey.window == evt->xkey.window
+ && ahead.xkey.keycode == evt->xkey.keycode && ahead.xkey.time == evt->xkey.time)
+ {
+ /* Pop off the repeated KeyPress and ignore */
+ XNextEvent(iupmot_display, evt);
+ /* Ignore the auto repeated KeyRelease/KeyPress pair */
+ return 1;
+ }
+ }
+ /* No KeyPress found */
+ return 0;
+}
+
+/* this is called only for canvas */
+void iupmotCanvasKeyReleaseEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont)
+{
+ if (motKeyDiscardKeypressRepeat(evt))
+ {
+ /* call key_press because it was removed from the queue */
+ iupmotKeyPressEvent(w, ih, evt, cont);
+ }
+ else
+ {
+ int result;
+ int code = motKeyDecode((XKeyEvent*)evt);
+ if (code == 0)
+ return;
+ result = iupKeyCallKeyPressCb(ih, code, 0);
+ if (result == IUP_CLOSE)
+ {
+ IupExitLoop();
+ return;
+ }
+ if (result == IUP_IGNORE)
+ {
+ *cont = False;
+ return;
+ }
+ }
+}
+
+void iupmotKeyPressEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont)
+{
+ int result;
+ int code = motKeyDecode((XKeyEvent*)evt);
+ if (code == 0)
+ return;
+
+ if ((((XKeyEvent*)evt)->state & Mod1Mask || ((XKeyEvent*)evt)->state & Mod5Mask)) /* Alt */
+ {
+ KeySym motcode = XKeycodeToKeysym(iupmot_display, ((XKeyEvent*)evt)->keycode, 0);
+ if (motcode < 128)
+ {
+ IFni cb;
+ Ihandle* dialog = IupGetDialog(ih);
+ char attrib[22] = "_IUPMOT_MNEMONIC_ _CB";
+ attrib[17] = (char)toupper(motcode);
+ cb = (IFni)IupGetCallback(dialog, attrib);
+ if (cb)
+ {
+ cb(dialog, attrib[17]);
+ return;
+ }
+ }
+ }
+
+ result = iupKeyCallKeyCb(ih, code);
+ if (result == IUP_CLOSE)
+ {
+ IupExitLoop();
+ return;
+ }
+ if (result == IUP_IGNORE)
+ {
+ *cont = False;
+ return;
+ }
+
+ /* in the previous callback the dialog could be destroyed */
+ if (iupObjectCheck(ih))
+ {
+ /* this is called only for canvas */
+ if (ih->iclass->nativetype==IUP_TYPECANVAS)
+ {
+ result = iupKeyCallKeyPressCb(ih, code, 1);
+ if (result == IUP_CLOSE)
+ {
+ IupExitLoop();
+ return;
+ }
+ if (result == IUP_IGNORE)
+ {
+ *cont = False;
+ return;
+ }
+ }
+
+ if (!iupKeyProcessNavigation(ih, code, ((XKeyEvent*)evt)->state & ShiftMask))
+ {
+ *cont = False;
+ return;
+ }
+ }
+
+ (void)w;
+}
+
+void iupmotButtonKeySetStatus(unsigned int state, unsigned int but, char* status, int doubleclick)
+{
+ if (state & ShiftMask)
+ iupKEYSETSHIFT(status);
+
+ if (state & ControlMask)
+ iupKEYSETCONTROL(status);
+
+ if ((state & Button1Mask) || but==Button1)
+ iupKEYSETBUTTON1(status);
+
+ if ((state & Button2Mask) || but==Button2)
+ iupKEYSETBUTTON2(status);
+
+ if ((state & Button3Mask) || but==Button3)
+ iupKEYSETBUTTON3(status);
+
+ if ((state & Button4Mask) || but==Button4)
+ iupKEYSETBUTTON4(status);
+
+ if ((state & Button5Mask) || but==Button5)
+ iupKEYSETBUTTON5(status);
+
+ if (state & Mod1Mask || state & Mod5Mask) /* Alt */
+ iupKEYSETALT(status);
+
+ if (state & Mod4Mask) /* Apple/Win */
+ iupKEYSETSYS(status);
+
+ if (doubleclick)
+ iupKEYSETDOUBLE(status);
+}
+
diff --git a/iup/src/mot/iupmot_label.c b/iup/src/mot/iupmot_label.c
new file mode 100755
index 0000000..52dfc9a
--- /dev/null
+++ b/iup/src/mot/iupmot_label.c
@@ -0,0 +1,256 @@
+/** \file
+ * \brief Label Control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+#include <Xm/Label.h>
+#include <Xm/Separator.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdarg.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_object.h"
+#include "iup_childtree.h"
+#include "iup_attrib.h"
+#include "iup_dialog.h"
+#include "iup_str.h"
+#include "iup_label.h"
+#include "iup_drv.h"
+#include "iup_image.h"
+
+#include "iupmot_drv.h"
+
+
+static int motLabelSetTitleAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->type == IUP_LABEL_TEXT)
+ {
+ iupmotSetMnemonicTitle(ih, value);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int motLabelSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ /* ignore given value, must use only from parent */
+ value = iupBaseNativeParentGetBgColor(ih);
+
+ if (iupdrvBaseSetBgColorAttrib(ih, value))
+ return 1;
+ return 0;
+}
+
+static int motLabelSetBackgroundAttrib(Ihandle* ih, const char* value)
+{
+ /* ignore given value, must use only from parent */
+ value = iupAttribGetInheritNativeParent(ih, "BACKGROUND");
+
+ if (iupdrvBaseSetBgColorAttrib(ih, value))
+ return 1;
+ else
+ {
+ Pixmap pixmap = (Pixmap)iupImageGetImage(value, ih, 0);
+ if (pixmap)
+ {
+ XtVaSetValues(ih->handle, XmNbackgroundPixmap, pixmap, NULL);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int motLabelSetAlignmentAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->type != IUP_LABEL_SEP_HORIZ && ih->data->type != IUP_LABEL_SEP_VERT)
+ {
+ unsigned char align;
+ char value1[30]="", value2[30]="";
+
+ iupStrToStrStr(value, value1, value2, ':'); /* value2 is ignored, NOT supported in Motif */
+
+ if (iupStrEqualNoCase(value1, "ARIGHT"))
+ align = XmALIGNMENT_END;
+ else if (iupStrEqualNoCase(value1, "ACENTER"))
+ align = XmALIGNMENT_CENTER;
+ else /* "ALEFT" */
+ align = XmALIGNMENT_BEGINNING;
+
+ XtVaSetValues(ih->handle, XmNalignment, align, NULL);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static int motLabelSetImageAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->type == IUP_LABEL_IMAGE)
+ {
+ iupmotSetPixmap(ih, value, XmNlabelPixmap, 0);
+
+ if (!iupdrvIsActive(ih))
+ {
+ if (!iupAttribGet(ih, "IMINACTIVE"))
+ {
+ /* if not active and IMINACTIVE is not defined
+ then automaticaly create one based on IMAGE */
+ iupmotSetPixmap(ih, value, XmNlabelInsensitivePixmap, 1); /* make_inactive */
+ }
+ }
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static int motLabelSetImInactiveAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->type == IUP_LABEL_IMAGE)
+ {
+ iupmotSetPixmap(ih, value, XmNlabelInsensitivePixmap, 0);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static int motLabelSetActiveAttrib(Ihandle* ih, const char* value)
+{
+ /* update the inactive image if necessary */
+ if (ih->data->type == IUP_LABEL_IMAGE && !iupStrBoolean(value))
+ {
+ if (!iupAttribGet(ih, "IMINACTIVE"))
+ {
+ /* if not defined then automaticaly create one based on IMAGE */
+ char* name = iupAttribGet(ih, "IMAGE");
+ iupmotSetPixmap(ih, name, XmNlabelInsensitivePixmap, 1); /* make_inactive */
+ }
+ }
+
+ return iupBaseSetActiveAttrib(ih, value);
+}
+
+static int motLabelSetPaddingAttrib(Ihandle* ih, const char* value)
+{
+ iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
+ if (ih->handle && ih->data->type != IUP_LABEL_SEP_HORIZ && ih->data->type != IUP_LABEL_SEP_VERT)
+ {
+ XtVaSetValues(ih->handle, XmNmarginHeight, ih->data->vert_padding,
+ XmNmarginWidth, ih->data->horiz_padding, NULL);
+ }
+ return 0;
+}
+
+static int motLabelMapMethod(Ihandle* ih)
+{
+ char* value;
+ int num_args = 0;
+ Arg args[20];
+ WidgetClass widget_class;
+
+ value = iupAttribGet(ih, "SEPARATOR");
+ if (value)
+ {
+ widget_class = xmSeparatorWidgetClass;
+ if (iupStrEqualNoCase(value, "HORIZONTAL"))
+ {
+ ih->data->type = IUP_LABEL_SEP_HORIZ;
+ iupmotSetArg(args, num_args, XmNorientation, XmHORIZONTAL);
+ }
+ else /* "VERTICAL" */
+ {
+ ih->data->type = IUP_LABEL_SEP_VERT;
+ iupmotSetArg(args, num_args, XmNorientation, XmVERTICAL);
+ }
+ }
+ else
+ {
+ value = iupAttribGet(ih, "IMAGE");
+ widget_class = xmLabelWidgetClass;
+ if (value)
+ {
+ ih->data->type = IUP_LABEL_IMAGE;
+ iupmotSetArg(args, num_args, XmNlabelType, XmPIXMAP);
+ }
+ else
+ {
+ ih->data->type = IUP_LABEL_TEXT;
+ iupmotSetArg(args, num_args, XmNlabelType, XmSTRING);
+ }
+ }
+
+ /* Core */
+ iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+ iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+ iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ /* Primitive */
+ iupmotSetArg(args, num_args, XmNtraversalOn, False);
+ iupmotSetArg(args, num_args, XmNhighlightThickness, 0);
+ /* Label */
+ iupmotSetArg(args, num_args, XmNrecomputeSize, False); /* no automatic resize from text */
+ iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
+ iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+ iupmotSetArg(args, num_args, XmNmarginTop, 0); /* no extra margins */
+ iupmotSetArg(args, num_args, XmNmarginLeft, 0);
+ iupmotSetArg(args, num_args, XmNmarginBottom, 0);
+ iupmotSetArg(args, num_args, XmNmarginRight, 0);
+
+ ih->handle = XtCreateManagedWidget(
+ iupDialogGetChildIdStr(ih), /* child identifier */
+ widget_class, /* widget class */
+ iupChildTreeGetNativeParentHandle(ih), /* widget parent */
+ args, num_args);
+
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ ih->serial = iupDialogGetChildId(ih); /* must be after using the string */
+
+ /* Drag Source is enabled by default in label */
+ iupmotDisableDragSource(ih->handle);
+
+ /* initialize the widget */
+ XtRealizeWidget(ih->handle);
+
+ if (ih->data->type == IUP_LABEL_TEXT)
+ iupmotSetString(ih->handle, XmNlabelString, "");
+
+ return IUP_NOERROR;
+}
+
+void iupdrvLabelInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class functions */
+ ic->Map = motLabelMapMethod;
+
+ /* Driver Dependent Attribute functions */
+
+ /* Overwrite Visual */
+ iupClassRegisterAttribute(ic, "ACTIVE", iupBaseGetActiveAttrib, motLabelSetActiveAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BGCOLOR", iupmotGetBgColorAttrib, motLabelSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BACKGROUND", NULL, motLabelSetBackgroundAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+
+ /* Special */
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, iupdrvBaseSetFgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGFGCOLOR", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "TITLE", NULL, motLabelSetTitleAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+
+ /* IupLabel only */
+ iupClassRegisterAttribute(ic, "ALIGNMENT", NULL, motLabelSetAlignmentAttrib, "ALEFT:ACENTER", NULL, IUPAF_NO_INHERIT); /* force new default value */
+ iupClassRegisterAttribute(ic, "IMAGE", NULL, motLabelSetImageAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "PADDING", iupLabelGetPaddingAttrib, motLabelSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
+
+ /* IupLabel GTK and Motif only */
+ iupClassRegisterAttribute(ic, "IMINACTIVE", NULL, motLabelSetImInactiveAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+}
diff --git a/iup/src/mot/iupmot_list.c b/iup/src/mot/iupmot_list.c
new file mode 100755
index 0000000..f8e73ed
--- /dev/null
+++ b/iup/src/mot/iupmot_list.c
@@ -0,0 +1,1404 @@
+/** \file
+ * \brief List Control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+#include <Xm/List.h>
+#include <Xm/ComboBox.h>
+#include <Xm/ScrolledW.h>
+#include <Xm/TextF.h>
+#include <X11/keysym.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdarg.h>
+#include <time.h>
+#include <limits.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_object.h"
+#include "iup_childtree.h"
+#include "iup_attrib.h"
+#include "iup_dialog.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_mask.h"
+#include "iup_key.h"
+#include "iup_list.h"
+
+#include "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+static void motListComboBoxSelectionCallback(Widget w, Ihandle* ih, XmComboBoxCallbackStruct* call_data);
+
+
+void iupdrvListAddItemSpace(Ihandle* ih, int *h)
+{
+ if (ih->data->has_editbox)
+ *h += 1;
+ else
+ *h += 3;
+}
+
+void iupdrvListAddBorders(Ihandle* ih, int *x, int *y)
+{
+ int border_size = 2*4;
+ (*x) += border_size;
+ (*y) += border_size;
+
+ if (ih->data->is_dropdown)
+ {
+ if (ih->data->has_editbox)
+ {
+ /* extra border for the editbox */
+ int internal_border_size = 2*2;
+ (*x) += internal_border_size;
+ (*y) += internal_border_size;
+ }
+ }
+ else
+ {
+ if (ih->data->has_editbox)
+ (*y) += 2*2; /* internal border between editbox and list */
+ else
+ (*x) += 2; /* extra border for the simple list */
+ }
+}
+
+static int motListConvertXYToPos(Ihandle* ih, int x, int y)
+{
+ (void)x;
+ if (ih->data->has_editbox)
+ {
+ Widget cblist;
+ XtVaGetValues(ih->handle, XmNlist, &cblist, NULL);
+ return XmListYToPos(cblist, (Position)y); /* XmListYToPos returns start at 1 */
+ }
+ else
+ return XmListYToPos(ih->handle, (Position)y);
+}
+
+int iupdrvListGetCount(Ihandle* ih)
+{
+ int count;
+ XtVaGetValues(ih->handle, XmNitemCount, &count, NULL);
+ return count;
+}
+
+static void motListAddItem(Ihandle* ih, int pos, const char* value)
+{
+ XmString str = XmStringCreateLocalized((String)value);
+ /* The utility functions use 0=last 1=first */
+ if (ih->data->is_dropdown || ih->data->has_editbox)
+ XmComboBoxAddItem(ih->handle, str, pos+1, False);
+ else
+ XmListAddItem(ih->handle, str, pos+1);
+ XmStringFree(str);
+}
+
+static void motListAddSortedItem(Ihandle* ih, const char *value)
+{
+ char *text;
+ XmString *strlist;
+ int u_bound, l_bound = 0;
+
+ XtVaGetValues(ih->handle, XmNitemCount, &u_bound, XmNitems, &strlist, NULL);
+
+ u_bound--;
+ /* perform binary search */
+ while (u_bound >= l_bound)
+ {
+ int i = l_bound + (u_bound - l_bound)/2;
+ text = (char*)XmStringUnparse(strlist[i], NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
+ if (!text)
+ break;
+ if (strcmp (text, value) > 0)
+ u_bound = i-1; /* newtext comes before item */
+ else
+ l_bound = i+1; /* newtext comes after item */
+ XtFree(text);
+ }
+
+ motListAddItem(ih, l_bound, value);
+}
+
+void iupdrvListAppendItem(Ihandle* ih, const char* value)
+{
+ if (iupAttribGetBoolean(ih, "SORT"))
+ motListAddSortedItem(ih, value);
+ else
+ motListAddItem(ih, -1, value);
+}
+
+void iupdrvListInsertItem(Ihandle* ih, int pos, const char* value)
+{
+ if (iupAttribGetBoolean(ih, "SORT"))
+ motListAddSortedItem(ih, value);
+ else
+ motListAddItem(ih, pos, value);
+}
+
+void iupdrvListRemoveItem(Ihandle* ih, int pos)
+{
+ /* The utility functions use 0=last 1=first */
+ if (ih->data->is_dropdown || ih->data->has_editbox)
+ XmComboBoxDeletePos(ih->handle, pos+1);
+ else
+ XmListDeletePos(ih->handle, pos+1);
+}
+
+void iupdrvListRemoveAllItems(Ihandle* ih)
+{
+ if (ih->data->is_dropdown || ih->data->has_editbox)
+ {
+ Widget cblist;
+ XtVaGetValues(ih->handle, XmNlist, &cblist, NULL);
+ XmListDeleteAllItems(cblist);
+ XmComboBoxUpdate(ih->handle);
+ }
+ else
+ XmListDeleteAllItems(ih->handle);
+}
+
+
+/*********************************************************************************/
+
+
+static char* motListGetIdValueAttrib(Ihandle* ih, const char* name_id)
+{
+ int pos = iupListGetPos(ih, name_id);
+ if (pos != -1)
+ {
+ XmString* items;
+ XtVaGetValues(ih->handle, XmNitems, &items, NULL);
+ return iupmotConvertString(items[pos]);
+ }
+ return NULL;
+}
+
+static int motListSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ Widget sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (sb_win)
+ {
+ Pixel color;
+
+ /* ignore given value for the scrollbars, must use only from parent */
+ char* parent_value = iupBaseNativeParentGetBgColor(ih);
+
+ color = iupmotColorGetPixelStr(parent_value);
+ if (color != (Pixel)-1)
+ {
+ Widget sb = NULL;
+
+ iupmotSetBgColor(sb_win, color);
+
+ XtVaGetValues(sb_win, XmNverticalScrollBar, &sb, NULL);
+ if (sb) iupmotSetBgColor(sb, color);
+
+ XtVaGetValues(sb_win, XmNhorizontalScrollBar, &sb, NULL);
+ if (sb) iupmotSetBgColor(sb, color);
+ }
+
+ return iupdrvBaseSetBgColorAttrib(ih, value); /* use given value for contents */
+ }
+ else
+ {
+ char* parent_value;
+
+ /* use given value for Edit and List also */
+ Pixel color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ {
+ Widget cbedit, cblist, sb;
+
+ iupmotSetBgColor(ih->handle, color);
+
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ if (cbedit) iupmotSetBgColor(cbedit, color);
+
+ XtVaGetValues(ih->handle, XmNlist, &cblist, NULL);
+ if (cblist) iupmotSetBgColor(cblist, color);
+
+ XtVaGetValues(cblist, XmNverticalScrollBar, &sb, NULL);
+ if (sb) iupmotSetBgColor(sb, color);
+
+ XtVaGetValues(cblist, XmNhorizontalScrollBar, &sb, NULL);
+ if (sb) iupmotSetBgColor(sb, color);
+ }
+
+ /* but reset just the background, so the combobox will look like a button */
+ parent_value = iupBaseNativeParentGetBgColor(ih);
+
+ color = iupmotColorGetPixelStr(parent_value);
+ if (color != (Pixel)-1)
+ XtVaSetValues(ih->handle, XmNbackground, color, NULL);
+
+ return 1;
+ }
+}
+
+static int motListSetFgColorAttrib(Ihandle* ih, const char* value)
+{
+ Pixel color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ {
+ XtVaSetValues(ih->handle, XmNforeground, color, NULL);
+
+ if (ih->data->is_dropdown || ih->data->has_editbox)
+ {
+ Widget w;
+ XtVaGetValues(ih->handle, XmNtextField, &w, NULL);
+ XtVaSetValues(w, XmNforeground, color, NULL);
+
+ XtVaGetValues(ih->handle, XmNlist, &w, NULL);
+ XtVaSetValues(w, XmNforeground, color, NULL);
+ }
+ }
+
+ return 1;
+}
+
+static char* motListGetValueAttrib(Ihandle* ih)
+{
+ if (ih->data->has_editbox)
+ {
+ char *str, *xstr;
+ Widget cbedit;
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ xstr = XmTextFieldGetString(cbedit);
+ str = iupStrGetMemoryCopy(xstr);
+ XtFree(xstr);
+ return str;
+ }
+ else
+ {
+ if (ih->data->is_dropdown)
+ {
+ char* str;
+ int pos;
+ XtVaGetValues(ih->handle, XmNselectedPosition, &pos, NULL);
+ str = iupStrGetMemory(50);
+ sprintf(str, "%d", pos+1); /* IUP starts at 1 */
+ return str;
+ }
+ else
+ {
+ int *pos, sel_count;
+ if (XmListGetSelectedPos(ih->handle, &pos, &sel_count)) /* XmListGetSelectedPos starts at 1 */
+ {
+ if (!ih->data->is_multiple)
+ {
+ char* str = iupStrGetMemory(50);
+ sprintf(str, "%d", pos[0]);
+ XtFree((char*)pos);
+ return str;
+ }
+ else
+ {
+ int i, count;
+ char* str;
+ XtVaGetValues(ih->handle, XmNitemCount, &count, NULL);
+ str = iupStrGetMemory(count+1);
+ memset(str, '-', count);
+ str[count]=0;
+ for (i=0; i<sel_count; i++)
+ str[pos[i]-1] = '+';
+ XtFree((char*)pos);
+ return str;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static int motListSetValueAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->has_editbox)
+ {
+ Widget cbedit;
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ if (!value) value = "";
+
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); /* disable callbacks */
+
+ XmTextFieldSetString(cbedit, (char*)value);
+
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ }
+ else
+ {
+ if (ih->data->is_dropdown)
+ {
+ int pos;
+ if (iupStrToInt(value, &pos)==1)
+ {
+ XtRemoveCallback(ih->handle, XmNselectionCallback, (XtCallbackProc)motListComboBoxSelectionCallback, (XtPointer)ih);
+
+ XtVaSetValues(ih->handle, XmNselectedPosition, pos-1, NULL); /* IUP starts at 1 */
+ iupAttribSetInt(ih, "_IUPLIST_OLDVALUE", pos);
+
+ XtAddCallback(ih->handle, XmNselectionCallback, (XtCallbackProc)motListComboBoxSelectionCallback, (XtPointer)ih);
+ }
+ }
+ else
+ {
+ if (!ih->data->is_multiple)
+ {
+ int pos;
+ if (iupStrToInt(value, &pos)==1)
+ {
+ XmListSelectPos(ih->handle, pos, FALSE); /* XmListSelectPos starts at 1 */
+ iupAttribSetInt(ih, "_IUPLIST_OLDVALUE", pos);
+ }
+ else
+ {
+ XmListDeselectAllItems(ih->handle);
+ iupAttribSetStr(ih, "_IUPLIST_OLDVALUE", NULL);
+ }
+ }
+ else
+ {
+ /* User has changed a multiple selection on a simple list. */
+ int i, count, len;
+
+ /* Clear all selections */
+ XmListDeselectAllItems(ih->handle);
+
+ if (!value)
+ {
+ iupAttribSetStr(ih, "_IUPLIST_OLDVALUE", NULL);
+ return 0;
+ }
+
+ XtVaGetValues(ih->handle, XmNitemCount, &count, NULL);
+ len = strlen(value);
+ if (len < count)
+ count = len;
+
+ XtVaSetValues(ih->handle, XmNselectionPolicy, XmMULTIPLE_SELECT, NULL);
+
+ /* update selection list */
+ for (i = 0; i<count; i++)
+ {
+ if (value[i]=='+')
+ XmListSelectPos(ih->handle, i+1, False); /* XmListSelectPos starts at 1 */
+ }
+
+ XtVaSetValues(ih->handle, XmNselectionPolicy, XmEXTENDED_SELECT,
+ XmNselectionMode, XmNORMAL_MODE, NULL); /* must also restore this */
+ iupAttribStoreStr(ih, "_IUPLIST_OLDVALUE", value);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int motListSetVisibleItemsAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->is_dropdown)
+ {
+ int count;
+ if (iupStrToInt(value, &count)==1)
+ XtVaSetValues(ih->handle, XmNvisibleItemCount, count, NULL);
+ }
+ return 1;
+}
+
+static int motListSetShowDropdownAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->is_dropdown)
+ {
+ if (iupStrBoolean(value))
+ {
+ XButtonEvent ev;
+ memset(&ev, 0, sizeof(XButtonEvent));
+ ev.type = ButtonPress;
+ ev.display = XtDisplay(ih->handle);
+ ev.send_event = True;
+ ev.root = RootWindow(iupmot_display, iupmot_screen);
+ ev.time = clock()*CLOCKS_PER_SEC;
+ ev.window = XtWindow(ih->handle);
+ ev.state = Button1Mask;
+ ev.button = Button1;
+ ev.same_screen = True;
+ XtCallActionProc(ih->handle, "CBDropDownList", (XEvent*)&ev, 0, 0 );
+ }
+ else
+ XtCallActionProc(ih->handle, "CBDisarm", 0, 0, 0 );
+ }
+ return 0;
+}
+
+static int motListSetTopItemAttrib(Ihandle* ih, const char* value)
+{
+ if (!ih->data->is_dropdown)
+ {
+ int pos = 1;
+ if (iupStrToInt(value, &pos))
+ {
+ if (ih->data->has_editbox)
+ {
+ Widget cblist;
+ XtVaGetValues(ih->handle, XmNlist, &cblist, NULL);
+ XtVaSetValues(cblist, XmNtopItemPosition, pos, NULL);
+ }
+ else
+ XtVaSetValues(ih->handle, XmNtopItemPosition, pos, NULL);
+ }
+ }
+ return 0;
+}
+
+static int motListSetSpacingAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->is_dropdown)
+ return 0;
+
+ if (!iupStrToInt(value, &ih->data->spacing))
+ ih->data->spacing = 0;
+
+ if (ih->handle)
+ {
+ if (ih->data->has_editbox)
+ {
+ Widget cblist;
+ XtVaGetValues(ih->handle, XmNlist, &cblist, NULL);
+ XtVaSetValues(cblist, XmNlistSpacing, ih->data->spacing*2,
+ XmNlistMarginWidth, ih->data->spacing,
+ XmNlistMarginHeight, ih->data->spacing,
+ NULL);
+ }
+ else
+ XtVaSetValues(ih->handle, XmNlistSpacing, ih->data->spacing*2,
+ XmNlistMarginWidth, ih->data->spacing,
+ XmNlistMarginHeight, ih->data->spacing,
+ NULL);
+ return 0;
+ }
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
+}
+
+static int motListSetPaddingAttrib(Ihandle* ih, const char* value)
+{
+ if (!ih->data->has_editbox)
+ return 0;
+
+ iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
+ if (ih->handle)
+ {
+ Widget cbedit;
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XtVaSetValues(cbedit, XmNmarginHeight, ih->data->vert_padding,
+ XmNmarginWidth, ih->data->horiz_padding, NULL);
+ return 0;
+ }
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
+}
+
+static int motListSetReadOnlyAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->has_editbox)
+ {
+ Widget cbedit;
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XtVaSetValues(cbedit, XmNeditable, iupStrBoolean(value)? False: True, NULL);
+ }
+ return 0;
+}
+
+static char* motListGetReadOnlyAttrib(Ihandle* ih)
+{
+ if (ih->data->has_editbox)
+ {
+ Boolean editable;
+ Widget cbedit;
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XtVaGetValues(cbedit, XmNeditable, &editable, NULL);
+ if (editable)
+ return "YES";
+ else
+ return "NO";
+ }
+ else
+ return NULL;
+}
+
+static int motListSetInsertAttrib(Ihandle* ih, const char* value)
+{
+ if (!value)
+ return 0;
+
+ if (ih->data->has_editbox)
+ {
+ Widget cbedit;
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); /* disable callbacks */
+ XmTextFieldRemove(cbedit);
+ XmTextFieldInsert(cbedit, XmTextFieldGetInsertionPosition(cbedit), (char*)value);
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ }
+
+ return 0;
+}
+
+static int motListSetSelectedTextAttrib(Ihandle* ih, const char* value)
+{
+ XmTextPosition start, end;
+ Widget cbedit;
+ if (!ih->data->has_editbox)
+ return 0;
+
+ if (!value)
+ return 0;
+
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ if (XmTextFieldGetSelectionPosition(cbedit, &start, &end) && start!=end)
+ {
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); /* disable callbacks */
+ XmTextFieldReplace(cbedit, start, end, (char*)value);
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ }
+
+ return 0;
+}
+
+static char* motListGetSelectedTextAttrib(Ihandle* ih)
+{
+ if (ih->data->has_editbox)
+ {
+ char* selectedtext, *str;
+ Widget cbedit;
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ selectedtext = XmTextFieldGetSelection(cbedit);
+ str = iupStrGetMemoryCopy(selectedtext);
+ XtFree(selectedtext);
+ return str;
+ }
+ else
+ return NULL;
+}
+
+static int motListSetAppendAttrib(Ihandle* ih, const char* value)
+{
+ if (value && ih->data->has_editbox)
+ {
+ XmTextPosition pos;
+ Widget cbedit;
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ pos = XmTextFieldGetLastPosition(cbedit);
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); /* disable callbacks */
+ XmTextFieldInsert(cbedit, pos+1, (char*)value);
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ }
+ return 0;
+}
+
+static int motListSetSelectionAttrib(Ihandle* ih, const char* value)
+{
+ int start=1, end=1;
+ Widget cbedit;
+ if (!ih->data->has_editbox)
+ return 0;
+
+ if (!value || iupStrEqualNoCase(value, "NONE"))
+ {
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XmTextFieldClearSelection(cbedit, CurrentTime);
+ return 0;
+ }
+
+ if (iupStrEqualNoCase(value, "ALL"))
+ {
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XmTextFieldSetSelection(cbedit, (XmTextPosition)0, (XmTextPosition)XmTextFieldGetLastPosition(cbedit), CurrentTime);
+ return 0;
+ }
+
+ if (iupStrToIntInt(value, &start, &end, ':')!=2)
+ return 0;
+
+ if(start<1 || end<1)
+ return 0;
+
+ start--; /* IUP starts at 1 */
+ end--;
+
+ /* end is inside the selection, in IUP is outside */
+ end--;
+
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XmTextFieldSetSelection(cbedit, (XmTextPosition)start, (XmTextPosition)end, CurrentTime);
+
+ return 0;
+}
+
+static char* motListGetSelectionAttrib(Ihandle* ih)
+{
+ XmTextPosition start = 0, end = 0;
+ char* str;
+ Widget cbedit;
+ if (!ih->data->has_editbox)
+ return NULL;
+
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ if (!XmTextFieldGetSelectionPosition(cbedit, &start, &end) || start==end)
+ return NULL;
+
+ str = iupStrGetMemory(100);
+
+ /* end is inside the selection, in IUP is outside */
+ end++;
+
+ start++; /* IUP starts at 1 */
+ end++;
+ sprintf(str, "%d:%d", (int)start, (int)end);
+
+ return str;
+}
+
+static int motListSetSelectionPosAttrib(Ihandle* ih, const char* value)
+{
+ int start=0, end=0;
+ Widget cbedit;
+ if (!ih->data->has_editbox)
+ return 0;
+
+ if (!value || iupStrEqualNoCase(value, "NONE"))
+ {
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XmTextFieldClearSelection(cbedit, CurrentTime);
+ return 0;
+ }
+
+ if (iupStrEqualNoCase(value, "ALL"))
+ {
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XmTextFieldSetSelection(cbedit, (XmTextPosition)0, (XmTextPosition)XmTextFieldGetLastPosition(cbedit), CurrentTime);
+ return 0;
+ }
+
+ if (iupStrToIntInt(value, &start, &end, ':')!=2)
+ return 0;
+
+ if(start<0 || end<0)
+ return 0;
+
+ /* end is inside the selection, in IUP is outside */
+ end--;
+
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XmTextFieldSetSelection(cbedit, (XmTextPosition)start, (XmTextPosition)end, CurrentTime);
+
+ return 0;
+}
+
+static char* motListGetSelectionPosAttrib(Ihandle* ih)
+{
+ XmTextPosition start = 0, end = 0;
+ char* str;
+ Widget cbedit;
+ if (!ih->data->has_editbox)
+ return NULL;
+
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ if (!XmTextFieldGetSelectionPosition(cbedit, &start, &end) || start==end)
+ return NULL;
+
+ str = iupStrGetMemory(100);
+
+ /* end is inside the selection, in IUP is outside */
+ end++;
+
+ sprintf(str, "%d:%d", (int)start, (int)end);
+
+ return str;
+}
+
+static int motListSetCaretAttrib(Ihandle* ih, const char* value)
+{
+ int pos = 1;
+ Widget cbedit;
+ if (!ih->data->has_editbox)
+ return 0;
+
+ if (!value)
+ return 0;
+
+ sscanf(value,"%i",&pos);
+ pos--; /* IUP starts at 1 */
+
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XmTextFieldSetInsertionPosition(cbedit, (XmTextPosition)pos);
+ XmTextFieldShowPosition(cbedit, (XmTextPosition)pos);
+
+ return 0;
+}
+
+static char* motListGetCaretAttrib(Ihandle* ih)
+{
+ if (ih->data->has_editbox)
+ {
+ XmTextPosition pos;
+ Widget cbedit;
+ char* str = iupStrGetMemory(50);
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ pos = XmTextFieldGetInsertionPosition(cbedit);
+ pos++; /* IUP starts at 1 */
+ sprintf(str, "%d", (int)pos);
+ return str;
+ }
+ else
+ return NULL;
+}
+
+static int motListSetCaretPosAttrib(Ihandle* ih, const char* value)
+{
+ int pos = 0;
+ Widget cbedit;
+ if (!ih->data->has_editbox)
+ return 0;
+
+ if (!value)
+ return 0;
+
+ sscanf(value,"%i",&pos);
+ if (pos < 0) pos = 0;
+
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XmTextFieldSetInsertionPosition(cbedit, (XmTextPosition)pos);
+ XmTextFieldShowPosition(cbedit, (XmTextPosition)pos);
+
+ return 0;
+}
+
+static char* motListGetCaretPosAttrib(Ihandle* ih)
+{
+ if (ih->data->has_editbox)
+ {
+ XmTextPosition pos;
+ Widget cbedit;
+ char* str = iupStrGetMemory(50);
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ pos = XmTextFieldGetInsertionPosition(cbedit);
+ sprintf(str, "%d", (int)pos);
+ return str;
+ }
+ else
+ return NULL;
+}
+
+static int motListSetScrollToAttrib(Ihandle* ih, const char* value)
+{
+ int pos = 1;
+ Widget cbedit;
+ if (!ih->data->has_editbox)
+ return 0;
+
+ if (!value)
+ return 0;
+
+ sscanf(value,"%i",&pos);
+ if (pos < 1) pos = 1;
+ pos--; /* return to Motif referece */
+
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XmTextFieldShowPosition(cbedit, (XmTextPosition)pos);
+
+ return 0;
+}
+
+static int motListSetScrollToPosAttrib(Ihandle* ih, const char* value)
+{
+ int pos = 0;
+ Widget cbedit;
+ if (!ih->data->has_editbox)
+ return 0;
+
+ if (!value)
+ return 0;
+
+ sscanf(value,"%i",&pos);
+ if (pos < 0) pos = 0;
+
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XmTextFieldShowPosition(cbedit, (XmTextPosition)pos);
+
+ return 0;
+}
+
+static int motListSetNCAttrib(Ihandle* ih, const char* value)
+{
+ if (!ih->data->has_editbox)
+ return 0;
+
+ if (!iupStrToInt(value, &ih->data->nc))
+ ih->data->nc = INT_MAX;
+
+ if (ih->handle)
+ {
+ Widget cbedit;
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XtVaSetValues(cbedit, XmNmaxLength, ih->data->nc, NULL);
+ }
+ return 0;
+}
+
+static int motListSetClipboardAttrib(Ihandle *ih, const char *value)
+{
+ Widget cbedit;
+ if (!ih->data->has_editbox)
+ return 0;
+
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+
+ if (iupStrEqualNoCase(value, "COPY"))
+ {
+ char *str = XmTextFieldGetSelection(cbedit);
+
+ XmTextFieldCopy(cbedit, CurrentTime);
+
+ /* do it also for the X clipboard */
+ XStoreBytes(iupmot_display, str, strlen(str)+1);
+ XtFree(str);
+ }
+ else if (iupStrEqualNoCase(value, "CUT"))
+ {
+ char *str = XmTextFieldGetSelection(cbedit);
+
+ /* disable callbacks */
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+
+ XmTextFieldCut(cbedit, CurrentTime);
+
+ /* do it also for the X clipboard */
+ XStoreBytes(iupmot_display, str, strlen(str)+1);
+ XtFree(str);
+ XmTextFieldRemove(cbedit);
+
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ }
+ else if (iupStrEqualNoCase(value, "PASTE"))
+ {
+ int size;
+ char* str = XFetchBytes(iupmot_display, &size);
+
+ /* disable callbacks */
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+
+ XmTextFieldPaste(cbedit); /* TODO: this could force 2 pastes, check in CDE */
+
+ /* do it also for the X clipboard */
+ XmTextFieldRemove(cbedit);
+ XmTextFieldInsert(cbedit, XmTextFieldGetInsertionPosition(cbedit), str);
+ XFree(str);
+
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ }
+ else if (iupStrEqualNoCase(value, "CLEAR"))
+ {
+ /* disable callbacks */
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+ XmTextFieldRemove(cbedit);
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ }
+ return 0;
+}
+
+
+/*********************************************************************************/
+
+
+static void motListEditModifyVerifyCallback(Widget cbedit, Ihandle *ih, XmTextVerifyPtr text)
+{
+ int start, end, key = 0;
+ char *value, *new_value, *insert_value;
+ KeySym motcode = 0;
+ IFnis cb;
+
+ if (iupAttribGet(ih, "_IUPMOT_DISABLE_TEXT_CB"))
+ return;
+
+ cb = (IFnis)IupGetCallback(ih, "EDIT_CB");
+ if (!cb && !ih->data->mask)
+ return;
+
+ if (text->event && text->event->type == KeyPress)
+ {
+ unsigned int state = ((XKeyEvent*)text->event)->state;
+ if (state & ControlMask || /* Ctrl */
+ state & Mod1Mask ||
+ state & Mod5Mask || /* Alt */
+ state & Mod4Mask) /* Apple/Win */
+ return;
+
+ motcode = XKeycodeToKeysym(iupmot_display, ((XKeyEvent*)text->event)->keycode, 0);
+ }
+
+ value = XmTextFieldGetString(cbedit);
+ start = text->startPos;
+ end = text->endPos;
+ insert_value = text->text->ptr;
+
+ if (motcode == XK_Delete)
+ {
+ new_value = value;
+ iupStrRemove(value, start, end, 1);
+ }
+ else if (motcode == XK_BackSpace)
+ {
+ new_value = value;
+ iupStrRemove(value, start, end, -1);
+ }
+ else
+ {
+ if (!value)
+ new_value = iupStrDup(insert_value);
+ else if (insert_value)
+ new_value = iupStrInsert(value, insert_value, start, end);
+ else
+ new_value = value;
+ }
+
+ if (insert_value && insert_value[0]!=0 && insert_value[1]==0)
+ key = insert_value[0];
+
+ if (ih->data->mask && iupMaskCheck(ih->data->mask, new_value)==0)
+ {
+ if (new_value != value) free(new_value);
+ XtFree(value);
+ text->doit = False; /* abort processing */
+ return;
+ }
+
+ if (cb)
+ {
+ int cb_ret = cb(ih, key, (char*)new_value);
+ if (cb_ret==IUP_IGNORE)
+ text->doit = False; /* abort processing */
+ else if (cb_ret==IUP_CLOSE)
+ {
+ IupExitLoop();
+ text->doit = False; /* abort processing */
+ }
+ else if (cb_ret!=0 && key!=0 &&
+ cb_ret != IUP_DEFAULT && cb_ret != IUP_CONTINUE)
+ {
+ insert_value[0] = (char)cb_ret; /* replace key */
+ }
+ }
+
+ if (new_value != value) free(new_value);
+ XtFree(value);
+}
+
+static void motListEditMotionVerifyCallback(Widget w, Ihandle* ih, XmTextVerifyCallbackStruct* textverify)
+{
+ int pos;
+
+ IFniii cb = (IFniii)IupGetCallback(ih, "CARET_CB");
+ if (!cb) return;
+
+ pos = textverify->newInsert;
+
+ if (pos != ih->data->last_caret_pos)
+ {
+ ih->data->last_caret_pos = pos;
+ cb(ih, 1, pos+1, pos);
+ }
+
+ (void)w;
+}
+
+static void motListEditKeyPressEvent(Widget cbedit, Ihandle *ih, XKeyEvent *evt, Boolean *cont)
+{
+ *cont = True;
+ iupmotKeyPressEvent(cbedit, ih, (XEvent*)evt, cont);
+ if (*cont == False)
+ return;
+
+ if (evt->state & ControlMask) /* Ctrl */
+ {
+ KeySym motcode = XKeycodeToKeysym(iupmot_display, evt->keycode, 0);
+ if (motcode == XK_c)
+ {
+ motListSetClipboardAttrib(ih, "COPY");
+ *cont = False;
+ return;
+ }
+ else if (motcode == XK_x)
+ {
+ motListSetClipboardAttrib(ih, "CUT");
+ *cont = False;
+ return;
+ }
+ else if (motcode == XK_v)
+ {
+ motListSetClipboardAttrib(ih, "PASTE");
+ *cont = False;
+ return;
+ }
+ else if (motcode == XK_a)
+ {
+ XmTextFieldSetSelection(cbedit, 0, XmTextFieldGetLastPosition(cbedit), CurrentTime);
+ *cont = False;
+ return;
+ }
+ }
+}
+
+static void motListEditValueChangedCallback(Widget w, Ihandle* ih, XmAnyCallbackStruct* valuechanged)
+{
+ if (iupAttribGet(ih, "_IUPMOT_DISABLE_TEXT_CB"))
+ return;
+
+ iupBaseCallValueChangedCb(ih);
+
+ (void)valuechanged;
+ (void)w;
+}
+
+static void motListDropDownPopupCallback(Widget w, Ihandle* ih, XtPointer call_data)
+{
+ IFni cb = (IFni)IupGetCallback(ih, "DROPDOWN_CB");
+ if (cb)
+ cb(ih, 1);
+ (void)w;
+ (void)call_data;
+}
+
+static void motListDropDownPopdownCallback(Widget w, Ihandle* ih, XtPointer call_data)
+{
+ IFni cb = (IFni)IupGetCallback(ih, "DROPDOWN_CB");
+ if (cb)
+ cb(ih, 0);
+ (void)w;
+ (void)call_data;
+}
+
+static void motListDefaultActionCallback(Widget w, Ihandle* ih, XmListCallbackStruct* call_data)
+{
+ if (call_data->event->type == ButtonPress || call_data->event->type == ButtonRelease)
+ {
+ IFnis cb = (IFnis) IupGetCallback(ih, "DBLCLICK_CB");
+ if (cb)
+ {
+ int pos = call_data->item_position; /* Here Motif already starts at 1 */
+ iupListSingleCallDblClickCallback(ih, cb, pos);
+ }
+ }
+
+ (void)w;
+}
+
+static void motListComboBoxSelectionCallback(Widget w, Ihandle* ih, XmComboBoxCallbackStruct* call_data)
+{
+ IFnsii cb = (IFnsii) IupGetCallback(ih, "ACTION");
+ if (cb)
+ {
+ int pos = call_data->item_position;
+ if (pos==0)
+ {
+ /* must check if it is really checked or it is for the edit box */
+ XmString* items;
+ XtVaGetValues(ih->handle, XmNitems, &items, NULL);
+ if (!XmStringCompare(call_data->item_or_text, items[0]))
+ return;
+ }
+ pos++; /* IUP starts at 1 */
+ iupListSingleCallActionCallback(ih, cb, pos);
+ }
+
+ if (!ih->data->has_editbox)
+ iupBaseCallValueChangedCb(ih);
+
+ (void)w;
+}
+
+static void motListBrowseSelectionCallback(Widget w, Ihandle* ih, XmListCallbackStruct* call_data)
+{
+ IFnsii cb = (IFnsii) IupGetCallback(ih, "ACTION");
+ if (cb)
+ {
+ int pos = call_data->item_position; /* Here Motif already starts at 1 */
+ iupListSingleCallActionCallback(ih, cb, pos);
+ }
+
+ if (!ih->data->has_editbox)
+ iupBaseCallValueChangedCb(ih);
+
+ (void)w;
+}
+
+static void motListExtendedSelectionCallback(Widget w, Ihandle* ih, XmListCallbackStruct* call_data)
+{
+ IFns multi_cb = (IFns)IupGetCallback(ih, "MULTISELECT_CB");
+ IFnsii cb = (IFnsii) IupGetCallback(ih, "ACTION");
+ if (multi_cb || cb)
+ {
+ int* pos = call_data->selected_item_positions;
+ int sel_count = call_data->selected_item_count;
+ int i;
+
+ /* In Motif, the position of item is "plus one".
+ "iupListMultipleCallActionCallback" works with the list of selected items from the zero position.
+ So, "minus one" here. */
+ for (i = 0; i < sel_count; i++)
+ pos[i] -= 1;
+
+ iupListMultipleCallActionCallback(ih, cb, multi_cb, pos, sel_count);
+ }
+
+ if (!ih->data->has_editbox)
+ iupBaseCallValueChangedCb(ih);
+
+ (void)w;
+}
+
+
+/*********************************************************************************/
+
+
+static int motListMapMethod(Ihandle* ih)
+{
+ int num_args = 0;
+ Arg args[30];
+ Widget parent = iupChildTreeGetNativeParentHandle(ih);
+ char* child_id = iupDialogGetChildIdStr(ih);
+
+ if (ih->data->is_dropdown || ih->data->has_editbox)
+ {
+ /* could not set XmNmappedWhenManaged to False because the list and the edit box where not displayed */
+ /* iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); */
+ iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+ iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+ iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ iupmotSetArg(args, num_args, XmNmarginHeight, 0);
+ iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+ iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ else
+ iupmotSetArg(args, num_args, XmNtraversalOn, False);
+
+ iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
+ iupmotSetArg(args, num_args, XmNshadowThickness, 2);
+
+ if (ih->data->has_editbox)
+ {
+ if (ih->data->is_dropdown)
+ iupmotSetArg(args, num_args, XmNcomboBoxType, XmDROP_DOWN_COMBO_BOX); /* hidden-list+edit */
+ else
+ iupmotSetArg(args, num_args, XmNcomboBoxType, XmCOMBO_BOX); /* visible-list+edit */
+ }
+ else
+ iupmotSetArg(args, num_args, XmNcomboBoxType, XmDROP_DOWN_LIST); /* hidden-list */
+
+ ih->handle = XtCreateManagedWidget(
+ child_id, /* child identifier */
+ xmComboBoxWidgetClass, /* widget class */
+ parent, /* widget parent */
+ args, num_args);
+ }
+ else
+ {
+ Widget sb_win;
+
+ /* Create the scrolled window */
+
+ iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupmotSetArg(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED);
+ iupmotSetArg(args, num_args, XmNvisualPolicy, XmVARIABLE);
+ iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC); /* can NOT be XmAS_NEEDED because XmAPPLICATION_DEFINED */
+ iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */
+ iupmotSetArg(args, num_args, XmNborderWidth, 0);
+ iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+
+ sb_win = XtCreateManagedWidget(
+ child_id, /* child identifier */
+ xmScrolledWindowWidgetClass, /* widget class */
+ parent, /* widget parent */
+ args, num_args);
+
+ if (!sb_win)
+ return IUP_ERROR;
+
+ parent = sb_win;
+ child_id = "list";
+
+ /* Create the list */
+
+ num_args = 0;
+ iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+ iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+ iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+ iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ else
+ iupmotSetArg(args, num_args, XmNtraversalOn, False);
+
+ iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
+ iupmotSetArg(args, num_args, XmNshadowThickness, 2);
+
+ iupmotSetArg(args, num_args, XmNlistMarginHeight, 0); /* default padding */
+ iupmotSetArg(args, num_args, XmNlistMarginWidth, 0);
+ iupmotSetArg(args, num_args, XmNlistSpacing, 0);
+ iupmotSetArg(args, num_args, XmNlistSizePolicy, XmCONSTANT); /* don't grow to fit, add scrollbar */
+
+ if (ih->data->is_multiple)
+ iupmotSetArg(args, num_args, XmNselectionPolicy, XmEXTENDED_SELECT);
+ else
+ iupmotSetArg(args, num_args, XmNselectionPolicy, XmBROWSE_SELECT);
+
+ if (iupAttribGetBoolean(ih, "AUTOHIDE"))
+ iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmAS_NEEDED);
+ else
+ iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC);
+
+ ih->handle = XtCreateManagedWidget(
+ child_id, /* child identifier */
+ xmListWidgetClass, /* widget class */
+ parent, /* widget parent */
+ args, num_args);
+ }
+
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ ih->serial = iupDialogGetChildId(ih); /* must be after using the string */
+
+ if (ih->data->is_dropdown || ih->data->has_editbox)
+ {
+ Widget cbedit, cblist;
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XtVaGetValues(ih->handle, XmNlist, &cblist, NULL);
+
+ XtAddEventHandler(cbedit, FocusChangeMask, False, (XtEventHandler)iupmotFocusChangeEvent, (XtPointer)ih);
+ XtAddEventHandler(cbedit, EnterWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(cbedit, LeaveWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddCallback(cbedit, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih);
+
+ XtAddCallback(ih->handle, XmNselectionCallback, (XtCallbackProc)motListComboBoxSelectionCallback, (XtPointer)ih);
+
+ if (ih->data->has_editbox)
+ {
+ XtAddEventHandler(cbedit, KeyPressMask, False, (XtEventHandler)motListEditKeyPressEvent, (XtPointer)ih);
+ XtAddCallback(cbedit, XmNmodifyVerifyCallback, (XtCallbackProc)motListEditModifyVerifyCallback, (XtPointer)ih);
+ XtAddCallback(cbedit, XmNmotionVerifyCallback, (XtCallbackProc)motListEditMotionVerifyCallback, (XtPointer)ih);
+ XtAddCallback(cbedit, XmNvalueChangedCallback, (XtCallbackProc)motListEditValueChangedCallback, (XtPointer)ih);
+
+ /* Disable Drag Source */
+ iupmotDisableDragSource(cbedit);
+ }
+ else
+ XtAddEventHandler(cbedit, KeyPressMask, False, (XtEventHandler)iupmotKeyPressEvent, (XtPointer)ih);
+
+ if (ih->data->is_dropdown)
+ {
+ XtVaSetValues(ih->handle, XmNvisibleItemCount, 5, NULL);
+ XtAddCallback(XtParent(XtParent(cblist)), XmNpopupCallback, (XtCallbackProc)motListDropDownPopupCallback, (XtPointer)ih);
+ XtAddCallback(XtParent(XtParent(cblist)), XmNpopdownCallback, (XtCallbackProc)motListDropDownPopdownCallback, (XtPointer)ih);
+ }
+ else
+ {
+ XtAddCallback(cblist, XmNdefaultActionCallback, (XtCallbackProc)motListDefaultActionCallback, (XtPointer)ih);
+ XtAddEventHandler(cblist, PointerMotionMask, False, (XtEventHandler)iupmotPointerMotionEvent, (XtPointer)ih);
+ XtAddEventHandler(cblist, ButtonPressMask|ButtonReleaseMask, False, (XtEventHandler)iupmotButtonPressReleaseEvent, (XtPointer)ih);
+
+ /* Disable Drag Source */
+ iupmotDisableDragSource(cblist);
+ }
+ }
+ else
+ {
+ iupAttribSetStr(ih, "_IUP_EXTRAPARENT", (char*)parent);
+ XtVaSetValues(parent, XmNworkWindow, ih->handle, NULL);
+
+ XtAddEventHandler(ih->handle, FocusChangeMask, False, (XtEventHandler)iupmotFocusChangeEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, EnterWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, LeaveWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, KeyPressMask, False, (XtEventHandler)iupmotKeyPressEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, PointerMotionMask, False, (XtEventHandler)iupmotPointerMotionEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, ButtonPressMask|ButtonReleaseMask, False, (XtEventHandler)iupmotButtonPressReleaseEvent, (XtPointer)ih);
+
+ XtAddCallback(ih->handle, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih);
+ XtAddCallback (ih->handle, XmNbrowseSelectionCallback, (XtCallbackProc)motListBrowseSelectionCallback, (XtPointer)ih);
+ XtAddCallback (ih->handle, XmNextendedSelectionCallback, (XtCallbackProc)motListExtendedSelectionCallback, (XtPointer)ih);
+ XtAddCallback (ih->handle, XmNdefaultActionCallback, (XtCallbackProc)motListDefaultActionCallback, (XtPointer)ih);
+ }
+
+ /* Disable Drag Source */
+ iupmotDisableDragSource(ih->handle);
+
+ /* initialize the widget */
+ if (ih->data->is_dropdown || ih->data->has_editbox)
+ XtRealizeWidget(ih->handle);
+ else
+ XtRealizeWidget(parent);
+
+ if (IupGetGlobal("_IUP_RESET_TXTCOLORS"))
+ {
+ iupmotSetGlobalColorAttrib(ih->handle, XmNbackground, "TXTBGCOLOR");
+ iupmotSetGlobalColorAttrib(ih->handle, XmNforeground, "TXTFGCOLOR");
+ IupSetGlobal("_IUP_RESET_TXTCOLORS", NULL);
+ }
+
+ IupSetCallback(ih, "_IUP_XY2POS_CB", (Icallback)motListConvertXYToPos);
+
+ iupListSetInitialItems(ih);
+
+ return IUP_NOERROR;
+}
+
+void iupdrvListInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class functions */
+ ic->Map = motListMapMethod;
+
+ /* Driver Dependent Attribute functions */
+
+ /* Visual */
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, motListSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTBGCOLOR", IUPAF_DEFAULT);
+
+ /* Special */
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, motListSetFgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTFGCOLOR", IUPAF_DEFAULT);
+
+ /* IupList only */
+ iupClassRegisterAttributeId(ic, "IDVALUE", motListGetIdValueAttrib, iupListSetIdValueAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "VALUE", motListGetValueAttrib, motListSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "VISIBLE_ITEMS", NULL, motListSetVisibleItemsAttrib, IUPAF_SAMEASSYSTEM, "5", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "TOPITEM", NULL, motListSetTopItemAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SHOWDROPDOWN", NULL, motListSetShowDropdownAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SPACING", iupListGetSpacingAttrib, motListSetSpacingAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
+
+ iupClassRegisterAttribute(ic, "PADDING", iupListGetPaddingAttrib, motListSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "SELECTEDTEXT", motListGetSelectedTextAttrib, motListSetSelectedTextAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SELECTION", motListGetSelectionAttrib, motListSetSelectionAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SELECTIONPOS", motListGetSelectionPosAttrib, motListSetSelectionPosAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "CARET", motListGetCaretAttrib, motListSetCaretAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "CARETPOS", motListGetCaretPosAttrib, motListSetCaretPosAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "INSERT", NULL, motListSetInsertAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "APPEND", NULL, motListSetAppendAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "READONLY", motListGetReadOnlyAttrib, motListSetReadOnlyAttrib, NULL, NULL, IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "NC", iupListGetNCAttrib, motListSetNCAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "CLIPBOARD", NULL, motListSetClipboardAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SCROLLTO", NULL, motListSetScrollToAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SCROLLTOPOS", NULL, motListSetScrollToPosAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+}
diff --git a/iup/src/mot/iupmot_loop.c b/iup/src/mot/iupmot_loop.c
new file mode 100755
index 0000000..828ddcd
--- /dev/null
+++ b/iup/src/mot/iupmot_loop.c
@@ -0,0 +1,108 @@
+/** \file
+ * \brief Motif Message Loop
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+
+#include <Xm/Xm.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iupmot_drv.h"
+
+
+/* local variables */
+static int mot_mainloop = 0;
+static int mot_exitmainloop = 0;
+static IFidle mot_idle_cb = NULL;
+static XtWorkProcId mot_idle_id;
+
+
+static Boolean motIdlecbWorkProc(XtPointer client_data)
+{
+ (void)client_data;
+ if (mot_idle_cb)
+ {
+ int ret = mot_idle_cb();
+ if (ret == IUP_CLOSE)
+ {
+ mot_idle_cb = NULL;
+ IupExitLoop();
+ return True; /* removes the working procedure */
+ }
+ if (ret == IUP_IGNORE)
+ {
+ mot_idle_cb = NULL;
+ return True; /* removes the working procedure */
+ }
+
+ return False; /* keeps the working procedure */
+ }
+
+ return True; /* removes the working procedure */
+}
+
+void iupdrvSetIdleFunction(Icallback f)
+{
+ if (mot_idle_cb)
+ XtRemoveWorkProc(mot_idle_id);
+
+ mot_idle_cb = (IFidle)f;
+
+ if (mot_idle_cb)
+ mot_idle_id = XtAppAddWorkProc(iupmot_appcontext, motIdlecbWorkProc, NULL);
+}
+
+static int motLoopStep(void)
+{
+ XtAppProcessEvent(iupmot_appcontext, XtIMAll);
+ return (mot_exitmainloop)? IUP_CLOSE : IUP_DEFAULT;
+}
+
+void IupExitLoop(void)
+{
+ mot_exitmainloop = 1;
+}
+
+int IupMainLoopLevel(void)
+{
+ return mot_mainloop;
+}
+
+int IupMainLoop(void)
+{
+ mot_mainloop++;
+ mot_exitmainloop = 0;
+
+ while (!mot_exitmainloop)
+ {
+ if (motLoopStep() == IUP_CLOSE)
+ break;
+ }
+
+ mot_exitmainloop = 0;
+ mot_mainloop--;
+ return IUP_NOERROR;
+}
+
+int IupLoopStep(void)
+{
+ if (!XtAppPending(iupmot_appcontext))
+ return IUP_DEFAULT;
+
+ return motLoopStep();
+}
+
+void IupFlush(void)
+{
+ while (XPending(iupmot_display) != 0)
+ {
+ if (motLoopStep() == IUP_CLOSE)
+ break;
+ }
+
+ XFlush(iupmot_display);
+}
diff --git a/iup/src/mot/iupmot_menu.c b/iup/src/mot/iupmot_menu.c
new file mode 100755
index 0000000..be9b953
--- /dev/null
+++ b/iup/src/mot/iupmot_menu.c
@@ -0,0 +1,457 @@
+/** \file
+ * \brief Menu Resources
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+#include <Xm/RowColumn.h>
+#include <Xm/Separator.h>
+#include <Xm/CascadeB.h>
+#include <Xm/ToggleB.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdarg.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_object.h"
+#include "iup_childtree.h"
+#include "iup_attrib.h"
+#include "iup_dialog.h"
+#include "iup_str.h"
+#include "iup_label.h"
+#include "iup_drv.h"
+#include "iup_drvfont.h"
+#include "iup_image.h"
+#include "iup_menu.h"
+
+#include "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+static int mot_menu_exitloop = 0;
+
+int iupdrvMenuPopup(Ihandle* ih, int x, int y)
+{
+ XButtonEvent ev;
+ ev.x_root = x;
+ ev.y_root = y;
+ XmMenuPosition(ih->handle, &ev);
+
+ XtManageChild(ih->handle);
+
+ mot_menu_exitloop = 0;
+ while (!mot_menu_exitloop)
+ XtAppProcessEvent(iupmot_appcontext, XtIMAll);
+ mot_menu_exitloop = 0;
+
+ return IUP_NOERROR;
+}
+
+int iupdrvMenuGetMenuBarSize(Ihandle* ih)
+{
+ int ch;
+ iupdrvFontGetCharSize(ih, NULL, &ch);
+ return 5 + ch + 5;
+}
+
+
+/*******************************************************************************************/
+
+
+static void motItemActivateCallback(Widget w, Ihandle* ih, XtPointer call_data)
+{
+ Icallback cb;
+
+ if (XmIsToggleButton(ih->handle) && !iupAttribGetBoolean(ih, "AUTOTOGGLE") && !iupAttribGetBoolean(ih->parent, "RADIO"))
+ {
+ /* Motif by default will do autotoggle */
+ XmToggleButtonSetState(ih->handle, !XmToggleButtonGetState(ih->handle),0);
+ }
+
+ cb = IupGetCallback(ih, "ACTION");
+ if (cb && cb(ih)==IUP_CLOSE)
+ IupExitLoop();
+
+ (void)w;
+ (void)call_data;
+}
+
+static void motItemArmCallback(Widget w, Ihandle* ih, XtPointer call_data)
+{
+ Icallback cb = IupGetCallback(ih, "HIGHLIGHT_CB");
+ if (cb)
+ cb(ih);
+
+ (void)w;
+ (void)call_data;
+}
+
+static void motMenuMapCallback(Widget w, Ihandle* ih, XtPointer call_data)
+{
+ Icallback cb = IupGetCallback(ih, "OPEN_CB");
+ if (!cb && ih->parent) cb = (Icallback)IupGetCallback(ih->parent, "OPEN_CB"); /* check also in the Submenu */
+ if (cb) cb(ih);
+
+ (void)w;
+ (void)call_data;
+}
+
+static void motMenuUnmapCallback(Widget w, Ihandle* ih, XtPointer call_data)
+{
+ Icallback cb = IupGetCallback(ih, "MENUCLOSE_CB");
+ if (!cb && ih->parent) cb = (Icallback)IupGetCallback(ih->parent, "MENUCLOSE_CB"); /* check also in the Submenu */
+ if (cb) cb(ih);
+
+ (void)w;
+ (void)call_data;
+}
+
+static void motPopupMenuUnmapCallback(Widget w, Ihandle* ih, XtPointer call_data)
+{
+ motMenuUnmapCallback(w, ih, call_data);
+ mot_menu_exitloop = 1;
+}
+
+
+/*******************************************************************************************/
+
+
+static void motMenuUnMapMethod(Ihandle* ih)
+{
+ if (iupMenuIsMenuBar(ih))
+ XtDestroyWidget(ih->handle);
+ else
+ XtDestroyWidget(XtParent(ih->handle)); /* in this case the RowColumn widget is a child of a MenuShell. */
+}
+
+static int motMenuMapMethod(Ihandle* ih)
+{
+ int num_args = 0;
+ Arg args[30];
+
+ if (iupMenuIsMenuBar(ih))
+ {
+ /* top level menu used for MENU attribute in IupDialog (a menu bar) */
+
+ ih->handle = XtVaCreateManagedWidget(
+ iupMenuGetChildIdStr(ih),
+ xmRowColumnWidgetClass,
+ iupChildTreeGetNativeParentHandle(ih),
+ XmNrowColumnType, XmMENU_BAR,
+ XmNmarginHeight, 0,
+ XmNmarginWidth, 0,
+ XmNresizeWidth, False,
+ NULL);
+ if (!ih->handle)
+ return IUP_ERROR;
+ }
+ else
+ {
+ /* all XmCreate* functions here, also create RowColumn Widgets. */
+
+ if (ih->parent)
+ {
+ /* parent is a submenu */
+
+ if (iupAttribGetBoolean(ih, "RADIO"))
+ {
+ iupmotSetArg(args, num_args, XmNpacking, XmPACK_COLUMN);
+ iupmotSetArg(args, num_args, XmNradioBehavior, TRUE);
+ }
+
+ ih->handle = XmCreatePulldownMenu(
+ ih->parent->handle,
+ iupMenuGetChildIdStr(ih),
+ args,
+ num_args);
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ /* update the CascadeButton */
+ XtVaSetValues(ih->parent->handle, XmNsubMenuId, ih->handle, NULL);
+
+ XtAddCallback(ih->handle, XmNmapCallback, (XtCallbackProc)motMenuMapCallback, (XtPointer)ih);
+ XtAddCallback(ih->handle, XmNunmapCallback, (XtCallbackProc)motMenuUnmapCallback, (XtPointer)ih);
+ }
+ else
+ {
+ /* top level menu used for IupPopup */
+
+ iupmotSetArg(args, num_args, XmNpopupEnabled, XmPOPUP_AUTOMATIC);
+
+ ih->handle = XmCreatePopupMenu(
+ iupmot_appshell,
+ iupMenuGetChildIdStr(ih),
+ args,
+ num_args);
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ XtAddCallback(ih->handle, XmNmapCallback, (XtCallbackProc)motMenuMapCallback, (XtPointer)ih);
+ XtAddCallback(ih->handle, XmNunmapCallback, (XtCallbackProc)motPopupMenuUnmapCallback, (XtPointer)ih);
+ }
+ }
+
+ ih->serial = iupMenuGetChildId(ih); /* must be after using the string */
+
+ return IUP_NOERROR;
+}
+
+void iupdrvMenuInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class functions */
+ ic->Map = motMenuMapMethod;
+ ic->UnMap = motMenuUnMapMethod;
+
+ /* Used by iupdrvMenuGetMenuBarSize */
+ iupClassRegisterAttribute(ic, "STANDARDFONT", NULL, NULL, IUPAF_SAMEASSYSTEM, "DEFAULTFONT", IUPAF_DEFAULT); /* use inheritance to retrieve standard fonts */
+
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, iupdrvBaseSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+}
+
+
+/*******************************************************************************************/
+
+
+static int motItemSetTitleImageAttrib(Ihandle* ih, const char* value)
+{
+ iupmotSetPixmap(ih, value, XmNlabelPixmap, 0);
+ return 1;
+}
+
+static int motItemSetTitleAttrib(Ihandle* ih, const char* value)
+{
+ char *str;
+
+ if (!value)
+ {
+ str = " ";
+ value = str;
+ }
+ else
+ str = iupMenuProcessTitle(ih, value);
+
+ if (XmIsToggleButton(ih->handle))
+ {
+ char *p = strchr(str, '\t');
+ if (p)
+ {
+ int offset = (p-str);
+ char* new_value = iupStrDup(str);
+ char* acc_value = new_value + offset + 1;
+ new_value[offset] = 0;
+ iupmotSetMnemonicTitle(ih, new_value);
+ iupmotSetString(ih->handle, XmNacceleratorText, acc_value);
+ free(new_value);
+
+ if (str != value) free(str);
+ return 1;
+ }
+ }
+
+ iupmotSetMnemonicTitle(ih, str);
+
+ if (str != value) free(str);
+ return 1;
+}
+
+static int motItemSetValueAttrib(Ihandle* ih, const char* value)
+{
+ if (XmIsToggleButton(ih->handle))
+ {
+ if (iupAttribGetBoolean(ih->parent, "RADIO"))
+ value = "ON";
+
+ XmToggleButtonSetState(ih->handle, iupStrBoolean(value),0);
+ }
+ return 0;
+}
+
+static char* motItemGetValueAttrib(Ihandle* ih)
+{
+ if (XmIsToggleButton(ih->handle) && XmToggleButtonGetState(ih->handle))
+ return "ON";
+ else
+ return "OFF";
+}
+
+static int motItemMapMethod(Ihandle* ih)
+{
+ int pos;
+
+ if (!ih->parent)
+ return IUP_ERROR;
+
+ /* Menu bar can contain only CascadeButtons */
+ if (iupMenuIsMenuBar(ih->parent))
+ {
+ ih->handle = XtVaCreateManagedWidget(
+ iupMenuGetChildIdStr(ih),
+ xmCascadeButtonWidgetClass,
+ ih->parent->handle,
+ NULL);
+
+ XtAddCallback(ih->handle, XmNactivateCallback, (XtCallbackProc)motItemActivateCallback, (XtPointer)ih);
+ XtAddCallback(ih->handle, XmNcascadingCallback, (XtCallbackProc)motItemArmCallback, (XtPointer)ih);
+ }
+ else
+ {
+ int num_args = 0;
+ Arg args[10];
+
+ if (iupAttribGetBoolean(ih->parent, "RADIO"))
+ {
+ iupmotSetArg(args, num_args, XmNtoggleMode, XmTOGGLE_BOOLEAN);
+ iupmotSetArg(args, num_args, XmNindicatorType, XmONE_OF_MANY_ROUND);
+ iupmotSetArg(args, num_args, XmNindicatorOn, XmINDICATOR_CHECK_BOX);
+ iupmotSetArg(args, num_args, XmNindicatorSize, 13);
+ iupmotSetArg(args, num_args, XmNselectColor, iupmotColorGetPixel(0, 0, 0));
+ }
+ else
+ {
+ if (iupAttribGetBoolean(ih, "HIDEMARK"))
+ iupmotSetArg(args, num_args, XmNindicatorOn, XmINDICATOR_NONE);
+ else
+ iupmotSetArg(args, num_args, XmNindicatorOn, XmINDICATOR_CHECK);
+ iupmotSetArg(args, num_args, XmNlabelType, iupAttribGet(ih, "TITLEIMAGE")? XmPIXMAP: XmSTRING);
+ }
+
+ ih->handle = XtCreateManagedWidget(
+ iupMenuGetChildIdStr(ih),
+ xmToggleButtonWidgetClass,
+ ih->parent->handle,
+ args,
+ num_args);
+
+ XtAddCallback(ih->handle, XmNvalueChangedCallback, (XtCallbackProc)motItemActivateCallback, (XtPointer)ih);
+ XtAddCallback(ih->handle, XmNarmCallback, (XtCallbackProc)motItemArmCallback, (XtPointer)ih);
+ }
+
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ ih->serial = iupMenuGetChildId(ih); /* must be after using the string */
+
+ XtAddCallback (ih->handle, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih);
+
+ pos = IupGetChildPos(ih->parent, ih);
+ XtVaSetValues(ih->handle, XmNpositionIndex, pos, NULL); /* RowColumn Constraint */
+
+ iupUpdateStandardFontAttrib(ih);
+
+ return IUP_NOERROR;
+}
+
+void iupdrvItemInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class functions */
+ ic->Map = motItemMapMethod;
+ ic->UnMap = iupdrvBaseUnMapMethod;
+
+ /* Common */
+ iupClassRegisterAttribute(ic, "STANDARDFONT", NULL, iupdrvSetStandardFontAttrib, IUPAF_SAMEASSYSTEM, "DEFAULTFONT", IUPAF_NOT_MAPPED); /* use inheritance to retrieve standard fonts */
+
+ /* Visual */
+ iupClassRegisterAttribute(ic, "ACTIVE", iupBaseGetActiveAttrib, iupBaseSetActiveAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, iupdrvBaseSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+
+ /* IupItem only */
+ iupClassRegisterAttribute(ic, "VALUE", motItemGetValueAttrib, motItemSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "TITLE", NULL, motItemSetTitleAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "TITLEIMAGE", NULL, motItemSetTitleImageAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+
+ /* IupItem Gtk and Motif only */
+ iupClassRegisterAttribute(ic, "HIDEMARK", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED);
+}
+
+
+/*******************************************************************************************/
+
+
+static int motSubmenuMapMethod(Ihandle* ih)
+{
+ int pos;
+
+ if (!ih->parent)
+ return IUP_ERROR;
+
+ ih->handle = XtVaCreateManagedWidget(
+ iupMenuGetChildIdStr(ih),
+ xmCascadeButtonWidgetClass,
+ ih->parent->handle,
+ NULL);
+
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ ih->serial = iupMenuGetChildId(ih); /* must be after using the string */
+
+ pos = IupGetChildPos(ih->parent, ih);
+ XtVaSetValues(ih->handle, XmNpositionIndex, pos, NULL); /* RowColumn Constraint */
+
+ XtAddCallback(ih->handle, XmNcascadingCallback, (XtCallbackProc)motItemArmCallback, (XtPointer)ih);
+
+ iupUpdateStandardFontAttrib(ih);
+
+ return IUP_NOERROR;
+}
+
+void iupdrvSubmenuInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class functions */
+ ic->Map = motSubmenuMapMethod;
+ ic->UnMap = iupdrvBaseUnMapMethod;
+
+ /* Common */
+ iupClassRegisterAttribute(ic, "STANDARDFONT", NULL, iupdrvSetStandardFontAttrib, IUPAF_SAMEASSYSTEM, "DEFAULTFONT", IUPAF_NOT_MAPPED); /* use inheritance to retrieve standard fonts */
+
+ /* Visual */
+ iupClassRegisterAttribute(ic, "ACTIVE", iupBaseGetActiveAttrib, iupBaseSetActiveAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, iupdrvBaseSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+
+ /* IupSubmenu only */
+ iupClassRegisterAttribute(ic, "TITLE", NULL, motItemSetTitleAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+}
+
+
+/*******************************************************************************************/
+
+
+static int motSeparatorMapMethod(Ihandle* ih)
+{
+ int pos;
+
+ if (!ih->parent)
+ return IUP_ERROR;
+
+ ih->handle = XtVaCreateManagedWidget(
+ iupMenuGetChildIdStr(ih),
+ xmSeparatorWidgetClass,
+ ih->parent->handle,
+ NULL);
+
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ ih->serial = iupMenuGetChildId(ih); /* must be after using the string */
+
+ pos = IupGetChildPos(ih->parent, ih);
+ XtVaSetValues(ih->handle, XmNpositionIndex, pos, NULL); /* RowColumn Constraint */
+
+ return IUP_NOERROR;
+}
+
+void iupdrvSeparatorInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class functions */
+ ic->Map = motSeparatorMapMethod;
+ ic->UnMap = iupdrvBaseUnMapMethod;
+
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, iupdrvBaseSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+}
diff --git a/iup/src/mot/iupmot_messagedlg.c b/iup/src/mot/iupmot_messagedlg.c
new file mode 100755
index 0000000..6660503
--- /dev/null
+++ b/iup/src/mot/iupmot_messagedlg.c
@@ -0,0 +1,191 @@
+/** \file
+ * \brief Motif IupMessageDlg pre-defined dialog
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <Xm/Xm.h>
+#include <Xm/MwmUtil.h>
+#include <Xm/MessageB.h>
+#include <Xm/Protocols.h>
+
+#include "iup.h"
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drvinfo.h"
+#include "iup_dialog.h"
+#include "iup_strmessage.h"
+
+#include "iupmot_drv.h"
+
+
+static void motMessageDlgDeleteWindowCallback(Widget w, XtPointer client_data, XtPointer call_data)
+{
+ Ihandle *ih = (Ihandle*)client_data;
+ if (!ih) return;
+ (void)call_data;
+ (void)w;
+ if (iupStrEqualNoCase(iupAttribGetStr(ih, "BUTTONS"), "OK"))
+ iupAttribSetStr(ih, "BUTTONRESPONSE", "1");
+ else
+ iupAttribSetStr(ih, "BUTTONRESPONSE", "2");
+ iupAttribSetStr(ih, "_IUP_WM_DELETE", "1");
+}
+
+static void motMessageDlgCallback(Widget w, Ihandle* ih, XmAnyCallbackStruct* call_data)
+{
+ (void)w;
+ if (call_data->reason == XmCR_OK)
+ iupAttribSetStr(ih, "BUTTONRESPONSE", "1");
+ else if (call_data->reason == XmCR_CANCEL)
+ iupAttribSetStr(ih, "BUTTONRESPONSE", "2");
+}
+
+static void motMessageDlgHelpCallback(Widget w, XtPointer client_data, XtPointer call_data)
+{
+ Ihandle *ih = (Ihandle*)client_data;
+ Icallback cb = (Icallback)IupGetCallback(ih, "HELP_CB");
+ if (cb && cb(ih) == IUP_CLOSE)
+ {
+ if (iupStrEqualNoCase(iupAttribGetStr(ih, "BUTTONS"), "OK"))
+ iupAttribSetStr(ih, "BUTTONRESPONSE", "1");
+ else
+ iupAttribSetStr(ih, "BUTTONRESPONSE", "2");
+ }
+
+ (void)call_data;
+ (void)w;
+}
+
+static int motMessageDlgPopup(Ihandle* ih, int x, int y)
+{
+ InativeHandle* parent = iupDialogGetNativeParent(ih);
+ Widget msgbox, dialog;
+ int style = XmDIALOG_FULL_APPLICATION_MODAL;
+ int type = XmDIALOG_MESSAGE;
+ int num_but = 2;
+ char *value;
+
+ iupAttribSetInt(ih, "_IUPDLG_X", x); /* used in iupDialogUpdatePosition */
+ iupAttribSetInt(ih, "_IUPDLG_Y", y);
+
+ if (parent)
+ {
+ msgbox = XmCreateMessageDialog(parent, "messagedialog", NULL, 0);
+ dialog = XtParent(msgbox);
+ }
+ else
+ {
+ dialog = XtAppCreateShell(NULL, "messagedialog", topLevelShellWidgetClass, iupmot_display, NULL, 0);
+ msgbox = XmCreateMessageBox(dialog, "messagebox", NULL, 0);
+ style = XmDIALOG_MODELESS;
+ XtVaSetValues(dialog,
+ XmNmwmInputMode, MWM_INPUT_FULL_APPLICATION_MODAL,
+ XmNmappedWhenManaged, False,
+ XmNsaveUnder, True,
+ NULL);
+ }
+ if (!msgbox)
+ return IUP_NOERROR;
+
+ value = iupAttribGetStr(ih, "DIALOGTYPE");
+ if (iupStrEqualNoCase(value, "ERROR"))
+ type = XmDIALOG_ERROR;
+ else if (iupStrEqualNoCase(value, "WARNING"))
+ type = XmDIALOG_WARNING;
+ else if (iupStrEqualNoCase(value, "INFORMATION"))
+ type = XmDIALOG_INFORMATION;
+ else if (iupStrEqualNoCase(value, "QUESTION"))
+ type = XmDIALOG_QUESTION;
+
+
+ value = iupAttribGet(ih, "TITLE");
+ if (value)
+ iupmotSetString(msgbox, XmNdialogTitle, value);
+ else
+ {
+ if (parent)
+ {
+ XmString title;
+ XtVaGetValues(parent, XmNdialogTitle, &title, NULL);
+ XtVaSetValues(msgbox, XmNdialogTitle, title, NULL);
+ }
+ }
+
+ value = iupAttribGet(ih, "VALUE");
+ if (value)
+ iupmotSetString(msgbox, XmNmessageString, value);
+
+ XtVaSetValues(msgbox,
+ XmNdialogType, type,
+ XmNdialogStyle, style,
+ XmNautoUnmanage, False,
+ XmNnoResize, True,
+ NULL);
+
+ value = iupAttribGetStr(ih, "BUTTONS");
+ if (iupStrEqualNoCase(value, "OK"))
+ {
+ XtUnmanageChild(XmMessageBoxGetChild(msgbox, XmDIALOG_CANCEL_BUTTON));
+ num_but = 1;
+ }
+ else if (iupStrEqualNoCase(value, "YESNO"))
+ {
+ iupmotSetString(msgbox, XmNokLabelString, iupStrMessageGet("IUP_YES"));
+ iupmotSetString(msgbox, XmNcancelLabelString, iupStrMessageGet("IUP_NO"));
+ }
+
+ if (!IupGetCallback(ih, "HELP_CB"))
+ XtUnmanageChild(XmMessageBoxGetChild(msgbox, XmDIALOG_HELP_BUTTON));
+
+ if (num_but == 2 && iupAttribGetInt(ih, "BUTTONDEFAULT") == 2)
+ XtVaSetValues(msgbox, XmNdefaultButtonType, XmDIALOG_CANCEL_BUTTON, NULL);
+ else
+ XtVaSetValues(msgbox, XmNdefaultButtonType, XmDIALOG_OK_BUTTON, NULL);
+
+ XtAddCallback(msgbox, XmNokCallback, (XtCallbackProc)motMessageDlgCallback, (XtPointer)ih);
+ XtAddCallback(msgbox, XmNcancelCallback, (XtCallbackProc)motMessageDlgCallback, (XtPointer)ih);
+ XtAddCallback(msgbox, XmNhelpCallback, (XtCallbackProc)motMessageDlgHelpCallback, (XtPointer)ih);
+
+ XmAddWMProtocolCallback(dialog, iupmot_wm_deletewindow, motMessageDlgDeleteWindowCallback, (XtPointer)ih);
+ XtManageChild(msgbox);
+
+ XtRealizeWidget(dialog);
+ ih->handle = dialog;
+ iupDialogUpdatePosition(ih);
+ ih->handle = NULL; /* reset handle */
+
+ if (style == XmDIALOG_MODELESS)
+ XtPopup(dialog, XtGrabExclusive);
+
+ /* while the user hasn't provided an answer, simulate main loop.
+ ** The answer changes as soon as the user selects one of the
+ ** buttons and the callback routine changes its value. */
+ iupAttribSetStr(ih, "BUTTONRESPONSE", NULL);
+ while (iupAttribGet(ih, "BUTTONRESPONSE") == NULL)
+ XtAppProcessEvent(iupmot_appcontext, XtIMAll);
+
+ if (!iupAttribGet(ih, "_IUP_WM_DELETE"))
+ {
+ XtUnmanageChild(msgbox);
+
+ if (style == XmDIALOG_MODELESS)
+ {
+ XtPopdown(dialog);
+ XtDestroyWidget(dialog);
+ }
+ }
+
+ return IUP_NOERROR;
+}
+
+void iupdrvMessageDlgInitClass(Iclass* ic)
+{
+ ic->DlgPopup = motMessageDlgPopup;
+}
diff --git a/iup/src/mot/iupmot_open.c b/iup/src/mot/iupmot_open.c
new file mode 100755
index 0000000..a59dbff
--- /dev/null
+++ b/iup/src/mot/iupmot_open.c
@@ -0,0 +1,141 @@
+/** \file
+ * \brief Motif Open/Close
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <locale.h>
+#include <string.h>
+
+#include <Xm/Xm.h>
+
+#include "iup.h"
+
+#include "iup_object.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_globalattrib.h"
+
+#include "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+/* global variables */
+Widget iupmot_appshell = 0;
+Display* iupmot_display = 0;
+int iupmot_screen = 0;
+Visual* iupmot_visual = 0;
+XtAppContext iupmot_appcontext = 0;
+
+void* iupdrvGetDisplay(void)
+{
+ return iupmot_display;
+}
+
+void iupmotSetGlobalColorAttrib(Widget w, const char* xmname, const char* name)
+{
+ unsigned char r, g, b;
+ Pixel color;
+
+ XtVaGetValues(w, xmname, &color, NULL);
+ iupmotColorGetRGB(color, &r, &g, &b);
+
+ iupGlobalSetDefaultColorAttrib(name, r, g, b);
+}
+
+int iupdrvOpen(int *argc, char ***argv)
+{
+ IupSetGlobal("DRIVER", "Motif");
+
+ /* XtSetLanguageProc(NULL, NULL, NULL);
+ Removed to avoid invalid locale in modern Linux that set LANG=en_US.UTF-8 */
+
+ /* We do NOT use XtVaOpenApplication because it crashes when using internal dummy argc and argv.
+ iupmot_appshell = XtVaOpenApplication(&iupmot_appcontext, "Iup", NULL, 0, argc, *argv, NULL,
+ sessionShellWidgetClass, NULL); */
+
+ XtToolkitInitialize();
+
+ iupmot_appcontext = XtCreateApplicationContext();
+
+ iupmot_display = XtOpenDisplay(iupmot_appcontext, NULL, NULL, "Iup", NULL, 0, argc, *argv);
+ if (!iupmot_display)
+ {
+ fprintf (stderr, "IUP error: cannot open display.\n");
+ return IUP_ERROR;
+ }
+
+ iupmot_appshell = XtAppCreateShell(NULL, "Iup", sessionShellWidgetClass, iupmot_display, NULL, 0);
+ if (!iupmot_appshell)
+ {
+ fprintf(stderr, "IUP error: cannot create shell.\n");
+ return IUP_ERROR;
+ }
+ IupSetGlobal("APPSHELL", (char*)iupmot_appshell);
+
+ IupStoreGlobal("SYSTEMLANGUAGE", setlocale(LC_ALL, NULL));
+
+ iupmot_screen = XDefaultScreen(iupmot_display);
+
+ IupSetGlobal("XDISPLAY", (char*)iupmot_display);
+ IupSetGlobal("XSCREEN", (char*)iupmot_screen);
+
+ /* screen depth can be 8bpp, but canvas can be 24bpp */
+ {
+ XVisualInfo vinfo;
+ if (XMatchVisualInfo(iupmot_display, iupmot_screen, 24, TrueColor, &vinfo) ||
+ XMatchVisualInfo(iupmot_display, iupmot_screen, 16, TrueColor, &vinfo))
+ {
+ iupmot_visual = vinfo.visual;
+ IupSetGlobal("TRUECOLORCANVAS", "YES");
+ }
+ else
+ {
+ iupmot_visual = DefaultVisual(iupmot_display, iupmot_screen);
+ IupSetGlobal("TRUECOLORCANVAS", "NO");
+ }
+ }
+
+ /* driver system version */
+ {
+ int major = xmUseVersion/1000;
+ int minor = xmUseVersion - major * 1000;
+ IupSetfAttribute(NULL, "MOTIFVERSION", "%d.%d", major, minor);
+ IupSetfAttribute(NULL, "MOTIFNUMBER", "%d", (XmVERSION * 1000 + XmREVISION * 100 + XmUPDATE_LEVEL));
+
+ IupSetGlobal("XSERVERVENDOR", ServerVendor(iupmot_display));
+ IupSetfAttribute(NULL, "XVENDORRELEASE", "%d", VendorRelease(iupmot_display));
+ }
+
+ iupmotColorInit();
+
+ /* dialog background color */
+ {
+ iupmotSetGlobalColorAttrib(iupmot_appshell, XmNbackground, "DLGBGCOLOR");
+ iupGlobalSetDefaultColorAttrib("DLGFGCOLOR", 0, 0, 0);
+ IupSetGlobal("_IUP_RESET_DLGBGCOLOR", "YES"); /* will update the DLGFGCOLOR when the first dialog is mapped */
+
+ iupGlobalSetDefaultColorAttrib("TXTBGCOLOR", 255, 255, 255);
+ iupGlobalSetDefaultColorAttrib("TXTFGCOLOR", 0, 0, 0);
+ IupSetGlobal("_IUP_RESET_TXTCOLORS", "YES"); /* will update the TXTCOLORS when the first text or list is mapped */
+ }
+
+ if (getenv("IUP_DEBUG"))
+ XSynchronize(iupmot_display, 1);
+
+ return IUP_NOERROR;
+}
+
+void iupdrvClose(void)
+{
+ iupmotColorFinish();
+ iupmotTipsFinish();
+
+ if (iupmot_appshell)
+ XtDestroyWidget(iupmot_appshell);
+
+ if (iupmot_appcontext)
+ XtDestroyApplicationContext(iupmot_appcontext);
+}
diff --git a/iup/src/mot/iupmot_progressbar.c b/iup/src/mot/iupmot_progressbar.c
new file mode 100755
index 0000000..7266d38
--- /dev/null
+++ b/iup/src/mot/iupmot_progressbar.c
@@ -0,0 +1,165 @@
+/** \file
+* \brief Progress bar Control
+*
+* See Copyright Notice in "iup.h"
+*/
+
+#include <Xm/Xm.h>
+#include <Xm/Scale.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdarg.h>
+#include <limits.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_object.h"
+#include "iup_childtree.h"
+#include "iup_attrib.h"
+#include "iup_dialog.h"
+#include "iup_str.h"
+#include "iup_progressbar.h"
+#include "iup_drv.h"
+
+#include "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+static int motProgressBarSetValueAttrib(Ihandle* ih, const char* value)
+{
+ if (!value)
+ ih->data->value = 0;
+ else
+ ih->data->value = atof(value);
+ iProgressBarCropValue(ih);
+
+ XtVaSetValues(ih->handle, XmNvalue, (int)(SHRT_MAX * (ih->data->value - ih->data->vmin) / (ih->data->vmax - ih->data->vmin)), NULL);
+
+ return 0;
+}
+
+static int motProgressBarSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ if (!iupAttribGetStr(ih, "FGCOLOR"))
+ {
+ Pixel color;
+ unsigned char r, g, b;
+ if (!iupStrToRGB(value, &r, &g, &b))
+ return 0;
+
+ r = (r*8)/10;
+ g = (g*8)/10;
+ b = (b*8)/10;
+
+ color = iupmotColorGetPixel(r, g, b);
+ if (color != (Pixel)-1)
+ {
+ Widget w = XtNameToWidget(ih->handle, "*Scrollbar");
+ XtVaSetValues(w, XmNtroughColor, color, NULL);
+ }
+ }
+
+ return iupdrvBaseSetBgColorAttrib(ih, value);
+}
+
+
+static int motProgressBarSetFgColorAttrib(Ihandle* ih, const char* value)
+{
+ Pixel color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ {
+ Widget w = XtNameToWidget(ih->handle, "*Scrollbar");
+ XtVaSetValues(w, XmNtroughColor, color, NULL);
+ }
+
+ return 1;
+}
+
+static void motProgressBarLayoutUpdateMethod(Ihandle *ih)
+{
+ unsigned char orientation;
+ XtVaGetValues(ih->handle, XmNorientation, &orientation, NULL);
+
+ if (orientation == XmVERTICAL)
+ XtVaSetValues(ih->handle, XmNscaleWidth, ih->currentwidth, NULL);
+ else
+ XtVaSetValues(ih->handle, XmNscaleHeight, ih->currentheight, NULL);
+
+ iupdrvBaseLayoutUpdateMethod(ih);
+}
+
+static int motProgressBarMapMethod(Ihandle* ih)
+{
+ int num_args = 0;
+ Arg args[30];
+
+ /* Core */
+ iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+ iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+ iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ /* Primitive */
+ iupmotSetArg(args, num_args, XmNtraversalOn, False);
+ iupmotSetArg(args, num_args, XmNhighlightThickness, 0);
+ /* Scale */
+ iupmotSetArg(args, num_args, XmNminimum, 0);
+ iupmotSetArg(args, num_args, XmNmaximum, SHRT_MAX);
+ iupmotSetArg(args, num_args, XmNslidingMode, XmTHERMOMETER); /* thermometer effect */
+ iupmotSetArg(args, num_args, XmNsliderMark, XmNONE);
+ iupmotSetArg(args, num_args, XmNeditable, False);
+ iupmotSetArg(args, num_args, XmNshowValue, XmNONE);
+
+ if (iupStrEqualNoCase(iupAttribGetStr(ih, "ORIENTATION"), "VERTICAL"))
+ {
+ iupmotSetArg(args, num_args, XmNorientation, XmVERTICAL);
+
+ if (ih->currentheight < ih->currentwidth)
+ {
+ int tmp = ih->currentheight;
+ ih->currentheight = ih->currentwidth;
+ ih->currentwidth = tmp;
+ }
+ }
+ else
+ iupmotSetArg(args, num_args, XmNorientation, XmHORIZONTAL);
+
+ ih->handle = XtCreateManagedWidget(
+ iupDialogGetChildIdStr(ih), /* child identifier */
+ xmScaleWidgetClass, /* widget class */
+ iupChildTreeGetNativeParentHandle(ih), /* widget parent */
+ args, num_args);
+
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ ih->serial = iupDialogGetChildId(ih); /* must be after using the string */
+
+ /* initialize the widget */
+ XtRealizeWidget(ih->handle);
+
+ return IUP_NOERROR;
+}
+
+void iupdrvProgressBarInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class functions */
+ ic->Map = motProgressBarMapMethod;
+ ic->LayoutUpdate = motProgressBarLayoutUpdateMethod;
+
+ /* Driver Dependent Attribute functions */
+
+ /* Visual */
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, motProgressBarSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+
+ /* Special */
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, motProgressBarSetFgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGFGCOLOR", IUPAF_DEFAULT);
+
+ /* IupProgressBar only */
+ iupClassRegisterAttribute(ic, "VALUE", iProgressBarGetValueAttrib, motProgressBarSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "ORIENTATION", NULL, NULL, "HORIZONTAL", NULL, IUPAF_NO_INHERIT);
+}
diff --git a/iup/src/mot/iupmot_tabs.c b/iup/src/mot/iupmot_tabs.c
new file mode 100755
index 0000000..7c8a6b5
--- /dev/null
+++ b/iup/src/mot/iupmot_tabs.c
@@ -0,0 +1,593 @@
+/** \file
+* \brief Tabs Control
+*
+* See Copyright Notice in "iup.h"
+*/
+
+#include <Xm/Xm.h>
+#include <Xm/Notebook.h>
+#include <Xm/BulletinB.h>
+#include <Xm/PushB.h>
+#include <Xm/Label.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <memory.h>
+#include <stdarg.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_object.h"
+#include "iup_layout.h"
+#include "iup_childtree.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_dialog.h"
+#include "iup_drv.h"
+#include "iup_drvfont.h"
+#include "iup_stdcontrols.h"
+#include "iup_tabs.h"
+#include "iup_image.h"
+
+#include "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+int iupdrvTabsExtraDecor(Ihandle* ih)
+{
+ (void)ih;
+ return 1;
+}
+
+int iupdrvTabsGetLineCountAttrib(Ihandle* ih)
+{
+ (void)ih;
+ return 1;
+}
+
+void iupdrvTabsSetCurrentTab(Ihandle* ih, int pos)
+{
+ Ihandle* child = IupGetChild(ih, pos);
+ Ihandle* prev_child = IupGetChild(ih, iupdrvTabsGetCurrentTab(ih));
+ IupSetAttribute(child, "VISIBLE", "YES");
+ IupSetAttribute(prev_child, "VISIBLE", "NO");
+
+ XtVaSetValues(ih->handle, XmNcurrentPageNumber, pos, NULL);
+}
+
+int iupdrvTabsGetCurrentTab(Ihandle* ih)
+{
+ int pos;
+ XtVaGetValues(ih->handle, XmNcurrentPageNumber, &pos, NULL);
+ return pos;
+}
+
+static void motTabsUpdatePageNumber(Ihandle* ih)
+{
+ int pos, old_pos;
+ Ihandle* child;
+ for (pos = 0, child = ih->firstchild; child; child = child->brother, pos++)
+ {
+ Widget child_manager = (Widget)iupAttribGet(child, "_IUPTAB_CONTAINER");
+ if (child_manager)
+ {
+ old_pos = iupAttribGetInt(child, "_IUPMOT_TABNUMBER"); /* did not work when using XtVaGetValues(child_manager, XmNpageNumber) */
+ if (pos != old_pos)
+ {
+ Widget tab_button = (Widget)iupAttribGet(child, "_IUPMOT_TABBUTTON");
+ XtVaSetValues(child_manager, XmNpageNumber, pos, NULL);
+ XtVaSetValues(tab_button, XmNpageNumber, pos, NULL);
+ iupAttribSetInt(child, "_IUPMOT_TABNUMBER", pos);
+ }
+ }
+ }
+}
+
+static void motTabsUpdatePageBgPixmap(Ihandle* ih, Pixmap pixmap)
+{
+ Ihandle* child;
+ for (child = ih->firstchild; child; child = child->brother)
+ {
+ Widget child_manager = (Widget)iupAttribGet(child, "_IUPTAB_CONTAINER");
+ if (child_manager)
+ XtVaSetValues(child_manager, XmNbackgroundPixmap, pixmap, NULL);
+ }
+}
+
+static void motTabsUpdatePageBgColor(Ihandle* ih, Pixel color)
+{
+ Ihandle* child;
+ for (child = ih->firstchild; child; child = child->brother)
+ {
+ Widget child_manager = (Widget)iupAttribGet(child, "_IUPTAB_CONTAINER");
+ if (child_manager)
+ iupmotSetBgColor(child_manager, color);
+ }
+}
+
+static void motTabsUpdateButtonsFgColor(Ihandle* ih, Pixel color)
+{
+ Ihandle* child;
+ for (child = ih->firstchild; child; child = child->brother)
+ {
+ Widget tab_button = (Widget)iupAttribGet(child, "_IUPMOT_TABBUTTON");
+ if (tab_button)
+ XtVaSetValues(tab_button, XmNforeground, color, NULL);
+ }
+}
+
+static void motTabsUpdateButtonsBgColor(Ihandle* ih, Pixel color)
+{
+ Ihandle* child;
+ for (child = ih->firstchild; child; child = child->brother)
+ {
+ Widget tab_button = (Widget)iupAttribGet(child, "_IUPMOT_TABBUTTON");
+ if (tab_button)
+ iupmotSetBgColor(tab_button, color);
+ }
+}
+
+static void motTabsUpdateButtonsPadding(Ihandle* ih)
+{
+ Ihandle* child;
+ for (child = ih->firstchild; child; child = child->brother)
+ {
+ Widget tab_button = (Widget)iupAttribGet(child, "_IUPMOT_TABBUTTON");
+ if (tab_button)
+ XtVaSetValues(tab_button, XmNmarginHeight, ih->data->vert_padding,
+ XmNmarginWidth, ih->data->horiz_padding, NULL);
+ }
+}
+
+static void motTabsUpdatePageFont(Ihandle* ih)
+{
+ Ihandle* child;
+ XmFontList fontlist = (XmFontList)iupmotGetFontListAttrib(ih);
+
+ for (child = ih->firstchild; child; child = child->brother)
+ {
+ Widget tab_button = (Widget)iupAttribGet(child, "_IUPMOT_TABBUTTON");
+ if (tab_button)
+ XtVaSetValues(tab_button, XmNrenderTable, fontlist, NULL);
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* motTabs - Sets and Gets accessors */
+/* ------------------------------------------------------------------------- */
+
+static int motTabsSetPaddingAttrib(Ihandle* ih, const char* value)
+{
+ iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
+
+ if (ih->handle)
+ motTabsUpdateButtonsPadding(ih);
+ return 0;
+}
+
+static void motTabsUpdateTabType(Ihandle* ih)
+{
+ if (ih->data->type == ITABS_LEFT)
+ XtVaSetValues(ih->handle, XmNbackPagePlacement, XmBOTTOM_LEFT,
+ XmNorientation, XmHORIZONTAL,
+ NULL);
+ else if(ih->data->type == ITABS_RIGHT)
+ XtVaSetValues(ih->handle, XmNbackPagePlacement, XmBOTTOM_RIGHT,
+ XmNorientation, XmHORIZONTAL,
+ NULL);
+ else if(ih->data->type == ITABS_BOTTOM)
+ XtVaSetValues(ih->handle, XmNbackPagePlacement, XmBOTTOM_RIGHT,
+ XmNorientation, XmVERTICAL,
+ NULL);
+ else /* "TOP" */
+ XtVaSetValues(ih->handle, XmNbackPagePlacement, XmTOP_RIGHT,
+ XmNorientation, XmVERTICAL,
+ NULL);
+}
+
+static int motTabsSetTabTypeAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "LEFT"))
+ ih->data->type = ITABS_LEFT;
+ else if(iupStrEqualNoCase(value, "RIGHT"))
+ ih->data->type = ITABS_RIGHT;
+ else if(iupStrEqualNoCase(value, "BOTTOM"))
+ ih->data->type = ITABS_BOTTOM;
+ else /* "TOP" */
+ ih->data->type = ITABS_TOP;
+
+ if (ih->handle)
+ motTabsUpdateTabType(ih);
+
+ return 0;
+}
+
+static int motTabsSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ Pixel color;
+
+ /* given value is used only for child, to the Tabs must use only from parent */
+ char* parent_value = iupBaseNativeParentGetBgColor(ih);
+
+ color = iupmotColorGetPixelStr(parent_value);
+ if (color != (Pixel)-1)
+ {
+ iupmotSetBgColor(ih->handle, color);
+ motTabsUpdatePageBgColor(ih, color);
+ }
+
+ color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ motTabsUpdateButtonsBgColor(ih, color);
+
+ return 1;
+}
+
+static int motTabsSetBackgroundAttrib(Ihandle* ih, const char* value)
+{
+ /* given value is used only for child, to the Tabs must use only from parent */
+ char* parent_value = iupAttribGetInheritNativeParent(ih, "BACKGROUND");
+
+ Pixel color = iupmotColorGetPixelStr(parent_value);
+ if (color != (Pixel)-1)
+ {
+ iupmotSetBgColor(ih->handle, color);
+ motTabsUpdatePageBgColor(ih, color);
+ }
+ else
+ {
+ Pixmap pixmap = (Pixmap)iupImageGetImage(parent_value, ih, 0);
+ if (pixmap)
+ {
+ XtVaSetValues(ih->handle, XmNbackgroundPixmap, pixmap, NULL);
+ motTabsUpdatePageBgPixmap(ih, pixmap);
+ }
+ }
+
+ (void)value;
+ return 1;
+}
+
+static int motTabsSetFgColorAttrib(Ihandle* ih, const char* value)
+{
+ Pixel color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ {
+ XtVaSetValues(ih->handle, XmNforeground, color, NULL);
+ motTabsUpdateButtonsFgColor(ih, color);
+ return 1;
+ }
+ return 0;
+}
+
+static int motTabsSetStandardFontAttrib(Ihandle* ih, const char* value)
+{
+ iupdrvSetStandardFontAttrib(ih, value);
+ if (ih->handle)
+ motTabsUpdatePageFont(ih);
+ return 1;
+}
+
+static int motTabsSetTabTitleAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int pos;
+ if (value && iupStrToInt(name_id, &pos)==1)
+ {
+ Ihandle* child = IupGetChild(ih, pos);
+ Widget tab_button = (Widget)iupAttribGet(child, "_IUPMOT_TABBUTTON");
+ if (tab_button)
+ iupmotSetString(tab_button, XmNlabelString, value);
+ }
+ return 1;
+}
+
+static int motTabsSetTabImageAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int pos;
+ if (value && iupStrToInt(name_id, &pos)==1)
+ {
+ Ihandle* child = IupGetChild(ih, pos);
+ Widget tab_button = (Widget)iupAttribGet(child, "_IUPMOT_TABBUTTON");
+ if (tab_button)
+ {
+ Pixmap pixmap = (Pixmap)iupImageGetImage(value, ih, 0);
+ if (pixmap)
+ XtVaSetValues(tab_button, XmNlabelPixmap, pixmap, NULL);
+ }
+ }
+ return 1;
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* motTabs - Callback */
+/* ------------------------------------------------------------------------- */
+
+void motTabsPageChangedCallback(Widget w, Ihandle* ih, XmNotebookCallbackStruct *nptr)
+{
+ if (nptr->reason == XmCR_MAJOR_TAB)
+ {
+ IFnnn cb;
+ Ihandle* child = IupGetChild(ih, nptr->page_number);
+ Ihandle* prev_child = IupGetChild(ih, nptr->prev_page_number);
+ IupSetAttribute(child, "VISIBLE", "YES");
+ IupSetAttribute(prev_child, "VISIBLE", "NO");
+
+ cb = (IFnnn)IupGetCallback(ih, "TABCHANGE_CB");
+ if (cb)
+ cb(ih, child, prev_child);
+ }
+ (void)w;
+}
+
+static void motTabsConfigureNotify(Widget w, XEvent *evt, String* s, Cardinal *card)
+{
+ /* Motif does not process the changed of position and/or size of children outside the parent's client area.
+ Since Notebook pages are not resized until they are moved into the visible area,
+ we must update the children position and size when a tab page is resize.
+ Since tab pages are not hidden, they are moved outside the visible area,
+ a resize occours every time a tab is activated.
+ */
+ Ihandle *child;
+ (void)s;
+ (void)card;
+ (void)evt;
+
+ XtVaGetValues(w, XmNuserData, &child, NULL);
+ if (!child) return;
+
+ iupLayoutUpdate(child);
+}
+
+/* ------------------------------------------------------------------------- */
+/* motTabs - Methods and Init Class */
+/* ------------------------------------------------------------------------- */
+
+static void motTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
+{
+ if (IupGetName(child) == NULL)
+ iupAttribSetHandleName(child);
+
+ if (ih->handle)
+ {
+ Widget child_manager;
+ Widget tab_button;
+ int num_args = 0, pos;
+ Arg args[30];
+ char *tabtitle, *tabimage, *background;
+ Pixel color;
+
+ /* open space for new tab number */
+ motTabsUpdatePageNumber(ih);
+
+ pos = IupGetChildPos(ih, child);
+
+ /* Create pages */
+ child_manager = XtVaCreateManagedWidget(
+ "child_manager",
+ xmBulletinBoardWidgetClass,
+ ih->handle,
+ /* Core */
+ XmNborderWidth, 0,
+ /* Manager */
+ XmNshadowThickness, 0,
+ XmNnavigationType, XmTAB_GROUP,
+ XmNuserData, child, /* used only in motTabsConfigureNotify */
+ /* BulletinBoard */
+ XmNmarginWidth, 0,
+ XmNmarginHeight, 0,
+ XmNresizePolicy, XmRESIZE_NONE, /* no automatic resize of children */
+ /* Notebook Constraint */
+ XmNnotebookChildType, XmPAGE,
+ XmNpageNumber, pos,
+ XmNresizable, True,
+ NULL);
+
+ XtOverrideTranslations(child_manager, XtParseTranslationTable("<Configure>: iupTabsConfigure()"));
+
+ tabtitle = iupAttribGet(child, "TABTITLE");
+ if (!tabtitle) tabtitle = iupTabsAttribGetStrId(ih, "TABTITLE", pos);
+ tabimage = iupAttribGet(child, "TABIMAGE");
+ if (!tabimage) tabimage = iupTabsAttribGetStrId(ih, "TABIMAGE", pos);
+ if (!tabtitle && !tabimage)
+ tabtitle = " ";
+
+ /* Create tabs */
+ /* Label */
+ iupmotSetArg(args, num_args, XmNlabelType, tabtitle? XmSTRING: XmPIXMAP);
+ iupmotSetArg(args, num_args, XmNmarginHeight, 0);
+ iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+ /* Notebook Constraint */
+ iupmotSetArg(args, num_args, XmNnotebookChildType, XmMAJOR_TAB);
+ iupmotSetArg(args, num_args, XmNpageNumber, pos);
+ tab_button = XtCreateManagedWidget("tab_button", xmPushButtonWidgetClass, ih->handle, args, num_args);
+
+ /* Disable Drag Source */
+ iupmotDisableDragSource(tab_button);
+
+ XtAddEventHandler(tab_button, EnterWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(tab_button, LeaveWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(tab_button, FocusChangeMask, False, (XtEventHandler)iupmotFocusChangeEvent, (XtPointer)ih);
+ XtAddEventHandler(tab_button, KeyPressMask, False, (XtEventHandler)iupmotKeyPressEvent, (XtPointer)ih);
+
+ if (tabtitle)
+ iupmotSetString(tab_button, XmNlabelString, tabtitle);
+ else
+ {
+ Pixmap pixmap = (Pixmap)iupImageGetImage(tabimage, ih, 0);
+ if (pixmap)
+ XtVaSetValues(tab_button, XmNlabelPixmap, pixmap, NULL);
+ }
+
+ background = iupBaseNativeParentGetBgColorAttrib(ih);
+ color = iupmotColorGetPixelStr(background);
+ if (color != -1)
+ iupmotSetBgColor(child_manager, color);
+ else
+ {
+ Pixmap pixmap = (Pixmap)iupImageGetImage(background, ih, 0);
+ if (pixmap)
+ {
+ XtVaSetValues(child_manager, XmNbackgroundPixmap, pixmap, NULL);
+ }
+ }
+
+ background = iupAttribGetStr(ih, "BGCOLOR");
+ color = iupmotColorGetPixelStr(background);
+ if (color != -1)
+ iupmotSetBgColor(tab_button, color);
+
+ color = iupmotColorGetPixelStr(IupGetAttribute(ih, "FGCOLOR"));
+ XtVaSetValues(tab_button, XmNforeground, color, NULL);
+
+ XtRealizeWidget(child_manager);
+ XtRealizeWidget(tab_button);
+
+ iupAttribSetStr(child, "_IUPTAB_CONTAINER", (char*)child_manager);
+ iupAttribSetStr(child, "_IUPMOT_TABBUTTON", (char*)tab_button);
+ iupAttribSetInt(child, "_IUPMOT_TABNUMBER", pos);
+
+ if (pos == iupdrvTabsGetCurrentTab(ih))
+ IupSetAttribute(child, "VISIBLE", "YES");
+ else
+ IupSetAttribute(child, "VISIBLE", "NO");
+ }
+}
+
+static void motTabsChildRemovedMethod(Ihandle* ih, Ihandle* child)
+{
+ if (ih->handle)
+ {
+ Widget child_manager = (Widget)iupAttribGet(child, "_IUPTAB_CONTAINER");
+ if (child_manager)
+ {
+ int cur_pos, pos;
+ Widget tab_button = (Widget)iupAttribGet(child, "_IUPMOT_TABBUTTON");
+
+ cur_pos = iupdrvTabsGetCurrentTab(ih);
+ pos = iupAttribGetInt(child, "_IUPMOT_TABNUMBER"); /* did not work when using XtVaGetValues(child_manager, XmNpageNumber) */
+ if (cur_pos == pos)
+ {
+ if (cur_pos == 0)
+ cur_pos = 1;
+ else
+ cur_pos--;
+
+ iupdrvTabsSetCurrentTab(ih, cur_pos);
+ }
+
+ XtDestroyWidget(tab_button);
+ XtDestroyWidget(child_manager);
+
+ /* compact the tab number usage */
+ motTabsUpdatePageNumber(ih);
+
+ iupAttribSetStr(child, "_IUPTAB_CONTAINER", NULL);
+ iupAttribSetStr(child, "_IUPMOT_TABBUTTON", NULL);
+ iupAttribSetStr(child, "_IUPMOT_TABNUMBER", NULL);
+ }
+ }
+}
+
+static int motTabsMapMethod(Ihandle* ih)
+{
+ int num_args = 0;
+ Arg args[30];
+
+ if (!ih->parent)
+ return IUP_ERROR;
+
+ /* Core */
+ iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+ iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+ iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ /* Manager */
+ iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+ iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ iupmotSetArg(args, num_args, XmNhighlightThickness, 0);
+ /* Notebook */
+ iupmotSetArg(args, num_args, XmNbindingType, XmNONE);
+ iupmotSetArg(args, num_args, XmNbindingWidth, 0);
+ iupmotSetArg(args, num_args, XmNfirstPageNumber, 0); /* IupTabs index always starts with zero */
+ iupmotSetArg(args, num_args, XmNbackPageSize, 0);
+ iupmotSetArg(args, num_args, XmNbackPageNumber, 1);
+ iupmotSetArg(args, num_args, XmNframeShadowThickness, 2);
+
+ ih->handle = XtCreateManagedWidget(
+ iupDialogGetChildIdStr(ih), /* child identifier */
+ xmNotebookWidgetClass, /* widget class */
+ iupChildTreeGetNativeParentHandle(ih), /* widget parent */
+ args, num_args);
+
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ ih->serial = iupDialogGetChildId(ih); /* must be after using the string */
+
+ /* Disable page scroller */
+ {
+ Widget scroller;
+ scroller = XtNameToWidget(ih->handle, "*PageScroller");
+ XtUnmanageChild(scroller);
+ }
+
+ /* Callbacks */
+ XtAddCallback(ih->handle, XmNpageChangedCallback, (XtCallbackProc)motTabsPageChangedCallback, (XtPointer)ih);
+ XtAddCallback(ih->handle, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih);
+
+ /* update Tab position */
+ motTabsUpdateTabType(ih);
+
+ /* current value is now given by the native system */
+ iupAttribSetStr(ih, "_IUPTABS_VALUE_HANDLE", NULL);
+
+ /* initialize the widget */
+ XtRealizeWidget(ih->handle);
+
+ /* Create pages and tabs */
+ if (ih->firstchild)
+ {
+ Ihandle* child;
+ for (child = ih->firstchild; child; child = child->brother)
+ motTabsChildAddedMethod(ih, child);
+ }
+
+ return IUP_NOERROR;
+}
+
+void iupdrvTabsInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class functions */
+ ic->Map = motTabsMapMethod;
+ ic->ChildAdded = motTabsChildAddedMethod;
+ ic->ChildRemoved = motTabsChildRemovedMethod;
+
+ {
+ /* Set up a translation table that captures "Resize" events
+ (also called ConfigureNotify or Configure events). */
+ XtActionsRec rec = {"iupTabsConfigure", motTabsConfigureNotify};
+ XtAppAddActions(iupmot_appcontext, &rec, 1);
+ }
+
+ /* Driver Dependent Attribute functions */
+
+ /* Common */
+ iupClassRegisterAttribute(ic, "STANDARDFONT", NULL, motTabsSetStandardFontAttrib, IUPAF_SAMEASSYSTEM, "DEFAULTFONT", IUPAF_NOT_MAPPED);
+
+ /* Visual */
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, motTabsSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, motTabsSetFgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGFGCOLOR", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BACKGROUND", NULL, motTabsSetBackgroundAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+
+ /* IupTabs only */
+ iupClassRegisterAttribute(ic, "TABTYPE", iupTabsGetTabTypeAttrib, motTabsSetTabTypeAttrib, IUPAF_SAMEASSYSTEM, "TOP", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "TABORIENTATION", iupTabsGetTabOrientationAttrib, NULL, IUPAF_SAMEASSYSTEM, "HORIZONTAL", IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); /* can not be set, always HORIZONTAL in Motif */
+ iupClassRegisterAttributeId(ic, "TABTITLE", NULL, motTabsSetTabTitleAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "TABIMAGE", NULL, motTabsSetTabImageAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "PADDING", iupTabsGetPaddingAttrib, motTabsSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
+}
diff --git a/iup/src/mot/iupmot_text.c b/iup/src/mot/iupmot_text.c
new file mode 100755
index 0000000..4a8f936
--- /dev/null
+++ b/iup/src/mot/iupmot_text.c
@@ -0,0 +1,1165 @@
+/** \file
+ * \brief Text Control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+#include <Xm/TextF.h>
+#include <Xm/Text.h>
+#include <Xm/ScrolledW.h>
+#include <Xm/SpinB.h>
+#include <X11/keysym.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdarg.h>
+#include <limits.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_object.h"
+#include "iup_childtree.h"
+#include "iup_attrib.h"
+#include "iup_dialog.h"
+#include "iup_str.h"
+#include "iup_mask.h"
+#include "iup_drv.h"
+#include "iup_array.h"
+#include "iup_text.h"
+
+#include "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+#ifndef XmIsSpinBox
+#define XmIsSpinBox(w) XtIsSubclass(w, xmSpinBoxWidgetClass)
+#endif
+
+#ifndef XmNwrap
+#define XmNwrap "Nwrap"
+#endif
+
+void iupdrvTextAddFormatTag(Ihandle* ih, Ihandle* formattag)
+{
+ (void)ih;
+ (void)formattag;
+}
+
+void iupdrvTextAddSpin(int *w, int h)
+{
+ *w += h/2;
+}
+
+void iupdrvTextAddBorders(int *w, int *h)
+{
+ int border_size = 2*5;
+ (*w) += border_size;
+ (*h) += border_size;
+}
+
+static void motTextGetLinColFromPosition(const char *str, int pos, int *lin, int *col )
+{
+ int i;
+
+ *lin = 0;
+ *col = 0;
+
+ for (i=0; i<pos; i++)
+ {
+ if (*str == '\n')
+ {
+ (*lin)++;
+ *col = 0;
+ }
+ else
+ (*col)++;
+
+ str++;
+ }
+
+ (*lin)++; /* IUP starts at 1 */
+ (*col)++;
+}
+
+static int motTextSetLinColToPosition(const char *str, int lin, int col)
+{
+ int pos=0, cur_lin=0, cur_col=0;
+
+ lin--; /* IUP starts at 1 */
+ col--;
+
+ while (*str)
+ {
+ if (lin<=cur_lin && col<=cur_col)
+ break;
+
+ if (*str == '\n')
+ {
+ cur_lin++;
+ cur_col = 0;
+ }
+ else
+ cur_col++;
+
+ str++;
+ pos++;
+ }
+
+ return pos;
+}
+
+void iupdrvTextConvertLinColToPos(Ihandle* ih, int lin, int col, int *pos)
+{
+ char* str = XmTextGetString(ih->handle);
+ *pos = motTextSetLinColToPosition(str, lin, col);
+ XtFree(str);
+}
+
+void iupdrvTextConvertPosToLinCol(Ihandle* ih, int pos, int *lin, int *col)
+{
+ char *str = XmTextGetString(ih->handle);
+ motTextGetLinColFromPosition(str, pos, lin, col);
+ XtFree(str);
+}
+
+static int motTextConvertXYToPos(Ihandle* ih, int x, int y)
+{
+ return XmTextXYToPos(ih->handle, x, y);
+}
+
+
+/*******************************************************************************************/
+
+
+static int motTextSetPaddingAttrib(Ihandle* ih, const char* value)
+{
+ iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
+ if (ih->handle)
+ {
+ XtVaSetValues(ih->handle, XmNmarginHeight, ih->data->vert_padding,
+ XmNmarginWidth, ih->data->horiz_padding, NULL);
+ }
+ return 0;
+}
+
+static int motTextSetReadOnlyAttrib(Ihandle* ih, const char* value)
+{
+ XtVaSetValues(ih->handle, XmNeditable, iupStrBoolean(value)? False: True, NULL);
+ return 0;
+}
+
+static char* motTextGetReadOnlyAttrib(Ihandle* ih)
+{
+ Boolean editable;
+ XtVaGetValues(ih->handle, XmNeditable, &editable, NULL);
+ if (editable)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int motTextSetInsertAttrib(Ihandle* ih, const char* value)
+{
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+ if (!value)
+ return 0;
+
+ /* disable callbacks */
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+ XmTextRemove(ih->handle);
+ XmTextInsert(ih->handle, XmTextGetInsertionPosition(ih->handle), (char*)value);
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+
+ return 0;
+}
+
+static int motTextSetSelectedTextAttrib(Ihandle* ih, const char* value)
+{
+ XmTextPosition start, end;
+
+ if (!value)
+ return 0;
+
+ if (XmTextGetSelectionPosition(ih->handle, &start, &end) && start!=end)
+ {
+ /* disable callbacks */
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+ XmTextReplace(ih->handle, start, end, (char*)value);
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ }
+
+ return 0;
+}
+
+static char* motTextGetSelectedTextAttrib(Ihandle* ih)
+{
+ char* selectedtext = XmTextGetSelection(ih->handle);
+ char* str = iupStrGetMemoryCopy(selectedtext);
+ XtFree(selectedtext);
+ return str;
+}
+
+static int motTextSetAppendAttrib(Ihandle* ih, const char* value)
+{
+ XmTextPosition pos;
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+ pos = XmTextGetLastPosition(ih->handle);
+ /* disable callbacks */
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+ if (ih->data->is_multiline && ih->data->append_newline)
+ XmTextInsert(ih->handle, pos, "\n");
+ if (value)
+ XmTextInsert(ih->handle, pos+1, (char*)value);
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ return 0;
+}
+
+static int motTextSetSelectionAttrib(Ihandle* ih, const char* value)
+{
+ int start=1, end=1;
+
+ if (!value || iupStrEqualNoCase(value, "NONE"))
+ {
+ XmTextClearSelection(ih->handle, CurrentTime);
+ return 0;
+ }
+
+ if (iupStrEqualNoCase(value, "ALL"))
+ {
+ XmTextSetSelection(ih->handle, (XmTextPosition)0, (XmTextPosition)XmTextGetLastPosition(ih->handle), CurrentTime);
+ return 0;
+ }
+
+ if (ih->data->is_multiline)
+ {
+ int lin_start=1, col_start=1, lin_end=1, col_end=1;
+ char *str;
+
+ if (sscanf(value, "%d,%d:%d,%d", &lin_start, &col_start, &lin_end, &col_end)!=4) return 0;
+ if (lin_start<1 || col_start<1 || lin_end<1 || col_end<1) return 0;
+
+ str = XmTextGetString(ih->handle);
+ start = motTextSetLinColToPosition(str, lin_start, col_start);
+ end = motTextSetLinColToPosition(str, lin_end, col_end);
+ XtFree(str);
+ }
+ else
+ {
+ if (iupStrToIntInt(value, &start, &end, ':')!=2)
+ return 0;
+
+ if(start<1 || end<1)
+ return 0;
+
+ start--; /* IUP starts at 1 */
+ end--;
+ }
+
+ /* end is inside the selection, in IUP is outside */
+ end--;
+
+ XmTextSetSelection(ih->handle, (XmTextPosition)start, (XmTextPosition)end, CurrentTime);
+
+ return 0;
+}
+
+static char* motTextGetSelectionAttrib(Ihandle* ih)
+{
+ XmTextPosition start = 0, end = 0;
+ char* str;
+
+ if (!XmTextGetSelectionPosition(ih->handle, &start, &end) || start==end)
+ return NULL;
+
+ str = iupStrGetMemory(100);
+
+ /* end is inside the selection, in IUP is outside */
+ end++;
+
+ if (ih->data->is_multiline)
+ {
+ int start_col, start_lin, end_col, end_lin;
+
+ char *value = XmTextGetString(ih->handle);
+ motTextGetLinColFromPosition(value, start, &start_lin, &start_col);
+ motTextGetLinColFromPosition(value, end, &end_lin, &end_col);
+ XtFree(value);
+
+ sprintf(str,"%d,%d:%d,%d", start_lin, start_col, end_lin, end_col);
+ }
+ else
+ {
+ start++; /* IUP starts at 1 */
+ end++;
+ sprintf(str, "%d:%d", (int)start, (int)end);
+ }
+
+ return str;
+}
+
+static int motTextSetSelectionPosAttrib(Ihandle* ih, const char* value)
+{
+ int start=0, end=0;
+
+ if (!value || iupStrEqualNoCase(value, "NONE"))
+ {
+ XmTextClearSelection(ih->handle, CurrentTime);
+ return 0;
+ }
+
+ if (iupStrEqualNoCase(value, "ALL"))
+ {
+ XmTextSetSelection(ih->handle, (XmTextPosition)0, (XmTextPosition)XmTextGetLastPosition(ih->handle), CurrentTime);
+ return 0;
+ }
+
+ if (iupStrToIntInt(value, &start, &end, ':')!=2)
+ return 0;
+
+ if(start<0 || end<0)
+ return 0;
+
+ /* end is inside the selection, in IUP is outside */
+ end--;
+
+ XmTextSetSelection(ih->handle, (XmTextPosition)start, (XmTextPosition)end, CurrentTime);
+
+ return 0;
+}
+
+static char* motTextGetSelectionPosAttrib(Ihandle* ih)
+{
+ XmTextPosition start = 0, end = 0;
+ char* str;
+
+ if (!XmTextGetSelectionPosition(ih->handle, &start, &end) || start==end)
+ return NULL;
+
+ str = iupStrGetMemory(100);
+
+ /* end is inside the selection, in IUP is outside */
+ end++;
+
+ sprintf(str, "%d:%d", (int)start, (int)end);
+
+ return str;
+}
+
+static int motTextSetCaretAttrib(Ihandle* ih, const char* value)
+{
+ int pos = 1;
+
+ if (!value)
+ return 0;
+
+ if (ih->data->is_multiline)
+ {
+ int lin = 1, col = 1;
+ char *str;
+
+ iupStrToIntInt(value, &lin, &col, ',');
+
+ str = XmTextGetString(ih->handle);
+ pos = motTextSetLinColToPosition(str, lin, col);
+ XtFree(str);
+ }
+ else
+ {
+ sscanf(value,"%i",&pos);
+ pos--; /* IUP starts at 1 */
+ }
+
+ XmTextSetInsertionPosition(ih->handle, (XmTextPosition)pos);
+ XmTextShowPosition(ih->handle, (XmTextPosition)pos);
+
+ return 0;
+}
+
+static char* motTextGetCaretAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(50);
+
+ XmTextPosition pos = XmTextGetInsertionPosition(ih->handle);
+
+ if (ih->data->is_multiline)
+ {
+ int col, lin;
+
+ char *value = XmTextGetString(ih->handle);
+ motTextGetLinColFromPosition(value, pos, &lin, &col);
+ XtFree(value);
+
+ sprintf(str, "%d,%d", lin, col);
+ }
+ else
+ {
+ pos++; /* IUP starts at 1 */
+ sprintf(str, "%d", (int)pos);
+ }
+
+ return str;
+}
+
+static int motTextSetCaretPosAttrib(Ihandle* ih, const char* value)
+{
+ int pos = 0;
+
+ if (!value)
+ return 0;
+
+ sscanf(value,"%i",&pos);
+ if (pos < 0) pos = 0;
+
+ XmTextSetInsertionPosition(ih->handle, (XmTextPosition)pos);
+ XmTextShowPosition(ih->handle, (XmTextPosition)pos);
+
+ return 0;
+}
+
+static char* motTextGetCaretPosAttrib(Ihandle* ih)
+{
+ XmTextPosition pos = XmTextGetInsertionPosition(ih->handle);
+ char* str = iupStrGetMemory(50);
+ sprintf(str, "%d", (int)pos);
+ return str;
+}
+
+static int motTextSetScrollToAttrib(Ihandle* ih, const char* value)
+{
+ int pos = 1;
+
+ if (!value)
+ return 0;
+
+ if (ih->data->is_multiline)
+ {
+ int lin = 1, col = 1, pos;
+ char* str;
+
+ iupStrToIntInt(value, &lin, &col, ',');
+ if (lin < 1) lin = 1;
+ if (col < 1) col = 1;
+
+ str = XmTextGetString(ih->handle);
+ pos = motTextSetLinColToPosition(str, lin, col);
+ XtFree(str);
+ }
+ else
+ {
+ sscanf(value,"%i",&pos);
+ if (pos < 1) pos = 1;
+ pos--; /* return to Motif referece */
+ }
+
+ XmTextShowPosition(ih->handle, (XmTextPosition)pos);
+
+ return 0;
+}
+
+static int motTextSetScrollToPosAttrib(Ihandle* ih, const char* value)
+{
+ int pos = 0;
+
+ if (!value)
+ return 0;
+
+ sscanf(value,"%i",&pos);
+ if (pos < 0) pos = 0;
+
+ XmTextShowPosition(ih->handle, (XmTextPosition)pos);
+
+ return 0;
+}
+
+static int motTextSetNCAttrib(Ihandle* ih, const char* value)
+{
+ if (!iupStrToInt(value, &ih->data->nc))
+ ih->data->nc = INT_MAX;
+ if (ih->handle)
+ XtVaSetValues(ih->handle, XmNmaxLength, ih->data->nc, NULL);
+ return 0;
+}
+
+static int motTextSetClipboardAttrib(Ihandle *ih, const char *value)
+{
+ if (iupStrEqualNoCase(value, "COPY"))
+ {
+ char *str = XmTextGetSelection(ih->handle);
+ if (!str) return 0;
+
+ XmTextCopy(ih->handle, CurrentTime);
+
+ /* do it also for the X clipboard */
+ XStoreBytes(iupmot_display, str, strlen(str)+1);
+ XtFree(str);
+ }
+ else if (iupStrEqualNoCase(value, "CUT"))
+ {
+ char *str = XmTextGetSelection(ih->handle);
+ if (!str) return 0;
+
+ /* disable callbacks */
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+
+ XmTextCut(ih->handle, CurrentTime);
+
+ /* do it also for the X clipboard */
+ XStoreBytes(iupmot_display, str, strlen(str)+1);
+ XtFree(str);
+ XmTextRemove(ih->handle);
+
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ }
+ else if (iupStrEqualNoCase(value, "PASTE"))
+ {
+ int size;
+ char* str = XFetchBytes(iupmot_display, &size);
+ if (!str) return 0;
+
+ /* disable callbacks */
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+
+ XmTextPaste(ih->handle); /* TODO: this could force 2 pastes, check in CDE */
+
+ /* do it also for the X clipboard */
+ XmTextRemove(ih->handle);
+ XmTextInsert(ih->handle, XmTextGetInsertionPosition(ih->handle), str);
+ XFree(str);
+
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ }
+ else if (iupStrEqualNoCase(value, "CLEAR"))
+ {
+ /* disable callbacks */
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+ XmTextRemove(ih->handle);
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ }
+ return 0;
+}
+
+static int motTextSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ Widget sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (sb_win)
+ {
+ Pixel color;
+
+ /* ignore given value for the scrollbars, must use only from parent */
+ char* parent_value = iupBaseNativeParentGetBgColor(ih);
+
+ color = iupmotColorGetPixelStr(parent_value);
+ if (color != (Pixel)-1)
+ {
+ Widget sb = NULL;
+
+ iupmotSetBgColor(sb_win, color);
+
+ XtVaGetValues(sb_win, XmNverticalScrollBar, &sb, NULL);
+ if (sb) iupmotSetBgColor(sb, color);
+
+ XtVaGetValues(sb_win, XmNhorizontalScrollBar, &sb, NULL);
+ if (sb) iupmotSetBgColor(sb, color);
+ }
+ }
+
+ return iupdrvBaseSetBgColorAttrib(ih, value); /* use given value for contents */
+}
+
+static int motTextSetSpinMinAttrib(Ihandle* ih, const char* value)
+{
+ Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (spinbox && XmIsSpinBox(spinbox))
+ {
+ int min;
+ if (iupStrToInt(value, &min))
+ {
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+ XtVaSetValues(ih->handle, XmNminimumValue, min, NULL);
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ }
+ }
+ return 1;
+}
+
+static int motTextSetSpinMaxAttrib(Ihandle* ih, const char* value)
+{
+ Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (spinbox && XmIsSpinBox(spinbox))
+ {
+ int max;
+ if (iupStrToInt(value, &max))
+ {
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+ XtVaSetValues(ih->handle, XmNmaximumValue, max, NULL);
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ }
+ }
+ return 1;
+}
+
+static int motTextSetSpinIncAttrib(Ihandle* ih, const char* value)
+{
+ Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (spinbox && XmIsSpinBox(spinbox))
+ {
+ int inc;
+ if (iupStrToInt(value, &inc))
+ {
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+ XtVaSetValues(ih->handle, XmNincrementValue, inc, NULL);
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ }
+ }
+ return 1;
+}
+
+static int motTextSetSpinValueAttrib(Ihandle* ih, const char* value)
+{
+ Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (spinbox && XmIsSpinBox(spinbox))
+ {
+ int pos;
+ if (iupStrToInt(value, &pos))
+ {
+ char* value = NULL;
+ int min, max;
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+ XtVaGetValues(ih->handle, XmNminimumValue, &min,
+ XmNmaximumValue, &max, NULL);
+ if (pos < min) pos = min;
+ if (pos > max) pos = max;
+ if (iupAttribGet(ih, "_IUPMOT_SPIN_NOAUTO"))
+ value = XmTextGetString(ih->handle);
+
+ XtVaSetValues(ih->handle, XmNposition, pos, NULL);
+
+ if (value)
+ {
+ XmTextSetString(ih->handle, (char*)value);
+ XtFree(value);
+ }
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static char* motTextGetSpinValueAttrib(Ihandle* ih)
+{
+ Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (spinbox && XmIsSpinBox(spinbox))
+ {
+ int pos;
+ char *str = iupStrGetMemory(50);
+ XtVaGetValues(ih->handle, XmNposition, &pos, NULL);
+ sprintf(str, "%d", pos);
+ return str;
+ }
+ return NULL;
+}
+
+static int motTextSetValueAttrib(Ihandle* ih, const char* value)
+{
+ if (!value) value = "";
+ motTextSetSpinValueAttrib(ih, value);
+ /* disable callbacks */
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+ XmTextSetString(ih->handle, (char*)value);
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ return 0;
+}
+
+static char* motTextGetValueAttrib(Ihandle* ih)
+{
+ char* value = XmTextGetString(ih->handle);
+ char* str = iupStrGetMemoryCopy(value);
+ XtFree(value);
+ return str;
+}
+
+
+/******************************************************************************/
+
+
+static void motTextSpinModifyVerifyCallback(Widget w, Ihandle* ih, XmSpinBoxCallbackStruct *cbs)
+{
+ IFni cb = (IFni) IupGetCallback(ih, "SPIN_CB");
+ if (cb)
+ {
+ int ret = cb(ih, cbs->position);
+ if (ret == IUP_IGNORE)
+ {
+ cbs->doit = 1;
+ return;
+ }
+ }
+ (void)w;
+
+ iupAttribSetStr(ih, "_IUPMOT_SPIN_DISABLE_TEXT_CB", "1");
+}
+
+static void motTextModifyVerifyCallback(Widget w, Ihandle *ih, XmTextVerifyPtr text)
+{
+ int start, end, key = 0;
+ char *value, *new_value, *insert_value;
+ KeySym motcode = 0;
+ IFnis cb;
+
+ if (iupAttribGet(ih, "_IUPMOT_DISABLE_TEXT_CB"))
+ return;
+
+ if (iupAttribGet(ih, "_IUPMOT_SPIN_DISABLE_TEXT_CB"))
+ {
+ if (iupAttribGet(ih, "_IUPMOT_SPIN_NOAUTO"))
+ text->doit = False;
+
+ iupAttribSetStr(ih, "_IUPMOT_SPIN_DISABLE_TEXT_CB", NULL);
+ return;
+ }
+
+ cb = (IFnis)IupGetCallback(ih, "ACTION");
+ if (!cb && !ih->data->mask)
+ return;
+
+ if (text->event && text->event->type == KeyPress)
+ {
+ unsigned int state = ((XKeyEvent*)text->event)->state;
+ if (state & ControlMask || /* Ctrl */
+ state & Mod1Mask ||
+ state & Mod5Mask || /* Alt */
+ state & Mod4Mask) /* Apple/Win */
+ return;
+
+ motcode = XKeycodeToKeysym(iupmot_display, ((XKeyEvent*)text->event)->keycode, 0);
+ }
+
+ value = XmTextGetString(ih->handle);
+ start = text->startPos;
+ end = text->endPos;
+ insert_value = text->text->ptr;
+
+ if (motcode == XK_Delete)
+ {
+ new_value = value;
+ iupStrRemove(value, start, end, 1);
+ }
+ else if (motcode == XK_BackSpace)
+ {
+ new_value = value;
+ iupStrRemove(value, start, end, -1);
+ }
+ else
+ {
+ if (!value)
+ new_value = iupStrDup(insert_value);
+ else if (insert_value)
+ new_value = iupStrInsert(value, insert_value, start, end);
+ else
+ new_value = value;
+ }
+
+ if (insert_value && insert_value[0]!=0 && insert_value[1]==0)
+ key = insert_value[0];
+
+ if (ih->data->mask && iupMaskCheck(ih->data->mask, new_value)==0)
+ {
+ if (new_value != value) free(new_value);
+ XtFree(value);
+ text->doit = False; /* abort processing */
+ return;
+ }
+
+ if (cb)
+ {
+ int cb_ret = cb(ih, key, (char*)new_value);
+ if (cb_ret==IUP_IGNORE)
+ text->doit = False; /* abort processing */
+ else if (cb_ret==IUP_CLOSE)
+ {
+ IupExitLoop();
+ text->doit = False; /* abort processing */
+ }
+ else if (cb_ret!=0 && key!=0 &&
+ cb_ret != IUP_DEFAULT && cb_ret != IUP_CONTINUE)
+ {
+ insert_value[0] = (char)cb_ret; /* replace key */
+ }
+ }
+
+ if (text->doit)
+ {
+ /* Spin is not automatically updated when you directly edit the text */
+ Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (spinbox && XmIsSpinBox(spinbox) && !iupAttribGet(ih, "_IUPMOT_SPIN_NOAUTO"))
+ {
+ int pos;
+ if (iupStrToInt(new_value, &pos))
+ {
+ XmTextPosition caret_pos = text->currInsert;
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+ XtVaSetValues(ih->handle, XmNposition, pos, NULL);
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL);
+ /* do not handle all situations, but handle the basic ones */
+ if (text->startPos == text->endPos) /* insert */
+ caret_pos++;
+ else if (text->startPos < text->endPos && text->startPos < text->currInsert) /* backspace */
+ caret_pos--;
+ XmTextSetInsertionPosition(ih->handle, caret_pos);
+ text->doit = False;
+ }
+ }
+ }
+
+ if (new_value != value) free(new_value);
+ XtFree(value);
+ (void)w;
+}
+
+static void motTextMotionVerifyCallback(Widget w, Ihandle* ih, XmTextVerifyCallbackStruct* textverify)
+{
+ int col, lin, pos;
+
+ IFniii cb = (IFniii)IupGetCallback(ih, "CARET_CB");
+ if (!cb) return;
+
+ pos = textverify->newInsert;
+
+ if (ih->data->is_multiline)
+ {
+ char *value = XmTextGetString(ih->handle);
+ motTextGetLinColFromPosition(value, pos, &lin, &col);
+ XtFree(value);
+ }
+ else
+ {
+ col = pos;
+ col++; /* IUP starts at 1 */
+ lin = 1;
+ }
+
+ if (pos != ih->data->last_caret_pos)
+ {
+ ih->data->last_caret_pos = pos;
+ cb(ih, lin, col, pos);
+ }
+
+ (void)w;
+}
+
+static void motTextValueChangedCallback(Widget w, Ihandle* ih, XmAnyCallbackStruct* valuechanged)
+{
+ if (iupAttribGet(ih, "_IUPMOT_DISABLE_TEXT_CB"))
+ return;
+
+ iupBaseCallValueChangedCb(ih);
+
+ (void)valuechanged;
+ (void)w;
+}
+
+static void motTextKeyPressEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean *cont)
+{
+ Widget spinbox;
+
+ *cont = True;
+ iupmotKeyPressEvent(w, ih, (XEvent*)evt, cont);
+ if (*cont == False)
+ return;
+
+ if (evt->state & ControlMask) /* Ctrl */
+ {
+ KeySym motcode = XKeycodeToKeysym(iupmot_display, evt->keycode, 0);
+ if (motcode == XK_c)
+ motTextSetClipboardAttrib(ih, "COPY");
+ else if (motcode == XK_x)
+ motTextSetClipboardAttrib(ih, "CUT");
+ else if (motcode == XK_v)
+ motTextSetClipboardAttrib(ih, "PASTE");
+ else if (motcode == XK_a)
+ XmTextSetSelection(ih->handle, 0, XmTextGetLastPosition(ih->handle), CurrentTime);
+ }
+
+ spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (spinbox && XmIsSpinBox(spinbox))
+ {
+ KeySym motcode = XKeycodeToKeysym(iupmot_display, evt->keycode, 0);
+ if (motcode == XK_Left || motcode == XK_Right)
+ {
+ /* avoid spin increment using Left/Right arrows,
+ but must manually handle the new cursor position */
+ XmTextPosition caret_pos = XmTextGetInsertionPosition(ih->handle);
+ XmTextSetInsertionPosition(ih->handle, (motcode == XK_Left)? caret_pos-1: caret_pos+1);
+ *cont = False;
+ }
+ }
+}
+
+
+/******************************************************************************/
+
+
+static void motTextLayoutUpdateMethod(Ihandle* ih)
+{
+ Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (spinbox && XmIsSpinBox(spinbox))
+ {
+ XtVaSetValues(ih->handle,
+ XmNwidth, (XtArgVal)ih->currentwidth-ih->currentheight/2,
+ XmNheight, (XtArgVal)ih->currentheight,
+ NULL);
+
+ XtVaSetValues(spinbox,
+ XmNx, (XtArgVal)ih->x,
+ XmNy, (XtArgVal)ih->y,
+ XmNwidth, (XtArgVal)ih->currentwidth,
+ XmNheight, (XtArgVal)ih->currentheight,
+ XmNarrowSize, ih->currentheight/2,
+ NULL);
+ }
+ else
+ iupdrvBaseLayoutUpdateMethod(ih);
+}
+
+static int motTextMapMethod(Ihandle* ih)
+{
+ int num_args = 0;
+ Arg args[30];
+ Widget parent = iupChildTreeGetNativeParentHandle(ih);
+ char* child_id = iupDialogGetChildIdStr(ih);
+ int spin = 0;
+ WidgetClass widget_class = xmTextWidgetClass;
+
+ if (ih->data->is_multiline)
+ {
+ Widget sb_win;
+ int wordwrap = 0;
+
+ if (iupAttribGetBoolean(ih, "WORDWRAP"))
+ {
+ wordwrap = 1;
+ ih->data->sb &= ~IUP_SB_HORIZ; /* must remove the horizontal scroolbar */
+ }
+
+ /******************************/
+ /* Create the scrolled window */
+ /******************************/
+
+ iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupmotSetArg(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED);
+ iupmotSetArg(args, num_args, XmNvisualPolicy, XmVARIABLE);
+ iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC); /* can NOT be XmAS_NEEDED because XmAPPLICATION_DEFINED */
+ iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */
+ iupmotSetArg(args, num_args, XmNborderWidth, 0);
+ iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+
+ sb_win = XtCreateManagedWidget(
+ child_id, /* child identifier */
+ xmScrolledWindowWidgetClass, /* widget class */
+ parent, /* widget parent */
+ args, num_args);
+
+ if (!sb_win)
+ return IUP_ERROR;
+
+ parent = sb_win;
+ child_id = "text";
+
+ num_args = 0;
+ iupmotSetArg(args, num_args, XmNeditMode, XmMULTI_LINE_EDIT);
+ if (wordwrap)
+ iupmotSetArg(args, num_args, XmNwordWrap, True);
+ }
+ else
+ {
+ widget_class = xmTextFieldWidgetClass;
+
+ if (iupAttribGetBoolean(ih, "SPIN"))
+ {
+ Widget spinbox;
+
+ num_args = 0;
+ iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between spin and text */
+ iupmotSetArg(args, num_args, XmNborderWidth, 0);
+ iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+ iupmotSetArg(args, num_args, XmNmarginHeight, 0);
+ iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+ iupmotSetArg(args, num_args, XmNarrowSize, 8);
+
+ if (iupStrEqualNoCase(iupAttribGetStr(ih, "SPINALIGN"), "LEFT"))
+ iupmotSetArg(args, num_args, XmNarrowLayout, XmARROWS_BEGINNING);
+ else
+ iupmotSetArg(args, num_args, XmNarrowLayout, XmARROWS_END);
+
+ spinbox = XtCreateManagedWidget(
+ child_id, /* child identifier */
+ xmSpinBoxWidgetClass, /* widget class */
+ parent, /* widget parent */
+ args, num_args);
+
+ if (!spinbox)
+ return IUP_ERROR;
+
+ XtAddCallback(spinbox, XmNmodifyVerifyCallback, (XtCallbackProc)motTextSpinModifyVerifyCallback, (XtPointer)ih);
+
+ parent = spinbox;
+ child_id = "text";
+ spin = 1;
+
+ if (!iupAttribGetBoolean(ih, "SPINAUTO"))
+ iupAttribSetStr(ih, "_IUPMOT_SPIN_NOAUTO", "1");
+ }
+
+ num_args = 0;
+ iupmotSetArg(args, num_args, XmNeditMode, XmSINGLE_LINE_EDIT);
+
+ if (spin)
+ {
+ /* Spin Constraints */
+ iupmotSetArg(args, num_args, XmNspinBoxChildType, XmNUMERIC);
+ iupmotSetArg(args, num_args, XmNminimumValue, 0);
+ iupmotSetArg(args, num_args, XmNmaximumValue, 100);
+ iupmotSetArg(args, num_args, XmNposition, 0);
+
+ if (iupAttribGetBoolean(ih, "SPINWRAP"))
+ iupmotSetArg(args, num_args, XmNwrap, TRUE);
+ else
+ iupmotSetArg(args, num_args, XmNwrap, FALSE);
+ }
+ else
+ {
+ iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ }
+ }
+
+ iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+ iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+ iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+
+ iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
+ iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+ iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ else
+ iupmotSetArg(args, num_args, XmNtraversalOn, False);
+
+ iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
+ iupmotSetArg(args, num_args, XmNverifyBell, False);
+ iupmotSetArg(args, num_args, XmNspacing, 0);
+
+ if (iupAttribGetBoolean(ih, "BORDER"))
+ iupmotSetArg(args, num_args, XmNshadowThickness, 2);
+ else
+ iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+
+ if (ih->data->is_multiline)
+ {
+ if (ih->data->sb & IUP_SB_HORIZ)
+ iupmotSetArg(args, num_args, XmNscrollHorizontal, True);
+ else
+ iupmotSetArg(args, num_args, XmNscrollHorizontal, False);
+
+ if (ih->data->sb & IUP_SB_VERT)
+ iupmotSetArg(args, num_args, XmNscrollVertical, True);
+ else
+ iupmotSetArg(args, num_args, XmNscrollVertical, False);
+ }
+
+ ih->handle = XtCreateManagedWidget(
+ child_id, /* child identifier */
+ widget_class, /* widget class */
+ parent, /* widget parent */
+ args, num_args);
+
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ ih->serial = iupDialogGetChildId(ih); /* must be after using the string */
+
+ if (ih->data->is_multiline)
+ {
+ iupAttribSetStr(ih, "_IUP_EXTRAPARENT", (char*)parent);
+ XtVaSetValues(parent, XmNworkWindow, ih->handle, NULL);
+ }
+ else if (spin)
+ iupAttribSetStr(ih, "_IUP_EXTRAPARENT", (char*)parent);
+
+ XtAddCallback(ih->handle, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, EnterWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, LeaveWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, FocusChangeMask, False, (XtEventHandler)iupmotFocusChangeEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, KeyPressMask, False, (XtEventHandler)motTextKeyPressEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, PointerMotionMask, False, (XtEventHandler)iupmotPointerMotionEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, ButtonPressMask|ButtonReleaseMask, False, (XtEventHandler)iupmotButtonPressReleaseEvent, (XtPointer)ih);
+
+ XtAddCallback(ih->handle, XmNmodifyVerifyCallback, (XtCallbackProc)motTextModifyVerifyCallback, (XtPointer)ih);
+ XtAddCallback(ih->handle, XmNmotionVerifyCallback, (XtCallbackProc)motTextMotionVerifyCallback, (XtPointer)ih);
+ XtAddCallback(ih->handle, XmNvalueChangedCallback, (XtCallbackProc)motTextValueChangedCallback, (XtPointer)ih);
+
+ /* Disable Drag Source */
+ iupmotDisableDragSource(ih->handle);
+
+ /* initialize the widget */
+ if (ih->data->is_multiline || spin)
+ XtRealizeWidget(parent);
+ else
+ XtRealizeWidget(ih->handle);
+
+ if (IupGetGlobal("_IUP_RESET_TXTCOLORS"))
+ {
+ iupmotSetGlobalColorAttrib(ih->handle, XmNbackground, "TXTBGCOLOR");
+ iupmotSetGlobalColorAttrib(ih->handle, XmNforeground, "TXTFGCOLOR");
+ IupSetGlobal("_IUP_RESET_TXTCOLORS", NULL);
+ }
+
+ IupSetCallback(ih, "_IUP_XY2POS_CB", (Icallback)motTextConvertXYToPos);
+
+ return IUP_NOERROR;
+}
+
+void iupdrvTextInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class functions */
+ ic->Map = motTextMapMethod;
+ ic->LayoutUpdate = motTextLayoutUpdateMethod;
+
+ /* Driver Dependent Attribute functions */
+
+ /* Overwrite Visual */
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, motTextSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTBGCOLOR", IUPAF_DEFAULT);
+
+ /* Special */
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, iupdrvBaseSetFgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTFGCOLOR", IUPAF_DEFAULT);
+
+ /* IupText only */
+ iupClassRegisterAttribute(ic, "PADDING", iupTextGetPaddingAttrib, motTextSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "VALUE", motTextGetValueAttrib, motTextSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SELECTEDTEXT", motTextGetSelectedTextAttrib, motTextSetSelectedTextAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SELECTION", motTextGetSelectionAttrib, motTextSetSelectionAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SELECTIONPOS", motTextGetSelectionPosAttrib, motTextSetSelectionPosAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "CARET", motTextGetCaretAttrib, motTextSetCaretAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "CARETPOS", motTextGetCaretPosAttrib, motTextSetCaretPosAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "INSERT", NULL, motTextSetInsertAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "APPEND", NULL, motTextSetAppendAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "READONLY", motTextGetReadOnlyAttrib, motTextSetReadOnlyAttrib, NULL, NULL, IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "NC", iupTextGetNCAttrib, motTextSetNCAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "CLIPBOARD", NULL, motTextSetClipboardAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "FORMATTING", NULL, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); /* formatting not supported in Motif */
+ iupClassRegisterAttribute(ic, "SCROLLTO", NULL, motTextSetScrollToAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SCROLLTOPOS", NULL, motTextSetScrollToPosAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SPINMIN", NULL, motTextSetSpinMinAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SPINMAX", NULL, motTextSetSpinMaxAttrib, IUPAF_SAMEASSYSTEM, "100", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SPININC", NULL, motTextSetSpinIncAttrib, IUPAF_SAMEASSYSTEM, "1", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SPINVALUE", motTextGetSpinValueAttrib, motTextSetSpinValueAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NO_INHERIT);
+}
diff --git a/iup/src/mot/iupmot_timer.c b/iup/src/mot/iupmot_timer.c
new file mode 100755
index 0000000..d23867e
--- /dev/null
+++ b/iup/src/mot/iupmot_timer.c
@@ -0,0 +1,70 @@
+/** \file
+ * \brief Timer for the Motif Driver.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <Xm/Xm.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_assert.h"
+#include "iup_timer.h"
+
+#include "iupmot_drv.h"
+
+
+static void motTimerProc(XtPointer client_data, XtIntervalId *id)
+{
+ Ihandle *ih = (Ihandle*)client_data;
+ Icallback cb;
+ (void)id;
+
+ if (!iupObjectCheck(ih)) /* control could be destroyed before timer callback */
+ return;
+
+ ih->serial = -1;
+ /* we have to restart the timer everytime */
+ iupdrvTimerRun(ih);
+
+ cb = IupGetCallback(ih, "ACTION_CB");
+ if (cb)
+ {
+ if (cb(ih)==IUP_CLOSE)
+ IupExitLoop();
+ }
+}
+
+void iupdrvTimerRun(Ihandle *ih)
+{
+ unsigned int time_ms;
+
+ if (ih->serial > 0) /* timer already started */
+ return;
+
+ time_ms = iupAttribGetInt(ih, "TIME");
+ if (time_ms > 0)
+ ih->serial = XtAppAddTimeOut(iupmot_appcontext, time_ms, motTimerProc, (XtPointer)ih);
+}
+
+void iupdrvTimerStop(Ihandle* ih)
+{
+ if (ih->serial > 0)
+ {
+ XtRemoveTimeOut(ih->serial);
+ ih->serial = -1;
+ }
+}
+
+void iupdrvTimerInitClass(Iclass* ic)
+{
+ (void)ic;
+}
diff --git a/iup/src/mot/iupmot_tips.c b/iup/src/mot/iupmot_tips.c
new file mode 100755
index 0000000..25bdbea
--- /dev/null
+++ b/iup/src/mot/iupmot_tips.c
@@ -0,0 +1,226 @@
+/** \file
+ * \brief Motif Driver TIPS Control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+#include <Xm/Label.h>
+
+#include <stdio.h>
+
+#include "iup.h"
+
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_drvfont.h"
+
+#include "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+/* Default offset from cursor */
+#define TIP_X_OFFSET 12
+#define TIP_Y_OFFSET 12
+
+typedef struct _Imottips
+{
+ Widget Dialog;
+ Widget Label;
+ XtIntervalId ShowTimerId; /* Timer: from enterwin to show tip */
+ XtIntervalId HideTimerId; /* Timer: from visible to hide tip */
+ unsigned long ShowInterval; /* Time for tipPopupTimerId */
+ unsigned long HideInterval; /* Time for tipActiveTimerId */
+ int Visible;
+ Ihandle* ih;
+} Imottips;
+
+static Imottips mot_tips = {0, 0, 0, 0, 0, 0};
+
+static void motTipsShow(void)
+{
+ Window root, child;
+ int cx, cy, x, y;
+ unsigned int keys;
+ char* value;
+
+ XQueryPointer(iupmot_display, RootWindow(iupmot_display, iupmot_screen),
+ &root, &child, &x, &y, &cx, &cy, &keys);
+
+ value = iupAttribGet(mot_tips.ih, "TIPRECT");
+ if (value)
+ {
+ int x1, x2, y1, y2, wx = x, wy = y;
+ sscanf(value, "%d %d %d %d", &x1, &y1, &x2, &y2);
+ iupdrvScreenToClient(mot_tips.ih, &wx, &wy);
+ if (wx < x1 || wx > x2 || wy < y1 || wy > y2)
+ {
+ iupmotTipLeaveNotify();
+ return;
+ }
+ }
+
+ XtVaSetValues(mot_tips.Dialog,
+ XmNx, (XtArgVal)(x+TIP_X_OFFSET),
+ XmNy, (XtArgVal)(y+TIP_Y_OFFSET),
+ NULL);
+
+ if (mot_tips.Visible)
+ XRaiseWindow(iupmot_display, XtWindow(mot_tips.Dialog));
+ else
+ XtMapWidget(mot_tips.Dialog);
+
+ mot_tips.ShowTimerId = (XtIntervalId) NULL;
+ mot_tips.Visible = TRUE;
+}
+
+static void motTipsHide(void)
+{
+ mot_tips.HideTimerId = (XtIntervalId) NULL;
+ iupmotTipLeaveNotify();
+}
+
+static int motTipsSet(Ihandle *ih)
+{
+ char* tipText = iupAttribGet(ih, "TIP");
+ if (!tipText)
+ return FALSE;
+
+ if (!mot_tips.Dialog)
+ {
+ mot_tips.Dialog = XtVaAppCreateShell(" ", "tip",
+ overrideShellWidgetClass, iupmot_display,
+ XmNmappedWhenManaged, False,
+ NULL);
+
+ mot_tips.Label = XtVaCreateManagedWidget("label tip",
+ xmLabelWidgetClass, mot_tips.Dialog, /* must use IupGetAttribute to use inheritance */
+ XmNforeground, iupmotColorGetPixelStr(IupGetAttribute(ih, "TIPFGCOLOR")),
+ XmNbackground, iupmotColorGetPixelStr(IupGetAttribute(ih, "TIPBGCOLOR")),
+ NULL);
+
+ XtRealizeWidget(mot_tips.Dialog);
+ }
+
+ /* set label font */
+ {
+ XmFontList fontlist = (XmFontList)iupmotGetFontListAttrib(ih);
+ char* value = iupAttribGetStr(ih, "TIPFONT");
+ if (value)
+ {
+ if (iupStrEqualNoCase(value, "SYSTEM"))
+ fontlist = NULL;
+ else
+ fontlist = iupmotGetFontList(iupAttribGet(ih, "TIPFOUNDRY"), value);
+ }
+
+ if (fontlist)
+ XtVaSetValues(mot_tips.Label, XmNfontList, fontlist, NULL);
+ }
+
+ /* set label contents */
+ iupmotSetString(mot_tips.Label, XmNlabelString, tipText);
+
+ /* set label size */
+ {
+ int lw = 0, lh = 0;
+ iupdrvFontGetMultiLineStringSize(ih, tipText, &lw, &lh);
+
+ /* add room for margin */
+ lw += 2*(2);
+ lh += 2*(2);
+
+ XtVaSetValues(mot_tips.Label,
+ XmNwidth, (XtArgVal)lw,
+ XmNheight, (XtArgVal)lh,
+ NULL);
+ XtVaSetValues(mot_tips.Dialog,
+ XmNwidth, (XtArgVal)lw,
+ XmNheight, (XtArgVal)lh,
+ NULL);
+ }
+
+ mot_tips.ShowTimerId = (XtIntervalId) NULL;
+ mot_tips.HideTimerId = (XtIntervalId) NULL;
+ mot_tips.Visible = FALSE;
+ mot_tips.ShowInterval = 500; /* 1/2 second to show */
+
+ {
+ int delay = IupGetInt(ih, "TIPDELAY"); /* must use IupGetInt to use inheritance */
+ mot_tips.HideInterval = delay + mot_tips.ShowInterval;
+ }
+
+ return TRUE;
+}
+
+int iupdrvBaseSetTipVisibleAttrib(Ihandle* ih, const char* value)
+{
+ /* must use IupGetAttribute to use inheritance */
+ if (!IupGetAttribute(ih, "TIP"))
+ return 0;
+
+ if (iupStrBoolean(value))
+ iupmotTipEnterNotify(ih);
+ else
+ iupmotTipLeaveNotify();
+
+ return 0;
+}
+
+void iupmotTipEnterNotify(Ihandle *ih)
+{
+ iupmotTipLeaveNotify();
+
+ if (motTipsSet(ih) == FALSE)
+ return;
+
+ mot_tips.ih = ih;
+
+ mot_tips.ShowTimerId = XtAppAddTimeOut( /* EnterWin to Show */
+ iupmot_appcontext,
+ mot_tips.ShowInterval,
+ (XtTimerCallbackProc)motTipsShow,
+ NULL);
+ mot_tips.HideTimerId = XtAppAddTimeOut( /* Visible to Hide */
+ iupmot_appcontext,
+ mot_tips.HideInterval,
+ (XtTimerCallbackProc)motTipsHide,
+ NULL);
+}
+
+void iupmotTipLeaveNotify(void)
+{
+ if (mot_tips.ShowTimerId)
+ {
+ XtRemoveTimeOut(mot_tips.ShowTimerId);
+ mot_tips.ShowTimerId = (XtIntervalId) NULL;
+ }
+ if (mot_tips.HideTimerId)
+ {
+ XtRemoveTimeOut(mot_tips.HideTimerId);
+ mot_tips.HideTimerId = (XtIntervalId) NULL;
+ }
+ if (mot_tips.Visible)
+ {
+ XtUnmapWidget(mot_tips.Dialog);
+ mot_tips.Visible = FALSE;
+ }
+}
+
+void iupmotTipsFinish(void)
+{
+ if (mot_tips.Dialog)
+ {
+ XtDestroyWidget(mot_tips.Dialog);
+ memset(&mot_tips, 0, sizeof(Imottips));
+ }
+}
+
+int iupdrvBaseSetTipAttrib(Ihandle* ih, const char* value)
+{
+ /* implement this stub here because of the other drivers. */
+ (void)ih;
+ (void)value;
+ return 1;
+}
diff --git a/iup/src/mot/iupmot_toggle.c b/iup/src/mot/iupmot_toggle.c
new file mode 100755
index 0000000..b18f24d
--- /dev/null
+++ b/iup/src/mot/iupmot_toggle.c
@@ -0,0 +1,469 @@
+/** \file
+ * \brief Toggle Control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+#include <Xm/ToggleB.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdarg.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_object.h"
+#include "iup_childtree.h"
+#include "iup_attrib.h"
+#include "iup_dialog.h"
+#include "iup_str.h"
+#include "iup_toggle.h"
+#include "iup_drv.h"
+#include "iup_image.h"
+#include "iup_key.h"
+
+#include "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+void iupdrvToggleAddCheckBox(int *x, int *y)
+{
+ (*x) += 15+6+3;
+ if ((*y) < 15+6) (*y) = 12+6; /* minimum height */
+ (*y) += 6;
+}
+
+
+/*********************************************************************************/
+
+
+static int motToggleSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->type == IUP_TOGGLE_TEXT)
+ {
+ char* parent_value = iupAttribGetInheritNativeParent(ih, "BGCOLOR");
+ if (!parent_value)
+ {
+ /* if not defined at a native parent,
+ then change the toggle button color to the given color instead using the default */
+ if (iupdrvBaseSetBgColorAttrib(ih, value)) /* let XmChangeColor do its job */
+ {
+ parent_value = IupGetGlobal("DLGBGCOLOR");
+ XtVaSetValues(ih->handle, XmNbackground, iupmotColorGetPixelStr(parent_value), NULL); /* reset just the background */
+
+ if (ih->data->radio)
+ XtVaSetValues(ih->handle, XmNselectColor, iupmotColorGetPixel(0, 0, 0), NULL);
+ XtVaSetValues(ih->handle, XmNunselectColor, iupmotColorGetPixelStr(value), NULL);
+ return 1;
+ }
+ }
+ else
+ {
+ /* ignore given value, must use only from parent */
+ if (iupdrvBaseSetBgColorAttrib(ih, parent_value))
+ {
+ if (ih->data->radio)
+ XtVaSetValues(ih->handle, XmNselectColor, iupmotColorGetPixel(0, 0, 0), NULL);
+ XtVaSetValues(ih->handle, XmNunselectColor, iupmotColorGetPixelStr(parent_value), NULL);
+ return 1;
+ }
+ }
+ return 0;
+ }
+ else
+ return iupdrvBaseSetBgColorAttrib(ih, value);
+}
+
+static int motToggleSetBackgroundAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->type == IUP_TOGGLE_TEXT)
+ {
+ Pixel color;
+
+ /* ignore given value, must use only from parent */
+ value = iupAttribGetInheritNativeParent(ih, "BACKGROUND");
+
+ color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ {
+ XtVaSetValues(ih->handle, XmNbackground, color, NULL);
+ return 1;
+ }
+ else
+ {
+ Pixmap pixmap = (Pixmap)iupImageGetImage(value, ih, 0);
+ if (pixmap)
+ {
+ XtVaSetValues(ih->handle, XmNbackgroundPixmap, pixmap, NULL);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int motToggleSetTitleAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->type == IUP_TOGGLE_TEXT)
+ {
+ iupmotSetMnemonicTitle(ih, value);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int motToggleSetAlignmentAttrib(Ihandle* ih, const char* value)
+{
+ unsigned char align;
+ char value1[30]="", value2[30]="";
+
+ if (ih->data->type == IUP_TOGGLE_TEXT)
+ return 0;
+
+ iupStrToStrStr(value, value1, value2, ':'); /* value2 is ignored, NOT supported in Motif */
+
+ if (iupStrEqualNoCase(value1, "ARIGHT"))
+ align = XmALIGNMENT_END;
+ else if (iupStrEqualNoCase(value1, "ACENTER"))
+ align = XmALIGNMENT_CENTER;
+ else /* "ALEFT" */
+ align = XmALIGNMENT_BEGINNING;
+
+ XtVaSetValues (ih->handle, XmNalignment, align, NULL);
+ return 1;
+}
+
+static int motToggleSetImageAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->type == IUP_TOGGLE_IMAGE)
+ {
+ iupmotSetPixmap(ih, value, XmNlabelPixmap, 0);
+
+ if (!iupAttribGet(ih, "IMINACTIVE"))
+ {
+ /* if not active and IMINACTIVE is not defined
+ then automaticaly create one based on IMAGE */
+ iupmotSetPixmap(ih, value, XmNlabelInsensitivePixmap, 1); /* make_inactive */
+ }
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static int motToggleSetImInactiveAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->type == IUP_TOGGLE_IMAGE)
+ {
+ iupmotSetPixmap(ih, value, XmNlabelInsensitivePixmap, 0);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static int motToggleSetImPressAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->type == IUP_TOGGLE_IMAGE)
+ {
+ iupmotSetPixmap(ih, value, XmNselectPixmap, 0);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static int motToggleSetValueAttrib(Ihandle* ih, const char* value)
+{
+ Ihandle *radio;
+ unsigned char check;
+
+ if (iupStrEqualNoCase(value,"NOTDEF"))
+ check = XmINDETERMINATE;
+ else if (iupStrBoolean(value))
+ check = XmSET;
+ else
+ check = XmUNSET;
+
+ /* This is necessary because Motif toggle does not have support for radio.
+ It is implemented using an external RadioBox that we do not use. */
+ radio = iupRadioFindToggleParent(ih);
+ if (radio)
+ {
+ Ihandle* last_tg;
+ unsigned char oldcheck;
+
+ XtVaGetValues(ih->handle, XmNset, &oldcheck, NULL);
+
+ last_tg = (Ihandle*)iupAttribGet(radio, "_IUPMOT_LASTTOGGLE");
+ if (check)
+ {
+ if (iupObjectCheck(last_tg) && last_tg != ih)
+ XtVaSetValues(last_tg->handle, XmNset, XmUNSET, NULL);
+ iupAttribSetStr(radio, "_IUPMOT_LASTTOGGLE", (char*)ih);
+ }
+
+ if (last_tg != ih && oldcheck != check)
+ XtVaSetValues(ih->handle, XmNset, check, NULL);
+ }
+ else
+ XtVaSetValues(ih->handle, XmNset, check, NULL);
+
+ return 0;
+}
+
+static char* motToggleGetValueAttrib(Ihandle* ih)
+{
+ unsigned char check = 0;
+ XtVaGetValues (ih->handle, XmNset, &check, NULL);
+ if (check == XmINDETERMINATE)
+ return "NOTDEF";
+ else if (check == XmSET)
+ return "ON";
+ else
+ return "OFF";
+}
+
+static int motToggleSetPaddingAttrib(Ihandle* ih, const char* value)
+{
+ iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
+ if (ih->handle && ih->data->type == IUP_TOGGLE_IMAGE)
+ {
+ XtVaSetValues(ih->handle, XmNmarginHeight, ih->data->vert_padding,
+ XmNmarginWidth, ih->data->horiz_padding, NULL);
+ }
+ return 0;
+}
+
+static char* motToggleGetSelectColorAttrib(Ihandle* ih)
+{
+ unsigned char r, g, b;
+ Pixel color;
+ char* str = iupStrGetMemory(20);
+ XtVaGetValues(ih->handle, XmNselectColor, &color, NULL);
+ iupmotColorGetRGB(color, &r, &g, &b);
+ sprintf(str, "%d %d %d", (int)r, (int)g, (int)b);
+ return str;
+}
+
+static int motToggleSetSelectColorAttrib(Ihandle* ih, const char *value)
+{
+ Pixel color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ XtVaSetValues(ih->handle, XmNselectColor, color, NULL);
+ return 1;
+}
+
+static void motToggleValueChangedCallback(Widget w, Ihandle* ih, XmToggleButtonCallbackStruct* call_data)
+{
+ Ihandle *radio;
+ IFni cb;
+ int check = call_data->set;
+
+ /* Must manually hide the tip if the toggle is pressed. */
+ iupmotTipLeaveNotify();
+
+ /* This is necessary because Motif toggle does not have support for radio.
+ It is implemented using an external RadioBox that we do not use. */
+ radio = iupRadioFindToggleParent(ih);
+ if (radio)
+ {
+ if (check)
+ {
+ Ihandle* last_tg = (Ihandle*)iupAttribGet(radio, "_IUPMOT_LASTTOGGLE");
+ if (iupObjectCheck(last_tg) && last_tg != ih)
+ {
+ /* uncheck last toggle */
+ XtVaSetValues(last_tg->handle, XmNset, XmUNSET, NULL);
+
+ cb = (IFni) IupGetCallback(last_tg, "ACTION");
+ if (cb && cb(last_tg, 0) == IUP_CLOSE)
+ IupExitLoop();
+
+ iupBaseCallValueChangedCb(last_tg);
+ }
+ iupAttribSetStr(radio, "_IUPMOT_LASTTOGGLE", (char*)ih);
+
+ if (last_tg != ih)
+ {
+ cb = (IFni)IupGetCallback(ih, "ACTION");
+ if (cb && cb (ih, 1) == IUP_CLOSE)
+ IupExitLoop();
+
+ iupBaseCallValueChangedCb(ih);
+ }
+ }
+ else
+ {
+ /* Force stay checked */
+ XtVaSetValues(ih->handle, XmNset, XmSET, NULL);
+ }
+ }
+ else
+ {
+ if (check == XmINDETERMINATE)
+ check = -1;
+
+ cb = (IFni)IupGetCallback(ih, "ACTION");
+ if (cb)
+ {
+ if (cb(ih, check) == IUP_CLOSE)
+ IupExitLoop();
+ }
+
+ iupBaseCallValueChangedCb(ih);
+ }
+
+ (void)w;
+}
+
+static int motToggleMapMethod(Ihandle* ih)
+{
+ Ihandle* radio = iupRadioFindToggleParent(ih);
+ char* value;
+ int num_args = 0;
+ Arg args[40];
+
+ if (radio)
+ ih->data->radio = 1;
+
+ value = iupAttribGet(ih, "IMAGE");
+ if (value)
+ {
+ ih->data->type = IUP_TOGGLE_IMAGE;
+ iupmotSetArg(args, num_args, XmNlabelType, XmPIXMAP);
+ }
+ else
+ {
+ ih->data->type = IUP_TOGGLE_TEXT;
+ iupmotSetArg(args, num_args, XmNlabelType, XmSTRING);
+ }
+
+ /* Core */
+ iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+ iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+ iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ /* Primitive */
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+ iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ else
+ iupmotSetArg(args, num_args, XmNtraversalOn, False);
+ iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
+ iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ /* Label */
+ iupmotSetArg(args, num_args, XmNrecomputeSize, False); /* no automatic resize from text */
+ iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
+ iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+ iupmotSetArg(args, num_args, XmNmarginTop, 0); /* no extra margins */
+ iupmotSetArg(args, num_args, XmNmarginLeft, 0);
+ iupmotSetArg(args, num_args, XmNmarginBottom, 0);
+ iupmotSetArg(args, num_args, XmNmarginRight, 0);
+
+ if (radio)
+ {
+ iupmotSetArg(args, num_args, XmNtoggleMode, XmTOGGLE_BOOLEAN);
+ iupmotSetArg(args, num_args, XmNindicatorType, XmONE_OF_MANY_ROUND);
+
+ if (!iupAttribGet(radio, "_IUPMOT_LASTTOGGLE"))
+ {
+ /* this is the first toggle in the radio, and the last toggle with VALUE=ON */
+ iupAttribSetStr(ih, "VALUE","ON");
+ }
+ }
+ else
+ {
+ if (ih->data->type == IUP_TOGGLE_TEXT && iupAttribGetBoolean(ih, "3STATE"))
+ iupmotSetArg(args, num_args, XmNtoggleMode, XmTOGGLE_INDETERMINATE);
+ else
+ iupmotSetArg(args, num_args, XmNtoggleMode, XmTOGGLE_BOOLEAN);
+ iupmotSetArg(args, num_args, XmNindicatorType, XmN_OF_MANY);
+ }
+
+ if (ih->data->type == IUP_TOGGLE_IMAGE)
+ {
+ iupmotSetArg(args, num_args, XmNindicatorOn, XmINDICATOR_NONE);
+ iupmotSetArg(args, num_args, XmNalignment, XmALIGNMENT_CENTER);
+ iupmotSetArg(args, num_args, XmNshadowThickness, 2);
+ }
+ else
+ {
+ iupmotSetArg(args, num_args, XmNspacing, 3);
+ iupmotSetArg(args, num_args, XmNindicatorOn, XmINDICATOR_CHECK_BOX);
+ iupmotSetArg(args, num_args, XmNalignment, XmALIGNMENT_BEGINNING);
+ if (radio)
+ {
+ iupmotSetArg(args, num_args, XmNindicatorSize, 13);
+ iupmotSetArg(args, num_args, XmNselectColor, iupmotColorGetPixel(0, 0, 0));
+ }
+ else
+ iupmotSetArg(args, num_args, XmNindicatorSize, 15);
+
+ iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+ iupmotSetArg(args, num_args, XmNdetailShadowThickness, 2);
+ }
+
+ ih->handle = XtCreateManagedWidget(
+ iupDialogGetChildIdStr(ih), /* child identifier */
+ xmToggleButtonWidgetClass, /* widget class */
+ iupChildTreeGetNativeParentHandle(ih), /* widget parent */
+ args, num_args);
+
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ ih->serial = iupDialogGetChildId(ih); /* must be after using the string */
+
+ XtAddCallback(ih->handle, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih);
+
+ XtAddEventHandler(ih->handle, EnterWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, LeaveWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+
+ XtAddEventHandler(ih->handle, FocusChangeMask, False, (XtEventHandler)iupmotFocusChangeEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, KeyPressMask, False, (XtEventHandler)iupmotKeyPressEvent, (XtPointer)ih);
+
+ XtAddCallback(ih->handle, XmNvalueChangedCallback, (XtCallbackProc)motToggleValueChangedCallback, (XtPointer)ih);
+
+ /* Disable Drag Source */
+ iupmotDisableDragSource(ih->handle);
+
+ /* initialize the widget */
+ XtRealizeWidget(ih->handle);
+
+ if (ih->data->type == IUP_TOGGLE_TEXT)
+ iupmotSetString(ih->handle, XmNlabelString, "");
+
+ return IUP_NOERROR;
+}
+
+void iupdrvToggleInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class functions */
+ ic->Map = motToggleMapMethod;
+
+ /* Driver Dependent Attribute functions */
+
+ /* Overwrite Visual */
+ iupClassRegisterAttribute(ic, "BGCOLOR", iupmotGetBgColorAttrib, motToggleSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BACKGROUND", NULL, motToggleSetBackgroundAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+
+ /* Special */
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, iupdrvBaseSetFgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGFGCOLOR", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "TITLE", NULL, motToggleSetTitleAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+
+ /* IupToggle only */
+ iupClassRegisterAttribute(ic, "ALIGNMENT", NULL, motToggleSetAlignmentAttrib, IUPAF_SAMEASSYSTEM, "ACENTER:ACENTER", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "IMAGE", NULL, motToggleSetImageAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "IMINACTIVE", NULL, motToggleSetImInactiveAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "IMPRESS", NULL, motToggleSetImPressAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "VALUE", motToggleGetValueAttrib, motToggleSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SELECTCOLOR", motToggleGetSelectColorAttrib, motToggleSetSelectColorAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute(ic, "PADDING", iupToggleGetPaddingAttrib, motToggleSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
+}
diff --git a/iup/src/mot/iupmot_tree.c b/iup/src/mot/iupmot_tree.c
new file mode 100755
index 0000000..eb230af
--- /dev/null
+++ b/iup/src/mot/iupmot_tree.c
@@ -0,0 +1,2848 @@
+#include <Xm/Xm.h>
+#include <Xm/Form.h>
+#include <Xm/Container.h>
+#include <Xm/IconG.h>
+#include <Xm/ScrolledW.h>
+#include <Xm/XmosP.h>
+#include <Xm/Text.h>
+#include <Xm/Transfer.h>
+#include <Xm/DragDrop.h>
+#include <X11/keysym.h>
+
+#include <sys/stat.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <time.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_object.h"
+#include "iup_childtree.h"
+#include "iup_dialog.h"
+#include "iup_layout.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_drvinfo.h"
+#include "iup_drvfont.h"
+#include "iup_stdcontrols.h"
+#include "iup_key.h"
+#include "iup_image.h"
+#include "iup_array.h"
+#include "iup_tree.h"
+
+#include "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+typedef struct _motTreeItemData
+{
+ Pixmap image, image_mask;
+ Pixmap image_expanded, image_expanded_mask;
+ unsigned char kind;
+ void* userdata;
+} motTreeItemData;
+
+
+static void motTreeShowEditField(Ihandle* ih, Widget wItem);
+static int motTreeGetNodeId(Ihandle* ih, Widget wItem);
+
+typedef int (*motTreeNodeFunc)(Ihandle* ih, Widget wItem, void* userdata);
+
+static int motTreeForEach(Ihandle* ih, Widget wItem, motTreeNodeFunc func, void* userdata)
+{
+ WidgetList wItemChildList = NULL;
+ int i, numChild;
+
+ if (!wItem)
+ wItem = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+
+ if (!func(ih, wItem, userdata))
+ return 0;
+
+ numChild = XmContainerGetItemChildren(ih->handle, wItem, &wItemChildList);
+ for (i=0; i<numChild; i++)
+ {
+ /* Recursively traverse child items */
+ if (!motTreeForEach(ih, wItemChildList[i], func, userdata))
+ {
+ XtFree((char*)wItemChildList);
+ return 0;
+ }
+ }
+ if (wItemChildList) XtFree((char*)wItemChildList);
+
+ return 1;
+}
+
+/*****************************************************************************/
+/* COPYING ITEMS (Branches and its children) */
+/*****************************************************************************/
+/* Insert the copied item in a new location. Returns the new item. */
+static Widget motTreeCopyItem(Ihandle* ih, Widget wItem, Widget wParent, int pos, int full_copy)
+{
+ Widget wNewItem;
+ XmString title;
+ motTreeItemData *itemData;
+ Pixel fgcolor, bgcolor;
+ int num_args = 0;
+ Arg args[30];
+ Pixmap image = XmUNSPECIFIED_PIXMAP, mask = XmUNSPECIFIED_PIXMAP;
+ unsigned char state;
+
+ iupmotSetArg(args, num_args, XmNentryParent, wParent);
+ iupmotSetArg(args, num_args, XmNmarginHeight, ih->data->spacing);
+ iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+ iupmotSetArg(args, num_args, XmNviewType, XmSMALL_ICON);
+ iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+
+ /* Get values to copy */
+ XtVaGetValues(wItem, XmNlabelString, &title,
+ XmNuserData, &itemData,
+ XmNforeground, &fgcolor,
+ XmNsmallIconPixmap, &image,
+ XmNsmallIconMask, &mask,
+ XmNoutlineState, &state,
+ NULL);
+
+ if (full_copy) /* during a full copy the userdata reference is not copied */
+ {
+ /* create a new one */
+ motTreeItemData* itemDataNew = malloc(sizeof(motTreeItemData));
+ memcpy(itemDataNew, itemData, sizeof(motTreeItemData));
+ itemDataNew->userdata = NULL;
+ itemData = itemDataNew;
+ }
+
+ iupmotSetArg(args, num_args, XmNlabelString, title);
+ iupmotSetArg(args, num_args, XmNuserData, itemData);
+ iupmotSetArg(args, num_args, XmNforeground, fgcolor);
+ iupmotSetArg(args, num_args, XmNsmallIconPixmap, image);
+ iupmotSetArg(args, num_args, XmNsmallIconMask, mask);
+ iupmotSetArg(args, num_args, XmNoutlineState, state);
+
+ iupmotSetArg(args, num_args, XmNentryParent, wParent);
+ iupmotSetArg(args, num_args, XmNpositionIndex, pos);
+
+ XtVaGetValues(ih->handle, XmNbackground, &bgcolor, NULL);
+ iupmotSetArg(args, num_args, XmNbackground, bgcolor);
+
+ wNewItem = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args);
+
+ /* Root always expanded */
+ XtVaSetValues((Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"), XmNoutlineState, XmEXPANDED, NULL);
+
+ XtRealizeWidget(wNewItem);
+
+ return wNewItem;
+}
+
+static void motTreeCopyChildren(Ihandle* ih, Widget wItemSrc, Widget wItemDst, int full_copy)
+{
+ WidgetList wItemChildList = NULL;
+ int i = 0;
+ int numChild = XmContainerGetItemChildren(ih->handle, wItemSrc, &wItemChildList);
+ while(i != numChild)
+ {
+ Widget wNewItem = motTreeCopyItem(ih, wItemChildList[i], wItemDst, i, full_copy); /* Use the same order they where enumerated */
+
+ /* Recursively transfer all the items */
+ motTreeCopyChildren(ih, wItemChildList[i], wNewItem, full_copy);
+
+ /* Go to next sibling item */
+ i++;
+ }
+
+ if (wItemChildList) XtFree((char*)wItemChildList);
+}
+
+/* Copies all items in a branch to a new location. Returns the new branch node. */
+static Widget motTreeCopyNode(Ihandle* ih, Widget wItemSrc, Widget wItemDst, int full_copy)
+{
+ Widget wNewItem, wParent;
+ motTreeItemData *itemDataDst;
+ unsigned char stateDst;
+ int pos;
+
+ XtVaGetValues(wItemDst, XmNoutlineState, &stateDst,
+ XmNuserData, &itemDataDst,
+ NULL);
+
+ if (itemDataDst->kind == ITREE_BRANCH && stateDst == XmEXPANDED)
+ {
+ /* copy as first child of expanded branch */
+ wParent = wItemDst;
+ pos = 0;
+ }
+ else
+ {
+ /* copy as next brother of item or collapsed branch */
+ XtVaGetValues(wItemDst, XmNentryParent, &wParent, NULL);
+ XtVaGetValues(wItemDst, XmNpositionIndex, &pos, NULL);
+ pos++;
+ }
+
+ wNewItem = motTreeCopyItem(ih, wItemSrc, wParent, pos, full_copy);
+
+ motTreeCopyChildren(ih, wItemSrc, wNewItem, full_copy);
+
+ return wNewItem;
+}
+
+static void motTreeContainerDeselectAll(Ihandle *ih)
+{
+ XKeyEvent ev;
+
+ memset(&ev, 0, sizeof(XKeyEvent));
+ ev.type = KeyPress;
+ ev.display = XtDisplay(ih->handle);
+ ev.send_event = True;
+ ev.root = RootWindow(iupmot_display, iupmot_screen);
+ ev.time = clock()*CLOCKS_PER_SEC;
+ ev.window = XtWindow(ih->handle);
+ ev.state = ControlMask;
+ ev.keycode = XK_backslash;
+ ev.same_screen = True;
+
+ XtCallActionProc(ih->handle, "ContainerDeselectAll", (XEvent*)&ev, 0, 0);
+}
+
+static void motTreeContainerSelectAll(Ihandle *ih)
+{
+ XKeyEvent ev;
+
+ memset(&ev, 0, sizeof(XKeyEvent));
+ ev.type = KeyPress;
+ ev.display = XtDisplay(ih->handle);
+ ev.send_event = True;
+ ev.root = RootWindow(iupmot_display, iupmot_screen);
+ ev.time = clock()*CLOCKS_PER_SEC;
+ ev.window = XtWindow(ih->handle);
+ ev.state = ControlMask;
+ ev.keycode = XK_slash;
+ ev.same_screen = True;
+
+ XtCallActionProc(ih->handle, "ContainerSelectAll", (XEvent*)&ev, 0, 0);
+}
+
+static Widget motTreeGetLastVisibleNode(Ihandle* ih, Widget wItem)
+{
+ unsigned char itemState;
+
+ XtVaGetValues(wItem, XmNoutlineState, &itemState, NULL);
+
+ if (itemState == XmEXPANDED)
+ {
+ WidgetList wChildrenTree = NULL;
+ int numChildren = XmContainerGetItemChildren(ih->handle, wItem, &wChildrenTree);
+ if(numChildren)
+ wItem = motTreeGetLastVisibleNode(ih, wChildrenTree[numChildren - 1]);
+ if (wChildrenTree) XtFree((char*)wChildrenTree);
+ }
+
+ return wItem;
+}
+
+static Widget motTreeFindVisibleNodeId(Ihandle* ih, WidgetList itemList, int numItems, Widget itemNode)
+{
+ Widget itemChild;
+ WidgetList itemChildList;
+ int i = 0;
+ int numChild;
+ unsigned char itemState;
+
+ while(i != numItems)
+ {
+ /* ID control to traverse items */
+ ih->data->id_control++; /* not the real id since it counts only the visible ones */
+
+ /* StateID founded! */
+ if(itemList[i] == itemNode)
+ return itemList[i];
+
+ /* Check whether we have child items */
+ itemChildList = NULL;
+ numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+ XtVaGetValues(itemList[i], XmNoutlineState, &itemState, NULL);
+
+ /* The itemWidget has child and it is expanded (visible) */
+ if (numChild && itemState == XmEXPANDED)
+ {
+ /* pass the list of children of this item */
+ itemChild = motTreeFindVisibleNodeId(ih, itemChildList, numChild, itemNode);
+
+ /* StateID founded! */
+ if(itemChild)
+ {
+ XtFree((char*)itemChildList);
+ return itemChild;
+ }
+ }
+
+ if (itemChildList) XtFree((char*)itemChildList);
+ /* Go to next sibling item */
+ i++;
+ }
+
+ return NULL;
+}
+
+static Widget motTreeFindVisibleNodeFromId(Ihandle* ih, WidgetList itemList, int numItems)
+{
+ Widget itemChild;
+ WidgetList itemChildList;
+ int i = 0;
+ int numChild;
+ unsigned char itemState;
+
+ while(i != numItems)
+ {
+ /* ID control to traverse items */
+ ih->data->id_control--; /* not the real id since it counts only the visible ones */
+
+ /* StateID founded! */
+ if(ih->data->id_control < 0)
+ return itemList[i];
+
+ /* Check whether we have child items */
+ itemChildList = NULL;
+ numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+ XtVaGetValues(itemList[i], XmNoutlineState, &itemState, NULL);
+
+ /* The itemWidget has child and it is expanded (visible) */
+ if (numChild && itemState == XmEXPANDED)
+ {
+ /* pass the list of children of this item */
+ itemChild = motTreeFindVisibleNodeFromId(ih, itemChildList, numChild);
+
+ /* StateID founded! */
+ if(ih->data->id_control < 0)
+ {
+ if (itemChildList) XtFree((char*)itemChildList);
+ return itemChild;
+ }
+ }
+
+ if (itemChildList) XtFree((char*)itemChildList);
+ /* Go to next sibling item */
+ i++;
+ }
+
+ return NULL;
+}
+
+static Widget motTreeGetNextVisibleNode(Ihandle* ih, Widget wRoot, Widget wItem)
+{
+ Widget wNext;
+
+ ih->data->id_control = -1;
+ motTreeFindVisibleNodeId(ih, &wRoot, 1, wItem);
+ ih->data->id_control++; /* more 1 visible node */
+
+ wNext = motTreeFindVisibleNodeFromId(ih, &wRoot, 1);
+
+ if (ih->data->id_control >= 0)
+ wNext = motTreeGetLastVisibleNode(ih, wRoot);
+
+ return wNext;
+}
+
+static Widget motTreeGetPreviousVisibleNode(Ihandle* ih, Widget wRoot, Widget wItem)
+{
+ ih->data->id_control = -1;
+ motTreeFindVisibleNodeId(ih, &wRoot, 1, wItem);
+ ih->data->id_control--; /* less 1 visible node */
+
+ if (ih->data->id_control < 0)
+ ih->data->id_control = 0; /* Begin of tree = Root id */
+
+ return motTreeFindVisibleNodeFromId(ih, &wRoot, 1);
+}
+
+static void motTreeUpdateBgColor(Ihandle* ih, WidgetList itemList, int numItems, Pixel bgcolor)
+{
+ WidgetList itemChildList;
+ int i = 0;
+ int numChild;
+
+ while(i != numItems)
+ {
+ XtVaSetValues(itemList[i], XmNbackground, bgcolor, NULL);
+
+ /* Check whether we have child items */
+ itemChildList = NULL;
+ numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+ if(numChild)
+ motTreeUpdateBgColor(ih, itemChildList, numChild, bgcolor);
+ if (itemChildList) XtFree((char*)itemChildList);
+
+ /* Go to next sibling item */
+ i++;
+ }
+}
+
+static void motTreeUpdateImages(Ihandle* ih, WidgetList itemList, int numItems, int mode)
+{
+ motTreeItemData *itemData;
+ int i = 0;
+
+ /* called when one of the default images is changed */
+
+ while(i != numItems)
+ {
+ /* Get node attributes */
+ XtVaGetValues(itemList[i], XmNuserData, &itemData, NULL);
+
+ if (itemData->kind == ITREE_BRANCH)
+ {
+ unsigned char itemState;
+ XtVaGetValues(itemList[i], XmNoutlineState, &itemState, NULL);
+
+ if (itemState == XmEXPANDED)
+ {
+ if (mode == ITREE_UPDATEIMAGE_EXPANDED)
+ {
+ XtVaSetValues(itemList[i], XmNsmallIconPixmap, (itemData->image_expanded!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded: (Pixmap)ih->data->def_image_expanded, NULL);
+ XtVaSetValues(itemList[i], XmNsmallIconMask, (itemData->image_expanded_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded_mask: (Pixmap)ih->data->def_image_expanded_mask, NULL);
+ }
+ }
+ else
+ {
+ if (mode == ITREE_UPDATEIMAGE_COLLAPSED)
+ {
+ XtVaSetValues(itemList[i], XmNsmallIconPixmap, (itemData->image!=XmUNSPECIFIED_PIXMAP)? itemData->image: (Pixmap)ih->data->def_image_collapsed, NULL);
+ XtVaSetValues(itemList[i], XmNsmallIconMask, (itemData->image_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_mask: (Pixmap)ih->data->def_image_collapsed_mask, NULL);
+ }
+ }
+
+ /* Recursively traverse child items */
+ {
+ WidgetList itemChildList;
+ int numChild;
+ itemChildList = NULL;
+ numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+ motTreeUpdateImages(ih, itemChildList, numChild, mode);
+ if (itemChildList) XtFree((char*)itemChildList);
+ }
+ }
+ else
+ {
+ if (mode == ITREE_UPDATEIMAGE_LEAF)
+ {
+ XtVaSetValues(itemList[i], XmNsmallIconPixmap, (itemData->image!=XmUNSPECIFIED_PIXMAP)? itemData->image: (Pixmap)ih->data->def_image_leaf, NULL);
+ XtVaSetValues(itemList[i], XmNsmallIconMask, (itemData->image_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_mask: (Pixmap)ih->data->def_image_leaf_mask, NULL);
+ }
+ }
+
+ /* Go to next sibling node */
+ i++;
+ }
+}
+
+static int motTreeSelectFunc(Ihandle* ih, Widget wItem, int *select)
+{
+ int do_select = *select;
+ if (do_select == -1)
+ {
+ unsigned char isSelected;
+ XtVaGetValues(wItem, XmNvisualEmphasis, &isSelected, NULL);
+ do_select = (isSelected == XmSELECTED)? 0: 1; /* toggle */
+ }
+
+ if (do_select)
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
+ else
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
+
+ (void)ih;
+ return 1;
+}
+
+static void motTreeInvertAllNodeMarking(Ihandle* ih)
+{
+ int select = -1;
+ motTreeForEach(ih, NULL, (motTreeNodeFunc)motTreeSelectFunc, &select);
+}
+
+typedef struct _motTreeRange{
+ Widget wItem1, wItem2;
+ char inside, clear;
+}motTreeRange;
+
+static int motTreeSelectRangeFunc(Ihandle* ih, Widget wItem, motTreeRange* range)
+{
+ int end_range = 0;
+
+ if (range->inside == 0) /* detect the range start */
+ {
+ if (range->wItem1 == wItem) range->inside=1;
+ else if (range->wItem2 == wItem) range->inside=1;
+ }
+ else if (range->inside == 1) /* detect the range end */
+ {
+ if (range->wItem1 == wItem) end_range=1;
+ else if (range->wItem2 == wItem) end_range=1;
+ }
+
+ if (range->inside == 1) /* if inside, select */
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
+ else if (range->clear) /* if outside and clear, unselect */
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
+
+ if (end_range || (range->inside && range->wItem1==range->wItem2))
+ range->inside=-1; /* update after selecting the node */
+
+ (void)ih;
+ return 1;
+}
+
+static void motTreeSelectRange(Ihandle* ih, Widget wItem1, Widget wItem2, int clear)
+{
+ motTreeRange range;
+ range.wItem1 = wItem1;
+ range.wItem2 = wItem2;
+ range.inside = 0;
+ range.clear = (char)clear;
+ motTreeForEach(ih, NULL, (motTreeNodeFunc)motTreeSelectRangeFunc, &range);
+}
+
+void motTreeExpandCollapseAllNodes(Ihandle* ih, WidgetList itemList, int numItems, unsigned char itemState)
+{
+ WidgetList itemChildList;
+ int numChild;
+ int i = 0;
+
+ while(i != numItems)
+ {
+ /* Check whether we have child items */
+ itemChildList = NULL;
+ numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+
+ if(numChild)
+ {
+ XtVaSetValues(itemList[i], XmNoutlineState, itemState, NULL);
+ motTreeExpandCollapseAllNodes(ih, itemChildList, numChild, itemState);
+ }
+
+ if (itemChildList) XtFree((char*)itemChildList);
+ /* Go to next sibling item */
+ i++;
+ }
+}
+
+static void motTreeDestroyItemData(Ihandle* ih, Widget wItem)
+{
+ motTreeItemData *itemData = NULL;
+ XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
+ if (itemData)
+ {
+ IFnis cb = (IFnis)IupGetCallback(ih, "NODEREMOVED_CB");
+ if (cb) cb(ih, motTreeGetNodeId(ih, wItem), (char*)itemData->userdata);
+ free(itemData);
+ XtVaSetValues(wItem, XmNuserData, NULL, NULL);
+ }
+}
+
+static void motTreeRemoveChildren(Ihandle* ih, WidgetList itemList, int numItems, int del_userdata)
+{
+ WidgetList itemChildList;
+ int numChild;
+ int i = 0;
+
+ while(i != numItems)
+ {
+ /* Check whether we have child items */
+ itemChildList = NULL;
+ numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+ if (numChild)
+ motTreeRemoveChildren(ih, itemChildList, numChild, del_userdata);
+
+ if (del_userdata)
+ motTreeDestroyItemData(ih, itemList[i]);
+
+ XtDestroyWidget(itemList[i]);
+
+ if (itemChildList) XtFree((char*)itemChildList);
+ /* Go to next sibling item */
+ i++;
+ }
+}
+
+static void motTreeRemoveNode(Ihandle* ih, Widget wItem, int del_userdata)
+{
+ WidgetList wChildList = NULL;
+ int numChild = XmContainerGetItemChildren(ih->handle, wItem, &wChildList);
+ if (numChild)
+ motTreeRemoveChildren(ih, wChildList, numChild, del_userdata);
+ if (del_userdata)
+ motTreeDestroyItemData(ih, wItem);
+ XtDestroyWidget(wItem);
+ if (wChildList) XtFree((char*)wChildList);
+}
+
+static Widget motTreeFindNodeID(Ihandle* ih, WidgetList itemList, int numItems, Widget itemNode)
+{
+ Widget itemChild;
+ WidgetList itemChildList;
+ int i = 0;
+ int numChild;
+
+ while(i != numItems)
+ {
+ /* ID control to traverse items */
+ ih->data->id_control++;
+
+ /* StateID founded! */
+ if(itemList[i] == itemNode)
+ return itemList[i];
+
+ /* Check whether we have child items */
+ itemChildList = NULL;
+ numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+ if(numChild)
+ {
+ /* pass the list of children of this item */
+ itemChild = motTreeFindNodeID(ih, itemChildList, numChild, itemNode);
+
+ /* StateID founded! */
+ if(itemChild)
+ {
+ if (itemChildList) XtFree((char*)itemChildList);
+ return itemChild;
+ }
+ }
+
+ if (itemChildList) XtFree((char*)itemChildList);
+ /* Go to next sibling item */
+ i++;
+ }
+
+ return NULL;
+}
+
+static Widget motTreeFindNodeFromID(Ihandle* ih, WidgetList itemList, int numItems)
+{
+ Widget itemChild;
+ WidgetList itemChildList;
+ int i = 0;
+ int numChild;
+
+ while(i != numItems)
+ {
+ /* ID control to traverse items */
+ ih->data->id_control--;
+
+ /* StateID founded! */
+ if(ih->data->id_control < 0)
+ return itemList[i];
+
+ /* Check whether we have child items */
+ itemChildList = NULL;
+ numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+ if(numChild)
+ {
+ /* pass the list of children of this item */
+ itemChild = motTreeFindNodeFromID(ih, itemChildList, numChild);
+
+ /* StateID founded! */
+ if(ih->data->id_control < 0)
+ {
+ if (itemChildList) XtFree((char*)itemChildList);
+ return itemChild;
+ }
+ }
+
+ if (itemChildList) XtFree((char*)itemChildList);
+ /* Go to next sibling item */
+ i++;
+ }
+
+ return NULL;
+}
+
+static int motTreeGetNodeId(Ihandle* ih, Widget wItem)
+{
+ Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+ ih->data->id_control = -1;
+ if (motTreeFindNodeID(ih, &wRoot, 1, wItem))
+ return ih->data->id_control;
+ else
+ return -1;
+}
+
+static Widget motTreeFindUserDataID(Ihandle* ih, WidgetList itemList, int numItems, void* userdata)
+{
+ Widget itemChild;
+ WidgetList itemChildList;
+ motTreeItemData *itemData;
+ int i = 0;
+ int numChild;
+
+ while(i != numItems)
+ {
+ /* ID control to traverse items */
+ ih->data->id_control++;
+
+ XtVaGetValues(itemList[i], XmNuserData, &itemData, NULL);
+
+ /* StateID founded! */
+ if(itemData->userdata == userdata)
+ return itemList[i];
+
+ /* Check whether we have child items */
+ itemChildList = NULL;
+ numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+ if(numChild)
+ {
+ /* pass the list of children of this item */
+ itemChild = motTreeFindUserDataID(ih, itemChildList, numChild, userdata);
+
+ /* StateID founded! */
+ if (itemChild)
+ {
+ if (itemChildList) XtFree((char*)itemChildList);
+ return itemChild;
+ }
+ }
+
+ if (itemChildList) XtFree((char*)itemChildList);
+ /* Go to next sibling item */
+ i++;
+ }
+
+ return NULL;
+}
+
+static int motTreeGetUserDataId(Ihandle* ih, void* userdata)
+{
+ Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+ ih->data->id_control = -1;
+ if (motTreeFindUserDataID(ih, &wRoot, 1, userdata))
+ return ih->data->id_control;
+ else
+ return -1;
+}
+
+static void motTreeSetFocusNode(Ihandle* ih, Widget wItem)
+{
+ iupAttribSetStr(ih, "_IUPTREE_LAST_FOCUS", (char*)wItem);
+ XmProcessTraversal(wItem, XmTRAVERSE_CURRENT);
+}
+
+static Widget motTreeGetFocusNode(Ihandle* ih)
+{
+ Widget wItem = XmGetFocusWidget(ih->handle); /* returns the focus in the dialog */
+ if (wItem && XtParent(wItem) == ih->handle) /* is a node */
+ return wItem;
+
+ return (Widget)iupAttribGet(ih, "_IUPTREE_LAST_FOCUS");
+}
+
+static Widget motTreeFindNodeFromString(Ihandle* ih, const char* name_id)
+{
+ if (name_id[0])
+ {
+ Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+ iupStrToInt(name_id, &ih->data->id_control);
+ return motTreeFindNodeFromID(ih, &wRoot, 1);
+ }
+ else
+ return motTreeGetFocusNode(ih);
+}
+
+static void motTreeEnterLeaveWindowEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont)
+{
+ if (iupAttribGet(ih, "_IUPTREE_EDITFIELD"))
+ return;
+
+ /* usually when one Gadget is selected different than the previous one,
+ leave/enter events are generated. But we could not find the exact condition,
+ so this is a workaround. Some leave events will be lost. */
+ if (evt->type == EnterNotify)
+ {
+ if (iupAttribGet(ih, "_IUPTREE_IGNORE_ENTERLEAVE"))
+ {
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_ENTERLEAVE", NULL);
+ return;
+ }
+ }
+ else if (evt->type == LeaveNotify)
+ {
+ if (iupAttribGet(ih, "_IUPTREE_IGNORE_ENTERLEAVE"))
+ return;
+ }
+
+ iupmotEnterLeaveWindowEvent(w, ih, evt, cont);
+}
+
+static void motTreeFocusChangeEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont)
+{
+ unsigned char selpol;
+ Widget wItem = XmGetFocusWidget(w); /* returns the focus in the dialog */
+ Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+
+ if (XtParent(wItem) == w) /* is a node */
+ iupAttribSetStr(ih, "_IUPTREE_LAST_FOCUS", (char*)wItem);
+
+ if (wItem == NULL || wItem == wRoot)
+ {
+ iupmotFocusChangeEvent(w, ih, evt, cont);
+ return;
+ }
+
+ XtVaGetValues(w, XmNselectionPolicy, &selpol, NULL);
+ if (selpol != XmSINGLE_SELECT)
+ return;
+
+ if (evt->type == FocusIn && !iupStrBoolean(IupGetGlobal("CONTROLKEY")))
+ {
+ XtVaSetValues(w, XmNselectedObjects, NULL, NULL);
+ XtVaSetValues(w, XmNselectedObjectCount, 0, NULL);
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
+ }
+}
+
+void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* title, int add)
+{
+ Widget wItemPrev = motTreeFindNodeFromString(ih, name_id);
+ Widget wNewItem;
+ XmString itemTitle;
+ motTreeItemData *itemData, *itemDataPrev;
+ Pixel bgcolor, fgcolor;
+ int kindPrev, num_args = 0;
+ Arg args[30];
+
+ if (!wItemPrev)
+ return;
+
+ itemData = calloc(1, sizeof(motTreeItemData));
+ itemData->image = XmUNSPECIFIED_PIXMAP;
+ itemData->image_expanded = XmUNSPECIFIED_PIXMAP;
+ itemData->image_mask = XmUNSPECIFIED_PIXMAP;
+ itemData->image_expanded_mask = XmUNSPECIFIED_PIXMAP;
+ itemData->kind = (unsigned char)kind;
+
+ itemTitle = XmStringCreateLocalized((String)title);
+
+ /* Get default colors */
+ XtVaGetValues(ih->handle, XmNforeground, &fgcolor, NULL);
+ XtVaGetValues(ih->handle, XmNbackground, &bgcolor, NULL);
+
+ /* Get the kind of previous item */
+ XtVaGetValues(wItemPrev, XmNuserData, &itemDataPrev, NULL);
+ kindPrev = itemDataPrev->kind;
+
+ if (kindPrev == ITREE_BRANCH && add)
+ {
+ /* wItemPrev is parent of the new item (firstchild of it) */
+ iupmotSetArg(args, num_args, XmNentryParent, wItemPrev);
+ iupmotSetArg(args, num_args, XmNpositionIndex, 0);
+ }
+ else
+ {
+ /* wItemPrev is sibling of the new item (set its parent to the new item) */
+ Widget wItemParent;
+ int pos;
+
+ XtVaGetValues(wItemPrev, XmNentryParent, &wItemParent, NULL);
+ XtVaGetValues(wItemPrev, XmNpositionIndex, &pos, NULL);
+
+ iupmotSetArg(args, num_args, XmNentryParent, wItemParent);
+ iupmotSetArg(args, num_args, XmNpositionIndex, pos+1);
+ }
+
+ iupmotSetArg(args, num_args, XmNuserData, itemData);
+ iupmotSetArg(args, num_args, XmNforeground, fgcolor);
+ iupmotSetArg(args, num_args, XmNbackground, bgcolor);
+ iupmotSetArg(args, num_args, XmNmarginHeight, ih->data->spacing);
+ iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+ iupmotSetArg(args, num_args, XmNviewType, XmSMALL_ICON);
+ iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+ iupmotSetArg(args, num_args, XmNlabelString, itemTitle);
+
+ if (kind == ITREE_BRANCH)
+ {
+ if (ih->data->add_expanded)
+ {
+ iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_expanded);
+ iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_expanded_mask);
+ }
+ else
+ {
+ iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_collapsed);
+ iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_collapsed_mask);
+ }
+ }
+ else
+ {
+ iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_leaf);
+ iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_leaf_mask);
+ }
+
+
+ wNewItem = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args);
+
+ if (kind == ITREE_BRANCH)
+ {
+ if (ih->data->add_expanded)
+ {
+ iupAttribSetStr(ih, "_IUP_IGNORE_BRANCHOPEN", "1");
+ XtVaSetValues(wNewItem, XmNoutlineState, XmEXPANDED, NULL);
+ }
+ else
+ XtVaSetValues(wNewItem, XmNoutlineState, XmCOLLAPSED, NULL);
+ }
+
+ /* Root always expanded */
+ XtVaSetValues((Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"), XmNoutlineState, XmEXPANDED, NULL);
+
+ XtRealizeWidget(wNewItem);
+ XmStringFree(itemTitle);
+}
+
+static void motTreeAddRootNode(Ihandle* ih)
+{
+ Widget wRootItem;
+ motTreeItemData *itemData;
+ Pixel bgcolor, fgcolor;
+ int num_args = 0;
+ Arg args[30];
+
+ itemData = calloc(1, sizeof(motTreeItemData));
+ itemData->image = XmUNSPECIFIED_PIXMAP;
+ itemData->image_expanded = XmUNSPECIFIED_PIXMAP;
+ itemData->image_mask = XmUNSPECIFIED_PIXMAP;
+ itemData->image_expanded_mask = XmUNSPECIFIED_PIXMAP;
+ itemData->kind = ITREE_BRANCH;
+
+ /* Get default foreground color */
+ XtVaGetValues(ih->handle, XmNforeground, &fgcolor, NULL);
+ XtVaGetValues(ih->handle, XmNbackground, &bgcolor, NULL);
+
+ iupmotSetArg(args, num_args, XmNentryParent, NULL);
+ iupmotSetArg(args, num_args, XmNuserData, itemData);
+ iupmotSetArg(args, num_args, XmNforeground, fgcolor);
+ iupmotSetArg(args, num_args, XmNbackground, bgcolor);
+ iupmotSetArg(args, num_args, XmNoutlineState, XmEXPANDED);
+ iupmotSetArg(args, num_args, XmNmarginHeight, ih->data->spacing);
+ iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+ iupmotSetArg(args, num_args, XmNviewType, XmSMALL_ICON);
+ iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+ iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_expanded);
+ iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_expanded_mask);
+
+ wRootItem = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args);
+
+ /* Select the new item */
+ XtVaSetValues(wRootItem, XmNvisualEmphasis, XmSELECTED, NULL);
+
+ XtRealizeWidget(wRootItem);
+
+ /* Save the root node for later use */
+ iupAttribSetStr(ih, "_IUPTREE_ROOTITEM", (char*)wRootItem);
+
+ /* MarkStart node */
+ iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)wRootItem);
+
+ /* Set the default VALUE */
+ /* In Motif this will set also the current focus */
+ motTreeSetFocusNode(ih, wRootItem);
+}
+
+/*****************************************************************************/
+
+static int motTreeSetImageExpandedAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ motTreeItemData *itemData;
+ unsigned char itemState;
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return 0;
+
+ XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
+ XtVaGetValues(wItem, XmNoutlineState, &itemState, NULL);
+ itemData->image_expanded = (Pixmap)iupImageGetImage(value, ih, 0);
+ if (!itemData->image_expanded)
+ {
+ itemData->image_expanded = XmUNSPECIFIED_PIXMAP;
+ itemData->image_expanded_mask = XmUNSPECIFIED_PIXMAP;
+ }
+ else
+ {
+ itemData->image_expanded_mask = (Pixmap)iupImageGetMask(value);
+ if (!itemData->image_expanded_mask) itemData->image_expanded_mask = XmUNSPECIFIED_PIXMAP;
+ }
+
+ if (itemData->kind == ITREE_BRANCH && itemState == XmEXPANDED)
+ {
+ if (itemData->image_expanded == XmUNSPECIFIED_PIXMAP)
+ XtVaSetValues(wItem, XmNsmallIconPixmap, (Pixmap)ih->data->def_image_expanded,
+ XmNsmallIconMask, (Pixmap)ih->data->def_image_expanded_mask,
+ NULL);
+ else
+ XtVaSetValues(wItem, XmNsmallIconPixmap, itemData->image_expanded,
+ XmNsmallIconMask, itemData->image_expanded_mask,
+ NULL);
+ }
+
+ return 1;
+}
+
+static int motTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ motTreeItemData *itemData;
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return 0;
+
+ XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
+ itemData->image = (Pixmap)iupImageGetImage(value, ih, 0);
+ if (!itemData->image)
+ {
+ itemData->image = XmUNSPECIFIED_PIXMAP;
+ itemData->image_mask = XmUNSPECIFIED_PIXMAP;
+ }
+ else
+ {
+ itemData->image_mask = (Pixmap)iupImageGetMask(value);
+ if (!itemData->image_mask) itemData->image_mask = XmUNSPECIFIED_PIXMAP;
+ }
+
+ if (itemData->kind == ITREE_BRANCH)
+ {
+ unsigned char itemState;
+ XtVaGetValues(wItem, XmNoutlineState, &itemState, NULL);
+ if (itemState == XmCOLLAPSED)
+ {
+ if (itemData->image == XmUNSPECIFIED_PIXMAP)
+ XtVaSetValues(wItem, XmNsmallIconPixmap, (Pixmap)ih->data->def_image_collapsed,
+ XmNsmallIconMask, (Pixmap)ih->data->def_image_collapsed_mask,
+ NULL);
+ else
+ XtVaSetValues(wItem, XmNsmallIconPixmap, itemData->image,
+ XmNsmallIconMask, itemData->image_mask,
+ NULL);
+ }
+ }
+ else
+ {
+ if (itemData->image == XmUNSPECIFIED_PIXMAP)
+ XtVaSetValues(wItem, XmNsmallIconPixmap, (Pixmap)ih->data->def_image_leaf,
+ XmNsmallIconMask, (Pixmap)ih->data->def_image_leaf_mask,
+ NULL);
+ else
+ XtVaSetValues(wItem, XmNsmallIconPixmap, itemData->image,
+ XmNsmallIconMask, itemData->image_mask,
+ NULL);
+ }
+
+ return 1;
+}
+
+static int motTreeSetImageBranchExpandedAttrib(Ihandle* ih, const char* value)
+{
+ Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+ ih->data->def_image_expanded = iupImageGetImage(value, ih, 0);
+ if (!ih->data->def_image_expanded)
+ {
+ ih->data->def_image_expanded = (void*)XmUNSPECIFIED_PIXMAP;
+ ih->data->def_image_expanded_mask = (void*)XmUNSPECIFIED_PIXMAP;
+ }
+ else
+ {
+ ih->data->def_image_expanded_mask = iupImageGetMask(value);
+ if (!ih->data->def_image_expanded_mask) ih->data->def_image_expanded_mask = (void*)XmUNSPECIFIED_PIXMAP;
+ }
+
+ /* Update all images, starting at root node */
+ motTreeUpdateImages(ih, &wRoot, 1, ITREE_UPDATEIMAGE_EXPANDED);
+
+ return 1;
+}
+
+static int motTreeSetImageBranchCollapsedAttrib(Ihandle* ih, const char* value)
+{
+ Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+ ih->data->def_image_collapsed = iupImageGetImage(value, ih, 0);
+ if (!ih->data->def_image_collapsed)
+ {
+ ih->data->def_image_collapsed = (void*)XmUNSPECIFIED_PIXMAP;
+ ih->data->def_image_collapsed_mask = (void*)XmUNSPECIFIED_PIXMAP;
+ }
+ else
+ {
+ ih->data->def_image_collapsed_mask = iupImageGetMask(value);
+ if (!ih->data->def_image_collapsed_mask) ih->data->def_image_collapsed_mask = (void*)XmUNSPECIFIED_PIXMAP;
+ }
+
+ /* Update all images, starting at root node */
+ motTreeUpdateImages(ih, &wRoot, 1, ITREE_UPDATEIMAGE_COLLAPSED);
+
+ return 1;
+}
+
+static int motTreeSetImageLeafAttrib(Ihandle* ih, const char* value)
+{
+ Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+ ih->data->def_image_leaf = iupImageGetImage(value, ih, 0);
+ if (!ih->data->def_image_leaf)
+ {
+ ih->data->def_image_leaf = (void*)XmUNSPECIFIED_PIXMAP;
+ ih->data->def_image_leaf_mask = (void*)XmUNSPECIFIED_PIXMAP;
+ }
+ else
+ {
+ ih->data->def_image_leaf_mask = iupImageGetMask(value);
+ if (!ih->data->def_image_leaf_mask) ih->data->def_image_leaf_mask = (void*)XmUNSPECIFIED_PIXMAP;
+ }
+
+ /* Update all images, starting at root node */
+ motTreeUpdateImages(ih, &wRoot, 1, ITREE_UPDATEIMAGE_LEAF);
+
+ return 1;
+}
+
+static char* motTreeGetStateAttrib(Ihandle* ih, const char* name_id)
+{
+ int hasChildren;
+ unsigned char itemState;
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return 0;
+
+ XtVaGetValues(wItem, XmNnumChildren, &hasChildren, NULL);
+ XtVaGetValues(wItem, XmNoutlineState, &itemState, NULL);
+
+ if (hasChildren)
+ {
+ if(itemState == XmEXPANDED)
+ return "EXPANDED";
+ else
+ return "COLLAPSED";
+ }
+
+ return NULL;
+}
+
+static int motTreeSetStateAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return 0;
+
+ if (iupStrEqualNoCase(value, "EXPANDED"))
+ XtVaSetValues(wItem, XmNoutlineState, XmEXPANDED, NULL);
+ else
+ XtVaSetValues(wItem, XmNoutlineState, XmCOLLAPSED, NULL);
+
+ return 0;
+}
+
+static char* motTreeGetColorAttrib(Ihandle* ih, const char* name_id)
+{
+ unsigned char r, g, b;
+ Pixel color;
+ char* str;
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return NULL;
+
+ XtVaGetValues(wItem, XmNforeground, &color, NULL);
+ iupmotColorGetRGB(color, &r, &g, &b);
+
+ str = iupStrGetMemory(20);
+ sprintf(str, "%d %d %d", (int)r, (int)g, (int)b);
+ return str;
+}
+
+static int motTreeSetColorAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ Pixel color;
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return 0;
+
+ color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ XtVaSetValues(wItem, XmNforeground, color, NULL);
+ return 0;
+}
+
+static char* motTreeGetDepthAttrib(Ihandle* ih, const char* name_id)
+{
+ Widget wRoot;
+ int dep = 0;
+ char* depth;
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return NULL;
+
+ wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+
+ while((wRoot != wItem) && (wItem != NULL))
+ {
+ XtVaGetValues(wItem, XmNentryParent, &wItem, NULL);
+ dep++;
+ }
+
+ depth = iupStrGetMemory(10);
+ sprintf(depth, "%d", dep);
+ return depth;
+}
+
+static int motTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ Widget wItemDst, wParent, wItemSrc;
+
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+ wItemSrc = motTreeFindNodeFromString(ih, name_id);
+ if (!wItemSrc)
+ return 0;
+ wItemDst = motTreeFindNodeFromString(ih, value);
+ if (!wItemDst)
+ return 0;
+
+ /* If Drag item is an ancestor of Drop item then return */
+ wParent = wItemDst;
+ while(wParent)
+ {
+ XtVaGetValues(wParent, XmNentryParent, &wParent, NULL);
+ if (wParent == wItemSrc)
+ return 0;
+ }
+
+ /* Copying the node and its children to the new position */
+ motTreeCopyNode(ih, wItemSrc, wItemDst, 0); /* not a full copy, preserve user data */
+
+ /* Deleting the node (and its children) inserted into the old position */
+ motTreeRemoveNode(ih, wItemSrc, 0); /* do not delete the user data, we copy the references in CopyNode */
+
+ return 0;
+}
+
+static int motTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ Widget wItemDst, wParent, wItemSrc;
+
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+ wItemSrc = motTreeFindNodeFromString(ih, name_id);
+ if (!wItemSrc)
+ return 0;
+ wItemDst = motTreeFindNodeFromString(ih, value);
+ if (!wItemDst)
+ return 0;
+
+ /* If Drag item is an ancestor of Drop item then return */
+ wParent = wItemDst;
+ while(wParent)
+ {
+ XtVaGetValues(wParent, XmNentryParent, &wParent, NULL);
+ if (wParent == wItemSrc)
+ return 0;
+ }
+
+ /* Copying the node and its children to the new position */
+ motTreeCopyNode(ih, wItemSrc, wItemDst, 1);
+
+ return 0;
+}
+
+static char* motTreeGetParentAttrib(Ihandle* ih, const char* name_id)
+{
+ Widget wItemParent;
+ char* str;
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return NULL;
+
+ /* get the parent item */
+ XtVaGetValues(wItem, XmNentryParent, &wItemParent, NULL);
+ if (!wItemParent)
+ return NULL;
+
+ str = iupStrGetMemory(10);
+ sprintf(str, "%d", motTreeGetNodeId(ih, wItemParent));
+ return str;
+}
+
+static char* motTreeGetChildCountAttrib(Ihandle* ih, const char* name_id)
+{
+ char* str;
+ WidgetList wList = NULL;
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return NULL;
+
+ str = iupStrGetMemory(10);
+ sprintf(str, "%d", XmContainerGetItemChildren(ih->handle, wItem, &wList));
+ if (wList) XtFree((char*)wList);
+ return str;
+}
+
+static int motTreeCount(Ihandle* ih, Widget wItem)
+{
+ WidgetList wList = NULL;
+ int i, count = 0;
+ int childCount = XmContainerGetItemChildren(ih->handle, wItem, &wList);
+ count++;
+ for (i=0; i<childCount; i++)
+ count += motTreeCount(ih, wList[i]);
+ if (wList) XtFree((char*)wList);
+ return count;
+}
+
+static char* motTreeGetCountAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(10);
+ Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+ sprintf(str, "%d", motTreeCount(ih, wRoot));
+ return str;
+}
+
+static char* motTreeGetKindAttrib(Ihandle* ih, const char* name_id)
+{
+ motTreeItemData *itemData;
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return NULL;
+
+ XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
+
+ if(itemData->kind == ITREE_BRANCH)
+ return "BRANCH";
+ else
+ return "LEAF";
+}
+
+static char* motTreeGetValueAttrib(Ihandle* ih)
+{
+ char* str;
+ Widget wItem = motTreeGetFocusNode(ih);
+ if (!wItem)
+ return "0"; /* default VALUE is root */
+
+ str = iupStrGetMemory(10);
+ sprintf(str, "%d", motTreeGetNodeId(ih, wItem));
+ return str;
+}
+
+static int motTreeSetMarkAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->mark_mode==ITREE_MARK_SINGLE)
+ return 0;
+
+ if(iupStrEqualNoCase(value, "CLEARALL"))
+ motTreeContainerDeselectAll(ih);
+ else if(iupStrEqualNoCase(value, "MARKALL"))
+ motTreeContainerSelectAll(ih);
+ else if(iupStrEqualNoCase(value, "INVERTALL")) /* INVERTALL *MUST* appear before INVERT, or else INVERTALL will never be called. */
+ motTreeInvertAllNodeMarking(ih);
+ else if(iupStrEqualPartial(value, "INVERT"))
+ {
+ unsigned char isSelected;
+ Widget wItem = motTreeFindNodeFromString(ih, &value[strlen("INVERT")]);
+ if (!wItem)
+ return 0;
+
+ XtVaGetValues(wItem, XmNvisualEmphasis, &isSelected, NULL);
+ if (isSelected == XmSELECTED)
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
+ else
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
+ }
+ else if(iupStrEqualNoCase(value, "BLOCK"))
+ {
+ Widget wItem = (Widget)iupAttribGet(ih, "_IUPTREE_MARKSTART_NODE");
+ Widget wFocusItem = motTreeGetFocusNode(ih);
+ if(!wFocusItem || !wItem)
+ return 0;
+ motTreeSelectRange(ih, wFocusItem, wItem, 0);
+ }
+ else
+ {
+ Widget wItem1, wItem2;
+ char str1[50], str2[50];
+ if (iupStrToStrStr(value, str1, str2, '-')!=2)
+ return 0;
+
+ wItem1 = motTreeFindNodeFromString(ih, str1);
+ if (!wItem1)
+ return 0;
+ wItem2 = motTreeFindNodeFromString(ih, str2);
+ if (!wItem2)
+ return 0;
+
+ motTreeSelectRange(ih, wItem1, wItem2, 0);
+ }
+
+ return 1;
+}
+
+static int motTreeSetValueAttrib(Ihandle* ih, const char* value)
+{
+ Widget wRoot, wItem;
+
+ if (motTreeSetMarkAttrib(ih, value))
+ return 0;
+
+ wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+
+ if (iupStrEqualNoCase(value, "ROOT"))
+ wItem = wRoot;
+ else if(iupStrEqualNoCase(value, "LAST"))
+ wItem = motTreeGetLastVisibleNode(ih, wRoot);
+ else if(iupStrEqualNoCase(value, "PGUP"))
+ {
+ Widget wItemFocus = motTreeGetFocusNode(ih);
+ if(!wItemFocus)
+ return 0;
+
+ ih->data->id_control = -1;
+ motTreeFindVisibleNodeId(ih, &wRoot, 1, wItemFocus);
+ ih->data->id_control -= 10; /* less 10 visible nodes */
+
+ if(ih->data->id_control < 0)
+ ih->data->id_control = 0; /* Begin of tree = Root id */
+
+ wItem = motTreeFindVisibleNodeFromId(ih, &wRoot, 1);
+ }
+ else if(iupStrEqualNoCase(value, "PGDN"))
+ {
+ Widget wNext, wItemFocus;
+
+ wItemFocus = motTreeGetFocusNode(ih);
+ if(!wItemFocus)
+ return 0;
+
+ ih->data->id_control = -1;
+ motTreeFindVisibleNodeId(ih, &wRoot, 1, wItemFocus);
+ ih->data->id_control += 10; /* more 10 visible nodes */
+
+ wNext = motTreeFindVisibleNodeFromId(ih, &wRoot, 1);
+
+ if (ih->data->id_control >= 0)
+ wNext = motTreeGetLastVisibleNode(ih, wRoot);
+
+ wItem = wNext;
+ }
+ else if(iupStrEqualNoCase(value, "NEXT"))
+ {
+ Widget wItemFocus = motTreeGetFocusNode(ih);
+ if (!wItemFocus)
+ return 0;
+
+ wItem = motTreeGetNextVisibleNode(ih, wRoot, wItemFocus);
+ }
+ else if(iupStrEqualNoCase(value, "PREVIOUS"))
+ {
+ Widget wItemFocus = motTreeGetFocusNode(ih);
+ if(!wItemFocus)
+ return 0;
+
+ wItem = motTreeGetPreviousVisibleNode(ih, wRoot, wItemFocus);
+ }
+ else
+ wItem = motTreeFindNodeFromString(ih, value);
+
+ if (!wItem)
+ return 0;
+
+ /* select */
+ if (ih->data->mark_mode==ITREE_MARK_SINGLE)
+ {
+ /* clear previous selection */
+ XtVaSetValues(ih->handle, XmNselectedObjects, NULL, NULL);
+ XtVaSetValues(ih->handle, XmNselectedObjectCount, 0, NULL);
+
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
+ }
+
+ /* set focus (will scroll to visible) */
+ motTreeSetFocusNode(ih, wItem);
+
+ iupAttribSetInt(ih, "_IUPTREE_OLDVALUE", motTreeGetNodeId(ih, wItem));
+
+ return 0;
+}
+
+static int motTreeSetMarkStartAttrib(Ihandle* ih, const char* name_id)
+{
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return 0;
+
+ iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)wItem);
+
+ return 1;
+}
+
+static char* motTreeGetMarkedAttrib(Ihandle* ih, const char* name_id)
+{
+ unsigned char isSelected;
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return NULL;
+
+ XtVaGetValues(wItem, XmNvisualEmphasis, &isSelected, NULL);
+
+ if(isSelected == XmSELECTED)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int motTreeSetMarkedAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return 0;
+
+ if (iupStrBoolean(value))
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
+ else
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
+
+ return 0;
+}
+
+static char* motTreeGetTitle(Widget wItem)
+{
+ char *title;
+ XmString itemTitle;
+ XtVaGetValues(wItem, XmNlabelString, &itemTitle, NULL);
+ title = iupmotConvertString(itemTitle);
+ XmStringFree(itemTitle);
+ return title;
+}
+
+static char* motTreeGetTitleAttrib(Ihandle* ih, const char* name_id)
+{
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return NULL;
+ return motTreeGetTitle(wItem);
+}
+
+static int motTreeSetTitleAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return 0;
+
+ iupmotSetString(wItem, XmNlabelString, value);
+
+ return 0;
+}
+
+static int motTreeSetTitleFontAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ XmFontList fontlist = NULL;
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return 0;
+
+ if (value)
+ {
+ char attr[20];
+ sprintf(attr, "TITLEFOUNDRY%s", name_id);
+ fontlist = iupmotGetFontList(iupAttribGet(ih, attr), value);
+ }
+ XtVaSetValues(wItem, XmNrenderTable, fontlist, NULL);
+
+ return 0;
+}
+
+static char* motTreeGetTitleFontAttrib(Ihandle* ih, const char* name_id)
+{
+ XmFontList fontlist;
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return NULL;
+
+ XtVaGetValues(wItem, XmNrenderTable, &fontlist, NULL);
+ return iupmotFindFontList(fontlist);
+}
+
+static char* motTreeGetFindUserDataAttrib(Ihandle* ih, const char* name_id)
+{
+ int id;
+ char* str = (char*)(name_id+1); /* skip ':' */
+ void* userdata = NULL;
+ if (sscanf(str, "%p", &userdata)!=1)
+ return NULL;
+ id = motTreeGetUserDataId(ih, userdata);
+ if (id == -1)
+ return NULL;
+ str = iupStrGetMemory(16);
+ sprintf(str, "%d", id);
+ return str;
+}
+
+static char* motTreeGetUserDataAttrib(Ihandle* ih, const char* name_id)
+{
+ motTreeItemData *itemData;
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return NULL;
+
+ XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
+
+ return itemData->userdata;
+}
+
+static int motTreeSetUserDataAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ motTreeItemData *itemData;
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ if (!wItem)
+ return 0;
+
+ XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
+ itemData->userdata = (void*)value;
+
+ return 0;
+}
+
+static int motTreeSetRenameAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->show_rename)
+ {
+ IFni cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB");
+ Widget wItemFocus = motTreeGetFocusNode(ih);
+ if (cbShowRename)
+ cbShowRename(ih, motTreeGetNodeId(ih, wItemFocus));
+ motTreeShowEditField(ih, wItemFocus);
+ }
+ else
+ {
+ IFnis cbRenameNode = (IFnis)IupGetCallback(ih, "RENAMENODE_CB");
+ if (cbRenameNode)
+ {
+ Widget wItemFocus = motTreeGetFocusNode(ih);
+ cbRenameNode(ih, motTreeGetNodeId(ih, wItemFocus), motTreeGetTitle(wItemFocus));
+ }
+ }
+
+ (void)value;
+ return 0;
+}
+
+static int motTreeSetDelNodeAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+ if(iupStrEqualNoCase(value, "SELECTED")) /* selected here means the specified one */
+ {
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+
+ /* the root node can't be deleted */
+ if(!wItem || wItem == wRoot) /* root is the unique child */
+ return 0;
+
+ /* deleting the specified node (and it's children) */
+ motTreeRemoveNode(ih, wItem, 1);
+ }
+ else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the specified one */
+ {
+ Widget wItem = motTreeFindNodeFromString(ih, name_id);
+
+ if(!wItem)
+ return 0;
+
+ {
+ /* deleting the selected node's children only */
+ WidgetList wItemList = NULL;
+ int numChild = XmContainerGetItemChildren(ih->handle, wItem, &wItemList);
+ if(numChild)
+ motTreeRemoveChildren(ih, wItemList, numChild, 1);
+ if (wItemList) XtFree((char*)wItemList);
+ }
+ }
+ else if(iupStrEqualNoCase(value, "MARKED")) /* Delete the array of marked nodes */
+ {
+ WidgetList wSelectedItemList = NULL;
+ Widget wRoot;
+ int countItems, i;
+
+ XtVaGetValues(ih->handle, XmNselectedObjects, &wSelectedItemList,
+ XmNselectedObjectCount, &countItems, NULL);
+
+ wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+
+ for(i = 0; i < countItems; i++)
+ {
+ int ok = XmIsIconGadget(wSelectedItemList[i]);
+ if ((wSelectedItemList[i] != wRoot) && ok) /* the root node can't be deleted */
+ motTreeRemoveNode(ih, wSelectedItemList[i], 1);
+ }
+ }
+
+ return 0;
+}
+
+static char* motTreeGetIndentationAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(255);
+ Dimension indent;
+ XtVaGetValues(ih->handle, XmNoutlineIndentation, &indent, NULL);
+ sprintf(str, "%d", (int)indent);
+ return str;
+}
+
+static int motTreeSetIndentationAttrib(Ihandle* ih, const char* value)
+{
+ int indent;
+ if (iupStrToInt(value, &indent))
+ XtVaSetValues(ih->handle, XmNoutlineIndentation, (Dimension)indent, NULL);
+ return 0;
+}
+
+static int motTreeSetTopItemAttrib(Ihandle* ih, const char* value)
+{
+ Widget wItem = motTreeFindNodeFromString(ih, value);
+ Widget sb_win;
+ Widget wItemParent;
+
+ if (!wItem)
+ return 0;
+
+ /* expand all parents */
+ XtVaGetValues(wItem, XmNentryParent, &wItemParent, NULL);
+ while(wItemParent)
+ {
+ XtVaSetValues(wItemParent, XmNoutlineState, XmEXPANDED, NULL);
+ XtVaGetValues(wItemParent, XmNentryParent, &wItemParent, NULL);
+ }
+
+ sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ XmScrollVisible(sb_win, wItem, 0, 0);
+
+ return 0;
+}
+
+static int motTreeSpacingFunc(Ihandle* ih, Widget wItem, void *data)
+{
+ XtVaSetValues(wItem, XmNmarginHeight, ih->data->spacing, NULL);
+ (void)data;
+ return 1;
+}
+
+static int motTreeSetSpacingAttrib(Ihandle* ih, const char* value)
+{
+ if (!iupStrToInt(value, &ih->data->spacing))
+ ih->data->spacing = 1;
+
+ if (ih->data->spacing < 1)
+ ih->data->spacing = 1;
+
+ if (ih->handle)
+ {
+ motTreeForEach(ih, NULL, (motTreeNodeFunc)motTreeSpacingFunc, 0);
+ return 0;
+ }
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
+}
+
+static int motTreeSetExpandAllAttrib(Ihandle* ih, const char* value)
+{
+ Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+
+ if (iupStrBoolean(value))
+ motTreeExpandCollapseAllNodes(ih, &wRoot, 1, XmEXPANDED);
+ else
+ {
+ motTreeExpandCollapseAllNodes(ih, &wRoot, 1, XmCOLLAPSED);
+
+ /* The root node is always expanded */
+ XtVaSetValues((Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"), XmNoutlineState, XmEXPANDED, NULL);
+ }
+
+ return 0;
+}
+
+static int motTreeSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ Widget sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ Pixel color;
+
+ /* ignore given value for the scrollbars, must use only from parent */
+ char* parent_value = iupBaseNativeParentGetBgColor(ih);
+
+ color = iupmotColorGetPixelStr(parent_value);
+ if (color != (Pixel)-1)
+ {
+ Widget sb = NULL;
+
+ iupmotSetBgColor(sb_win, color);
+
+ XtVaGetValues(sb_win, XmNverticalScrollBar, &sb, NULL);
+ if (sb) iupmotSetBgColor(sb, color);
+
+ XtVaGetValues(sb_win, XmNhorizontalScrollBar, &sb, NULL);
+ if (sb) iupmotSetBgColor(sb, color);
+ }
+
+ color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ {
+ Widget wRoot;
+ Widget clipwin = NULL;
+
+ XtVaGetValues(sb_win, XmNclipWindow, &clipwin, NULL);
+ if (clipwin) iupmotSetBgColor(clipwin, color);
+
+ wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+
+ /* Update all children, starting at root node */
+ motTreeUpdateBgColor(ih, &wRoot, 1, color);
+ }
+
+ iupdrvBaseSetBgColorAttrib(ih, value); /* use given value for contents */
+
+ /* update internal image cache */
+ iupTreeUpdateImages(ih);
+
+ return 1;
+}
+
+static int motTreeSetFgColorAttrib(Ihandle* ih, const char* value)
+{
+ Pixel color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ XtVaSetValues(ih->handle, XmNforeground, color, NULL);
+
+ return 1;
+}
+
+void iupdrvTreeUpdateMarkMode(Ihandle *ih)
+{
+ XtVaSetValues(ih->handle, XmNselectionPolicy, (ih->data->mark_mode==ITREE_MARK_SINGLE)? XmSINGLE_SELECT: XmEXTENDED_SELECT, NULL);
+}
+
+/************************************************************************************************/
+
+
+static void motTreeSetRenameCaretPos(Widget cbEdit, const char* value)
+{
+ int pos = 1;
+
+ if (iupStrToInt(value, &pos))
+ {
+ if (pos < 1) pos = 1;
+ pos--; /* IUP starts at 1 */
+
+ XtVaSetValues(cbEdit, XmNcursorPosition, pos, NULL);
+ }
+}
+
+static void motTreeSetRenameSelectionPos(Widget cbEdit, const char* value)
+{
+ int start = 1, end = 1;
+
+ if (iupStrToIntInt(value, &start, &end, ':') != 2)
+ return;
+
+ if(start < 1 || end < 1)
+ return;
+
+ start--; /* IUP starts at 1 */
+ end--;
+
+ XmTextSetSelection(cbEdit, start, end, CurrentTime);
+}
+
+/*****************************************************************************/
+
+static int motTreeCallBranchCloseCb(Ihandle* ih, Widget wItem)
+{
+ IFni cbBranchClose = (IFni)IupGetCallback(ih, "BRANCHCLOSE_CB");
+
+ if(cbBranchClose)
+ return cbBranchClose(ih, motTreeGetNodeId(ih, wItem));
+
+ return IUP_DEFAULT;
+}
+
+static int motTreeCallBranchOpenCb(Ihandle* ih, Widget wItem)
+{
+ IFni cbBranchOpen;
+
+ if (iupAttribGet(ih, "_IUP_IGNORE_BRANCHOPEN"))
+ {
+ iupAttribSetStr(ih, "_IUP_IGNORE_BRANCHOPEN", NULL);
+ return IUP_DEFAULT;
+ }
+
+ cbBranchOpen = (IFni)IupGetCallback(ih, "BRANCHOPEN_CB");
+ if (cbBranchOpen)
+ return cbBranchOpen(ih, motTreeGetNodeId(ih, wItem));
+
+ return IUP_DEFAULT;
+}
+
+static void motTreeCallMultiSelectionCb(Ihandle* ih)
+{
+ IFnIi cbMulti = (IFnIi)IupGetCallback(ih, "MULTISELECTION_CB");
+ IFnii cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB");
+ WidgetList wSelectedItemList = NULL;
+ Widget wRoot;
+ int countItems;
+
+ wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+
+ XtVaGetValues(ih->handle, XmNselectedObjects, &wSelectedItemList,
+ XmNselectedObjectCount, &countItems, NULL);
+ if (countItems == 0)
+ return;
+
+ if (cbMulti || cbSelec)
+ {
+ int* id_rowItem = malloc(sizeof(int) * countItems);
+ int i = 0;
+
+ for(i = 0; i < countItems; i++)
+ id_rowItem[i] = motTreeGetNodeId(ih, wSelectedItemList[i]);
+
+ if (cbMulti)
+ cbMulti(ih, id_rowItem, countItems);
+ else
+ {
+ for (i=0; i<countItems; i++)
+ cbSelec(ih, id_rowItem[i], 1);
+ }
+
+ free(id_rowItem);
+ }
+}
+
+static int motTreeConvertXYToPos(Ihandle* ih, int x, int y)
+{
+ Widget wItem = XmObjectAtPoint(ih->handle, (Position)x, (Position)y);
+ if (wItem)
+ return motTreeGetNodeId(ih, wItem);
+ return -1;
+}
+
+static void motTreeCallRightClickCb(Ihandle* ih, int x, int y)
+{
+ IFni cbRightClick = (IFni)IupGetCallback(ih, "RIGHTCLICK_CB");
+ if (cbRightClick)
+ {
+ int id = motTreeConvertXYToPos(ih, x, y);
+ if (id != -1)
+ cbRightClick(ih, id);
+ }
+}
+
+static void motTreeCallRenameCb(Ihandle* ih)
+{
+ IFnis cbRename;
+ Widget wItem, wEdit;
+ int ignore = 0;
+ String title = NULL;
+
+ wItem = (Widget)iupAttribGet(ih, "_IUPTREE_SELECTED");
+ wEdit = (Widget)iupAttribGet(ih, "_IUPTREE_EDITFIELD");
+
+ XtVaGetValues((Widget)iupAttribGet(ih, "_IUPTREE_EDITFIELD"), XmNvalue, &title, NULL);
+
+ cbRename = (IFnis)IupGetCallback(ih, "RENAME_CB");
+ if (cbRename)
+ {
+ if (cbRename(ih, motTreeGetNodeId(ih, wItem), title) == IUP_IGNORE)
+ ignore = 1;
+ }
+
+ if (!ignore)
+ iupmotSetString(wItem, XmNlabelString, title);
+
+ XtDestroyWidget(wEdit);
+
+ iupAttribSetStr(ih, "_IUPTREE_EDITFIELD", NULL);
+ iupAttribSetStr(ih, "_IUPTREE_SELECTED", NULL);
+}
+
+static int motTreeCallDragDropCb(Ihandle* ih, Widget wItemDrag, Widget wItemDrop, int *is_ctrl)
+{
+ IFniiii cbDragDrop = (IFniiii)IupGetCallback(ih, "DRAGDROP_CB");
+ int is_shift = 0;
+ char key[5];
+ iupdrvGetKeyState(key);
+ if (key[0] == 'S')
+ is_shift = 1;
+ if (key[1] == 'C')
+ *is_ctrl = 1;
+ else
+ *is_ctrl = 0;
+
+ if (cbDragDrop)
+ {
+ int drag_id = motTreeGetNodeId(ih, wItemDrag);
+ int drop_id = motTreeGetNodeId(ih, wItemDrop);
+ return cbDragDrop(ih, drag_id, drop_id, is_shift, *is_ctrl);
+ }
+
+ return IUP_CONTINUE; /* allow to move by default if callback not defined */
+}
+
+static void motTreeEditFocusChangeEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont)
+{
+ if (evt->type == FocusOut)
+ motTreeCallRenameCb(ih);
+
+ (void)cont;
+ (void)w;
+}
+
+static void motTreeEditKeyPressEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean *cont)
+{
+ KeySym motcode = XKeycodeToKeysym(iupmot_display, evt->keycode, 0);
+ if (motcode == XK_Return)
+ {
+ Widget wItem = (Widget)iupAttribGet(ih, "_IUPTREE_SELECTED");
+ motTreeCallRenameCb(ih);
+ motTreeSetFocusNode(ih, wItem);
+ }
+ else if (motcode == XK_Escape)
+ {
+ Widget wEdit = (Widget)iupAttribGet(ih, "_IUPTREE_EDITFIELD");
+ Widget wItem = (Widget)iupAttribGet(ih, "_IUPTREE_SELECTED");
+
+ XtDestroyWidget(wEdit);
+ motTreeSetFocusNode(ih, wItem);
+
+ iupAttribSetStr(ih, "_IUPTREE_EDITFIELD", NULL);
+ iupAttribSetStr(ih, "_IUPTREE_SELECTED", NULL);
+ }
+
+ (void)cont;
+ (void)w;
+}
+
+static void motTreeScrollbarOffset(Widget sb_win, Position *x, Position *y)
+{
+ Widget sb_horiz, sb_vert;
+ XtVaGetValues(sb_win, XmNhorizontalScrollBar, &sb_horiz, NULL);
+ if (sb_horiz)
+ {
+ int pos;
+ XtVaGetValues(sb_horiz, XmNvalue, &pos, NULL);
+ *x = *x - (Position)pos;
+ }
+ XtVaGetValues(sb_win, XmNverticalScrollBar, &sb_vert, NULL);
+ if (sb_vert)
+ {
+ int pos;
+ XtVaGetValues(sb_vert, XmNvalue, &pos, NULL);
+ *y = *y - (Position)pos;
+ }
+}
+
+static void motTreeShowEditField(Ihandle* ih, Widget wItem)
+{
+ int num_args = 0, w_img = 0;
+ Arg args[30];
+ Position x, y;
+ Dimension w, h;
+ char* child_id = iupDialogGetChildIdStr(ih);
+ Widget cbEdit;
+ XmString title;
+ char* value;
+ Pixel color;
+ Pixmap image = XmUNSPECIFIED_PIXMAP;
+ XmFontList fontlist;
+ Widget sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+
+ XtVaGetValues(wItem, XmNx, &x,
+ XmNy, &y,
+ XmNwidth, &w,
+ XmNheight, &h,
+ XmNlabelString, &title,
+ XmNsmallIconPixmap, &image,
+ XmNforeground, &color,
+ XmNrenderTable, &fontlist,
+ NULL);
+
+ motTreeScrollbarOffset(sb_win, &x, &y);
+ iupdrvImageGetInfo((void*)image, &w_img, NULL, NULL);
+ w_img += 3; /* add some room for borders */
+
+ iupmotSetArg(args, num_args, XmNx, x+w_img); /* x-position */
+ iupmotSetArg(args, num_args, XmNy, y); /* y-position */
+ iupmotSetArg(args, num_args, XmNwidth, w-w_img); /* default width to avoid 0 */
+ iupmotSetArg(args, num_args, XmNheight, h); /* default height to avoid 0 */
+ iupmotSetArg(args, num_args, XmNmarginHeight, ih->data->spacing); /* default padding */
+ iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+ iupmotSetArg(args, num_args, XmNforeground, color);
+ iupmotSetArg(args, num_args, XmNrenderTable, fontlist);
+ iupmotSetArg(args, num_args, XmNvalue, iupmotConvertString(title));
+ iupmotSetArg(args, num_args, XmNtraversalOn, True);
+
+ cbEdit = XtCreateManagedWidget(
+ child_id, /* child identifier */
+ xmTextWidgetClass, /* widget class */
+ sb_win,
+ args, num_args);
+
+ /* Disable Drag Source */
+ iupmotDisableDragSource(cbEdit);
+
+ XtAddEventHandler(cbEdit, EnterWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(cbEdit, LeaveWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(cbEdit, FocusChangeMask, False, (XtEventHandler)motTreeEditFocusChangeEvent, (XtPointer)ih);
+ XtAddEventHandler(cbEdit, KeyPressMask, False, (XtEventHandler)motTreeEditKeyPressEvent, (XtPointer)ih);
+
+ iupAttribSetStr(ih, "_IUPTREE_SELECTED", (char*)wItem);
+ iupAttribSetStr(ih, "_IUPTREE_EDITFIELD", (char*)cbEdit);
+
+ XmProcessTraversal(cbEdit, XmTRAVERSE_CURRENT);
+
+ XmTextSetSelection(cbEdit, (XmTextPosition)0, (XmTextPosition)XmTextGetLastPosition(cbEdit), CurrentTime);
+
+ value = iupAttribGetStr(ih, "RENAMECARET");
+ if (value)
+ motTreeSetRenameCaretPos(cbEdit, value);
+
+ value = iupAttribGetStr(ih, "RENAMESELECTION");
+ if (value)
+ motTreeSetRenameSelectionPos(cbEdit, value);
+
+ /* the parents callbacks can be called while editing
+ so we must avoid their processing if _IUPTREE_EDITFIELD is defined. */
+}
+
+static void motTreeSelectionCallback(Widget w, Ihandle* ih, XmContainerSelectCallbackStruct *nptr)
+{
+ IFnii cbSelec;
+ int is_ctrl = 0;
+ (void)w;
+ (void)nptr;
+
+printf("SelectionCallback(%d)\n", nptr->selected_item_count);
+
+ if (ih->data->mark_mode == ITREE_MARK_MULTIPLE)
+ {
+ char key[5];
+ iupdrvGetKeyState(key);
+ if (key[0] == 'S')
+ return;
+ else if (key[1] == 'C')
+ is_ctrl = 1;
+
+ if (nptr->selected_item_count>1 && !is_ctrl)
+ {
+ if (IupGetCallback(ih, "MULTISELECTION_CB"))
+ {
+ if (nptr->auto_selection_type==XmAUTO_NO_CHANGE)
+ motTreeCallMultiSelectionCb(ih);
+ }
+ else
+ {
+ if (nptr->auto_selection_type==XmAUTO_MOTION)
+ motTreeCallMultiSelectionCb(ih);
+ }
+ return;
+ }
+ }
+
+ cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB");
+ if (cbSelec)
+ {
+ Widget wItemFocus = motTreeGetFocusNode(ih);
+ int curpos = motTreeGetNodeId(ih, wItemFocus);
+ if (is_ctrl)
+ {
+ unsigned char isSelected;
+ XtVaGetValues(wItemFocus, XmNvisualEmphasis, &isSelected, NULL);
+ cbSelec(ih, curpos, isSelected == XmSELECTED? 1: 0);
+ }
+ else
+ {
+ int oldpos = iupAttribGetInt(ih, "_IUPTREE_OLDVALUE");
+ if (oldpos != curpos)
+ {
+ cbSelec(ih, oldpos, 0); /* unselected */
+ cbSelec(ih, curpos, 1); /* selected */
+
+ iupAttribSetInt(ih, "_IUPTREE_OLDVALUE", curpos);
+ }
+ }
+ }
+}
+
+static void motTreeDefaultActionCallback(Widget w, Ihandle* ih, XmContainerSelectCallbackStruct *nptr)
+{
+ unsigned char itemState;
+ WidgetList wSelectedItemList = NULL;
+ int countItems;
+ motTreeItemData *itemData;
+ Widget wItem;
+ (void)w;
+
+ wSelectedItemList = nptr->selected_items;
+ countItems = nptr->selected_item_count;
+
+ if (!countItems || (Widget)iupAttribGet(ih, "_IUPTREE_EDITFIELD"))
+ return;
+
+ /* this works also when using multiple selection */
+ wItem = wSelectedItemList[0];
+
+ XtVaGetValues(wItem, XmNoutlineState, &itemState,
+ XmNuserData, &itemData, NULL);
+
+ if (itemData->kind == ITREE_BRANCH)
+ {
+ if (itemState == XmEXPANDED)
+ XtVaSetValues(wItem, XmNoutlineState, XmCOLLAPSED, NULL);
+ else
+ XtVaSetValues(wItem, XmNoutlineState, XmEXPANDED, NULL);
+ }
+ else
+ {
+ IFni cbExecuteLeaf = (IFni)IupGetCallback(ih, "EXECUTELEAF_CB");
+ if (cbExecuteLeaf)
+ cbExecuteLeaf(ih, motTreeGetNodeId(ih, wItem));
+ }
+}
+
+static void motTreeOutlineChangedCallback(Widget w, Ihandle* ih, XmContainerOutlineCallbackStruct *nptr)
+{
+ motTreeItemData *itemData;
+ XtVaGetValues(nptr->item, XmNuserData, &itemData, NULL);
+
+ if (nptr->reason == XmCR_EXPANDED)
+ {
+ if (motTreeCallBranchOpenCb(ih, nptr->item) == IUP_IGNORE)
+ nptr->new_outline_state = XmCOLLAPSED; /* prevent the change */
+ else
+ {
+ XtVaSetValues(nptr->item, XmNsmallIconPixmap, (itemData->image_expanded!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded: (Pixmap)ih->data->def_image_expanded, NULL);
+ XtVaSetValues(nptr->item, XmNsmallIconMask, (itemData->image_expanded_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded_mask: (Pixmap)ih->data->def_image_expanded_mask, NULL);
+ }
+ }
+ else if (nptr->reason == XmCR_COLLAPSED)
+ {
+ if (motTreeCallBranchCloseCb(ih, nptr->item) == IUP_IGNORE)
+ nptr->new_outline_state = XmEXPANDED; /* prevent the change */
+ else
+ {
+ XtVaSetValues(nptr->item, XmNsmallIconPixmap, (itemData->image!=XmUNSPECIFIED_PIXMAP)? itemData->image: (Pixmap)ih->data->def_image_collapsed, NULL);
+ XtVaSetValues(nptr->item, XmNsmallIconMask, (itemData->image_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_mask: (Pixmap)ih->data->def_image_collapsed_mask, NULL);
+ }
+ }
+
+ (void)w;
+}
+
+static void motTreeTraverseObscuredCallback(Widget widget, Ihandle* ih, XmTraverseObscuredCallbackStruct *cbs)
+{
+ (void)ih;
+ /* allow to do automatic scroll when navigating in the tree */
+ XmScrollVisible(widget, cbs->traversal_destination, 10, 10);
+}
+
+static void motTreeKeyReleaseEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean *cont)
+{
+ KeySym motcode;
+
+ if (iupAttribGet(ih, "_IUPTREE_EDITFIELD"))
+ return;
+
+ motcode = XKeycodeToKeysym(iupmot_display, evt->keycode, 0);
+ if (motcode == XK_Down || motcode == XK_U || motcode == XK_Home || motcode == XK_End)
+ {
+ if (ih->data->mark_mode==ITREE_MARK_MULTIPLE && (evt->state & ShiftMask))
+ motTreeCallMultiSelectionCb(ih);
+ }
+
+ (void)w;
+ (void)cont;
+}
+
+static void motTreeKeyPressEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean *cont)
+{
+ KeySym motcode;
+
+ if (iupAttribGet(ih, "_IUPTREE_EDITFIELD"))
+ return;
+
+ *cont = True;
+ iupmotKeyPressEvent(w, ih, (XEvent*)evt, cont);
+ if (*cont == False)
+ return;
+
+ motcode = XKeycodeToKeysym(iupmot_display, evt->keycode, 0);
+ if (motcode == XK_F2)
+ motTreeSetRenameAttrib(ih, NULL);
+ else if (motcode == XK_F1)
+ iupmotHelpCallback(w, ih, NULL);
+ else if ((motcode == XK_Down || motcode == XK_Up) && (evt->state & ControlMask))
+ {
+ Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+ Widget wItem;
+ Widget wItemFocus = motTreeGetFocusNode(ih);
+
+ /* Ctrl+Arrows move only focus */
+ if (motcode == XK_Down)
+ wItem = motTreeGetNextVisibleNode(ih, wRoot, wItemFocus);
+ else
+ wItem = motTreeGetPreviousVisibleNode(ih, wRoot, wItemFocus);
+
+ motTreeSetFocusNode(ih, wItem);
+ *cont = False;
+ }
+ else if(motcode == XK_Home || motcode == XK_End)
+ {
+ Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+ Widget wItem;
+
+ /* Not processed by Motif */
+
+ if (motcode == XK_Home)
+ wItem = wRoot;
+ else
+ wItem = motTreeGetLastVisibleNode(ih, wRoot);
+
+ /* Ctrl+Arrows move only focus */
+ if (!(evt->state & ControlMask))
+ {
+ /* Shift+Arrows select block */
+ if (evt->state & ShiftMask)
+ {
+ Widget wItemFocus = motTreeGetFocusNode(ih);
+ if (!wItemFocus)
+ return;
+ motTreeSelectRange(ih, wItemFocus, wItem, 1);
+ }
+ else
+ {
+ /* clear previous selection */
+ XtVaSetValues(ih->handle, XmNselectedObjects, NULL, NULL);
+ XtVaSetValues(ih->handle, XmNselectedObjectCount, 0, NULL);
+
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
+ }
+ }
+
+ motTreeSetFocusNode(ih, wItem);
+ *cont = False;
+ }
+ else if(motcode == XK_space && (evt->state & ControlMask))
+ {
+ Widget wItemFocus = motTreeGetFocusNode(ih);
+ if (wItemFocus)
+ {
+ unsigned char isSelected;
+ XtVaGetValues(wItemFocus, XmNvisualEmphasis, &isSelected, NULL);
+ if (isSelected == XmSELECTED)
+ XtVaSetValues(wItemFocus, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
+ else
+ XtVaSetValues(wItemFocus, XmNvisualEmphasis, XmSELECTED, NULL);
+ }
+ }
+}
+
+static void motTreeButtonEvent(Widget w, Ihandle* ih, XButtonEvent* evt, Boolean* cont)
+{
+ (void)w;
+ (void)cont;
+
+ if (iupAttribGet(ih, "_IUPTREE_EDITFIELD"))
+ return;
+
+ *cont = True;
+ iupmotButtonPressReleaseEvent(w, ih, (XEvent*)evt, cont);
+ if (*cont == False)
+ return;
+
+ if (evt->type==ButtonPress)
+ {
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_ENTERLEAVE", "1");
+
+ if (evt->button==Button1)
+ {
+ Widget wItemFocus = motTreeGetFocusNode(ih);
+ static Widget wLastItem = NULL;
+ static Time last = 0;
+ int clicktwice = 0, doubleclicktime = XtGetMultiClickTime(iupmot_display);
+ int elapsed = (int)(evt->time - last);
+ last = evt->time;
+
+ /* stay away from double click and leave some room for clicks */
+ if (elapsed > (3*doubleclicktime)/2 && elapsed <= 3*doubleclicktime)
+ clicktwice = 1;
+
+ if (clicktwice && wLastItem && wLastItem==wItemFocus)
+ {
+ motTreeSetRenameAttrib(ih, NULL);
+ *cont = False;
+ }
+ wLastItem = wItemFocus;
+ }
+ else if (evt->button==Button3)
+ motTreeCallRightClickCb(ih, evt->x, evt->y);
+ }
+ else if (evt->type==ButtonRelease)
+ {
+ if (evt->button==Button1)
+ {
+ if (ih->data->mark_mode==ITREE_MARK_MULTIPLE && (evt->state & ShiftMask))
+ motTreeCallMultiSelectionCb(ih);
+ }
+ }
+}
+
+static void motTreeTransferProc(Widget drop_context, XtPointer client_data, Atom *seltype, Atom *type, XtPointer value, unsigned long *length, int format)
+{
+ Atom atomTreeItem = XInternAtom(iupmot_display, "TREE_ITEM", False);
+ Widget wItemDrop = (Widget)client_data;
+ Widget wItemDrag = (Widget)value;
+
+ if (*type == atomTreeItem)
+ {
+ Widget wParent;
+ Ihandle* ih = NULL;
+ int is_ctrl;
+
+ if (!wItemDrop || wItemDrag == wItemDrop)
+ return;
+
+ wParent = wItemDrop;
+ while(wParent)
+ {
+ XtVaGetValues(wParent, XmNentryParent, &wParent, NULL);
+ if (wParent == wItemDrag)
+ return;
+ }
+
+ XtVaGetValues(XtParent(wItemDrag), XmNuserData, &ih, NULL);
+
+ if (motTreeCallDragDropCb(ih, wItemDrag, wItemDrop, &is_ctrl) == IUP_CONTINUE)
+ {
+ /* Copy the dragged item to the new position. */
+ Widget wNewItem = motTreeCopyNode(ih, wItemDrag, wItemDrop, is_ctrl);
+
+ if (!is_ctrl)
+ {
+ /* do not delete the user data, we copy the references in CopyNode */
+ motTreeRemoveNode(ih, wItemDrag, 0);
+ }
+
+ /* Select the dragged item */
+ XtVaSetValues(ih->handle, XmNselectedObjects, NULL, NULL);
+ XtVaSetValues(ih->handle, XmNselectedObjectCount, 0, NULL);
+ XtVaSetValues(wNewItem, XmNvisualEmphasis, XmSELECTED, NULL);
+
+ motTreeSetFocusNode(ih, wNewItem);
+ }
+ }
+
+ (void)drop_context;
+ (void)seltype;
+ (void)format;
+ (void)length;
+}
+
+static void motTreeDropProc(Widget w, XtPointer client_data, XmDropProcCallbackStruct* drop_data)
+{
+ Atom atomTreeItem = XInternAtom(iupmot_display, "TREE_ITEM", False);
+ XmDropTransferEntryRec transferList[2];
+ Arg args[10];
+ int i, num_args = 0;
+ Widget wItemDrop, drop_context;
+ Cardinal numExportTargets;
+ Atom *exportTargets;
+ Boolean found = False;
+ (void)client_data;
+
+ drop_context = drop_data->dragContext;
+
+ /* retrieve the data targets */
+ iupmotSetArg(args, num_args, XmNexportTargets, &exportTargets);
+ iupmotSetArg(args, num_args, XmNnumExportTargets, &numExportTargets);
+ XtGetValues(drop_context, args, num_args);
+
+ for (i = 0; i < (int)numExportTargets; i++)
+ {
+ if (exportTargets[i] == atomTreeItem)
+ {
+ found = True;
+ break;
+ }
+ }
+
+ wItemDrop = XmObjectAtPoint(w, drop_data->x, drop_data->y);
+ if (!wItemDrop)
+ found = False;
+
+ num_args = 0;
+ if ((!found) || (drop_data->dropAction != XmDROP) || (drop_data->operation != XmDROP_COPY && drop_data->operation != XmDROP_MOVE))
+ {
+ iupmotSetArg(args, num_args, XmNtransferStatus, XmTRANSFER_FAILURE);
+ iupmotSetArg(args, num_args, XmNnumDropTransfers, 0);
+ }
+ else
+ {
+ /* set up transfer requests for drop site */
+ transferList[0].target = atomTreeItem;
+ transferList[0].client_data = (XtPointer)wItemDrop;
+ iupmotSetArg(args, num_args, XmNdropTransfers, transferList);
+ iupmotSetArg(args, num_args, XmNnumDropTransfers, 1);
+ iupmotSetArg(args, num_args, XmNtransferProc, motTreeTransferProc);
+ }
+
+ XmDropTransferStart(drop_context, args, num_args);
+}
+
+static void motTreeDragDropFinishCallback(Widget drop_context, XtPointer client_data, XtPointer call_data)
+{
+ Widget source_icon = NULL;
+ XtVaGetValues(drop_context, XmNsourceCursorIcon, &source_icon, NULL);
+ if (source_icon)
+ XtDestroyWidget(source_icon);
+ (void)call_data;
+ (void)client_data;
+}
+
+static void motTreeDragMotionCallback(Widget drop_context, Widget wItemDrag, XmDragMotionCallbackStruct* drag_motion)
+{
+ Ihandle* ih = NULL;
+ XtVaGetValues(XtParent(wItemDrag), XmNuserData, &ih, NULL);
+ if (!iupAttribGet(ih, "NODRAGFEEDBACK"))
+ {
+ Widget wItem;
+ int x = drag_motion->x;
+ int y = drag_motion->y;
+ iupdrvScreenToClient(ih, &x, &y);
+ wItem = XmObjectAtPoint(ih->handle, (Position)x, (Position)y);
+ if (wItem)
+ {
+ XtVaSetValues(ih->handle, XmNselectedObjects, NULL, NULL);
+ XtVaSetValues(ih->handle, XmNselectedObjectCount, 0, NULL);
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
+ }
+ }
+ (void)drop_context;
+}
+
+static Boolean motTreeConvertProc(Widget drop_context, Atom *selection, Atom *target, Atom *type_return,
+ XtPointer *value_return, unsigned long *length_return, int *format_return)
+{
+ Atom atomMotifDrop = XInternAtom(iupmot_display, "_MOTIF_DROP", False);
+ Atom atomTreeItem = XInternAtom(iupmot_display, "TREE_ITEM", False);
+ Widget wItemDrag = NULL;
+
+ /* check if we are dealing with a drop */
+ if (*selection != atomMotifDrop || *target != atomTreeItem)
+ return False;
+
+ XtVaGetValues(drop_context, XmNclientData, &wItemDrag, NULL);
+ if (!wItemDrag)
+ return False;
+
+ /* format the value for transfer */
+ *type_return = atomTreeItem;
+ *value_return = (XtPointer)wItemDrag;
+ *length_return = 1;
+ *format_return = 32;
+ return True;
+}
+
+static void motTreeStartDrag(Widget w, XButtonEvent* evt, String* params, Cardinal* num_params)
+{
+ Atom atomTreeItem = XInternAtom(iupmot_display, "TREE_ITEM", False);
+ Atom exportList[1];
+ Widget drag_icon, drop_context;
+ Pixmap pixmap = 0, mask = 0;
+ int num_args = 0;
+ Arg args[40];
+ Pixel fg, bg;
+ Widget wItemDrag = XmObjectAtPoint(w, (Position)evt->x, (Position)evt->y);
+ if (!wItemDrag)
+ return;
+
+ XtVaGetValues(wItemDrag, XmNsmallIconPixmap, &pixmap,
+ XmNsmallIconMask, &mask,
+ XmNbackground, &bg,
+ XmNforeground, &fg,
+ NULL);
+
+ iupmotSetArg(args, num_args, XmNpixmap, pixmap);
+ iupmotSetArg(args, num_args, XmNmask, mask);
+ drag_icon = XmCreateDragIcon(w, "drag_icon", args, num_args);
+
+ exportList[0] = atomTreeItem;
+
+ /* specify resources for DragContext for the transfer */
+ num_args = 0;
+ iupmotSetArg(args, num_args, XmNcursorBackground, bg);
+ iupmotSetArg(args, num_args, XmNcursorForeground, fg);
+ /* iupmotSetArg(args, num_args, XmNsourcePixmapIcon, drag_icon); works, but only outside the dialog, inside disapears */
+ iupmotSetArg(args, num_args, XmNsourceCursorIcon, drag_icon); /* does not work, shows the default cursor */
+ iupmotSetArg(args, num_args, XmNexportTargets, exportList);
+ iupmotSetArg(args, num_args, XmNnumExportTargets, 1);
+ iupmotSetArg(args, num_args, XmNdragOperations, XmDROP_MOVE|XmDROP_COPY);
+ iupmotSetArg(args, num_args, XmNconvertProc, motTreeConvertProc);
+ iupmotSetArg(args, num_args, XmNclientData, wItemDrag);
+
+ /* start the drag and register a callback to clean up when done */
+ drop_context = XmDragStart(w, (XEvent*)evt, args, num_args);
+ XtAddCallback(drop_context, XmNdragDropFinishCallback, (XtCallbackProc)motTreeDragDropFinishCallback, NULL);
+ XtAddCallback(drop_context, XmNdragMotionCallback, (XtCallbackProc)motTreeDragMotionCallback, (XtPointer)wItemDrag);
+
+ (void)params;
+ (void)num_params;
+}
+
+static void motTreeEnableDragDrop(Widget w)
+{
+ Atom atomTreeItem = XInternAtom(iupmot_display, "TREE_ITEM", False);
+ Atom importList[1];
+ Arg args[40];
+ int num_args = 0;
+ char dragTranslations[] = "#override <Btn2Down>: StartDrag()";
+ static int do_rec = 0;
+ if (!do_rec)
+ {
+ XtActionsRec rec = {"StartDrag", (XtActionProc)motTreeStartDrag};
+ XtAppAddActions(iupmot_appcontext, &rec, 1);
+ do_rec = 1;
+ }
+ XtOverrideTranslations(w, XtParseTranslationTable(dragTranslations));
+
+ importList[0] = atomTreeItem;
+ iupmotSetArg(args, num_args, XmNimportTargets, importList);
+ iupmotSetArg(args, num_args, XmNnumImportTargets, 1);
+ iupmotSetArg(args, num_args, XmNdropSiteOperations, XmDROP_MOVE|XmDROP_COPY);
+ iupmotSetArg(args, num_args, XmNdropProc, motTreeDropProc);
+ XmDropSiteUpdate(w, args, num_args);
+
+ XtVaSetValues(XmGetXmDisplay(iupmot_display), XmNenableDragIcon, True, NULL);
+}
+
+static int motTreeMapMethod(Ihandle* ih)
+{
+ int num_args = 0;
+ Arg args[40];
+ Widget parent = iupChildTreeGetNativeParentHandle(ih);
+ char* child_id = iupDialogGetChildIdStr(ih);
+ Widget sb_win;
+
+ /******************************/
+ /* Create the scrolled window */
+ /******************************/
+ iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupmotSetArg(args, num_args, XmNscrollingPolicy, XmAUTOMATIC);
+ iupmotSetArg(args, num_args, XmNvisualPolicy, XmVARIABLE);
+ iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmAS_NEEDED);
+ iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */
+ iupmotSetArg(args, num_args, XmNborderWidth, 0);
+ iupmotSetArg(args, num_args, XmNshadowThickness, 2);
+
+ sb_win = XtCreateManagedWidget(
+ child_id, /* child identifier */
+ xmScrolledWindowWidgetClass, /* widget class */
+ parent, /* widget parent */
+ args, num_args);
+
+ if (!sb_win)
+ return IUP_ERROR;
+
+ XtAddCallback (sb_win, XmNtraverseObscuredCallback, (XtCallbackProc)motTreeTraverseObscuredCallback, (XtPointer)ih);
+
+ parent = sb_win;
+ child_id = "container";
+
+ num_args = 0;
+
+ iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+ iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+ iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+
+ iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
+ iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+ iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ else
+ iupmotSetArg(args, num_args, XmNtraversalOn, False);
+
+ iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
+ iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+
+ iupmotSetArg(args, num_args, XmNlayoutType, XmOUTLINE);
+ iupmotSetArg(args, num_args, XmNentryViewType, XmSMALL_ICON);
+ iupmotSetArg(args, num_args, XmNselectionPolicy, XmSINGLE_SELECT);
+ iupmotSetArg(args, num_args, XmNoutlineIndentation, 20);
+
+ if (iupAttribGetBoolean(ih, "HIDELINES"))
+ iupmotSetArg(args, num_args, XmNoutlineLineStyle, XmNO_LINE);
+ else
+ iupmotSetArg(args, num_args, XmNoutlineLineStyle, XmSINGLE);
+
+ if (iupAttribGetBoolean(ih, "HIDEBUTTONS"))
+ iupmotSetArg(args, num_args, XmNoutlineButtonPolicy, XmOUTLINE_BUTTON_ABSENT);
+ else
+ iupmotSetArg(args, num_args, XmNoutlineButtonPolicy, XmOUTLINE_BUTTON_PRESENT);
+
+ ih->handle = XtCreateManagedWidget(
+ child_id, /* child identifier */
+ xmContainerWidgetClass, /* widget class */
+ parent, /* widget parent */
+ args, num_args);
+
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ ih->serial = iupDialogGetChildId(ih); /* must be after using the string */
+
+ iupAttribSetStr(ih, "_IUP_EXTRAPARENT", (char*)parent);
+
+ XtAddEventHandler(ih->handle, EnterWindowMask, False, (XtEventHandler)motTreeEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, LeaveWindowMask, False, (XtEventHandler)motTreeEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, FocusChangeMask, False, (XtEventHandler)motTreeFocusChangeEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, KeyPressMask, False, (XtEventHandler)motTreeKeyPressEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, KeyReleaseMask, False, (XtEventHandler)motTreeKeyReleaseEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, ButtonPressMask|ButtonReleaseMask, False, (XtEventHandler)motTreeButtonEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, PointerMotionMask, False, (XtEventHandler)iupmotPointerMotionEvent, (XtPointer)ih);
+
+ /* Callbacks */
+ /* XtAddCallback(ih->handle, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih); NOT WORKING */
+ XtAddCallback(ih->handle, XmNoutlineChangedCallback, (XtCallbackProc)motTreeOutlineChangedCallback, (XtPointer)ih);
+ XtAddCallback(ih->handle, XmNdefaultActionCallback, (XtCallbackProc)motTreeDefaultActionCallback, (XtPointer)ih);
+ XtAddCallback(ih->handle, XmNselectionCallback, (XtCallbackProc)motTreeSelectionCallback, (XtPointer)ih);
+
+ XtRealizeWidget(parent);
+
+ if (ih->data->show_dragdrop)
+ {
+ motTreeEnableDragDrop(ih->handle);
+ XtVaSetValues(ih->handle, XmNuserData, ih, NULL); /* to be used in motTreeTransferProc */
+ }
+ else
+ iupmotDisableDragSource(ih->handle);
+
+ /* Force background update before setting the images */
+ {
+ char* value = iupAttribGet(ih, "BGCOLOR");
+ if (value)
+ {
+ motTreeSetBgColorAttrib(ih, value);
+ iupAttribSetStr(ih, "BGCOLOR", NULL);
+ }
+ }
+
+ /* Initialize the default images */
+ ih->data->def_image_leaf = iupImageGetImage("IMGLEAF", ih, 0);
+ if (!ih->data->def_image_leaf)
+ {
+ ih->data->def_image_leaf = (void*)XmUNSPECIFIED_PIXMAP;
+ ih->data->def_image_leaf_mask = (void*)XmUNSPECIFIED_PIXMAP;
+ }
+ else
+ {
+ ih->data->def_image_leaf_mask = iupImageGetMask("IMGLEAF");
+ if (!ih->data->def_image_leaf_mask) ih->data->def_image_leaf_mask = (void*)XmUNSPECIFIED_PIXMAP;
+ }
+
+ ih->data->def_image_collapsed = iupImageGetImage("IMGCOLLAPSED", ih, 0);
+ if (!ih->data->def_image_collapsed)
+ {
+ ih->data->def_image_collapsed = (void*)XmUNSPECIFIED_PIXMAP;
+ ih->data->def_image_collapsed_mask = (void*)XmUNSPECIFIED_PIXMAP;
+ }
+ else
+ {
+ ih->data->def_image_collapsed_mask = iupImageGetMask("IMGCOLLAPSED");
+ if (!ih->data->def_image_collapsed_mask) ih->data->def_image_collapsed_mask = (void*)XmUNSPECIFIED_PIXMAP;
+ }
+
+ ih->data->def_image_expanded = iupImageGetImage("IMGEXPANDED", ih, 0);
+ if (!ih->data->def_image_expanded)
+ {
+ ih->data->def_image_expanded = (void*)XmUNSPECIFIED_PIXMAP;
+ ih->data->def_image_expanded_mask = (void*)XmUNSPECIFIED_PIXMAP;
+ }
+ else
+ {
+ ih->data->def_image_expanded_mask = iupImageGetMask("IMGEXPANDED");
+ if (!ih->data->def_image_expanded_mask) ih->data->def_image_expanded_mask = (void*)XmUNSPECIFIED_PIXMAP;
+ }
+
+ motTreeAddRootNode(ih);
+
+ IupSetCallback(ih, "_IUP_XY2POS_CB", (Icallback)motTreeConvertXYToPos);
+
+ return IUP_NOERROR;
+}
+
+void iupdrvTreeInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class functions */
+ ic->Map = motTreeMapMethod;
+
+ /* Visual */
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, motTreeSetBgColorAttrib, "TXTBGCOLOR", NULL, IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, motTreeSetFgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTFGCOLOR", IUPAF_DEFAULT);
+
+ /* IupTree Attributes - GENERAL */
+ iupClassRegisterAttribute(ic, "EXPANDALL", NULL, motTreeSetExpandAllAttrib, NULL, NULL, IUPAF_WRITEONLY||IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "INDENTATION", motTreeGetIndentationAttrib, motTreeSetIndentationAttrib, NULL, NULL, IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "COUNT", motTreeGetCountAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SPACING", iupTreeGetSpacingAttrib, motTreeSetSpacingAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "TOPITEM", NULL, motTreeSetTopItemAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+
+ /* IupTree Attributes - IMAGES */
+ iupClassRegisterAttributeId(ic, "IMAGE", NULL, motTreeSetImageAttrib, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "IMAGEEXPANDED", NULL, motTreeSetImageExpandedAttrib, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute(ic, "IMAGELEAF", NULL, motTreeSetImageLeafAttrib, IUPAF_SAMEASSYSTEM, "IMGLEAF", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "IMAGEBRANCHCOLLAPSED", NULL, motTreeSetImageBranchCollapsedAttrib, IUPAF_SAMEASSYSTEM, "IMGCOLLAPSED", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "IMAGEBRANCHEXPANDED", NULL, motTreeSetImageBranchExpandedAttrib, IUPAF_SAMEASSYSTEM, "IMGEXPANDED", IUPAF_NO_INHERIT);
+
+ /* IupTree Attributes - NODES */
+ iupClassRegisterAttributeId(ic, "STATE", motTreeGetStateAttrib, motTreeSetStateAttrib, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "DEPTH", motTreeGetDepthAttrib, NULL, IUPAF_READONLY|IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "KIND", motTreeGetKindAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "PARENT", motTreeGetParentAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "COLOR", motTreeGetColorAttrib, motTreeSetColorAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "NAME", motTreeGetTitleAttrib, motTreeSetTitleAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "TITLE", motTreeGetTitleAttrib, motTreeSetTitleAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "USERDATA", motTreeGetUserDataAttrib, motTreeSetUserDataAttrib, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "CHILDCOUNT", motTreeGetChildCountAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "TITLEFONT", motTreeGetTitleFontAttrib, motTreeSetTitleFontAttrib, IUPAF_NO_INHERIT);
+
+ /* IupTree Attributes - MARKS */
+ iupClassRegisterAttributeId(ic, "MARKED", motTreeGetMarkedAttrib, motTreeSetMarkedAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute (ic, "MARK", NULL, motTreeSetMarkAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute (ic, "STARTING", NULL, motTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute (ic, "MARKSTART", NULL, motTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute (ic, "VALUE", motTreeGetValueAttrib, motTreeSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+
+ /* IupTree Attributes - ACTION */
+ iupClassRegisterAttributeId(ic, "DELNODE", NULL, motTreeSetDelNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "RENAME", NULL, motTreeSetRenameAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "MOVENODE", NULL, motTreeSetMoveNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "COPYNODE", NULL, motTreeSetCopyNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "FINDUSERDATA", motTreeGetFindUserDataAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+}
diff --git a/iup/src/mot/iupmot_val.c b/iup/src/mot/iupmot_val.c
new file mode 100755
index 0000000..200d2b4
--- /dev/null
+++ b/iup/src/mot/iupmot_val.c
@@ -0,0 +1,488 @@
+/** \file
+ * \brief Valuator Control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <Xm/Xm.h>
+#include <Xm/Scale.h>
+#include <Xm/SeparatoG.h>
+#include <X11/keysym.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <memory.h>
+#include <stdarg.h>
+#include <limits.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_object.h"
+#include "iup_childtree.h"
+#include "iup_attrib.h"
+#include "iup_dialog.h"
+#include "iup_str.h"
+#include "iup_val.h"
+#include "iup_image.h"
+#include "iup_drv.h"
+
+#include "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+void iupdrvValGetMinSize(Ihandle* ih, int *w, int *h)
+{
+ int ticks_size = 0;
+ if (iupAttribGetInt(ih, "SHOWTICKS"))
+ ticks_size = 8;
+
+ if (ih->data->type == IVAL_HORIZONTAL)
+ {
+ *w = 30;
+ *h = 20+ticks_size;
+ }
+ else
+ {
+ *w = 20+ticks_size;
+ *h = 30;
+ }
+}
+
+static void motValRemoveOldTicks(Widget scale)
+{
+ WidgetList children = (WidgetList)0;
+ Cardinal num_children = (Cardinal)0;
+ Cardinal i;
+ String name;
+
+ XtVaGetValues(scale, XmNchildren, &children,
+ XmNnumChildren, &num_children,
+ NULL);
+
+ for (i = 0; i < num_children; i++)
+ {
+ if (XmIsSeparatorGadget(children[i]))
+ {
+ if ((name = XtName(children[i])) != (String)0)
+ {
+ if ((strcmp(name, "BigTic") == 0) ||
+ (strcmp(name, "MedTic") == 0) ||
+ (strcmp(name, "SmallTic") == 0))
+ {
+ XtDestroyWidget(children[i]);
+ }
+ }
+ }
+ }
+}
+
+static int motValSetShowTicksAttrib(Ihandle* ih, const char* value)
+{
+ int tick_freq, show_ticks;
+
+ if (!ih->data->show_ticks) /* can only set if already not zero */
+ return 0;
+
+ show_ticks = atoi(value);
+ if (show_ticks<2) show_ticks=2;
+ ih->data->show_ticks = show_ticks;
+
+ motValRemoveOldTicks(ih->handle);
+
+ /* Defines the interval frequency for tick marks */
+ tick_freq = SHRT_MAX/(show_ticks-1);
+ XmScaleSetTicks(ih->handle, tick_freq, 0, 0, 8, 0, 0);
+ return 0;
+}
+
+static int motValSetPageStepAttrib(Ihandle* ih, const char* value)
+{
+ int pagesize;
+ ih->data->pagestep = atof(value);
+ pagesize = (int)(ih->data->pagestep*SHRT_MAX);
+ XtVaSetValues(ih->handle, XmNscaleMultiple, pagesize, NULL);
+ return 0; /* do not store value in hash table */
+}
+
+static int motValSetStepAttrib(Ihandle* ih, const char* value)
+{
+ ih->data->step = atof(value);
+ return 0; /* do not store value in hash table */
+}
+
+static int motValSetValueAttrib(Ihandle* ih, const char* value)
+{
+ int ival;
+
+ ih->data->val = atof(value);
+ iupValCropValue(ih);
+
+ ival = (int)(((ih->data->val-ih->data->vmin)/(ih->data->vmax - ih->data->vmin))*SHRT_MAX);
+ XtVaSetValues(ih->handle, XmNvalue, ival, NULL);
+
+ return 0; /* do not store value in hash table */
+}
+
+static int motValSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ Pixel color;
+ unsigned char r, g, b;
+ if (!iupStrToRGB(value, &r, &g, &b))
+ return 0;
+
+ r = (r*8)/10;
+ g = (g*8)/10;
+ b = (b*8)/10;
+
+ color = iupmotColorGetPixel(r, g, b);
+ if (color != (Pixel)-1)
+ {
+ Widget w = XtNameToWidget(ih->handle, "*Scrollbar");
+ XtVaSetValues(w, XmNtroughColor, color, NULL);
+ }
+
+ return iupdrvBaseSetBgColorAttrib(ih, value);
+}
+
+static int motValSetBackgroundAttrib(Ihandle* ih, const char* value)
+{
+ Pixel color;
+
+ /* ignore given value, must use only from parent */
+ value = iupAttribGetInheritNativeParent(ih, "BACKGROUND");
+
+ color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ {
+ XtVaSetValues(ih->handle, XmNbackground, color, NULL);
+ return 1;
+ }
+ else
+ {
+ Pixmap pixmap = (Pixmap)iupImageGetImage(value, ih, 0);
+ if (pixmap)
+ {
+ XtVaSetValues(ih->handle, XmNbackgroundPixmap, pixmap, NULL);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/*********************************************************************************************/
+
+
+static void motValCallAction(Ihandle* ih, int ival, int cb_state)
+{
+ double old_val = ih->data->val;
+ IFn cb;
+
+ ih->data->val = (((double)ival/(double)SHRT_MAX)*(ih->data->vmax - ih->data->vmin)) + ih->data->vmin;
+ iupValCropValue(ih);
+
+ cb = (IFn)IupGetCallback(ih, "VALUECHANGED_CB");
+ if (cb)
+ {
+ if (ih->data->val == old_val)
+ return;
+
+ cb(ih);
+ }
+ else
+ {
+ IFnd cb_old;
+ if (cb_state == 0)
+ cb_old = (IFnd) IupGetCallback(ih, "MOUSEMOVE_CB");
+ else if (cb_state == -1)
+ cb_old = (IFnd) IupGetCallback(ih, "BUTTON_RELEASE_CB");
+ else
+ cb_old = (IFnd) IupGetCallback(ih, "BUTTON_PRESS_CB");
+
+ if (cb_old)
+ cb_old(ih, ih->data->val);
+ }
+}
+
+static void motValIncPageValue(Ihandle *ih, int dir)
+{
+ int pagesize, ival;
+ pagesize = (int)(ih->data->pagestep*SHRT_MAX);
+
+ if (ih->data->inverted)
+ dir *= -1;
+
+ XtVaGetValues(ih->handle, XmNvalue, &ival, NULL);
+ ival += dir*pagesize;
+ if (ival < 0) ival = 0;
+ if (ival > SHRT_MAX) ival = SHRT_MAX;
+ XtVaSetValues(ih->handle, XmNvalue, ival, NULL);
+
+ motValCallAction(ih, ival, 1);
+}
+
+static void motValIncLineValue(Ihandle *ih, int dir)
+{
+ int linesize, ival;
+ linesize = (int)(ih->data->step*SHRT_MAX);
+
+ if (ih->data->inverted)
+ dir *= -1;
+
+ XtVaGetValues(ih->handle, XmNvalue, &ival, NULL);
+ ival += dir*linesize;
+ if (ival < 0) ival = 0;
+ if (ival > SHRT_MAX) ival = SHRT_MAX;
+ XtVaSetValues(ih->handle, XmNvalue, ival, NULL);
+
+ motValCallAction(ih, ival, 1);
+}
+
+static void motValKeyPressEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean *cont)
+{
+ KeySym motcode;
+
+ *cont = True;
+ iupmotKeyPressEvent(w, ih, (XEvent*)evt, cont);
+ if (*cont == False)
+ return;
+
+ motcode = XKeycodeToKeysym(iupmot_display, evt->keycode, 0);
+
+ /* add missing support for numeric keyboard */
+ /* add missing support for left/right in vertical
+ and up/down in horizontal */
+ if (motcode == XK_Left || motcode == XK_KP_Left ||
+ motcode == XK_Up || motcode == XK_KP_Up)
+ {
+ motValIncLineValue(ih, -1);
+ *cont = False;
+ return;
+ }
+ if (motcode == XK_Right || motcode == XK_KP_Right ||
+ motcode == XK_Down || motcode == XK_KP_Down)
+ {
+ motValIncLineValue(ih, 1);
+ *cont = False;
+ return;
+ }
+ if (motcode == XK_Prior || motcode == XK_KP_Page_Up)
+ {
+ motValIncPageValue(ih, -1);
+ *cont = False;
+ return;
+ }
+ if (motcode == XK_Next || motcode == XK_KP_Page_Down)
+ {
+ motValIncPageValue(ih, 1);
+ *cont = False;
+ return;
+ }
+
+ /* change Home and End default behaviour */
+ if (ih->data->inverted)
+ {
+ if (motcode==XK_Home || motcode==XK_KP_Home)
+ {
+ int ival = SHRT_MAX; /* set to maximum */
+ XtVaSetValues(ih->handle, XmNvalue, ival, NULL);
+ motValCallAction(ih, ival, 1);
+ *cont = False;
+ return;
+ }
+ if (motcode==XK_End || motcode==XK_KP_End)
+ {
+ int ival = 0; /* set to minimum */
+ XtVaSetValues(ih->handle, XmNvalue, ival, NULL);
+ motValCallAction(ih, ival, 1);
+ *cont = False;
+ return;
+ }
+ }
+ else
+ {
+ /* add missing support for numeric keyboard */
+ if (motcode==XK_KP_Home)
+ {
+ int ival = 0; /* set to minimum */
+ XtVaSetValues(ih->handle, XmNvalue, ival, NULL);
+ motValCallAction(ih, ival, 1);
+ *cont = False;
+ return;
+ }
+ if (motcode==XK_KP_End)
+ {
+ int ival = SHRT_MAX; /* set to maximum */
+ XtVaSetValues(ih->handle, XmNvalue, ival, NULL);
+ motValCallAction(ih, ival, 1);
+ *cont = False;
+ return;
+ }
+ }
+}
+
+static void motValValueChangedCallback(Widget w, Ihandle* ih, XmScaleCallbackStruct *cbs)
+{
+ int cb_state = 1;
+
+ if(cbs->reason == XmCR_DRAG)
+ cb_state = 0;
+ else if (cbs->event && (cbs->event->type==ButtonRelease || cbs->event->type==KeyRelease))
+ cb_state = -1;
+
+ motValCallAction(ih, cbs->value, cb_state);
+
+ (void)w;
+}
+
+static void motValButtonPressReleaseEvent(Widget w, Ihandle* ih, XButtonEvent* evt, Boolean* cont)
+{
+ (void)w;
+ (void)cont;
+
+ /* When Button1 is pressed, the Scrollbar loses its focus to the scale,
+ So we avoid calling GETFOCUS/KILLFOCUS.
+ */
+
+ if (evt->type==ButtonPress && evt->button==Button1)
+ {
+ iupAttribSetStr(ih, "_IUPVAL_IGNOREFOCUS", "1");
+ }
+ if (evt->type==ButtonRelease && evt->button==Button1)
+ {
+ iupAttribSetStr(ih, "_IUPVAL_IGNOREFOCUS", NULL);
+ iupAttribSetStr(ih, "_IUPVAL_IGNOREKILLFOCUS", "1");
+ }
+}
+
+static void motValFocusChangeEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont)
+{
+ if (iupAttribGet(ih, "_IUPVAL_IGNOREFOCUS"))
+ return;
+
+ if (evt->type == FocusOut && iupAttribGet(ih, "_IUPVAL_IGNOREKILLFOCUS"))
+ {
+ iupAttribSetStr(ih, "_IUPVAL_IGNOREKILLFOCUS", NULL);
+ return;
+ }
+
+ iupmotFocusChangeEvent(w, ih, evt, cont);
+}
+
+
+/*********************************************************************************************/
+
+
+static int motValMapMethod(Ihandle* ih)
+{
+ int num_args = 0;
+ Arg args[30];
+ int show_ticks;
+
+ /* Core */
+ iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+ iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+ iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ /* Primitive */
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+ iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ else
+ iupmotSetArg(args, num_args, XmNtraversalOn, False);
+ iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
+ iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ /* Scale */
+ iupmotSetArg(args, num_args, XmNminimum, 0);
+ iupmotSetArg(args, num_args, XmNmaximum, SHRT_MAX);
+ iupmotSetArg(args, num_args, XmNslidingMode, XmSLIDER);
+ iupmotSetArg(args, num_args, XmNsliderMark, XmETCHED_LINE);
+ iupmotSetArg(args, num_args, XmNsliderSize, 16);
+ iupmotSetArg(args, num_args, XmNshowValue, XmNONE);
+
+ if (ih->data->type == IVAL_HORIZONTAL)
+ {
+ iupmotSetArg(args, num_args, XmNorientation, XmHORIZONTAL);
+ if (ih->data->inverted)
+ iupmotSetArg(args, num_args, XmNprocessingDirection, XmMAX_ON_LEFT);
+ else
+ iupmotSetArg(args, num_args, XmNprocessingDirection, XmMAX_ON_RIGHT);
+ }
+ else
+ {
+ iupmotSetArg(args, num_args, XmNorientation, XmVERTICAL);
+ if (ih->data->inverted)
+ iupmotSetArg(args, num_args, XmNprocessingDirection, XmMAX_ON_TOP);
+ else
+ iupmotSetArg(args, num_args, XmNprocessingDirection, XmMAX_ON_BOTTOM);
+ }
+
+ ih->handle = XtCreateManagedWidget(
+ iupDialogGetChildIdStr(ih), /* child identifier */
+ xmScaleWidgetClass, /* widget class */
+ iupChildTreeGetNativeParentHandle(ih), /* widget parent */
+ args, num_args);
+
+ if (!ih->handle)
+ return IUP_ERROR;
+
+ /* callbacks */
+ XtAddEventHandler(ih->handle, EnterWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+ XtAddEventHandler(ih->handle, LeaveWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
+
+ /* XmScale changes the default behavior of these, must set directly into the scrollbar */
+ /* XtAddEventHandler(ih->handle, FocusChangeMask, False, (XtEventHandler)iupmotFocusChangeEvent, (XtPointer)ih); */
+ /* XtAddEventHandler(ih->handle, KeyPressMask, False, (XtEventHandler)iupmotKeyPressEvent, (XtPointer)ih); */
+
+ XtAddCallback(ih->handle, XmNdragCallback, (XtCallbackProc)motValValueChangedCallback, (XtPointer)ih);
+ XtAddCallback(ih->handle, XmNvalueChangedCallback, (XtCallbackProc)motValValueChangedCallback, (XtPointer)ih);
+ XtAddCallback(ih->handle, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih);
+
+ {
+ Widget sb = XtNameToWidget(ih->handle, "Scrollbar"); /* TODO: Test this in other Motifs */
+ if (sb)
+ {
+ XtAddEventHandler(sb, FocusChangeMask, False, (XtEventHandler)motValFocusChangeEvent, (XtPointer)ih);
+ XtAddEventHandler(sb, KeyPressMask, False, (XtEventHandler)motValKeyPressEvent, (XtPointer)ih);
+ XtAddEventHandler(sb, ButtonPressMask|ButtonReleaseMask, False, (XtEventHandler)motValButtonPressReleaseEvent, (XtPointer)ih);
+ }
+ }
+
+ /* Ticks can only be created before XtRealizeWidget */
+ show_ticks = iupAttribGetInt(ih, "SHOWTICKS");
+ if (show_ticks)
+ {
+ if (show_ticks<2) show_ticks=2;
+ ih->data->show_ticks = show_ticks; /* non zero value, can be changed later, but not to zero */
+ }
+
+ ih->serial = iupDialogGetChildId(ih); /* must be after using the string */
+
+ /* initialize the widget */
+ XtRealizeWidget(ih->handle);
+
+ return IUP_NOERROR;
+}
+
+void iupdrvValInitClass(Iclass* ic)
+{
+ /* Driver Dependent Class functions */
+ ic->Map = motValMapMethod;
+
+ /* Driver Dependent Attribute functions */
+
+ /* Visual */
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, motValSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BACKGROUND", NULL, motValSetBackgroundAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+
+ /* Special */
+
+ /* IupVal only */
+ iupClassRegisterAttribute(ic, "VALUE", iupValGetValueAttrib, motValSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "PAGESTEP", iupValGetPageStepAttrib, motValSetPageStepAttrib, IUPAF_SAMEASSYSTEM, "0.1", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SHOWTICKS", iupValGetShowTicksAttrib, motValSetShowTicksAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "STEP", iupValGetStepAttrib, motValSetStepAttrib, IUPAF_SAMEASSYSTEM, "0.01", IUPAF_NO_INHERIT);
+}
diff --git a/iup/src/mot/iupunix_help.c b/iup/src/mot/iupunix_help.c
new file mode 100755
index 0000000..02be1da
--- /dev/null
+++ b/iup/src/mot/iupunix_help.c
@@ -0,0 +1,44 @@
+/** \file
+ * \brief Motif Driver IupHelp
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "iup.h"
+
+#include "iup_str.h"
+
+int IupHelp(const char *url)
+{
+ char *cmd;
+ int ret;
+ char *browser = getenv("IUP_HELPAPP");
+ if (!browser)
+ browser = IupGetGlobal("HELPAPP");
+
+ if (!browser)
+ {
+ char* system = IupGetGlobal("SYSTEM");
+ if (iupStrEqualNoCase(system, "Linux") ||
+ iupStrEqualNoCase(system, "FreeBSD"))
+ browser = "firefox";
+ else if (iupStrEqualNoCase(system, "Darwin"))
+ browser = "safari";
+ else if (iupStrEqualPartial(system, "CYGWIN"))
+ browser = "iexplore";
+ else
+ browser = "netscape";
+ }
+
+ cmd = (char*)malloc(sizeof(char)*(strlen(url)+strlen(browser)+3));
+ sprintf(cmd, "%s %s &", browser, url);
+ ret = system(cmd);
+ free(cmd);
+ if (ret == -1)
+ return -1;
+ return 1;
+}
diff --git a/iup/src/mot/iupunix_info.c b/iup/src/mot/iupunix_info.c
new file mode 100755
index 0000000..b522638
--- /dev/null
+++ b/iup/src/mot/iupunix_info.c
@@ -0,0 +1,305 @@
+/** \file
+ * \brief UNIX System Information
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/stat.h>
+
+/* This module should depend only on IUP core headers
+ and UNIX system headers. NO Motif headers allowed. */
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "iup_str.h"
+#include "iup_drvinfo.h"
+
+
+int iupdrvMakeDirectory(const char* name)
+{
+ mode_t oldmask = umask((mode_t)0);
+ int fail = mkdir(name, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
+ S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH);
+ umask (oldmask);
+ if (fail)
+ return 0;
+ return 1;
+}
+
+int iupdrvIsFile(const char* name)
+{
+ struct stat status;
+ if (stat(name, &status) != 0)
+ return 0;
+ if (S_ISDIR(status.st_mode))
+ return 0;
+ return 1;
+}
+
+int iupdrvIsDirectory(const char* name)
+{
+ struct stat status;
+ if (stat(name, &status) != 0)
+ return 0;
+ if (S_ISDIR(status.st_mode))
+ return 1;
+ return 0;
+}
+
+char* iupdrvGetCurrentDirectory(void)
+{
+ size_t size = 256;
+ char *buffer = (char *)malloc(size);
+
+ for (;;)
+ {
+ if (getcwd(buffer, size) != NULL)
+ return buffer;
+
+ if (errno != ERANGE)
+ {
+ free(buffer);
+ return NULL;
+ }
+
+ size += size;
+ buffer = (char *)realloc(buffer, size);
+ }
+
+ return NULL;
+}
+
+int iupdrvSetCurrentDirectory(const char* dir)
+{
+ return chdir(dir) == 0? 1: 0;
+}
+
+int iupdrvGetWindowDecor(void* wnd, int *border, int *caption)
+{
+ XWindowAttributes wa;
+ wa.x = 0; wa.y = 0;
+ XGetWindowAttributes((Display*)iupdrvGetDisplay(), (Window)wnd, &wa);
+ if (wa.x > 0 && wa.y > 0 && wa.y >= wa.x)
+ {
+ *border = wa.x;
+ *caption = wa.y - *border;
+ return 1;
+ }
+
+ *border = 0;
+ *caption = 0;
+
+ return 0;
+}
+
+static int xGetWorkAreaSize(Display* display, int screen, int *width, int *height)
+{
+ /* _NET_WORKAREA, x, y, width, height CARDINAL[][4]/32 */
+ static Atom workarea = 0;
+ Atom type;
+ long *data;
+ int format;
+ unsigned long after, ndata;
+
+ if (!workarea)
+ workarea = XInternAtom(display, "_NET_WORKAREA", False);
+
+ XGetWindowProperty(display, RootWindow(display, screen),
+ workarea, 0, LONG_MAX, False, XA_CARDINAL, &type, &format, &ndata,
+ &after, (unsigned char **)&data);
+ if (type != XA_CARDINAL || data == NULL)
+ {
+ if (data) XFree(data);
+ return 0;
+ }
+
+ *width = data[2]; /* get only for the first desktop */
+ *height = data[3];
+
+ XFree(data);
+ return 1;
+}
+
+void iupdrvGetScreenSize(int *width, int *height)
+{
+ Display* display = (Display*)iupdrvGetDisplay();
+ int screen = XDefaultScreen(display);
+ if (!xGetWorkAreaSize(display, screen, width, height))
+ {
+ *width = DisplayWidth(display, screen);
+ *height = DisplayHeight(display, screen);
+ }
+}
+
+void iupdrvGetFullSize(int *width, int *height)
+{
+ Display* display = (Display*)iupdrvGetDisplay();
+ int screen = XDefaultScreen(display);
+ Window root = RootWindow(display, screen);
+ XWindowAttributes wa;
+ XGetWindowAttributes(display, root, &wa);
+ *width = wa.width;
+ *height = wa.height;
+}
+
+static int xCheckVisualInfo(Display* drv_display, int bpp)
+{
+ int nitems;
+ XVisualInfo info, *ret_info;
+
+ info.depth = bpp;
+ ret_info = XGetVisualInfo(drv_display, VisualDepthMask, &info, &nitems);
+ if (ret_info != NULL)
+ {
+ XFree(ret_info);
+ return 1;
+ }
+ return 0;
+}
+
+int iupdrvGetScreenDepth(void)
+{
+ static int first = 1;
+ static int bpp;
+
+ if (first)
+ {
+ Display* drv_display = (Display*)iupdrvGetDisplay();
+
+ if (xCheckVisualInfo(drv_display, 24))
+ {
+ bpp = 24;
+ return bpp;
+ }
+
+ if (xCheckVisualInfo(drv_display, 16))
+ {
+ bpp = 16;
+ return bpp;
+ }
+
+ if (xCheckVisualInfo(drv_display, 8))
+ {
+ bpp = 8;
+ return bpp;
+ }
+
+ if (xCheckVisualInfo(drv_display, 4))
+ {
+ bpp = 4;
+ return bpp;
+ }
+
+ bpp = 2;
+
+ first = 0;
+ }
+
+ return bpp;
+}
+
+void iupdrvGetCursorPos(int *x, int *y)
+{
+ Window root, child;
+ int cx, cy;
+ unsigned int keys;
+ Display* display = (Display*)iupdrvGetDisplay();
+ int screen = XDefaultScreen(display);
+
+ XQueryPointer(display, RootWindow(display, screen),
+ &root, &child, x, y, &cx, &cy, &keys);
+}
+
+static int xCheckModifier(KeyCode* modifiermap, int max_keypermod, int index, const char* keys)
+{
+ int i;
+ for (i = 0; i < max_keypermod; i++)
+ {
+ KeyCode key = modifiermap[max_keypermod * index + i];
+ if (key)
+ {
+ int KeyIndex = key / 8;
+ int KeyMask = 1 << (key % 8);
+ if (keys[KeyIndex] & KeyMask)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void iupdrvGetKeyState(char* key)
+{
+ char keys[32];
+ Display* display = (Display*)iupdrvGetDisplay();
+ XModifierKeymap *modMap = XGetModifierMapping(display);
+ XQueryKeymap(display, keys);
+
+ if (xCheckModifier(modMap->modifiermap, modMap->max_keypermod, ShiftMapIndex, keys))
+ key[0] = 'S';
+ else
+ key[0] = ' ';
+ if (xCheckModifier(modMap->modifiermap, modMap->max_keypermod, ControlMapIndex, keys))
+ key[1] = 'C';
+ else
+ key[1] = ' ';
+ if (xCheckModifier(modMap->modifiermap, modMap->max_keypermod, Mod1MapIndex, keys) ||
+ xCheckModifier(modMap->modifiermap, modMap->max_keypermod, Mod5MapIndex, keys))
+ key[2] = 'A';
+ else
+ key[2] = ' ';
+ if (xCheckModifier(modMap->modifiermap, modMap->max_keypermod, Mod4MapIndex, keys))
+ key[3] = 'Y';
+ else
+ key[3] = ' ';
+
+ key[4] = 0;
+
+ XFreeModifiermap(modMap);
+}
+
+char *iupdrvGetSystemName(void)
+{
+ struct utsname un;
+ char *str = iupStrGetMemory(50);
+
+ uname(&un);
+ strcpy(str, un.sysname);
+
+ return str;
+}
+
+char *iupdrvGetSystemVersion(void)
+{
+ struct utsname un;
+ char *str = iupStrGetMemory(60);
+
+ uname(&un);
+ strcpy(str, un.release);
+ strcat(str, ".");
+ strcat(str, un.version);
+
+ return str;
+}
+
+char *iupdrvGetComputerName(void)
+{
+ char* str = iupStrGetMemory(50);
+ gethostname(str, 50);
+ return str;
+}
+
+char *iupdrvGetUserName(void)
+{
+ return (char*)getlogin();
+}