2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
27 * (c) Copyright 1996 Digital Equipment Corporation.
28 * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company
29 * (c) Copyright 1993, 1994, 1996 International Business Machines Corp.
30 * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.
31 * (c) Copyright 1993, 1994, 1996 Novell, Inc.
32 * (c) Copyright 1996 FUJITSU LIMITED.
33 * (c) Copyright 1996 Hitachi.
38 "$XConsortium: ComboBox.c /main/15 1996/10/29 12:48:08 cde-hp $"
41 /***********************************************************
42 Copyright 1993 Interleaf, Inc.
44 Permission to use, copy, modify, and distribute this software
45 and its documentation for any purpose without fee is granted,
46 provided that the above copyright notice appear in all copies
47 and that both copyright notice and this permission notice appear
48 in supporting documentation, and that the name of Interleaf not
49 be used in advertising or publicly pertaining to distribution of
50 the software without specific written prior permission.
52 Interleaf makes no representation about the suitability of this
53 software for any purpose. It is provided "AS IS" without any
54 express or implied warranty.
55 ******************************************************************/
58 * (C) Copyright 1991,1992, 1993
63 * ComboBox.c (DtComboBoxWidget):
65 * I wanted a margin around the widget (outside the shadow, like buttons),
66 * so that the combo-box could be made the same size as a
67 * push-button, etc. The bulletin-board widget always puts the shadow at
68 * the outside edge of the widget, so combo-box is a sublcass of
69 * manager, and we do everything ourselves.
71 * One must be carefull when using Dimension (for core width and height).
72 * Dimension is an unsigned short. This causes problems when subtracting
73 * and ending up with what should be a negative number (but it doesn't).
74 * All child widget positioning is done by the combo_box. We don't
75 * use any heavy-weight forms, etc. to help us out.
77 * There is no padding when editable. If using a label given it a
78 * small margin, so it doesn't run up against the side of our
79 * shadow or the arrow.
81 * Make some of the ComboBox functions common, so they can be shared
84 * The label-string resource got out of control. Its role kept getting
85 * expanded; now the whole thing is a mess. Currently it shadows the
86 * label's label-string. If the user sets it explicitly it will
87 * take affect for as long as update-label is false. If update-label
88 * is true, it will take affect until the end-user makes a selection
92 * Changing margin_width or margin_height resources when the
93 * combo_box has focus will probably result in display glitches.
97 * The DtComboBox widget is rigged with the Motif widget binary compatibilit
98 * mechanism. All Motif-specific changes for this mechanism are preceded
99 * by a comment including the string "MotifBc".
101 * For a description of the Motif widget binary compatibility mechanism
102 * see the reference manual entry on XmResolveAllPartOffsets().
106 /* _NO_PROTO support no longer required: */
108 #include <Xm/XmP.h> /* for fast subclassing in XmIsComboBox */
109 #include <Xm/XmosP.h> /* for INT_MAX */
110 #include <Dt/DtMsgsP.h>
111 #include "ComboBoxP.h"
112 #include <Xm/DrawP.h>
113 #include <Xm/DisplayP.h>
115 #include <Xm/ComboBox.h> /* for redirecting utility functions */
116 #include "DtWidgetI.h" /* for _Dt thread-safety macros */
117 /* some unpublished Motif interfaces */
118 #include <Xm/XmPrivate.h>
120 /* From MenuUtilP.h */
121 extern int _XmGrabKeyboard(Widget widget, int owner_events, int pointer_mode,
122 int keyboard_mode, Time time) ;
126 #define DtComboBoxIndex (XmManagerIndex + 1)
127 static XmOffsetPtr ipot; /* Instance part offset table */
128 static XmOffsetPtr cpot; /* Constraint part offset table */
130 #define ScrollBarVisible( wid) (wid && XtIsManaged( wid))
132 static void ClassInitialize (void);
133 static void Initialize (DtComboBoxWidget request,
134 DtComboBoxWidget new, ArgList given_args,
136 static XmNavigability WidgetNavigable (DtComboBoxWidget combo);
137 static void _ComboBoxFocusIn (DtComboBoxWidget combo, XEvent *event,
138 char **params, Cardinal *num_params);
139 static void _ComboBoxFocusOut (DtComboBoxWidget combo, XEvent *event,
140 char **params, Cardinal *num_params);
141 static void DrawHighlight (DtComboBoxWidget combo, Boolean clear);
142 static void _ComboBoxActivate (Widget w, XEvent *event, char **params,
143 Cardinal *num_params);
144 static void _ComboBoxKbdCancel (Widget w, XEvent *event, char **params,
145 Cardinal *num_params);
146 static void _ComboBoxPrevTabGroup (Widget w, XEvent *event,
147 char **params, Cardinal *num_params);
148 static void _ComboBoxNextTabGroup (Widget w, XEvent *event,
149 char **params, Cardinal *num_params);
150 static void CheckResources (DtComboBoxWidget combo);
151 static void Destroy (DtComboBoxWidget combo);
152 static void Resize (DtComboBoxWidget combo);
153 static void Redisplay (DtComboBoxWidget w, XEvent *event,
155 static XtGeometryResult GeometryManager (Widget w,
156 XtWidgetGeometry *request,
157 XtWidgetGeometry *reply);
158 static void SetComboBoxSize (DtComboBoxWidget combo);
159 static void ForceChildSizes (DtComboBoxWidget combo);
160 static void LayoutChildren (DtComboBoxWidget combo);
161 static Boolean SetValues (DtComboBoxWidget current,
162 DtComboBoxWidget request, DtComboBoxWidget new);
163 static void ClearShadow (DtComboBoxWidget w, Boolean all);
164 static void DrawShadow (DtComboBoxWidget w);
165 static char* GetTextString (XmString xm_string);
166 static void SetTextFieldData (DtComboBoxPart *combo_p, XmString item);
167 static void SetMaximumLabelSize (DtComboBoxPart *combo_p);
168 static void SetLabelData (DtComboBoxPart *combo_p, XmString item,
169 Boolean force_label_string);
170 static void select_cb (Widget w, XtPointer client_data,
171 XtPointer call_data);
172 static void shell_event_handler (Widget widget, XtPointer client_data,
173 XEvent* event, Boolean *dispatch);
174 static void list_event_handler (Widget widget, XtPointer client_data,
175 XEvent* event, Boolean *dispatch);
176 static void TextFieldActivate (DtComboBoxPart *combo_p, XtPointer call_data);
177 static void activate_cb (Widget w, XtPointer client_data,
178 XtPointer call_data);
179 static void arrow_expose_cb (Widget w, XtPointer client_data,
180 XtPointer call_data);
181 static void text_losing_focus_cb (Widget w, XtPointer client_data,
182 XtPointer call_data);
183 static void text_activate_cb (Widget w, XtPointer client_data,
184 XtPointer call_data);
185 static void text_focus_cb (Widget w, XtPointer client_data,
186 XtPointer call_data);
187 static void SyncWithList (DtComboBoxPart *combo_p);
188 static XmImportOperator _XmSetSyntheticResForChild (Widget widget,
192 static Boolean _CvtStringToType (Display *dpy, XrmValuePtr args,
193 Cardinal *num_args, XrmValuePtr from, XrmValuePtr to, XtPointer *data);
195 /* Grab and Ungrab processing */
196 static void input_ungrab ( DtComboBoxWidget combo, int ungrab_mask);
198 /* Resolution Independent Processing */
199 void _DtComboBoxGetArrowSize( Widget w,
202 void _DtComboBoxGetListMarginHeight( Widget w,
205 void _DtComboBoxGetListMarginWidth( Widget w,
208 void _DtComboBoxGetListSpacing( Widget w,
213 static XmString InitLabel = NULL;
219 #define Arrow(w) XmField(w,ipot,DtComboBox,arrow,Widget)
220 #define Shell(w) XmField(w,ipot,DtComboBox,shell,Widget)
221 #define Frame(w) XmField(w,ipot,DtComboBox,frame,Widget)
222 #define Label(w) XmField(w,ipot,DtComboBox,label,Widget)
223 #define Sep(w) XmField(w,ipot,DtComboBox,sep,Widget)
224 #define OldWidth(w) XmField(w,ipot,DtComboBox,old_width,Dimension)
225 #define OldHeight(w) XmField(w,ipot,DtComboBox,old_height,Dimension)
226 #define LabelMaxLength(w) XmField(w,ipot,DtComboBox,label_max_length,Dimension)
227 #define LabelMaxHeight(w) XmField(w,ipot,DtComboBox,label_max_height,Dimension)
229 #define MaxShellWidth(w) XmField(w,ipot,DtComboBox,max_shell_width,Dimension)
230 #define MaxShellHeight(w) XmField(w,ipot,DtComboBox,max_shell_height,Dimension)
232 #define MarginHeight(w) XmField(w,ipot,DtComboBox,margin_height,Dimension)
233 #define MarginWidth(w) XmField(w,ipot,DtComboBox,margin_width,Dimension)
234 #define SelectedItem(w) XmField(w,ipot,DtComboBox,selected_item,XmString)
235 #define SelectedPosition(w) XmField(w,ipot,DtComboBox,selected_position,int)
236 #define SelectionCallback(w) \
237 XmField(w,ipot,DtComboBox,selection_callback,XtCallbackList)
238 #define Type(w) XmField(w,ipot,DtComboBox,type,unsigned char)
239 #define ArrowSpacing(w) XmField(w,ipot,DtComboBox,arrow_spacing,Dimension)
241 #define ArrowSize(w) XmField(w,ipot,DtComboBox,arrow_size,Dimension)
242 #define ActivateCallback(w) \
243 XmField(w,ipot,DtComboBox,activate_callback,XtCallbackList)
244 #define Alignment(w) XmField(w,ipot,DtComboBox,alignment,unsigned char)
245 #define ArrowType(w) XmField(w,ipot,DtComboBox,arrow_type,unsigned char)
246 #define TextColumns(w) XmField(w,ipot,DtComboBox,text_columns,short)
247 #define FocusCallback(w) XmField(w,ipot,DtComboBox,focus_callback,XtCallbackList)
248 #define HorizontalSpacing(w) XmField(w,ipot,DtComboBox,horizontal_spacing,Dimension)
249 #define ItemCount(w) XmField(w,ipot,DtComboBox,item_count,int)
250 #define Items(w) XmField(w,ipot,DtComboBox,items,XmStringTable)
251 #define ListItems(w) XmField(w,ipot,DtComboBox,list_items,XmStringTable)
252 #define LabelString(w) XmField(w,ipot,DtComboBox,label_string,XmString)
253 #define List(w) XmField(w,ipot,DtComboBox,list,Widget)
254 #define ListFontList(w) XmField(w,ipot,DtComboBox,list_font_list,XmFontList)
255 #define ListMarginHeight(w) XmField(w,ipot,DtComboBox,list_margin_height,Dimension)
256 #define ListMarginWidth(w) XmField(w,ipot,DtComboBox,list_margin_width,Dimension)
257 #define ListSpacing(w) XmField(w,ipot,DtComboBox,list_spacing,Dimension)
258 #define LosingFocusCallback(w) XmField(w,ipot,DtComboBox,losing_focus_callback,XtCallbackList)
259 #define TextMaxLength(w) XmField(w,ipot,DtComboBox,text_max_length,unsigned int)
260 #define MenuPostCallback(w) XmField(w,ipot,DtComboBox,menu_post_callback,XtCallbackList)
261 #define Orientation(w) XmField(w,ipot,DtComboBox,orientation,unsigned char)
262 #define PoppedUp(w) XmField(w,ipot,DtComboBox,popped_up,Boolean)
263 #define RecomputeSize(w) XmField(w,ipot,DtComboBox,recompute_size,Boolean)
264 #define Text(w) XmField(w,ipot,DtComboBox,text,Widget)
265 #define TopItemPosition(w) XmField(w,ipot,DtComboBox,top_item_position,int)
266 #define UpdateLabel(w) XmField(w,ipot,DtComboBox,update_label,Boolean)
267 #define VerticalSpacing(w) XmField(w,ipot,DtComboBox,vertical_spacing,Dimension)
268 #define VisibleItemCount(w) XmField(w,ipot,DtComboBox,visible_item_count,int)
271 * DtComboBoxWidget specific defines.
273 #define PUnitType(w) w->primitive.unit_type
274 #define ShellPoppedUp(w) w->shell.popped_up
275 #define MUnitType(w) w->manager.unit_type
276 #define COMBO_SHADOW(w) w->manager.shadow_thickness
277 #define LayoutDirection(w) w->manager.string_direction
278 #define NavigationType(w) w->manager.navigation_type
279 #define TraversalOn(w) w->manager.traversal_on
280 #define BackgroundGC(w) w->manager.background_GC
281 #define HighlightGC(w) w->manager.highlight_GC
282 #define TopShadowGC(w) w->manager.top_shadow_GC
283 #define BottomShadowGC(w) w->manager.bottom_shadow_GC
284 #define BackgroundPixel(w) w->core.background_pixel
285 #define X(w) w->core.x
286 #define Y(w) w->core.y
287 #define Width(w) w->core.width
288 #define Height(w) w->core.height
289 #define BorderWidth(w) w->core.border_width
290 #define Sensitive(w) w->core.sensitive
291 #define AncestorSensitive(w) w->core.ancestor_sensitive
292 #define Parent(w) w->core.parent
293 #define COMBO_MARGIN_W(w) MarginWidth(w)
294 #define COMBO_MARGIN_H(w) MarginHeight(w)
295 #define COMBO_H_SPACING(w) HorizontalSpacing(w)
296 #define COMBO_V_SPACING(w) VerticalSpacing(w)
298 #define GRAB_POINTER 1 << 0
299 #define GRAB_KEYBOARD 1 << 1
301 #define DtNonePopup 0
302 #define DtPopup 1 << 0
303 #define DtButtonPressPopup 1 << 1
304 #define DtKeyPressPopup 1 << 2
306 #define LIST_EVENTS (ButtonReleaseMask | FocusChangeMask | EnterWindowMask)
307 #define SHELL_EVENTS (ButtonPressMask | ButtonReleaseMask)
308 #define INVALID_DIMENSION (0xFFFF)
311 static char ComboBoxTranslationTable[] = "\
312 <FocusIn>: ComboBoxFocusIn() \n\
313 <FocusOut>: ComboBoxFocusOut() \n\
314 <Key>osfDown: ComboBoxActivate() \n\
315 <Btn1Down>: ComboBoxActivate() \n\
316 <Key>osfSelect: ComboBoxActivate() \n\
317 ~s ~m ~a <Key>space: ComboBoxActivate() \n\
320 static char ComboBoxLabelTranslationTable[] = "\
321 <Key>osfDown: ComboBoxActivate(label) \n\
322 <Btn1Down>: ComboBoxActivate(label) \n\
323 <Key>osfSelect: ComboBoxActivate(label) \n\
324 ~s ~m ~a <Key>space: ComboBoxActivate(label) \n\
327 /* Keyboard Only Traversing During Editable-Mode */
328 static char ComboBoxTextTranslationTable[] = "\
329 <Key>osfUp: ComboBoxActivate(label) \n\
330 <Key>osfDown: ComboBoxActivate(label) \n\
333 static char ComboBoxButtonTranslationTable[] = "\
334 <Key>osfDown: ComboBoxActivate(label) \n\
335 <Btn1Down>: ComboBoxActivate(label) \n\
336 ~s ~m ~a <Key>space: ComboBoxActivate(label) \n\
337 s ~m ~a <Key>Tab: ComboBoxPrevTabGroup()\n\
338 ~m ~a <Key>Tab: ComboBoxNextTabGroup()\n\
341 static char ComboBoxListTranslationTable[] = "\
342 <Key>osfCancel: ListKbdCancel() ComboBoxKbdCancel() \n\
345 static XtActionsRec ComboBoxActionTable[] = {
346 {"ComboBoxFocusIn", (XtActionProc)_ComboBoxFocusIn},
347 {"ComboBoxFocusOut", (XtActionProc)_ComboBoxFocusOut},
348 {"ComboBoxActivate", (XtActionProc)_ComboBoxActivate},
349 {"ComboBoxKbdCancel", (XtActionProc)_ComboBoxKbdCancel},
350 {"ComboBoxPrevTabGroup", (XtActionProc)_ComboBoxPrevTabGroup},
351 {"ComboBoxNextTabGroup", (XtActionProc)_ComboBoxNextTabGroup},
356 * DtComboBoxWidget resources
358 #define offset(field) XtOffset(DtComboBoxWidget, field)
359 #define DtOffset(field) XmPartOffset(DtComboBox,field)
360 static XmPartResource resources[] = {
361 {XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension,
362 sizeof(Dimension), offset(manager.shadow_thickness),
363 XmRImmediate, (XtPointer)TEXT_FIELD_SHADOW},
366 * ComboBox specific resources
368 {DtNactivateCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
369 DtOffset(activate_callback), XmRCallback,
371 {DtNalignment, DtCAlignment, XmRAlignment, sizeof(unsigned char),
372 DtOffset(alignment), XmRImmediate,
373 (XtPointer)DtALIGNMENT_END},
374 {DtNarrowSpacing, DtCArrowSpacing, XmRHorizontalDimension,
375 sizeof(Dimension), DtOffset(arrow_spacing),
376 XmRImmediate, (XtPointer)0},
377 {DtNarrowType, DtCArrowType, DtRArrowType, sizeof(unsigned char),
378 DtOffset(arrow_type), XmRImmediate, (XtPointer)DtMOTIF},
379 {DtNcolumns, DtCColumns, XmRShort, sizeof(short),
380 DtOffset(text_columns), XmRImmediate, (XtPointer)20},
381 {DtNfocusCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
382 DtOffset(focus_callback), XmRCallback,
384 {DtNhorizontalSpacing, DtCHorizontalSpacing, XmRHorizontalDimension,
385 sizeof(Dimension), DtOffset(horizontal_spacing),
386 XmRImmediate, (XtPointer)INVALID_DIMENSION},
387 {DtNitemCount, DtCItemCount, XmRInt, sizeof(int),
388 DtOffset(item_count), XmRImmediate, (XtPointer)0},
390 * items is used only for seeing if the user changed the list. It
391 * is only a pointer that reflects the current list's items.
393 {DtNitems, DtCItems, XmRXmStringTable, sizeof(XmStringTable),
394 DtOffset(items), XmRImmediate, (XtPointer)NULL},
395 {DtNlabelString, DtCXmString, XmRXmString, sizeof(XmString),
396 DtOffset(label_string), XmRImmediate, (XtPointer)NULL},
397 {DtNlist, DtCList, XmRWidget, sizeof(Widget),
398 DtOffset(list), XmRImmediate, (XtPointer)NULL},
399 {DtNlistFontList, DtCListFontList, XmRFontList, sizeof(XmFontList),
400 DtOffset(list_font_list), XmRImmediate, (XtPointer)NULL},
401 {DtNlistMarginHeight, DtCListMarginHeight, XmRVerticalDimension,
402 sizeof(Dimension), DtOffset(list_margin_height),
403 XmRImmediate, (XtPointer)MARGIN},
404 {DtNlistMarginWidth, DtCListMarginWidth, XmRHorizontalDimension,
405 sizeof(Dimension), DtOffset(list_margin_width),
406 XmRImmediate, (XtPointer)MARGIN},
407 {DtNlistSpacing, DtCListSpacing, XmRVerticalDimension,sizeof(Dimension),
408 DtOffset(list_spacing), XmRImmediate, (XtPointer)0},
409 {DtNlosingFocusCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
410 DtOffset(losing_focus_callback), XmRCallback,
412 {DtNmarginHeight, DtCMarginHeight, XmRVerticalDimension,
413 sizeof(Dimension), DtOffset(margin_height),
414 XmRImmediate, (XtPointer)MARGIN},
415 {DtNmarginWidth, DtCMarginWidth, XmRHorizontalDimension, sizeof(Dimension),
416 DtOffset(margin_width), XmRImmediate, (XtPointer)MARGIN},
417 {DtNmaxLength, DtCMaxLength, XmRInt, sizeof(unsigned int),
418 DtOffset(text_max_length), XmRImmediate, (XtPointer)INT_MAX},
419 {DtNmenuPostCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
420 DtOffset(menu_post_callback), XmRCallback, (XtPointer)NULL},
421 {DtNorientation, DtCOrientation, XmROrientation, sizeof(unsigned char),
422 DtOffset(orientation), XmRImmediate, (XtPointer)DtRIGHT},
423 {DtNpoppedUp, DtCPoppedUp, XmRBoolean, sizeof(Boolean),
424 DtOffset(popped_up), XmRImmediate, (XtPointer)FALSE},
425 {DtNrecomputeSize, DtCRecomputeSize, XmRBoolean, sizeof(Boolean),
426 DtOffset(recompute_size), XmRImmediate, (XtPointer)TRUE},
427 {DtNselectedItem, DtCXmString, XmRXmString, sizeof(XmString),
428 DtOffset(selected_item), XmRImmediate, (XtPointer)NULL},
429 {DtNselectedPosition, DtCSelectedPosition, XmRInt, sizeof(int),
430 DtOffset(selected_position), XmRImmediate, (XtPointer)0},
431 {DtNselectionCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
432 DtOffset(selection_callback), XmRCallback, (XtPointer)NULL},
433 {DtNtextField, DtCTextField, XmRWidget, sizeof(Widget),
434 DtOffset(text), XmRImmediate, (XtPointer)NULL},
435 {DtNtopItemPosition, DtCTopItemPosition, XmRInt, sizeof(int),
436 DtOffset(top_item_position), XmRImmediate, (XtPointer)1},
437 {DtNcomboBoxType, DtCComboBoxType, DtRComboBoxType, sizeof(unsigned char),
438 DtOffset(type), XmRImmediate,(XtPointer)DtDROP_DOWN_LIST},
439 {DtNupdateLabel, DtCUpdateLabel, XmRBoolean, sizeof(Boolean),
440 DtOffset(update_label), XmRImmediate, (XtPointer)TRUE},
441 {DtNvisibleItemCount, DtCVisibleItemCount, XmRInt, sizeof(int),
442 DtOffset(visible_item_count), XmRImmediate, (XtPointer)10},
443 {DtNverticalSpacing, DtCVerticalSpacing, XmRVerticalDimension,
444 sizeof(Dimension), DtOffset(vertical_spacing),
445 XmRImmediate, (XtPointer)INVALID_DIMENSION},
449 * List resources (used for GetValues).
451 static XmSyntheticResource syn_resources[] = {
452 {DtNarrowSpacing, sizeof(Dimension), DtOffset(arrow_spacing),
453 XmeFromHorizontalPixels, XmeToHorizontalPixels},
454 {DtNhorizontalSpacing, sizeof(Dimension), DtOffset(horizontal_spacing),
455 XmeFromHorizontalPixels, XmeToHorizontalPixels},
456 {DtNverticalSpacing, sizeof(Dimension), DtOffset(vertical_spacing),
457 XmeFromVerticalPixels, XmeToVerticalPixels},
458 {DtNmarginWidth, sizeof(Dimension), DtOffset(margin_width),
459 XmeFromHorizontalPixels, XmeToHorizontalPixels},
460 {DtNmarginHeight, sizeof(Dimension), DtOffset(margin_height),
461 XmeFromVerticalPixels, XmeToVerticalPixels},
462 {DtNarrowSize, sizeof(Dimension), DtOffset(arrow_size),
463 _DtComboBoxGetArrowSize, XmeToHorizontalPixels},
464 {DtNlabelString, sizeof(XmString), DtOffset(label_string),
465 _DtComboBoxGetLabelString, _XmSetSyntheticResForChild},
466 {DtNitemCount, sizeof(int), DtOffset(item_count),
467 _DtComboBoxGetListItemCount, _XmSetSyntheticResForChild},
468 {DtNitems, sizeof(XmStringTable), DtOffset(items),
469 _DtComboBoxGetListItems, _XmSetSyntheticResForChild},
470 {DtNlistFontList, sizeof(XmFontList), DtOffset(list_font_list),
471 _DtComboBoxGetListFontList, _XmSetSyntheticResForChild},
472 {DtNlistMarginHeight, sizeof(Dimension),
473 DtOffset(list_margin_height),
474 _DtComboBoxGetListMarginHeight, XmeToVerticalPixels},
475 {DtNlistMarginWidth, sizeof(Dimension),DtOffset(list_margin_width),
476 _DtComboBoxGetListMarginWidth, XmeToHorizontalPixels},
477 {DtNlistSpacing, sizeof(Dimension), DtOffset(list_spacing),
478 _DtComboBoxGetListSpacing, XmeToVerticalPixels},
479 {DtNtopItemPosition, sizeof(int), DtOffset(top_item_position),
480 _DtComboBoxGetListTopItemPosition, _XmSetSyntheticResForChild},
481 {DtNvisibleItemCount, sizeof(int), DtOffset(visible_item_count),
482 _DtComboBoxGetListVisibleItemCount, _XmSetSyntheticResForChild},
487 /* Need Class Extension for widget navigation */
488 static XmBaseClassExtRec baseClassExtRec = {
491 XmBaseClassExtVersion,
492 sizeof(XmBaseClassExtRec),
493 (XtInitProc)NULL, /* InitializePrehook */
494 (XtSetValuesFunc)NULL, /* SetValuesPrehook */
495 (XtInitProc)NULL, /* InitializePosthook */
496 (XtSetValuesFunc)NULL, /* SetValuesPosthook */
497 NULL, /* secondaryObjectClass */
498 (XtInitProc)NULL, /* secondaryCreate */
499 (XmGetSecResDataFunc)NULL, /* getSecRes data */
500 { 0 }, /* fastSubclass flags */
501 (XtArgsProc)NULL, /* getValuesPrehook */
502 (XtArgsProc)NULL, /* getValuesPosthook */
503 (XtWidgetClassProc)NULL, /* classPartInitPrehook */
504 (XtWidgetClassProc)NULL, /* classPartInitPosthook*/
505 NULL, /* ext_resources */
506 NULL, /* compiled_ext_resources*/
507 0, /* num_ext_resources */
508 FALSE, /* use_sub_resources */
509 (XmWidgetNavigableProc)WidgetNavigable,
510 /* widgetNavigable */
511 (XmFocusChangeProc)NULL, /* focusChange */
512 (XmWrapperData)NULL /* wrapperData */
516 * Define Class Record.
518 externaldef(dtcomboBoxclassrec) DtComboBoxClassRec dtComboBoxClassRec =
520 { /* core_class fields */
521 (WidgetClass)&(xmManagerClassRec), /* superclass */
522 (String)"DtComboBox", /* class_name */
523 (Cardinal)sizeof(DtComboBoxPart), /* widget_size */
524 (XtProc)ClassInitialize, /* class_initialize */
525 (XtWidgetClassProc)NULL, /* class_part_init */
526 (XtEnum)FALSE, /* class_inited */
527 (XtInitProc)Initialize, /* initialize */
528 (XtArgsProc)NULL, /* initialize_hook */
529 (XtRealizeProc)XtInheritRealize, /* realize */
530 (XtActionList)ComboBoxActionTable, /* actions */
531 (Cardinal)XtNumber(ComboBoxActionTable), /* num_actions */
532 (XtResourceList)resources, /* resources */
533 (Cardinal)XtNumber(resources), /* num_resources */
534 (XrmClass)NULLQUARK, /* xrm_class */
535 (Boolean)TRUE, /* compress_motion */
536 (XtEnum)XtExposeCompressMaximal, /* compress_exposure */
537 (Boolean)TRUE, /* compress_enterleave*/
538 (Boolean)FALSE, /* visible_interest */
539 (XtWidgetProc)Destroy, /* destroy */
540 (XtWidgetProc)Resize, /* resize */
541 (XtExposeProc)Redisplay, /* expose */
542 (XtSetValuesFunc)SetValues, /* set_values */
543 (XtArgsFunc)NULL, /* set values hook */
544 (XtAlmostProc)XtInheritSetValuesAlmost, /* set values almost */
545 (XtArgsProc)NULL, /* get values hook */
546 (XtAcceptFocusProc)NULL, /* accept_focus */
547 (XtVersionType)XtVersionDontCheck, /* Version */
548 (XtPointer)NULL, /* PRIVATE cb list */
549 (String)XtInheritTranslations, /* tm_table */
550 (XtGeometryHandler)XtInheritQueryGeometry, /* query_geom */
551 (XtStringProc)XtInheritDisplayAccelerator, /* display_accelerator*/
552 (XtPointer)&baseClassExtRec /* extension */
554 { /* composite_class fields */
555 (XtGeometryHandler)GeometryManager, /* geometry_manager */
556 (XtWidgetProc)XtInheritChangeManaged, /* change_managed */
557 (XtWidgetProc)XtInheritInsertChild, /* insert_child */
558 (XtWidgetProc)XtInheritDeleteChild, /* delete_child */
559 (XtPointer)NULL /* extension */
561 { /* constraint_class fields */
562 (XtResourceList)NULL, /* resources */
563 (Cardinal)0, /* num_resources */
564 (Cardinal)0, /* constraint_size */
565 (XtInitProc)NULL, /* initialize */
566 (XtWidgetProc)NULL, /* destroy */
567 (XtSetValuesFunc)NULL, /* set_values */
568 (XtPointer)NULL /* extension */
570 { /* manager class */
571 (String)XtInheritTranslations, /* translations */
572 (XmSyntheticResource*)syn_resources, /* syn resources */
573 (int)XtNumber(syn_resources), /* num syn_resources */
574 (XmSyntheticResource*)NULL, /* get_cont_resources */
575 (int)0, /* num_get_cont_resources */
576 (XmParentProcessProc)XmInheritParentProcess,/* parent_process */
577 (XtPointer)NULL /* extension */
579 { /* combo_box_class fields */
584 externaldef(dtcomboBoxwidgetclass) WidgetClass dtComboBoxWidgetClass =
585 (WidgetClass)&dtComboBoxClassRec;
586 /* Parse the translation tables only once for the whole class
588 static XtTranslations trans;
589 static XtTranslations list_trans;
590 static XtTranslations label_trans;
591 static XtTranslations text_trans;
592 static XtTranslations button_trans;
595 * Must set up the record type for the class extensions to work.
598 ClassInitialize(void)
600 baseClassExtRec.record_type = XmQmotif;
604 XmResolveAllPartOffsets(dtComboBoxWidgetClass, &ipot, &cpot);
605 /* Parse the translation tables here
607 trans = XtParseTranslationTable(ComboBoxTranslationTable);
608 list_trans = XtParseTranslationTable(ComboBoxListTranslationTable);
609 label_trans = XtParseTranslationTable(ComboBoxLabelTranslationTable);
610 text_trans = XtParseTranslationTable(ComboBoxTextTranslationTable);
611 button_trans =XtParseTranslationTable(ComboBoxButtonTranslationTable);
613 /* Add a type converter for String to DtRComboBoxType
615 XtSetTypeConverter("String","ComboBoxType", _CvtStringToType, NULL, 0,
618 InitLabel = XmStringCreateLocalized(CB_LABEL);
622 * ComboBox initialization function. This builds the widgets inside
623 * our widget, to get the correct layout. If the type resource
624 * is DtDROP_DOWN_COMBO_BOX, we create a textField; if FALSE, we create a
625 * label. If the user changes this resource later, we will create the
626 * other widget (textField or Label). We don't want to carry backage from
627 * both widgets if the user never changes the type resource.
630 Initialize( DtComboBoxWidget request,
631 DtComboBoxWidget new,
635 /* use the address of the first element of DtComboBoxPart structure
636 * as of DtComboBoxPart
638 DtComboBoxPart *combo_p = (DtComboBoxPart*)
639 &(XmField(new,ipot,DtComboBox,arrow,Widget));
640 Boolean force_label_string = FALSE;
643 /* Resolution Independent */
644 unsigned char unit_type = MUnitType(new);
646 /* Overwrite the manager's focusIn and focusOut translations */
647 XtOverrideTranslations((Widget)new, trans);
651 * force_label_string usage if it is specified and items is not.
652 * This will be the perminant label string only if update-label
653 * is false, else it is only used until the user picks something
656 if (LabelString(new) == NULL)
657 LabelString(new) = InitLabel;
658 else if (!Items(new))
659 force_label_string = TRUE;
661 /* Copy given label-string. */
662 if (LabelString(new))
663 LabelString(new) = XmStringCopy(LabelString(new));
665 Text(new) = (Widget)NULL;
666 Label(new) = (Widget)NULL;
667 Sep(new) = (Widget)NULL;
674 * Create the text or label depending on the type resource.
675 * When part of X-Designer, we create both at initialization to
676 * avoid later crashes.
678 if (Type(new) == DtDROP_DOWN_COMBO_BOX)
681 XtSetArg(args[n], XmNcolumns, TextColumns(new)); n++;
682 XtSetArg(args[n], XmNmaxLength, TextMaxLength(new)); n++;
683 XtSetArg(args[n], XmNmarginWidth, TEXT_CONTEXT_MARGIN); n++;
684 XtSetArg(args[n], XmNmarginHeight, 2); n++;
685 /* Resolution Independent */
686 if (unit_type != XmPIXELS) {
687 XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
689 Text(new) = XtCreateManagedWidget("Text",
690 xmTextFieldWidgetClass,
691 (Widget)new, args, n);
692 XtAddCallback(Text(new), XmNlosingFocusCallback,
693 text_losing_focus_cb, (XtPointer)new);
694 XtAddCallback(Text(new), XmNactivateCallback,
695 text_activate_cb, (XtPointer)new);
696 XtAddCallback(Text(new), XmNfocusCallback,
697 text_focus_cb, (XtPointer)new);
699 XtOverrideTranslations(Text(new), text_trans);
701 if (HorizontalSpacing(new) == INVALID_DIMENSION)
702 HorizontalSpacing(new) = 0;
703 if (VerticalSpacing(new) == INVALID_DIMENSION)
704 VerticalSpacing(new) = 0;
705 if (unit_type != XmPIXELS) {
706 XtSetArg(args[0], XmNunitType, unit_type);
707 XtSetValues(Text(new), args, 1);
712 XmStringDirection new_direction =
713 XmDirectionToStringDirection(LayoutDirection(new));
715 COMBO_SHADOW(new) = LABEL_SHADOW;
717 XtSetArg(args[n], XmNalignment, Alignment(new)); n++;
718 XtSetArg(args[n], XmNrecomputeSize, FALSE); n++;
719 XtSetArg(args[n], XmNlabelString, InitLabel); n++;
720 XtSetArg(args[n], XmNmarginLeft, LABEL_PADDING); n++;
721 XtSetArg(args[n], XmNmarginRight, LABEL_PADDING); n++;
722 XtSetArg(args[n], XmNmarginWidth, TEXT_CONTEXT_MARGIN); n++;
723 XtSetArg(args[n], XmNmarginHeight, 0); n++;
724 XtSetArg(args[n], XmNstringDirection, new_direction); n++;
725 /* Resolution Independent */
726 if (unit_type != XmPIXELS) {
727 XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
729 Label(new) = XtCreateManagedWidget("Label",
731 (Widget)new, args, n);
732 XtOverrideTranslations(Label(new), label_trans);
733 if (HorizontalSpacing(new) == INVALID_DIMENSION)
734 HorizontalSpacing(new) = 1;
735 if (VerticalSpacing(new) == INVALID_DIMENSION)
736 VerticalSpacing(new) = 2;
737 if (unit_type != XmPIXELS) {
738 XtSetArg(args[0], XmNunitType, unit_type);
739 XtSetValues(Label(new), args, 1);
744 * Create the separator used if non-editable combo-box.
746 if (Type(new) == DtDROP_DOWN_LIST)
749 XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
750 /* Resolution Independent */
751 if (unit_type != XmPIXELS) {
752 XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
754 Sep(new) = XtCreateManagedWidget("ComboBoxSeparator",
755 xmSeparatorWidgetClass,
756 (Widget)new, args, n);
758 XtOverrideTranslations((Widget)Sep(new), button_trans);
759 if (unit_type != XmPIXELS) {
760 XtSetArg(args[0], XmNunitType, unit_type);
761 XtSetValues(Sep(new), args, 1);
766 * Create the ArrowWidget.
769 XtSetArg(args[n], XmNtraversalOn, FALSE); n++;
770 XtSetArg(args[n], XmNhighlightThickness, 0); n++;
771 XtSetArg(args[n], XmNshadowThickness, 0); n++;
772 if (ArrowType(new) == DtMOTIF) {
773 XtSetArg(args[n], XmNarrowDirection, XmARROW_DOWN); n++;
774 XtSetArg(args[n], XmNforeground, BackgroundPixel(new)); n++;
775 Arrow(new) = XtCreateManagedWidget("ComboBoxArrow",
776 xmArrowButtonWidgetClass,
777 (Widget)new, args, n);
780 Arrow(new) = XtCreateManagedWidget("ComboBoxArrow",
781 xmDrawnButtonWidgetClass,
782 (Widget)new, args, n);
783 XtAddCallback(Arrow(new), XmNexposeCallback, arrow_expose_cb,
786 XtAddCallback(Arrow(new), XmNactivateCallback, activate_cb,
789 XtOverrideTranslations((Widget)Arrow(new), button_trans);
792 * Create the shell and associated list widgets.
795 XtSetArg(args[n], XtNoverrideRedirect, TRUE); n++;
796 XtSetArg(args[n], XtNallowShellResize, TRUE); n++;
797 XtSetArg(args[n], XtNsaveUnder, TRUE); n++;
798 Shell(new) = XtCreatePopupShell("ComboBoxMenuShell",
799 topLevelShellWidgetClass,
800 (Widget)new, args, n);
803 Frame(new) = XtCreateManagedWidget("ComboBoxRowColumn",
805 Shell(new), args, n);
808 /* Store combo widget in list for later use */
809 XtSetArg(args[n], XmNuserData, (XtPointer)new); n++;
810 if (ListFontList(new)) {
811 XtSetArg(args[n], XmNfontList, ListFontList(new)); n++;
813 /* to disable double click */
814 XtSetArg(args[n], XmNdoubleClickInterval, 0); n++;
815 XtSetArg(args[n], XmNitemCount, ItemCount(new)); n++;
816 XtSetArg(args[n], XmNitems, Items(new)); n++;
817 XtSetArg(args[n], XmNlistMarginHeight, ListMarginHeight(new)); n++;
818 XtSetArg(args[n], XmNlistMarginWidth, ListMarginWidth(new)); n++;
819 XtSetArg(args[n], XmNlistSpacing, ListSpacing(new)); n++;
821 XmStringDirection new_direction =
822 XmDirectionToStringDirection(LayoutDirection(new));
823 XtSetArg(args[n], XmNstringDirection, new_direction); n++;
825 XtSetArg(args[n], XmNtopItemPosition, TopItemPosition(new)); n++;
826 XtSetArg(args[n], XmNvisibleItemCount, VisibleItemCount(new)); n++;
827 XtSetArg(args[n], XmNlistSizePolicy, XmRESIZE_IF_POSSIBLE); n++;
828 XtSetArg(args[n], XmNselectionPolicy, XmBROWSE_SELECT); n++;
829 /* Resolution Independent */
830 if (unit_type != XmPIXELS) {
831 XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
833 List(new) = XmCreateScrolledList(Frame(new), "List", args, n);
834 XtOverrideTranslations((Widget)List(new), list_trans);
837 XtSetArg(args[n], XmNshadowThickness, (XtArgVal) 0); n++;
838 XtSetValues(XtParent(List(new)), args, n);
840 /* selected_item resource used before selected_position */
841 if (SelectedItem(new) && XmeStringIsValid(SelectedItem(new)) ) {
842 SelectedItem(new) =XmStringCopy(SelectedItem(new));
843 DtComboBoxSelectItem((Widget)new, SelectedItem(new));
846 SelectedItem(new) = (XmString) NULL;
847 if (SelectedPosition(new)<0 || SelectedPosition(new)>=ItemCount(new))
848 SelectedPosition(new) = 0;
850 XmListSelectPos(List(new), SelectedPosition(new) + 1, FALSE);
852 if (unit_type != XmPIXELS) {
853 XtSetArg(args[0], XmNunitType, unit_type);
854 XtSetValues(List(new), args, 1);
857 SyncWithList(combo_p);
858 XtManageChild(List(new));
859 XtRealizeWidget(Shell(new));
861 MaxShellWidth(new) = Width(((Widget) Shell(new)));
862 MaxShellHeight(new) = Height(((Widget) Shell(new)));
864 XtAddCallback(List(new), XmNdefaultActionCallback, select_cb, new);
865 XtAddCallback(List(new), XmNbrowseSelectionCallback, select_cb, new);
868 * Set up event handlers needed for handling grab states.
870 XtInsertEventHandler(List(new), LIST_EVENTS, TRUE,
871 (XtEventHandler)list_event_handler,
872 (XtPointer)new, XtListHead);
873 XtInsertEventHandler(Shell(new), SHELL_EVENTS, TRUE,
874 (XtEventHandler)shell_event_handler,
875 (XtPointer)new, XtListHead);
878 * Set initial value in text or label if items was specified
880 if (Type(new) == DtDROP_DOWN_LIST) {
881 SetMaximumLabelSize(combo_p);
882 SetLabelData(combo_p, NULL, force_label_string);
885 SetTextFieldData(combo_p, NULL);
887 SetComboBoxSize(new);
893 * Allow the manager to gain focus if not editable. If editable (using
894 * text-field), then let the toolkit give focus to the text-field.
896 static XmNavigability
897 WidgetNavigable(DtComboBoxWidget combo)
899 XmNavigationType nav_type = NavigationType(((XmManagerWidget)combo));
901 if (Sensitive(combo) && AncestorSensitive(combo) &&
902 TraversalOn(((XmManagerWidget)combo))) {
903 if ((nav_type == XmSTICKY_TAB_GROUP) ||
904 (nav_type == XmEXCLUSIVE_TAB_GROUP) ||
905 ((nav_type == XmTAB_GROUP) &&
906 !_XmShellIsExclusive((Widget)combo))) {
907 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
908 return(XmDESCENDANTS_TAB_NAVIGABLE);
910 return(XmTAB_NAVIGABLE);
912 return(XmDESCENDANTS_NAVIGABLE);
914 return(XmNOT_NAVIGABLE);
918 * The combo_box gets focus.
921 _ComboBoxFocusIn( DtComboBoxWidget combo,
924 Cardinal *num_params)
926 DrawHighlight(combo, FALSE);
930 * The combo_box loses focus. Only happens if not editable.
933 _ComboBoxFocusOut( DtComboBoxWidget combo,
936 Cardinal *num_params)
938 DrawHighlight(combo, TRUE);
942 * This function gets called whenever we draw or clear the shadow (to
943 * redraw highlight during resize, etc), as well as during focus_in
944 * and focus_out events.
947 DrawHighlight( DtComboBoxWidget combo,
952 if (XtIsRealized((Widget)combo)) {
954 rect[0].x = rect[1].x = rect[2].x = 0;
955 rect[3].x = OldWidth(combo) - COMBO_MARGIN_W(combo);
956 rect[0].y = rect[2].y = rect[3].y = 0 ;
957 rect[1].y = OldHeight(combo) - COMBO_MARGIN_H(combo);
958 rect[0].width = rect[1].width = OldWidth(combo);
959 rect[2].width = rect[3].width = COMBO_MARGIN_W(combo);
960 rect[0].height = rect[1].height = COMBO_MARGIN_H(combo);
961 rect[2].height = rect[3].height = OldHeight(combo);
962 XFillRectangles(XtDisplayOfObject((Widget)combo),
963 XtWindowOfObject((Widget)combo),
964 BackgroundGC(combo), rect, 4);
966 else if (XmGetFocusWidget((Widget)combo) == (Widget)combo) {
967 rect[0].x = rect[1].x = rect[2].x = 0;
968 rect[3].x = XtWidth(combo) - COMBO_MARGIN_W(combo);
969 rect[0].y = rect[2].y = rect[3].y = 0 ;
970 rect[1].y = XtHeight(combo) - COMBO_MARGIN_H(combo);
971 rect[0].width = rect[1].width = XtWidth(combo);
972 rect[2].width = rect[3].width = COMBO_MARGIN_W(combo);
973 rect[0].height = rect[1].height = COMBO_MARGIN_H(combo);
974 rect[2].height = rect[3].height = XtHeight(combo);
975 XFillRectangles(XtDisplayOfObject((Widget)combo),
976 XtWindowOfObject((Widget)combo),
977 HighlightGC(combo), rect, 4);
982 /* Add a global variable to avoid the handler to process the
983 * the ButtonPress which popup the shell
985 static int popup_shell_init=DtNonePopup;
988 * osfSelect virtual key hit. Simulate hitting the arrow.
991 _ComboBoxActivate( Widget w,
994 Cardinal *num_params)
996 DtComboBoxWidget combo;
997 XmAnyCallbackStruct cb;
999 if (*num_params == 0) /* no params means combo */
1000 combo = (DtComboBoxWidget)w;
1001 else /* params means label */
1003 combo = (DtComboBoxWidget)XtParent(w);
1007 if (event->type == KeyPress)
1008 popup_shell_init = DtKeyPressPopup;
1009 else if (event->type == ButtonPress)
1010 popup_shell_init = DtButtonPressPopup;
1012 popup_shell_init = DtPopup;
1015 cb.reason = XmCR_ACTIVATE;
1017 activate_cb((Widget)Arrow(combo), (XtPointer)combo, (XtPointer)&cb);
1021 * osfCancel virtual key hit.
1024 _ComboBoxKbdCancel( Widget w,
1027 Cardinal *num_params)
1029 DtComboBoxWidget combo;
1033 /* Get combo-box off list data */
1034 XtSetArg(args[0], XmNuserData, &data);
1035 XtGetValues(w, args, 1);
1037 combo = (DtComboBoxWidget)data;
1039 input_ungrab( combo, GRAB_POINTER | GRAB_KEYBOARD );
1043 * Tab Group Action for Buttons
1046 _ComboBoxPrevTabGroup( Widget w,
1049 Cardinal *num_params)
1051 XmProcessTraversal ((Widget)XtParent(w), XmTRAVERSE_PREV_TAB_GROUP);
1054 _ComboBoxNextTabGroup( Widget w,
1057 Cardinal *num_params)
1059 XmProcessTraversal ((Widget)XtParent(w), XmTRAVERSE_NEXT_TAB_GROUP);
1064 * This function goes through most of the resources and makes sure
1065 * they have legal values.
1068 CheckResources( DtComboBoxWidget combo)
1070 if ((Alignment(combo) != DtALIGNMENT_CENTER) &&
1071 (Alignment(combo) != DtALIGNMENT_BEGINNING) &&
1072 (Alignment(combo) != DtALIGNMENT_END)) {
1073 XtWarning(CB_ALIGNMENT);
1074 Alignment(combo) = DtALIGNMENT_CENTER;
1076 if ((Orientation(combo) != DtLEFT) &&
1077 (Orientation(combo) != DtRIGHT)) {
1078 XtWarning(CB_ORIENTATION);
1079 Orientation(combo) = DtRIGHT;
1081 if (ItemCount(combo) < 0) {
1082 XtWarning(CB_ITEM_COUNT);
1083 ItemCount(combo) = 0;
1085 if ((SelectedPosition(combo) < 0) ||
1086 ((SelectedPosition(combo) >= ItemCount(combo)) &&
1087 (ItemCount(combo) > 0))) {
1088 XtWarning(CB_VISIBLE_ITEM);
1089 SelectedPosition(combo) = 0;
1091 /* NEW: to adjust the size of the list to its content *
1092 if (ItemCount(combo) < VisibleItemCount(combo))
1093 VisibleItemCount(combo) = ItemCount(combo); */
1097 * Destroy procedure called by the toolkit. Free local resources
1100 Destroy(DtComboBoxWidget combo)
1102 if (LabelString(combo))
1103 XmStringFree(LabelString(combo));
1104 if (SelectedItem(combo))
1105 XmStringFree( SelectedItem(combo) );
1109 * Resize function called by toolkit. The size of our combo-box
1110 * has already been changed. That is why we must store
1111 * old_width and old_height.
1114 Resize(DtComboBoxWidget combo)
1116 ClearShadow(combo, TRUE);
1117 LayoutChildren(combo);
1119 OldWidth(combo) = Width(combo);
1120 OldHeight(combo) = Height(combo);
1125 * Redisplay function called by toolkit. The widget didn't change size,
1126 * so just redisplay the shadow.
1129 Redisplay( DtComboBoxWidget w,
1138 * GeometryManager function called by toolkit when a child resizes/moves.
1139 * We are not allowing any changes but width/height of the text-field.
1140 * this is because the user can retrieve the text-field and make changes
1141 * that we want to honor. If they mess around with the label or arrow,
1142 * then we won't honor the request.
1143 * If the text-field requests a change, then make the change, and allow
1144 * our SetComboBoxSize() and LayoutChildren() figure out what size will
1146 * Returning GeometryDone was suppose to tell the toolkit
1147 * that we resized the child ourselves, but the text-field had trouble
1148 * with this (its' geometry_manager wasn't called or working right?), so
1149 * we return GeometryYes.
1151 static XtGeometryResult
1152 GeometryManager(Widget w,
1153 XtWidgetGeometry *request,
1154 XtWidgetGeometry *reply)
1156 DtComboBoxWidget combo = (DtComboBoxWidget) Parent(w);
1158 /* Ignore everything but text-field */
1159 if (w != Text(combo))
1160 return(XtGeometryNo);
1162 /* Only allow width/height changes */
1163 if (!(request->request_mode & (CWWidth | CWHeight)))
1164 return(XtGeometryNo);
1166 /* Set the text-field to the requested size */
1167 if (request->request_mode & CWWidth)
1168 Width(w) = request->width;
1169 if (request->request_mode & CWHeight)
1170 Height(w) = request->height;
1171 XtResizeWidget(w, Width(w), Height(w), BorderWidth(w));
1173 ClearShadow(combo, TRUE);
1174 if (RecomputeSize(combo))
1175 SetComboBoxSize(combo);
1176 LayoutChildren(combo);
1178 return(XtGeometryYes);
1182 * This function sets the size of the combo_box widget based on the
1183 * current size of the children. Don't worry if it doesn't work, the
1184 * children will be squeezed in later.
1187 SetComboBoxSize(DtComboBoxWidget combo)
1189 Widget text_holder = ((Type(combo) == DtDROP_DOWN_COMBO_BOX) ?
1190 Text(combo) : Label(combo));
1191 Dimension shadow = COMBO_SHADOW(combo) * 2;
1192 Dimension h_spacing = COMBO_H_SPACING(combo) * 2;
1193 Dimension v_spacing = COMBO_V_SPACING(combo) * 2;
1194 Dimension arrow_width, text_width, text_height;
1195 Dimension sep_width = 0;
1196 XtGeometryResult ResizeResult;
1198 unsigned char unit_type = XmPIXELS;
1200 /* Resolution Independent */
1201 if (MUnitType(combo) != XmPIXELS) {
1202 unit_type = MUnitType(combo);
1203 XtSetArg(args[0], XmNunitType, XmPIXELS);
1204 XtSetValues(text_holder, args, 1);
1205 if (Type(combo) == DtDROP_DOWN_LIST)
1206 XtSetValues((Widget)Sep(combo), args, 1);
1210 * Find out how big the arrow can be (needed to get
1211 * available_width for text_holder).
1214 XtSetArg(args[0], XmNwidth, &text_width);
1215 XtSetArg(args[1], XmNheight, &text_height);
1216 XtGetValues(text_holder, args, 2);
1218 arrow_width = (Dimension)((float)text_height * ARROW_MULT);
1219 arrow_width = (arrow_width < ARROW_MIN) ? ARROW_MIN : arrow_width;
1221 if (Type(combo) == DtDROP_DOWN_LIST) {
1222 XtSetArg(args[0], XmNwidth, &sep_width);
1223 XtGetValues((Widget)Sep(combo), args, 1);
1226 ResizeResult=XtMakeResizeRequest((Widget)combo, arrow_width + sep_width +
1227 ArrowSpacing(combo) +
1228 text_width + shadow + h_spacing +
1229 (COMBO_MARGIN_W(combo) * 2),
1230 text_height + shadow + v_spacing +
1231 (COMBO_MARGIN_H(combo) * 2),
1233 if (ResizeResult==XtGeometryNo || ResizeResult==XtGeometryAlmost) {
1234 XtWarning(CB_RESIZE);
1236 OldWidth(combo) = Width(combo);
1237 OldHeight(combo) = Height(combo);
1239 /* Resolution Independent */
1240 if (unit_type != XmPIXELS) {
1241 XtSetArg(args[0], XmNunitType, unit_type);
1242 XtSetValues(text_holder, args, 1);
1243 if (Type(combo) == DtDROP_DOWN_LIST)
1244 XtSetValues((Widget)Sep(combo), args, 1);
1249 * This function makes the text_holder (label or text-field) smaller
1250 * if the combo_box couldn't grow to the needed full size. It will
1251 * also make the text_holder grow if there is space. The textfield will
1252 * grow with the combo_box, but the label will only grow to its'
1253 * maximum size. The label will also shrink down to nothing, but the
1254 * text-field will always keep its' core height.
1257 ForceChildSizes(DtComboBoxWidget combo)
1259 Dimension full_available_height, available_height, available_width;
1260 Dimension arrow_width;
1261 Dimension sep_width = 0;
1262 Dimension tmp_width, tmp_height, tmp_borderwidth;
1264 unsigned char unit_type = XmPIXELS;
1266 /* Resolution Independent */
1267 if (MUnitType(combo) != XmPIXELS) {
1268 unit_type = MUnitType(combo);
1269 XtSetArg(args[0], XmNunitType, XmPIXELS);
1270 if (Type(combo) == DtDROP_DOWN_LIST) {
1271 XtSetValues(Sep(combo), args, 1);
1272 XtSetValues(Label(combo), args, 1);
1275 XtSetValues(Text(combo), args, 1);
1276 XtSetValues(Arrow(combo), args, 1);
1278 /* Calculate available height for children */
1279 if ((available_height = Height(combo) - (COMBO_SHADOW(combo) * 2) -
1280 (COMBO_MARGIN_H(combo) * 2) - (COMBO_V_SPACING(combo) * 2)) <= 0) {
1281 full_available_height = available_height = 1;
1284 /* Seperator need available_height plus the vertical_spacing */
1285 full_available_height = (available_height +
1286 (COMBO_V_SPACING(combo) * 2));
1289 /* Get initial available width for children */
1290 available_width = (Width(combo) - (COMBO_SHADOW(combo) * 2) -
1291 (COMBO_MARGIN_W(combo) * 2) -
1292 (COMBO_H_SPACING(combo) * 2));
1294 /* label only grows to maximum width needed */
1295 if ((Type(combo) == DtDROP_DOWN_LIST) &&
1296 ((int)available_height > (int)LabelMaxHeight(combo)))
1297 available_height = LabelMaxHeight(combo);
1298 else if (Type(combo) == DtDROP_DOWN_COMBO_BOX) {
1299 XtSetArg(args[0], XmNheight, &available_height);
1300 XtGetValues((Widget)Text(combo), args, 1);
1304 * Find out how big the arrow can be (needed to get
1305 * available_width for text_holder).
1307 arrow_width = (Dimension)((float)available_height * ARROW_MULT);
1308 arrow_width = (arrow_width < ARROW_MIN) ? ARROW_MIN : arrow_width;
1310 if (Type(combo) == DtDROP_DOWN_LIST) {
1311 XtSetArg(args[0], XmNwidth, &sep_width);
1312 XtGetValues((Widget)Sep(combo), args, 1);
1315 /* Make sure width isn't too small or too big */
1316 if ((available_width -=
1317 (arrow_width + sep_width + ArrowSpacing(combo) )) <= (Dimension)0)
1318 available_width = 1;
1321 XtSetArg(args[0], XmNwidth, &tmp_width);
1322 XtSetArg(args[1], XmNheight, &tmp_height);
1323 XtSetArg(args[2], XmNborderWidth, &tmp_borderwidth);
1324 if (Type(combo) == DtDROP_DOWN_LIST) { /** label **/
1325 if ((int)available_width > (int)LabelMaxLength(combo))
1326 available_width = LabelMaxLength(combo);
1329 XtGetValues((Widget)Label(combo), args, 3);
1330 if ((available_width != tmp_width) ||
1331 (available_height != tmp_height))
1332 XtResizeWidget(Label(combo), available_width, available_height,
1335 XtGetValues((Widget)Sep(combo), args, 3);
1336 if (full_available_height != tmp_height)
1337 XtResizeWidget(Sep(combo), tmp_width, full_available_height,
1342 XtGetValues((Widget)Text(combo), args, 3);
1343 if ( Width(((Widget)Text(combo))) != available_width) /** TextField **/
1344 XtResizeWidget(Text(combo), available_width,
1345 tmp_height, tmp_borderwidth);
1349 XtGetValues((Widget)Arrow(combo), args, 3);
1350 if ((arrow_width != tmp_width) || (tmp_height != available_height)) {
1351 available_height = (available_height < ARROW_MIN) ? ARROW_MIN :
1353 XtResizeWidget(Arrow(combo), arrow_width, available_height,
1357 /* Resolution Independent */
1358 if (unit_type != XmPIXELS) {
1359 XtSetArg(args[0], XmNunitType, unit_type);
1360 if (Type(combo) == DtDROP_DOWN_LIST) {
1361 XtSetValues(Sep(combo), args, 1);
1362 XtSetValues(Label(combo), args, 1);
1365 XtSetValues(Text(combo), args, 1);
1366 XtSetValues(Arrow(combo), args, 1);
1371 * This function positions the children within the combo_box widget.
1372 * It calls ForceChildSizes() to make sure the children fit within the
1373 * combo_box widget, but it will not try to resize the combo_box widget.
1376 LayoutChildren(DtComboBoxWidget combo)
1378 Widget text_holder = ((Type(combo) == DtDROP_DOWN_COMBO_BOX)
1379 ? Text(combo) : Label(combo));
1380 Position start_x = (COMBO_SHADOW(combo) + COMBO_MARGIN_W(combo) +
1381 COMBO_H_SPACING(combo));
1382 Position start_y = (COMBO_SHADOW(combo) + COMBO_MARGIN_H(combo) +
1383 COMBO_V_SPACING(combo));
1384 short available_height = Height(combo) - (start_y * 2);
1385 Position y, arrow_y;
1386 unsigned char unit_type = XmPIXELS;
1387 Dimension tmp_width, tmp_height, sep_width;
1390 ForceChildSizes(combo);
1392 /* Resolution Independent */
1393 if (MUnitType(combo) != XmPIXELS) {
1394 unit_type = MUnitType(combo);
1395 XtSetArg(args[0], XmNunitType, XmPIXELS);
1396 XtSetValues(text_holder, args, 1);
1397 XtSetValues(Arrow(combo), args, 1);
1398 if (Type(combo) == DtDROP_DOWN_LIST)
1399 XtSetValues(Sep(combo), args, 1);
1401 /* Center text_holder within combo_box */
1403 XtSetArg(args[0], XmNheight, &tmp_height);
1404 XtGetValues(text_holder, args, 1);
1405 y = available_height - tmp_height;
1406 y = ((y < 0) ? 0 : y)/2 + start_y;
1408 /* Center arrow within combo_box */
1410 XtSetArg(args[1], XmNwidth, &tmp_width);
1411 XtGetValues(Arrow(combo), args, 2);
1412 arrow_y = available_height - tmp_height;
1413 arrow_y = ((arrow_y < 0) ? 0 : arrow_y)/2 + start_y;
1416 if (Type(combo) == DtDROP_DOWN_LIST) {
1417 XtSetArg(args[0], XmNwidth, &sep_width);
1418 XtGetValues(Sep(combo), args, 1);
1420 if (Orientation(combo) == DtLEFT) {
1421 XtMoveWidget(Arrow(combo), start_x, arrow_y);
1422 start_x += tmp_width;
1423 if (Type(combo) == DtDROP_DOWN_LIST) {
1424 XtMoveWidget(Sep(combo), start_x, start_y -
1425 COMBO_V_SPACING(combo));
1426 start_x += sep_width;
1428 start_x += ArrowSpacing(combo);
1429 XtMoveWidget(text_holder, start_x, y);
1432 XtMoveWidget(text_holder, start_x, y);
1434 * We want the arrow at the end of the combo_box, so
1435 * the user can use recompute_size more effectively.
1437 start_x = Width(combo) - start_x - tmp_width;
1438 if (Type(combo) == DtDROP_DOWN_LIST) {
1439 start_x -= sep_width;
1440 XtMoveWidget(Sep(combo), start_x, start_y -
1441 COMBO_V_SPACING(combo));
1442 start_x += sep_width;
1444 XtMoveWidget(Arrow(combo), start_x, arrow_y);
1447 /* Resolution Independent */
1448 if (unit_type != XmPIXELS) {
1449 XtSetArg(args[0], XmNunitType, unit_type);
1450 XtSetValues(text_holder, args, 1);
1451 XtSetValues(Arrow(combo), args, 1);
1452 if (Type(combo) == DtDROP_DOWN_LIST)
1453 XtSetValues(Sep(combo), args, 1);
1458 * SetValues() routine for ComboBox widget.
1461 SetValues( DtComboBoxWidget current,
1462 DtComboBoxWidget request,
1463 DtComboBoxWidget new)
1465 DtComboBoxPart *new_p = (DtComboBoxPart*)
1466 &(XmField(new,ipot,DtComboBox,arrow,Widget));
1467 Boolean label_size_changed = FALSE;
1468 Boolean force_label_string = FALSE;
1471 unsigned char new_unit_type = XmPIXELS, curr_unit_type = XmPIXELS;
1473 CheckResources(new);
1475 /* Resolution Independent */
1476 if (MUnitType(new) != XmPIXELS) {
1477 new_unit_type = MUnitType(new);
1478 XtSetArg(args[0], XmNunitType, XmPIXELS);
1479 if (Arrow(new)) XtSetValues(Arrow(new), args, 1);
1480 if (List(new)) XtSetValues(List(new), args, 1);
1481 if (Shell(new)) XtSetValues(Shell(new), args, 1);
1482 if (Label(new)) XtSetValues(Label(new), args, 1);
1483 if (Text(new)) XtSetValues(Text(new), args, 1);
1484 if (Sep(new)) XtSetValues(Sep(new), args, 1);
1486 if (MUnitType(current) != XmPIXELS) {
1487 curr_unit_type = MUnitType(current);
1488 XtSetArg(args[0], XmNunitType, XmPIXELS);
1489 if (Arrow(current)) XtSetValues(Arrow(current), args, 1);
1490 if (List(current)) XtSetValues(List(current), args, 1);
1491 if (Shell(current)) XtSetValues(Shell(current), args, 1);
1492 if (Label(current)) XtSetValues(Label(current), args, 1);
1493 if (Text(current)) XtSetValues(Text(current), args, 1);
1494 if (Sep(current)) XtSetValues(Sep(current), args, 1);
1497 if (Text(new) != Text(current)) {
1499 Text(new) = Text(current);
1503 * Pass any list specific resources on to our List Widget.
1504 * Check each one, since it's too costly to always set them.
1507 if (ItemCount(new) != ItemCount(current)){
1508 if (Items(new) && (ItemCount(new) < 0)) {
1509 XtWarning(CB_ITEM_COUNT);
1512 XtSetArg(args[n], XmNitemCount, ItemCount(new)); n++;
1514 if (Items(new) != ListItems(current)) {
1515 XtSetArg(args[n], XmNitems, Items(new)); n++;
1516 /* Make sure itemCount will get sent to list */
1517 if (ItemCount(new) == ItemCount(current)) {
1518 XtSetArg(args[n], XmNitemCount, ItemCount(new)); n++;
1521 if (ListFontList(new) != ListFontList(current)) {
1522 XtSetArg(args[n], XmNfontList, ListFontList(new)); n++;
1524 if (ListMarginHeight(new) != ListMarginHeight(current)) {
1525 XtSetArg(args[n], XmNlistMarginHeight, ListMarginHeight(new)); n++;
1527 if (ListMarginWidth(new) != ListMarginWidth(current)) {
1528 XtSetArg(args[n], XmNlistMarginWidth, ListMarginWidth(new)); n++;
1530 if (ListSpacing(new) != ListSpacing(current)) {
1531 XtSetArg(args[n], XmNlistSpacing, ListSpacing(new)); n++;
1533 if (LayoutDirection(new) != LayoutDirection(current)) {
1534 XmStringDirection new_direction =
1535 XmDirectionToStringDirection(LayoutDirection(new));
1536 XtSetArg(args[n], XmNstringDirection, new_direction); n++;
1538 if (TopItemPosition(new) != TopItemPosition(current)) {
1539 XtSetArg(args[n], XmNtopItemPosition, TopItemPosition(new)); n++;
1541 if (VisibleItemCount(new) != VisibleItemCount(current)) {
1542 XtSetArg(args[n], XmNvisibleItemCount, VisibleItemCount(new)); n++;
1547 Dimension tmp_width, tmp_height;
1549 XtSetValues(List(new), args, n);
1551 XtSetArg(tmp_arg[0], XmNwidth, &tmp_width);
1552 XtSetArg(tmp_arg[1], XmNheight, &tmp_height);
1553 XtGetValues(((Widget) Shell(new)), tmp_arg, 2);
1554 MaxShellWidth(new) = tmp_width;
1555 MaxShellHeight(new) = tmp_height;
1558 /* If arrow type changes delete the old one and create the new one */
1559 if (ArrowType(new) != ArrowType(current)) {
1560 XtRemoveCallback(Arrow(new), XmNactivateCallback, activate_cb,
1562 if (ArrowType(current) == DtWINDOWS)
1563 XtRemoveCallback(Arrow(new), XmNexposeCallback,
1564 arrow_expose_cb, (XtPointer)new);
1565 XtDestroyWidget(Arrow(new));
1568 XtSetArg(args[n], XmNtraversalOn, FALSE); n++;
1569 XtSetArg(args[n], XmNhighlightThickness, 0); n++;
1570 XtSetArg(args[n], XmNshadowThickness, 0); n++;
1571 if (ArrowType(new) == DtMOTIF) {
1572 XtSetArg(args[n], XmNarrowDirection, XmARROW_DOWN); n++;
1573 XtSetArg(args[n], XmNforeground, BackgroundPixel(new)); n++;
1574 Arrow(new) = XtCreateManagedWidget("ComboBoxArrow",
1575 xmArrowButtonWidgetClass,
1576 (Widget)new, args, n);
1579 Arrow(new) = XtCreateManagedWidget("ComboBoxArrow",
1580 xmDrawnButtonWidgetClass,
1581 (Widget)new, args, n);
1582 XtAddCallback(Arrow(new), XmNexposeCallback, arrow_expose_cb,
1585 XtAddCallback(Arrow(new), XmNactivateCallback, activate_cb,
1590 * Type resource changed. If the widget (textField or Label)
1591 * doesn't exist, then create it. Always reset orientation
1592 * constraint resources when type changes; otherwise, the
1593 * text_holder widget positioning could be screwed up. We don't
1594 * reset both widgets if the orientation changes (because we might
1595 * not have created both widgets).
1596 * If label must be created, also create the separator widget.
1598 if (Type(new) != Type(current)) {
1599 if (Type(new) == DtDROP_DOWN_COMBO_BOX) {
1600 if (Text(new) == NULL) {
1602 XtSetArg(args[n], XmNcolumns, TextColumns(new)); n++;
1603 XtSetArg(args[n], XmNmaxLength, TextMaxLength(new)); n++;
1604 XtSetArg(args[n], XmNmarginWidth, 2); n++;
1605 XtSetArg(args[n], XmNmarginHeight, 2); n++;
1606 Text(new) = XtCreateWidget("ComboBoxTextField",
1607 xmTextFieldWidgetClass,
1608 (Widget)new, args, n);
1609 XtAddCallback(Text(new), XmNlosingFocusCallback,
1610 text_losing_focus_cb, (XtPointer)new);
1611 XtAddCallback(Text(new), XmNactivateCallback,
1612 text_activate_cb, (XtPointer)new);
1613 XtAddCallback(Text(new), XmNfocusCallback,
1614 text_focus_cb, (XtPointer)new);
1615 if (HorizontalSpacing(new) == HorizontalSpacing(current))
1616 HorizontalSpacing(new) = 0;
1617 if (VerticalSpacing(new) == VerticalSpacing(current))
1618 VerticalSpacing(new) = 0;
1620 XtUnmanageChild(Sep(new));
1621 XtUnmanageChild(Label(new));
1622 XtManageChild(Text(new));
1625 if (Label(new) == NULL) {
1626 XmStringDirection new_direction =
1627 XmDirectionToStringDirection(LayoutDirection(new));
1629 XtTranslations label_trans =
1630 XtParseTranslationTable(ComboBoxLabelTranslationTable);
1633 XtSetArg(args[n], XmNalignment, Alignment(new)); n++;
1634 XtSetArg(args[n], XmNrecomputeSize, FALSE); n++;
1635 XtSetArg(args[n], XmNmarginLeft, LABEL_PADDING); n++;
1636 XtSetArg(args[n], XmNmarginRight, LABEL_PADDING); n++;
1637 XtSetArg(args[n], XmNmarginWidth, TEXT_CONTEXT_MARGIN); n++;
1638 XtSetArg(args[n], XmNmarginHeight, 0); n++;
1639 XtSetArg(args[n], XmNstringDirection, new_direction); n++;
1640 Label(new) = XtCreateWidget("ComboBoxLabel",
1642 (Widget)new, args, n);
1643 XtOverrideTranslations((Widget)Label(new), label_trans);
1644 if (HorizontalSpacing(new) == HorizontalSpacing(current))
1645 HorizontalSpacing(new) = 1;
1646 if (VerticalSpacing(new) == VerticalSpacing(current))
1647 VerticalSpacing(new) = 2;
1650 XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
1651 Sep(new) = XtCreateWidget("ComboBoxSeparator",
1652 xmSeparatorWidgetClass,
1653 (Widget)new, args, n);
1655 else if (LayoutDirection(new) != LayoutDirection(current)) {
1656 XmStringDirection new_direction =
1657 XmDirectionToStringDirection(LayoutDirection(new));
1658 XtSetArg(args[0], XmNstringDirection, new_direction);
1659 XtSetValues(Label(new), args, 1);
1661 XtUnmanageChild(Text(new));
1662 XtManageChild(Label(new));
1663 XtManageChild(Sep(new));
1666 * Text-fields and labels have different shadows. Only
1667 * change if user didn't change the shadow resource.
1669 if (COMBO_SHADOW(new) == COMBO_SHADOW(current))
1670 COMBO_SHADOW(new) = ((Type(new) == DtDROP_DOWN_COMBO_BOX) ?
1671 TEXT_FIELD_SHADOW : LABEL_SHADOW);
1674 if (Text(new) && (Text(new) == Text(current))) {
1676 if (TextColumns(new) != TextColumns(current)) {
1677 XtSetArg(args[n], XmNcolumns, TextColumns(new)); n++;
1679 if (TextMaxLength(new) != TextMaxLength(current) ) {
1680 XtSetArg(args[n], XmNmaxLength, TextMaxLength(new)); n++;
1683 XtSetValues(Text(new), args, n);
1687 * LabelWidget alignment has changed.
1689 if (Label(new) && (Alignment(new) != Alignment(current))) {
1690 XtSetArg(args[0], XmNalignment, Alignment(new));
1691 XtSetValues(Label(new), args, 1);
1694 if (Label(new) && ((Items(new) != ListItems(current)) ||
1695 (ItemCount(new) != ItemCount(current)) ||
1696 (Label(new) != Label(current)))) {
1697 SetMaximumLabelSize(new_p);
1698 label_size_changed = TRUE;
1701 /* Copy and free label-string */
1702 if (LabelString(new) != LabelString(current)) {
1703 if (LabelString(new))
1704 LabelString(new) = XmStringCopy(LabelString(new));
1705 if (LabelString(current))
1706 XmStringFree(LabelString(current));
1708 * force_label_string usage if it is specified and items is not.
1709 * This will be the perminant label string only if update-label
1710 * is false, else it is only used until the user picks something
1713 if (Items(new) == ListItems(current))
1714 force_label_string = TRUE;
1717 if ((Items(new) != ListItems(current)) ||
1718 (Alignment(new) != Alignment(current)) ||
1719 (Type(new) != Type(current)) ||
1720 (ItemCount(new) != ItemCount(current)) ||
1721 (SelectedPosition(new) != SelectedPosition(current)) ||
1722 (XmStringByteCompare(SelectedItem(new), SelectedItem(current))!=True) ||
1723 (Label(new) != Label(current)) ||
1724 (UpdateLabel(new) != UpdateLabel(current)) ||
1725 (LabelString(new) != LabelString(current))) {
1727 /* selected_item resource used before selected_position */
1728 if (SelectedItem(new) && XmeStringIsValid(SelectedItem(new)) &&
1729 (XmStringByteCompare(SelectedItem(new),
1730 SelectedItem(current))!=True) ){
1731 if (SelectedItem(current)) {
1732 XmStringFree(SelectedItem(current));
1733 SelectedItem(current) = NULL;
1735 SelectedItem(new) = XmStringCopy(SelectedItem(new));
1736 DtComboBoxSelectItem((Widget)new, SelectedItem(new));
1739 if (SelectedPosition(new)<0||SelectedPosition(new)>=ItemCount(new))
1740 SelectedPosition(new) = 0;
1741 if ((ItemCount(new)) &&
1742 (SelectedPosition(new) != SelectedPosition(current))) {
1744 XmListSelectPos(List(new), SelectedPosition(new) + 1, FALSE);
1745 if (SelectedItem(current)) {
1747 XmStringFree(SelectedItem(current));
1748 SelectedItem(current) = NULL;
1750 SyncWithList(new_p);
1752 XmStringCopy((ListItems(new))[SelectedPosition(new)]);
1755 /* Else, same item selected as last time */
1757 SelectedItem(new) = XmStringCopy(SelectedItem(new));
1758 if ((SelectedItem(new) != NULL) && (ListItems(new) != NULL))
1759 DtComboBoxSelectItem((Widget)new, SelectedItem(new));
1760 if (SelectedItem(current)) {
1761 XmStringFree(SelectedItem(current));
1762 SelectedItem(current) = NULL;
1767 if (Type(new) == DtDROP_DOWN_COMBO_BOX)
1768 SetTextFieldData(new_p, NULL);
1770 SetLabelData(new_p, NULL, force_label_string);
1773 /* Else, same item selected as last time */
1775 SelectedItem(new) = XmStringCopy(SelectedItem(new));
1776 if ((SelectedItem(new) != NULL) && (ListItems(new) != NULL))
1777 DtComboBoxSelectItem((Widget)new, SelectedItem(new));
1778 if (SelectedItem(current)) {
1779 XmStringFree(SelectedItem(current));
1780 SelectedItem(current) = NULL;
1785 * Must recalculate the combo_box and re-layout the children.
1786 * If this is not editable, then set the label to its' maximum
1787 * size; it will get chopped if it is too big. This is needed
1788 * because we shrink the label down, and SetComboBoxSize() uses
1789 * the label's core sizes to figure what size to become.
1791 if ((Type(new) != Type(current)) ||
1792 (ArrowType(new) != ArrowType(current)) ||
1793 (COMBO_MARGIN_W(new) != COMBO_MARGIN_W(current)) ||
1794 (COMBO_MARGIN_H(new) != COMBO_MARGIN_H(current)) ||
1795 (COMBO_H_SPACING(new) != COMBO_H_SPACING(current)) ||
1796 (COMBO_V_SPACING(new) != COMBO_V_SPACING(current)) ||
1797 (COMBO_SHADOW(new) != COMBO_SHADOW(current)) ||
1798 (Orientation(new) != Orientation(current)) ||
1799 (ArrowSpacing(new) != ArrowSpacing(current)) ||
1800 ((Type(new) == DtDROP_DOWN_LIST) && label_size_changed)) {
1801 ClearShadow(current, TRUE);
1802 if (RecomputeSize(new))
1803 SetComboBoxSize(new);
1804 LayoutChildren(new);
1808 SyncWithList(new_p);
1809 /* Resolution Independent */
1810 if (new_unit_type != XmPIXELS) {
1811 XtSetArg(args[0], XmNunitType, new_unit_type);
1812 if (Arrow(new)) XtSetValues(Arrow(new), args, 1);
1813 if (List(new)) XtSetValues(List(new), args, 1);
1814 if (Shell(new)) XtSetValues(Shell(new), args, 1);
1815 if (Label(new)) XtSetValues(Label(new), args, 1);
1816 if (Text(new)) XtSetValues(Text(new), args, 1);
1817 if (Sep(new)) XtSetValues(Sep(new), args, 1);
1819 if (curr_unit_type != XmPIXELS) {
1820 XtSetArg(args[0], XmNunitType, curr_unit_type);
1821 if (Arrow(current)) XtSetValues(Arrow(current), args, 1);
1822 if (List(current)) XtSetValues(List(current), args, 1);
1823 if (Shell(current)) XtSetValues(Shell(current), args, 1);
1824 if (Label(current)) XtSetValues(Label(current), args, 1);
1825 if (Text(current)) XtSetValues(Text(current), args, 1);
1826 if (Sep(current)) XtSetValues(Sep(current), args, 1);
1833 * This function clears the shadow around our widget. If all is TRUE,
1834 * then clear all 4 sides; otherwise, only clear the right and bottom
1835 * sides (during resize).
1838 ClearShadow( DtComboBoxWidget w,
1841 Dimension shadow = COMBO_SHADOW(w);
1842 Dimension margin_w = COMBO_MARGIN_W(w);
1843 Dimension margin_h = COMBO_MARGIN_H(w);
1845 if ((shadow > 0) && XtIsRealized((Widget)w)) {
1847 XClearArea(XtDisplayOfObject((Widget)w),
1848 XtWindowOfObject((Widget)w),
1850 OldWidth(w) - (margin_w * 2),
1852 XClearArea(XtDisplayOfObject((Widget)w),
1853 XtWindowOfObject((Widget)w),
1854 margin_w, margin_h, shadow,
1855 OldHeight(w) - (margin_h * 2), FALSE);
1857 XClearArea(XtDisplayOfObject((Widget)w),
1858 XtWindowOfObject((Widget)w), margin_w,
1859 OldHeight(w) - margin_h - shadow,
1860 OldWidth(w) - (margin_w * 2), shadow, FALSE);
1861 XClearArea(XtDisplayOfObject((Widget)w), XtWindowOfObject((Widget)w),
1862 OldWidth(w) - margin_w - shadow,
1864 OldHeight(w) - (margin_h * 2), FALSE);
1866 DrawHighlight(w, TRUE);
1870 * This functions draws the shadow around our combo-box.
1873 DrawShadow(DtComboBoxWidget w)
1875 Dimension shadow = COMBO_SHADOW(w);
1876 Dimension margin_w = COMBO_MARGIN_W(w);
1877 Dimension margin_h = COMBO_MARGIN_H(w);
1879 if ((shadow > 0) && XtIsRealized((Widget)w)) {
1880 XmeDrawShadows(XtDisplayOfObject((Widget)w),
1881 XtWindowOfObject((Widget)w),
1885 Width(w) - (margin_w * 2),
1886 Height(w) - (margin_h * 2),
1887 shadow, XmSHADOW_OUT);
1889 DrawHighlight(w, FALSE);
1893 * Take the string out of the list and put it into the text-field.
1894 * text-fields don't handle xm-strings, so we must get the char*
1895 * out of it (only getting the first segment). This is slower than
1896 * storing the text-strings (char*) ourselves, but that would take
1897 * up a lot of memory. Since this setting happens during a user
1898 * action, speed isn't a problem.
1901 SetTextFieldData(DtComboBoxPart *combo_p, XmString item)
1903 XmListWidget list = (XmListWidget)combo_p->list;
1904 XmStringContext context;
1905 Boolean done = FALSE;
1907 XmStringComponentType type;
1909 XmStringCharSet charset;
1910 XmStringDirection direction;
1911 XmStringComponentType unknown_tag;
1914 XmStringTable list_items;
1916 Boolean isItemCopied = FALSE;
1919 XtSetArg(args[0], XmNitemCount, &item_count);
1920 XtSetArg(args[1], XmNitems, &list_items);
1921 XtGetValues((Widget)list, args, 2);
1922 if (item_count && item_count>combo_p->selected_position &&
1923 !item && list_items) {
1924 item = XmStringCopy(list_items[combo_p->selected_position]);
1925 isItemCopied = TRUE;
1929 combo_p->selected_item = NULL;
1930 XtSetArg(args[0], XmNvalue, "");
1931 XtSetValues(combo_p->text, args, 1);
1934 if (combo_p->selected_item != item)
1936 if (combo_p->selected_item)
1937 XmStringFree (combo_p->selected_item);
1938 combo_p->selected_item = XmStringCopy(item);
1940 XmStringInitContext(&context, item);
1942 /* Loop until 1st char* found */
1944 type = XmStringGetNextComponent(context, &text, &charset,
1945 &direction, &unknown_tag,
1948 case XmSTRING_COMPONENT_END:
1951 case XmSTRING_COMPONENT_TEXT:
1952 case XmSTRING_COMPONENT_LOCALE_TEXT:
1953 XtSetArg(args[0], XmNvalue, text);
1954 XtSetValues(combo_p->text, args, 1);
1962 XmStringFreeContext(context);
1970 * Set the maximum size of the label, depending on the
1971 * characteristics of the list of items.
1974 SetMaximumLabelSize(DtComboBoxPart *combo_p)
1976 XmListWidget list = (XmListWidget)combo_p->list;
1977 XmFontList font_list;
1978 Dimension width, height, border_width;
1979 Dimension longest = 0;
1980 Dimension highest = 0;
1983 XmStringTable list_items;
1984 unsigned char unit_type = XmPIXELS;
1986 /* Resolution Independent */
1987 XtSetArg(args[0], XmNunitType, &unit_type);
1988 XtGetValues(combo_p->list, args, 1); /* Assume list/Combo has same uniType*/
1989 if (unit_type != XmPIXELS) {
1990 XtSetArg(args[0], XmNunitType, XmPIXELS);
1991 XtSetValues(combo_p->label, args, 1);
1992 XtSetValues(combo_p->list, args, 1);
1995 /* Get font info from the widget */
1996 XtSetArg(args[0], XmNfontList, &font_list);
1997 XtGetValues(combo_p->label, args, 1);
2000 XtSetArg(args[0], XmNitems, &list_items);
2001 XtSetArg(args[1], XmNitemCount, &item_count);
2002 XtGetValues((Widget)list, args, 2);
2004 if ( item_count && item_count >= combo_p->item_count &&
2005 list_items && combo_p->update_label) {
2007 * Loop through all the items to find the biggest dimensions
2009 for (i = 0; i < combo_p->item_count; i++) {
2010 XmStringExtent(font_list, list_items[i], &width, &height);
2011 longest = (width > longest) ? width : longest;
2012 highest = (height > highest) ? height : highest;
2016 XmStringExtent(font_list, combo_p->label_string, &longest, &highest);
2019 combo_p->label_max_length = longest + ((LABEL_PADDING+TEXT_CONTEXT_MARGIN) * 2);
2020 combo_p->label_max_height = highest;
2022 XtSetArg(args[0], XmNborderWidth, &border_width);
2023 XtGetValues(combo_p->label, args, 1);
2024 XtResizeWidget(combo_p->label, combo_p->label_max_length, highest,
2027 /* Resolution Independent */
2028 if (unit_type != XmPIXELS) {
2029 XtSetArg(args[0], XmNunitType, unit_type);
2030 XtSetValues(combo_p->label, args, 1);
2031 XtSetValues(combo_p->list, args, 1);
2037 * Put the current list item into the label.
2038 * This could probably be faster if we see if the label is the
2039 * same as the new item?
2042 SetLabelData( DtComboBoxPart *combo_p,
2044 Boolean force_label_string)
2046 XmListWidget list = (XmListWidget)combo_p->list;
2047 int index = combo_p->selected_position;
2049 XmStringTable list_items;
2053 * If the item is empty, get the current item from the list, or
2054 * use label_string if update_label is FALSE. If that is empty,
2057 if (force_label_string || (combo_p->update_label == FALSE))
2058 item = combo_p->label_string ? combo_p->label_string : InitLabel;
2063 XtSetArg(args[0], XmNitemCount, &item_count);
2064 XtSetArg(args[1], XmNitems, &list_items);
2065 XtGetValues((Widget)list, args, 2);
2066 if (item_count && item_count>index && list_items)
2067 item = list_items[index];
2072 /* Keep label_string in sync with item picked */
2073 if (combo_p->label_string)
2074 XmStringFree(combo_p->label_string);
2075 combo_p->label_string = XmStringCopy(item);
2078 combo_p->selected_item = XmStringCopy(item);
2079 XtSetArg(args[0], XmNlabelString, item);
2080 XtSetValues(combo_p->label, args, 1);
2084 * This is the browseSelect and defaultAction callback handler for the
2085 * ListWidget. If using the textWidget, we only take the first
2086 * segment of the XmString (TextWidgets don't handle XmStrings). If we
2087 * are using a label, then just set the labelString resource.
2090 select_cb( Widget w,
2091 XtPointer client_data,
2092 XtPointer call_data)
2094 DtComboBoxWidget combo_w = (DtComboBoxWidget)client_data;
2095 DtComboBoxPart *combo_p = (DtComboBoxPart*)
2096 &(XmField(combo_w,ipot,DtComboBox,arrow,Widget));
2097 XmListCallbackStruct *info = (XmListCallbackStruct*)call_data;
2098 DtComboBoxCallbackStruct cb;
2100 SelectedPosition(combo_w) = info->item_position - 1;
2101 if (SelectedItem(combo_w))
2102 XmStringFree(SelectedItem(combo_w));
2103 SelectedItem(combo_w) = XmStringCopy(info->item);
2104 if (Type(combo_w) == DtDROP_DOWN_COMBO_BOX) {
2105 SetTextFieldData(combo_p, SelectedItem(combo_w));
2107 else { /* Set the labelWidget string */
2108 SetLabelData(combo_p, SelectedItem(combo_w), FALSE);
2112 * Only popdown if this is the defaultAction callback. We don't
2113 * want to popdown with browseSelect callback; that would cause the
2114 * menu to popdown when the user moved selection with the keyboard.
2115 * Doing it this way, allows the menu to stay up during
2116 * keyboard navigation. When menu goes away, make sure input
2117 * focus goes back into the textField (if editable).
2119 /* This is one of three places to popdown the menu and here is
2120 * to pop it down by Keyboard input: KSelect
2121 * Another place using keyboard input to popdown the menu is
2122 * in _ComboBoxKbdCancel() by <Key>osfEsc
2123 * the last place is in shell_event_handler and that is for
2124 * poping down through Button operation: BSelect
2126 if (info->reason == XmCR_DEFAULT_ACTION)
2127 input_ungrab( combo_w, GRAB_POINTER | GRAB_KEYBOARD );
2129 if ( ShellPoppedUp(((ShellWidget)Shell(combo_w))) == FALSE) {
2130 /* The list will free info->item */
2131 /* The semantic of a DtNselectionCallback is:
2132 * a callback to here + ShellPoppedUp==False
2133 * In reality, there are two scenario for this:
2134 * 1. XmList's XmNdefaultActionCallback which is activated by
2135 * KSelect, will first pop down the shell (see above) and
2136 * and then get here.
2137 * 2. BSelect on XmList, which first call the list_event_handler()
2138 * (for the handler is registered as LIST_HEAD) to pop down
2139 * the shell, and then call XmList's XmNbrowseSelectionCallback
2140 * which in turn get here
2142 cb.reason = DtCR_SELECT;
2143 cb.event = info->event;
2144 cb.item_or_text = XmStringCopy(info->item);
2145 cb.item_position = SelectedPosition(combo_w);
2146 XtCallCallbackList((Widget)combo_w, SelectionCallback(combo_w),
2148 if (cb.item_or_text != NULL) {
2149 XmStringFree(cb.item_or_text);
2150 cb.item_or_text = NULL;
2157 * This is the event_handler for our shell widget. The grab happens
2158 * on the shell while the user is not doing anything inside the list.
2159 * This allows us to know if the user pressed a button outside our
2160 * application. If the user pressed a button anywhere but inside
2161 * the shell, then popdown the menu and ungrab everything.
2165 shell_event_handler( Widget widget,
2166 XtPointer client_data,
2170 DtComboBoxWidget combo_w = (DtComboBoxWidget)client_data;
2171 XmScrolledWindowWidget sw = (XmScrolledWindowWidget)XtParent(List(combo_w));
2172 XmScrollBarWidget v_scrollbar;
2173 XmScrollBarWidget h_scrollbar;
2174 Window window = event->xbutton.window;
2178 if (popup_shell_init) {
2179 if (popup_shell_init != DtKeyPressPopup) {
2180 /* Menu popped up by ButtonPress */
2181 popup_shell_init = DtNonePopup;
2186 /* Menu popped up by KActivate */
2187 popup_shell_init = DtNonePopup;
2192 XtSetArg(args[0], XmNverticalScrollBar, &v_scrollbar);
2193 XtSetArg(args[1], XmNhorizontalScrollBar, &h_scrollbar);
2194 XtGetValues((Widget)sw, args, 2);
2196 /* condition : Shell is popped up;
2197 * ButtonPress event;
2198 * the cursor is Not inside the XmList area,
2199 * the horizontal scrollbar or the vertical one;
2200 * action: remove all the grabs by DtComboBox
2202 if ( ShellPoppedUp(((ShellWidget)Shell(combo_w))) &&
2203 (event->type == ButtonPress &&
2204 (window != XtWindowOfObject(List(combo_w))) &&
2205 !(ScrollBarVisible((Widget)h_scrollbar) &&
2206 (window == XtWindowOfObject((Widget)h_scrollbar))) &&
2207 !(ScrollBarVisible((Widget)v_scrollbar) &&
2208 (window == XtWindowOfObject((Widget)v_scrollbar))))
2210 input_ungrab( combo_w, GRAB_POINTER | GRAB_KEYBOARD );
2212 /* condition : ButtonRelease event
2213 * the cursor is outside the scrollbar(horizontal or vertical)
2214 * action: call action routine "Release" of ScrollBar to release
2215 * possible pressed slider arrow (up/down)
2217 if (event->type == ButtonRelease) {
2218 if ( ScrollBarVisible((Widget)h_scrollbar) &&
2219 window != XtWindowOfObject((Widget)h_scrollbar) )
2220 XtCallActionProc((Widget)h_scrollbar, "Release", event,NULL,0);
2221 if ( ScrollBarVisible((Widget)v_scrollbar) &&
2222 window != XtWindowOfObject((Widget)v_scrollbar) )
2223 XtCallActionProc((Widget)v_scrollbar, "Release", event,NULL,0);
2229 * This is the event_handler for our list widget. Getting the pointer
2230 * grabbing to work correctly was not very easy. In order for everything
2231 * to work correctly, we only do grab-pointer, for the shell, while not
2232 * doing anything inside the list. If doing something inside the list
2233 * we remove the grab on the shell. This is the only way that the
2234 * list will get the ButtonRelease if doing browse while outside the
2235 * list. The toolkit automatically does a grab in between ButtonPress
2236 * and ButtonRelease; therefore, the shell ungrab can't be done inside
2237 * the ButtonPress event.
2240 list_event_handler( Widget widget,
2241 XtPointer client_data,
2243 Boolean *dispatch) /* call remaining event handlers */
2245 DtComboBoxWidget combo_w = (DtComboBoxWidget)client_data;
2248 int top_item_position;
2249 int visible_item_count;
2251 XmScrolledWindowWidget sw = (XmScrolledWindowWidget)XtParent(widget);
2252 XmScrollBarWidget v_scrollbar;
2253 XmScrollBarWidget h_scrollbar;
2255 switch (event->type) {
2258 * Pop down the menu when Button is released inside the menu.
2260 /* Doing the popdown here upon receiving ButtonRelease event,
2261 * rather than in shell_even_hanlder(), is
2262 * essential to allow select_cb() to recognize that this
2263 * XmNbrowseSelectionCallback is the last one in this popup session
2264 * and must treat it as a DtNselectionCallback
2266 input_ungrab( combo_w, GRAB_KEYBOARD );
2268 /* condition : ButtonRelease event
2269 * cursor is outside the scrollbar(horizontal or vertical)
2270 * action: call action routine "Release" of ScrollBar to release
2271 * possible pressed slider arrow (up/down)
2274 XtSetArg(args[0], XmNverticalScrollBar, &v_scrollbar);
2275 XtSetArg(args[1], XmNhorizontalScrollBar, &h_scrollbar);
2276 XtGetValues((Widget)sw, args, 2);
2277 if ( ScrollBarVisible((Widget)h_scrollbar) )
2278 XtCallActionProc((Widget)h_scrollbar, "Release", event,NULL,0);
2279 if ( ScrollBarVisible((Widget)v_scrollbar) )
2280 XtCallActionProc((Widget)v_scrollbar, "Release", event,NULL,0);
2285 * There is interaction conflict between the list and the
2286 * scrollbars in terms of Focus. We always want our list
2287 * to have focus, so grab it back if we lose it.
2289 if ( ShellPoppedUp(((ShellWidget)(Shell(combo_w)))) ) {
2290 _XmGrabKeyboard(widget, False, GrabModeAsync, GrabModeAsync,
2292 XtSetKeyboardFocus(List(combo_w), None);
2296 /* call ListBeginSelect() action directly to simulate Btn1Down*/
2297 {Display *disp = XtDisplay(List(combo_w));
2298 Window win = XtWindow(List(combo_w));
2302 int root_x, root_y, win_x, win_y, item_pos;
2303 unsigned int keys_buttons;
2304 unsigned char unit_type = XmPIXELS;
2306 /* Resolution Independent */
2307 if ( MUnitType(combo_w) != XmPIXELS) {
2308 unit_type = MUnitType(combo_w);
2309 XtSetArg(args[0], XmNunitType, XmPIXELS);
2310 XtSetValues(List(combo_w), args, 1);
2312 root = XDefaultRootWindow( disp );
2313 XQueryPointer ( disp, win, &root,
2314 &child, &root_x, &root_y,
2315 &win_x, &win_y, &keys_buttons );
2316 if ( keys_buttons & Button1Mask ) {
2317 item_pos = XmListYToPos(List(combo_w), event->xbutton.y);
2318 list = (XmListWidget)List(combo_w);
2322 XtSetArg(args[num_args],XmNtopItemPosition,&top_item_position);
2324 XtSetArg(args[num_args], XmNvisibleItemCount,
2325 &visible_item_count);
2327 XtSetArg(args[num_args], XmNitemCount, &item_count);
2329 XtGetValues((Widget)list, args, num_args);
2330 /* Adjust top_item_position value to its' internal form */
2331 if (top_item_position)
2332 top_item_position--;
2334 top_item_position = item_count - 1;
2337 (item_pos>=(top_item_position + visible_item_count))||
2338 (item_pos < top_item_position) ||
2339 (item_pos >= item_count) )
2341 Position item_x, item_y;
2342 Dimension item_height, item_width;
2344 XmListPosToBounds((Widget)list,
2345 ((top_item_position + visible_item_count )>
2346 item_count)? item_count:
2347 (top_item_position + visible_item_count ),
2348 &item_x, &item_y, &item_width, &item_height);
2350 if ( item_pos ==0 && event->xbutton.y<(int)(item_height/2) )
2351 event->xbutton.y = item_height/2;
2353 event->xbutton.y = item_y + item_height/2;
2354 event->xbutton.x = item_x;
2357 XtCallActionProc(List(combo_w), "ListBeginSelect",
2362 /* Resolution Independent */
2363 if ( unit_type != XmPIXELS) {
2364 XtSetArg(args[0], XmNunitType, unit_type);
2365 XtSetValues(List(combo_w), args, 1);
2373 /* Caller must free string */
2375 GetTextString(XmString xm_string)
2377 XmStringContext context;
2378 XmStringComponentType type;
2379 XmStringCharSet charset;
2380 XmStringDirection direction;
2381 XmStringComponentType unknown_tag;
2385 Boolean done = FALSE;
2387 XmStringInitContext(&context, xm_string);
2389 /* Loop until 1st char* found */
2391 type = XmStringGetNextComponent(context, &text, &charset,
2392 &direction, &unknown_tag,
2395 case XmSTRING_COMPONENT_END:
2398 case XmSTRING_COMPONENT_TEXT:
2399 case XmSTRING_COMPONENT_LOCALE_TEXT:
2406 XmStringFreeContext(context);
2411 TextFieldActivate(DtComboBoxPart *combo_p, XtPointer call_data)
2413 XmTextFieldWidget w = (XmTextFieldWidget)(combo_p->text);
2414 XmListWidget list = (XmListWidget)combo_p->list;
2415 XmAnyCallbackStruct cb;
2419 XmStringTable list_items;
2421 XtSetArg(arg, XmNvalue, &data);
2422 XtGetValues((Widget)w, &arg, 1);
2425 XtSetArg(arg, XmNitems, &list_items);
2426 XtGetValues((Widget)list, &arg, 1);
2429 text = GetTextString(list_items[combo_p->selected_position]);
2431 if (text && data && (strcmp(text, data) == 0)) {
2434 /* Only send callback if both are not NULL */
2435 else if (!((text == NULL) && (data == NULL))) {
2436 XmAnyCallbackStruct *local_cb = (XmAnyCallbackStruct *)call_data;
2438 cb.reason = XmCR_ACTIVATE;
2439 cb.event = local_cb ? local_cb->event : NULL;
2442 if (XtHasCallbacks((Widget)w, XmNactivateCallback)==XtCallbackHasSome)
2443 XtCallCallbacks((Widget)w, XmNactivateCallback,
2454 * This is the activate callback for the arrow button. This
2455 * sets the shell position and width, does the correct grabs, and
2456 * puts the shell on the screen.
2459 activate_cb( Widget w,
2460 XtPointer client_data,
2461 XtPointer call_data)
2463 DtComboBoxWidget combo_w = (DtComboBoxWidget)client_data;
2464 DtComboBoxPart *combo_p = (DtComboBoxPart*)
2465 &(XmField(combo_w,ipot,DtComboBox,arrow,Widget));
2466 Display *disp = XtDisplayOfObject((Widget)combo_w);
2467 XmDisplay xmdisp = (XmDisplay) XmGetXmDisplay(disp);
2469 Dimension width, height;
2470 Dimension disp_width, disp_height;
2471 Position root_x, root_y, root_y0;
2474 unsigned char unit_type = XmPIXELS;
2476 /* Resolution Independent Handling */
2477 XtSetArg(args[0], XmNunitType, &unit_type);
2478 XtGetValues((Widget)combo_w, args, 1);
2480 if ( !_XmFocusIsHere( (Widget)combo_w) )
2481 XmProcessTraversal((Widget)combo_w,
2482 (XmTraversalDirection) XmTRAVERSE_CURRENT);
2484 if (Type(combo_w) == DtDROP_DOWN_COMBO_BOX)
2485 TextFieldActivate(combo_p, call_data);
2488 * Don't popup if no items in the list.
2492 XtSetArg(args[0], XmNitemCount, &n);
2493 XtGetValues(((Widget)List(combo_w)), args, 1);
2494 if ( n != ItemCount(combo_w) )
2495 SyncWithList(combo_p);
2499 screen = DefaultScreen(disp);
2500 disp_width = DisplayWidth(disp, screen);
2501 disp_height = DisplayHeight(disp, screen);
2504 * Call the menu-post callback if requested. This allows the
2505 * user to change the items, instead of using the losing-focus callback.
2506 * If the user used the losing-focus callback to change the items, the
2507 * size of the list/shell will change while it is popped up. We
2508 * could disallow SetValues while the menu is posted, but let's see
2509 * how things go first.
2511 if (MenuPostCallback(combo_w)) {
2512 XmAnyCallbackStruct info;
2514 info.reason = DtCR_MENU_POST;
2515 info.event = (XEvent*)NULL;
2516 XtCallCallbackList((Widget)combo_w, MenuPostCallback(combo_w),
2520 width = MaxShellWidth(combo_w);
2521 height = MaxShellHeight(combo_w);
2524 /* Get root coords of ComboBox */
2525 XtTranslateCoords((Widget)combo_w, X(combo_w), Y(combo_w),
2530 * Make necessary adjustments for offset of our widget
2531 * inside its' parent. Calculate the width of the shell.
2532 * This must be done every time the shell gets popped up, because
2533 * the x/y can change as well as the width (from list's visibleItemCount
2534 * or geometry management changes).
2536 root_x -= X(combo_w);
2537 root_y -= Y(combo_w);
2538 root_y += (Height(combo_w) - COMBO_MARGIN_H(combo_w));
2541 * Make sure the shell is at least as big as our combo-box, and
2542 * make sure it stays on the screen.
2544 /* to enforce a scrollbar with Shell */
2545 if (width < Width(combo_w))
2547 Dimension sb_width, spacing, list_width;
2550 XtSetArg(args[n], XmNverticalScrollBar, &sb); n++;
2551 XtSetArg(args[n], XmNspacing, &spacing); n++;
2552 XtGetValues(XtParent(List(combo_w)), args, n);
2553 /* Resolution Independent Resource */
2554 if ( unit_type != XmPIXELS) {
2555 n = XmConvertUnits(List(combo_w), XmHORIZONTAL,
2556 (int)unit_type, spacing, XmPIXELS);
2559 if (sb && XtIsWidget(sb) ) {
2561 XtSetArg(args[n], XmNwidth, &sb_width); n++;
2562 XtGetValues(sb, args, n);
2563 /* Resolution Independent Resource */
2564 if (unit_type != XmPIXELS) {
2565 n = XmConvertUnits(sb, XmHORIZONTAL,
2566 (int)unit_type, sb_width, XmPIXELS);
2574 width = Width(combo_w);
2575 list_width = ( ScrollBarVisible(sb) ?
2576 (width - sb_width - spacing)
2577 :(width - spacing) );
2579 if (unit_type != XmPIXELS) {
2580 n = XmConvertUnits(sb, XmHORIZONTAL,
2581 XmPIXELS, list_width, (int)unit_type);
2582 list_width = n; n=0;
2584 XtSetArg(args[n], XmNwidth, list_width); n++;
2585 XtSetValues(List(combo_w), args, n);
2587 if ((int)(root_x + width) > (int)disp_width)
2588 root_x = (disp_width - width);
2589 else if (root_x <=0)
2594 if ((int)(root_y + height) > (int)disp_height)
2595 root_y = root_y0 - Y(combo_w) - height;
2597 if (unit_type != XmPIXELS) {
2598 XtSetArg(args[0], XmNunitType, XmPIXELS);
2599 XtSetValues(Shell(combo_w), args, 1);
2602 XtSetArg(args[n], XmNx, root_x); n++;
2603 XtSetArg(args[n], XmNy, root_y); n++;
2604 XtSetValues(Shell(combo_w), args, n);
2605 if (unit_type != XmPIXELS) {
2606 XtSetArg(args[0], XmNunitType, unit_type);
2607 XtSetValues(Shell(combo_w), args, 1);
2611 PoppedUp(combo_w) = TRUE;
2612 XtPopup(Shell(combo_w), XtGrabNone);
2615 * Set up the grab for the shell and list. The shell gets the
2616 * pointer grab so that events will go into the list and scrollbars
2617 * correctly, but events outside the shell will go to the shell.
2618 * See shell and list event handlers for details about grabs.
2620 _XmAddGrab(Shell(combo_w), True, True);
2621 _XmGrabPointer(Shell(combo_w), True, ButtonPressMask |ButtonReleaseMask,
2622 GrabModeAsync, GrabModeAsync, None,
2623 XmGetMenuCursor(disp), CurrentTime);
2624 _XmGrabKeyboard(List(combo_w), False, GrabModeAsync, GrabModeAsync,
2626 xmdisp->display.userGrabbed = True;
2629 * Where to define the cursor for the list widget. It would be
2630 * nice to do it in the list's realize function, but that's not
2631 * possible. We can't use the ComboBox realize function, because
2632 * the list isn't realized at that point. This is the simpliest
2633 * way to get this done. This is needed to make sure the list has the
2634 * correct menu during browse scrolling, etc.
2636 XDefineCursor(disp, XtWindowOfObject(Shell(combo_w)),
2637 XmGetMenuCursor(disp));
2642 * Make sure arrow is symetrical. 45 degree angle. I'm not sure how
2643 * inefficient get/releasing the GC every time is (they are cached by
2647 arrow_expose_cb(Widget w,
2648 XtPointer client_data,
2649 XtPointer call_data)
2651 DtComboBoxWidget combo_w = (DtComboBoxWidget)client_data;
2652 Display *disp = XtDisplayOfObject(w);
2653 Window win = XtWindowOfObject(w);
2660 Dimension arrow_width, arrow_height;
2661 unsigned char unit_type = XmPIXELS;
2663 /* Resolution Independent */
2664 if ( MUnitType(combo_w) != XmPIXELS ) {
2665 unit_type = MUnitType(combo_w);
2666 XtSetArg(args[0], XmNunitType, XmPIXELS);
2667 XtSetValues(w, args, 1);
2670 XtSetArg(args[0], XmNwidth, &arrow_width);
2671 XtSetArg(args[1], XmNheight, &arrow_height);
2672 XtSetArg(args[2], XmNforeground, &(values.foreground));
2673 XtGetValues(w, args, 3);
2674 center_w = arrow_width/2;
2675 center_h = (int) (arrow_height -3.)/2;
2677 values.line_width = 0;
2678 values.line_style = LineSolid;
2679 values.fill_style = FillSolid;
2680 gc = XtGetGC(w, GCForeground | GCFillStyle | GCLineStyle | GCLineWidth,
2683 XDrawLine(disp, win, gc, 1, center_h + center_w + 1, Width(w) - 2,
2684 center_h + center_w + 1);
2686 /* A - bottom point */
2687 points[0].x = center_w;
2688 points[0].y = center_h + (int)(center_w * .8);
2690 /* B - far left point */
2691 points[1].x = center_w - (int)(center_w * .8);
2692 points[1].y = center_h;
2694 /* C - inner left point */
2695 points[2].x = center_w - (int)(center_w * .3);
2696 points[2].y = points[1].y;
2698 /* D - top left point */
2699 points[3].x = points[2].x;
2700 points[3].y = center_h - (int)(center_w * .8);
2702 /* E - top right point */
2703 points[4].x = center_w + (int)(center_w * .3);
2704 points[4].y = points[3].y;
2706 /* F - inner right point */
2707 points[5].x = points[4].x;
2708 points[5].y = points[1].y;
2710 /* G - far right point */
2711 points[6].x = center_w + (int)(center_w * .8);
2712 points[6].y = points[1].y;
2714 /* A - bottom point */
2715 points[7].x = points[0].x;
2716 points[7].y = points[0].y;
2718 XDrawLines(disp, win, gc, points, 8, CoordModeOrigin);
2719 XFillPolygon(disp, win, gc, points, 8, Convex, CoordModeOrigin);
2722 /* Resolution Independent */
2723 if ( unit_type != XmPIXELS ) {
2724 XtSetArg(args[0], XmNunitType, unit_type);
2725 XtSetValues(w, args, 1);
2730 * We get the text-field losing-focus callback, so pass it on to
2731 * the user if they requested it. Our losing-focus callback
2732 * is just a convenience callback, so that the user doesn't
2733 * have to get the text-field first. This make our integration
2734 * with XDesigner a little easier.d
2737 text_losing_focus_cb( Widget w,
2738 XtPointer client_data,
2739 XtPointer call_data)
2741 DtComboBoxWidget combo = (DtComboBoxWidget)client_data;
2742 DtComboBoxPart *combo_p = (DtComboBoxPart*)
2743 &(XmField(combo,ipot,DtComboBox,arrow,Widget));
2744 XmTextFieldWidget wt=(XmTextFieldWidget) Text(combo);
2748 int i, need_sync_flag=1;
2751 XtSetArg(arg, XmNvalue, &text_string);
2752 XtGetValues((Widget)wt, &arg, 1);
2753 xmStr = (XmString) XmStringCreateLocalized(text_string?text_string:"");
2755 XtFree (text_string);
2757 if (LosingFocusCallback(combo))
2758 XtCallCallbackList((Widget)combo, LosingFocusCallback(combo),
2759 (XtPointer)call_data);
2761 /* To synchronize the ComboBox record with XmList */
2762 XtVaGetValues(List(combo), XmNitemCount, &i, NULL);
2763 if (i != ItemCount(combo) ) {
2764 SyncWithList(combo_p);
2768 for (i = 0; i < ItemCount(combo); i++) {
2769 if ( need_sync_flag &&
2770 !( (ListItems(combo))[i] && XmeStringIsValid((ListItems(combo))[i]) )) {
2771 SyncWithList(combo_p);
2774 if (XmStringCompare(xmStr, (ListItems(combo))[i]))
2778 if (i < ItemCount(combo) && i != SelectedPosition(combo) ) {
2779 SelectedPosition(combo) = i;
2780 if (SelectedItem(combo))
2781 XmStringFree(SelectedItem(combo));
2782 SelectedItem(combo) = xmStr;
2783 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
2784 SetTextFieldData(combo_p, NULL);
2786 SetLabelData(combo_p, NULL, FALSE);
2787 XmListSetPos(List(combo), SelectedPosition(combo) + 1);
2788 XmListSelectPos(List(combo), SelectedPosition(combo) + 1, True);
2790 XtVaGetValues(List(combo), XmNtopItemPosition,
2791 &(combo_p->top_item_position), NULL);
2794 XmStringFree( xmStr );
2798 * We get the text-field activate callback, so pass it on to
2799 * the user if they requested it. Our activate callback
2800 * is just a convenience callback, so that the user doesn't
2801 * have to get the text-field first. This make our integration
2802 * with XDesigner a little easier.
2805 text_activate_cb( Widget w,
2806 XtPointer client_data,
2807 XtPointer call_data)
2809 DtComboBoxWidget combo = (DtComboBoxWidget)client_data;
2810 DtComboBoxPart *combo_p = (DtComboBoxPart*)
2811 &(XmField(combo,ipot,DtComboBox,arrow,Widget));
2812 XmTextFieldWidget wt=(XmTextFieldWidget) Text(combo);
2816 int i, need_sync_flag=1;
2819 XtSetArg(arg, XmNvalue, &text_string);
2820 XtGetValues((Widget)wt, &arg, 1);
2821 xmStr = (XmString) XmStringCreateLocalized(text_string?text_string:"");
2823 XtFree (text_string);
2825 if (ActivateCallback(combo))
2826 XtCallCallbackList((Widget)combo,
2827 ActivateCallback(combo),
2828 (XtPointer)call_data);
2830 /* To synchronize the ComboBox record with XmList */
2831 XtVaGetValues(List(combo), XmNitemCount, &i, NULL);
2832 if (i != ItemCount(combo) ) {
2833 SyncWithList(combo_p);
2837 for (i = 0; i < ItemCount(combo); i++) {
2838 if ( need_sync_flag &&
2839 !( (ListItems(combo))[i] &&
2840 XmeStringIsValid((ListItems(combo))[i]) )) {
2841 SyncWithList(combo_p);
2844 if (XmStringCompare(xmStr, (ListItems(combo))[i]))
2848 if (i < ItemCount(combo) && i != SelectedPosition(combo) ) {
2849 SelectedPosition(combo) = i;
2850 if (SelectedItem(combo))
2851 XmStringFree(SelectedItem(combo));
2852 SelectedItem(combo) = xmStr;
2853 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
2854 SetTextFieldData(combo_p, NULL);
2856 SetLabelData(combo_p, NULL, FALSE);
2857 XmListSetPos(List(combo), SelectedPosition(combo) + 1);
2858 XmListSelectPos(List(combo), SelectedPosition(combo) + 1, True);
2859 XtVaGetValues(List(combo), XmNtopItemPosition,
2860 &(combo_p->top_item_position), NULL);
2863 XmStringFree( xmStr );
2868 * We get the text-field focus callback, so pass it on to
2869 * the user if they requested it. Our focus callback
2870 * is just a convenience callback, so that the user doesn't
2871 * have to get the text-field first. This make our integration
2872 * with XDesigner a little easier.
2875 text_focus_cb( Widget w,
2876 XtPointer client_data,
2877 XtPointer call_data)
2879 DtComboBoxWidget combo = (DtComboBoxWidget)client_data;
2881 if (FocusCallback(combo))
2882 XtCallCallbackList((Widget)combo, FocusCallback(combo),
2883 (XtPointer)call_data);
2887 * Try and keep our list related rsources in sync with the list widget.
2888 * This is not always possible, depending on if the programmer makes
2889 * list widget calls directly. If we get out of sync with the
2890 * list widget, our SetValues() may not work correctly (when the
2891 * comparisons are done). Should do get values in case list widget
2892 * names are changed?
2895 SyncWithList(DtComboBoxPart *combo_p)
2897 XmListWidget list = (XmListWidget)combo_p->list;
2900 unsigned char unit_type = XmPIXELS;
2902 /* Resolution Independent */
2903 XtSetArg(args[0],XmNunitType,&unit_type);
2904 XtGetValues((Widget)list, args, 1);
2905 if (unit_type != XmPIXELS) {
2906 XtSetArg(args[0],XmNunitType,XmPIXELS);
2907 XtSetValues((Widget)list, args, 1);
2912 XtSetArg(args[num_args],XmNitems,&(combo_p->list_items)); num_args ++;
2913 XtSetArg(args[num_args],XmNitems,&(combo_p->items)); num_args ++;
2914 XtSetArg(args[num_args],XmNitemCount,&(combo_p->item_count)); num_args ++;
2915 XtSetArg(args[num_args],XmNfontList,&(combo_p->list_font_list));
2917 XtSetArg(args[num_args],XmNlistMarginHeight,&(combo_p->list_margin_height));
2919 XtSetArg(args[num_args],XmNlistMarginWidth,&(combo_p->list_margin_width));
2921 XtSetArg(args[num_args],XmNlistSpacing,&(combo_p->list_spacing));
2923 XtSetArg(args[num_args],XmNtopItemPosition,&(combo_p->top_item_position));
2925 XtSetArg(args[num_args],XmNvisibleItemCount,&(combo_p->visible_item_count));
2927 XtGetValues((Widget)list, args, num_args);
2928 /* Adjustment with empty list */
2929 if (! combo_p->item_count) {
2930 combo_p->items = NULL;
2931 combo_p->list_items = NULL;
2934 /* Resolution Independent */
2935 if (unit_type != XmPIXELS) {
2936 XtSetArg(args[0],XmNunitType,unit_type);
2937 XtSetValues((Widget)list, args, 1);
2942 * Routines which manipulate the ComboBox list. These are external
2943 * for use by users of our widget.
2946 DtCreateComboBox(Widget parent,
2951 return(XtCreateWidget(name, dtComboBoxWidgetClass, parent,
2952 arglist, num_args));
2956 DtComboBoxAddItem( Widget combow,
2961 DtComboBoxWidget combo = (DtComboBoxWidget)combow;
2962 DtComboBoxPart *combo_p = (DtComboBoxPart*)
2963 &(XmField(combo,ipot,DtComboBox,arrow,Widget));
2964 XmStringTable list_items;
2967 _DtWidgetToAppContext(combow);
2970 /* Try to help confused applications. */
2971 if (XmIsComboBox(combow))
2973 XmComboBoxAddItem(combow, item, pos, unique);
2980 XtSetArg(arg, XmNitems, &list_items);
2981 XtGetValues(((Widget)List(combo)), &arg, 1);
2983 if (item && list_items) {
2984 for (i = 0; i < ItemCount(combo); i++)
2985 if (XmStringCompare(item, list_items[i]))
2987 if ((i < ItemCount(combo)) && unique)
2994 XmListAddItemUnselected(List(combo), item, pos);
2995 SyncWithList(combo_p);
2998 SetMaximumLabelSize(combo_p);
2999 if (Type(combo) == DtDROP_DOWN_LIST) {
3000 ClearShadow(combo, TRUE);
3001 if (RecomputeSize(combo))
3002 SetComboBoxSize(combo);
3003 LayoutChildren(combo);
3007 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
3008 SetTextFieldData(combo_p, NULL);
3010 SetLabelData(combo_p, NULL, FALSE);
3018 DtComboBoxDeletePos( Widget combow,
3021 DtComboBoxWidget combo = (DtComboBoxWidget)combow;
3022 DtComboBoxPart *combo_p = (DtComboBoxPart*)
3023 &(XmField(combo,ipot,DtComboBox,arrow,Widget));
3024 int selection_changed = 0;
3025 _DtWidgetToAppContext(combow);
3028 /* Try to help confused applications. */
3029 if (XmIsComboBox(combow))
3031 XmComboBoxDeletePos(combow, pos);
3036 if ( pos <= 0 || pos >combo_p->item_count ) {
3037 XtWarning(CB_DEL_POS);
3042 XmListDeletePos(List(combo), pos);
3043 if ( pos == (combo_p->selected_position+1) ) {
3044 /* Since we delete the current item, we have to set one */
3045 if ( pos == combo_p->item_count && combo_p->selected_position>0) {
3046 combo_p->selected_position--;
3047 selection_changed ++;
3049 XmListSelectPos(List(combo), combo_p->selected_position+1, True);
3051 else if ( pos <= combo_p->selected_position) {
3052 combo_p->selected_position--;
3053 selection_changed ++;
3055 SyncWithList(combo_p);
3056 if ( selection_changed ) {
3057 if ( combo_p->selected_item )
3058 XmStringFree(combo_p->selected_item );
3059 combo_p->selected_item =
3061 XmStringCopy(combo_p->list_items[combo_p->selected_position]):
3066 SetMaximumLabelSize(combo_p);
3067 if (Type(combo) == DtDROP_DOWN_LIST) {
3068 ClearShadow(combo, TRUE);
3069 if (RecomputeSize(combo))
3070 SetComboBoxSize(combo);
3071 LayoutChildren(combo);
3075 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
3076 SetTextFieldData(combo_p, NULL);
3078 SetLabelData(combo_p, NULL, FALSE);
3084 DtComboBoxSetItem( Widget combow,
3087 DtComboBoxWidget combo = (DtComboBoxWidget)combow;
3088 DtComboBoxPart *combo_p = (DtComboBoxPart*)
3089 &(XmField(combo,ipot,DtComboBox,arrow,Widget));
3090 XmStringTable list_items;
3093 _DtWidgetToAppContext(combow);
3096 /* Try to help confused applications. */
3097 if (XmIsComboBox(combow))
3099 XmComboBoxSetItem(combow, item);
3106 XtSetArg(arg, XmNitems, &list_items);
3107 XtGetValues(((Widget)List(combow)), &arg, 1);
3109 if (item && list_items) {
3110 for (i = 0; i < ItemCount(combo); i++)
3111 if (XmStringCompare(item, list_items[i]))
3113 if (i < ItemCount(combo)) {
3114 SelectedPosition(combo) = i;
3115 if (SelectedItem(combo))
3116 XmStringFree(SelectedItem(combo));
3117 SelectedItem(combo) = XmStringCopy(item);
3118 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
3119 SetTextFieldData(combo_p, NULL);
3121 SetLabelData(combo_p, NULL, FALSE);
3122 XmListSetItem(List(combo), item);
3123 XmListSelectItem(List(combo), item, FALSE);
3124 SyncWithList(combo_p);
3127 XtWarning(CB_SET_ITEM);
3130 XtWarning(CB_SET_ITEM);
3136 DtComboBoxSelectItem( Widget combow,
3139 DtComboBoxWidget combo = (DtComboBoxWidget)combow;
3140 DtComboBoxPart *combo_p = (DtComboBoxPart*)
3141 &(XmField(combo,ipot,DtComboBox,arrow,Widget));
3142 XmStringTable list_items;
3146 _DtWidgetToAppContext(combow);
3149 /* Try to help confused applications. */
3150 if (XmIsComboBox(combow))
3152 XmComboBoxSelectItem(combow, item);
3159 XtSetArg(arg, XmNitems, &list_items);
3160 XtGetValues(((Widget)List(combo)), &arg, 1);
3162 if (item && list_items) {
3163 for (i = 0; i < ItemCount(combo); i++)
3164 if (XmStringCompare(item, list_items[i]))
3166 if (i < ItemCount(combo)) {
3167 SelectedPosition(combo) = i;
3168 tmpStr=SelectedItem(combo);
3169 SelectedItem(combo) = XmStringCopy(item);
3170 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
3171 SetTextFieldData(combo_p, NULL);
3173 SetLabelData(combo_p, NULL, FALSE);
3174 XmListDeselectAllItems(List(combo));
3175 XmListSelectItem(List(combo), item, FALSE);
3177 XmStringFree(tmpStr);
3178 SyncWithList(combo_p);
3181 XtWarning(CB_SELECT_ITEM);
3184 XtWarning(CB_SELECT_ITEM);
3191 * Synthetic GetValues for List resources.
3194 static XmImportOperator
3195 _XmSetSyntheticResForChild( Widget widget,
3199 return(XmSYNTHETIC_LOAD);
3203 _DtComboBoxGetArrowSize(Widget w,
3204 int resource_offset,
3207 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3211 XtSetArg(arg, XmNheight, &data);
3212 XtGetValues(Arrow(combo), &arg, 1);
3213 *value = (XtArgVal)data;
3217 _DtComboBoxGetLabelString( Widget w,
3218 int resource_offset,
3221 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3223 if (LabelString(combo))
3224 *value = (XtArgVal)XmStringCopy(LabelString(combo));
3226 *value = (XtArgVal)NULL;
3230 _DtComboBoxGetListItemCount( Widget w,
3231 int resource_offset,
3234 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3238 XtSetArg(arg, XmNitemCount, &data);
3239 XtGetValues(List(combo), &arg, 1);
3240 *value = (XtArgVal)data;
3244 _DtComboBoxGetListItems(Widget w,
3245 int resource_offset,
3248 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3252 XtSetArg(arg, XmNitems, &data);
3253 XtGetValues(List(combo), &arg, 1);
3254 *value = (XtArgVal)data;
3258 _DtComboBoxGetListFontList( Widget w,
3259 int resource_offset,
3262 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3266 XtSetArg(arg, XmNfontList, &data);
3267 XtGetValues(List(combo), &arg, 1);
3268 *value = (XtArgVal)data;
3272 _DtComboBoxGetListMarginHeight( Widget w,
3273 int resource_offset,
3276 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3280 XtSetArg(arg, XmNmarginHeight, &data);
3281 XtGetValues(List(combo), &arg, 1);
3282 *value = (XtArgVal)data;
3286 _DtComboBoxGetListMarginWidth( Widget w,
3287 int resource_offset,
3290 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3294 XtSetArg(arg, XmNmarginWidth, &data);
3295 XtGetValues(List(combo), &arg, 1);
3296 *value = (XtArgVal)data;
3300 _DtComboBoxGetListSpacing( Widget w,
3301 int resource_offset,
3304 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3308 XtSetArg(arg, XmNspacing, &data);
3309 XtGetValues(List(combo), &arg, 1);
3310 *value = (XtArgVal)data;
3314 _DtComboBoxGetListTopItemPosition( Widget w,
3315 int resource_offset,
3318 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3322 XtSetArg(arg, XmNtopItemPosition, &data);
3323 XtGetValues(List(combo), &arg, 1);
3324 *value = (XtArgVal)data;
3328 _DtComboBoxGetListVisibleItemCount( Widget w,
3329 int resource_offset,
3332 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3336 XtSetArg(arg, XmNvisibleItemCount, &data);
3337 XtGetValues(List(combo), &arg, 1);
3338 *value = (XtArgVal)data;
3351 static unsigned char to_value;
3353 if(*num_args !=0 ) {
3354 XtError(CB_CVTSTRING);
3357 from_str = (char *)from->addr;
3358 if(strcmp(from_str, "DROP_DOWN_LIST")==0 ||
3359 strcmp(from_str, "drop_down_list")==0 ||
3360 strcmp(from_str, "DtDROP_DOWN_LIST")==0)
3361 to_value = DtDROP_DOWN_LIST;
3362 else if (strcmp(from_str, "DROP_DOWN_COMBO_BOX")==0 ||
3363 strcmp(from_str, "drop_down_combo_box")==0 ||
3364 strcmp(from_str, "DtDROP_DOWN_COMBO_BOX")==0)
3365 to_value = DtDROP_DOWN_COMBO_BOX;
3367 XtDisplayStringConversionWarning(dpy, from->addr, "ComboBoxType");
3371 if (to->addr == NULL) to->addr = (caddr_t) &to_value;
3372 else if (to->size <sizeof(unsigned char)) {
3373 XtDisplayStringConversionWarning(dpy, from->addr, "ComboBoxType");
3377 *(unsigned char *) to->addr = to_value;
3379 to->size = sizeof(unsigned char);
3385 input_ungrab ( DtComboBoxWidget combo, int ungrab_mask)
3387 XmDisplay disp = (XmDisplay) XmGetXmDisplay(XtDisplay(combo));
3389 if ( ungrab_mask & GRAB_POINTER )
3390 XtUngrabPointer(Shell(combo), CurrentTime);
3391 if ( ungrab_mask & GRAB_KEYBOARD )
3392 XtUngrabKeyboard(List(combo), CurrentTime);
3393 _XmRemoveGrab(Shell(combo));
3395 /* We move XtPopdown() here and do _XmRemoveGrab first.
3396 * This is a fix to solve an MR in Desktop which over a time period
3397 * develope a possible core-dump due to duplicated removeGrab() calls
3399 PoppedUp(combo) = FALSE;
3400 XtPopdown(Shell(combo));
3401 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
3402 XmProcessTraversal(Text(combo), XmTRAVERSE_CURRENT);
3404 /* This is to enable the Drag-and-Drop operation */
3405 disp->display.userGrabbed = False;