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/DisplayP.h>
113 #include <Xm/ComboBox.h> /* for redirecting utility functions */
114 #include "DtWidgetI.h" /* for _Dt thread-safety macros */
119 #define DtComboBoxIndex (XmManagerIndex + 1)
120 static XmOffsetPtr ipot; /* Instance part offset table */
121 static XmOffsetPtr cpot; /* Constraint part offset table */
123 #define ScrollBarVisible( wid) (wid && XtIsManaged( wid))
125 static void ClassInitialize (void);
126 static void Initialize (DtComboBoxWidget request,
127 DtComboBoxWidget new, ArgList given_args,
129 static XmNavigability WidgetNavigable (DtComboBoxWidget combo);
130 static void _ComboBoxFocusIn (DtComboBoxWidget combo, XEvent *event,
131 char **params, Cardinal *num_params);
132 static void _ComboBoxFocusOut (DtComboBoxWidget combo, XEvent *event,
133 char **params, Cardinal *num_params);
134 static void DrawHighlight (DtComboBoxWidget combo, Boolean clear);
135 static void _ComboBoxActivate (Widget w, XEvent *event, char **params,
136 Cardinal *num_params);
137 static void _ComboBoxKbdCancel (Widget w, XEvent *event, char **params,
138 Cardinal *num_params);
139 static void _ComboBoxPrevTabGroup (Widget w, XEvent *event,
140 char **params, Cardinal *num_params);
141 static void _ComboBoxNextTabGroup (Widget w, XEvent *event,
142 char **params, Cardinal *num_params);
143 static void CheckResources (DtComboBoxWidget combo);
144 static void Destroy (DtComboBoxWidget combo);
145 static void Resize (DtComboBoxWidget combo);
146 static void Redisplay (DtComboBoxWidget w, XEvent *event,
148 static XtGeometryResult GeometryManager (Widget w,
149 XtWidgetGeometry *request,
150 XtWidgetGeometry *reply);
151 static void SetComboBoxSize (DtComboBoxWidget combo);
152 static void ForceChildSizes (DtComboBoxWidget combo);
153 static void LayoutChildren (DtComboBoxWidget combo);
154 static Boolean SetValues (DtComboBoxWidget current,
155 DtComboBoxWidget request, DtComboBoxWidget new);
156 static void ClearShadow (DtComboBoxWidget w, Boolean all);
157 static void DrawShadow (DtComboBoxWidget w);
158 static char* GetTextString (XmString xm_string);
159 static void SetTextFieldData (DtComboBoxPart *combo_p, XmString item);
160 static void SetMaximumLabelSize (DtComboBoxPart *combo_p);
161 static void SetLabelData (DtComboBoxPart *combo_p, XmString item,
162 Boolean force_label_string);
163 static void select_cb (Widget w, XtPointer client_data,
164 XtPointer call_data);
165 static void shell_event_handler (Widget widget, XtPointer client_data,
166 XEvent* event, Boolean *dispatch);
167 static void list_event_handler (Widget widget, XtPointer client_data,
168 XEvent* event, Boolean *dispatch);
169 static void TextFieldActivate (DtComboBoxPart *combo_p, XtPointer call_data);
170 static void activate_cb (Widget w, XtPointer client_data,
171 XtPointer call_data);
172 static void arrow_expose_cb (Widget w, XtPointer client_data,
173 XtPointer call_data);
174 static void text_losing_focus_cb (Widget w, XtPointer client_data,
175 XtPointer call_data);
176 static void text_activate_cb (Widget w, XtPointer client_data,
177 XtPointer call_data);
178 static void text_focus_cb (Widget w, XtPointer client_data,
179 XtPointer call_data);
180 static void SyncWithList (DtComboBoxPart *combo_p);
181 static XmImportOperator _XmSetSyntheticResForChild (Widget widget,
185 static Boolean _CvtStringToType (Display *dpy, XrmValuePtr args,
186 Cardinal *num_args, XrmValuePtr from, XrmValuePtr to, XtPointer *data);
188 /* Grab and Ungrab processing */
189 static void input_ungrab ( DtComboBoxWidget combo, int ungrab_mask);
191 /* Resolution Independent Processing */
192 void _DtComboBoxGetArrowSize( Widget w,
195 void _DtComboBoxGetListMarginHeight( Widget w,
198 void _DtComboBoxGetListMarginWidth( Widget w,
201 void _DtComboBoxGetListSpacing( Widget w,
206 static XmString InitLabel = NULL;
212 #define Arrow(w) XmField(w,ipot,DtComboBox,arrow,Widget)
213 #define Shell(w) XmField(w,ipot,DtComboBox,shell,Widget)
214 #define Frame(w) XmField(w,ipot,DtComboBox,frame,Widget)
215 #define Label(w) XmField(w,ipot,DtComboBox,label,Widget)
216 #define Sep(w) XmField(w,ipot,DtComboBox,sep,Widget)
217 #define OldWidth(w) XmField(w,ipot,DtComboBox,old_width,Dimension)
218 #define OldHeight(w) XmField(w,ipot,DtComboBox,old_height,Dimension)
219 #define LabelMaxLength(w) XmField(w,ipot,DtComboBox,label_max_length,Dimension)
220 #define LabelMaxHeight(w) XmField(w,ipot,DtComboBox,label_max_height,Dimension)
222 #define MaxShellWidth(w) XmField(w,ipot,DtComboBox,max_shell_width,Dimension)
223 #define MaxShellHeight(w) XmField(w,ipot,DtComboBox,max_shell_height,Dimension)
225 #define MarginHeight(w) XmField(w,ipot,DtComboBox,margin_height,Dimension)
226 #define MarginWidth(w) XmField(w,ipot,DtComboBox,margin_width,Dimension)
227 #define SelectedItem(w) XmField(w,ipot,DtComboBox,selected_item,XmString)
228 #define SelectedPosition(w) XmField(w,ipot,DtComboBox,selected_position,int)
229 #define SelectionCallback(w) \
230 XmField(w,ipot,DtComboBox,selection_callback,XtCallbackList)
231 #define Type(w) XmField(w,ipot,DtComboBox,type,unsigned char)
232 #define ArrowSpacing(w) XmField(w,ipot,DtComboBox,arrow_spacing,Dimension)
234 #define ArrowSize(w) XmField(w,ipot,DtComboBox,arrow_size,Dimension)
235 #define ActivateCallback(w) \
236 XmField(w,ipot,DtComboBox,activate_callback,XtCallbackList)
237 #define Alignment(w) XmField(w,ipot,DtComboBox,alignment,unsigned char)
238 #define ArrowType(w) XmField(w,ipot,DtComboBox,arrow_type,unsigned char)
239 #define TextColumns(w) XmField(w,ipot,DtComboBox,text_columns,short)
240 #define FocusCallback(w) XmField(w,ipot,DtComboBox,focus_callback,XtCallbackList)
241 #define HorizontalSpacing(w) XmField(w,ipot,DtComboBox,horizontal_spacing,Dimension)
242 #define ItemCount(w) XmField(w,ipot,DtComboBox,item_count,int)
243 #define Items(w) XmField(w,ipot,DtComboBox,items,XmStringTable)
244 #define ListItems(w) XmField(w,ipot,DtComboBox,list_items,XmStringTable)
245 #define LabelString(w) XmField(w,ipot,DtComboBox,label_string,XmString)
246 #define List(w) XmField(w,ipot,DtComboBox,list,Widget)
247 #define ListFontList(w) XmField(w,ipot,DtComboBox,list_font_list,XmFontList)
248 #define ListMarginHeight(w) XmField(w,ipot,DtComboBox,list_margin_height,Dimension)
249 #define ListMarginWidth(w) XmField(w,ipot,DtComboBox,list_margin_width,Dimension)
250 #define ListSpacing(w) XmField(w,ipot,DtComboBox,list_spacing,Dimension)
251 #define LosingFocusCallback(w) XmField(w,ipot,DtComboBox,losing_focus_callback,XtCallbackList)
252 #define TextMaxLength(w) XmField(w,ipot,DtComboBox,text_max_length,unsigned int)
253 #define MenuPostCallback(w) XmField(w,ipot,DtComboBox,menu_post_callback,XtCallbackList)
254 #define Orientation(w) XmField(w,ipot,DtComboBox,orientation,unsigned char)
255 #define PoppedUp(w) XmField(w,ipot,DtComboBox,popped_up,Boolean)
256 #define RecomputeSize(w) XmField(w,ipot,DtComboBox,recompute_size,Boolean)
257 #define Text(w) XmField(w,ipot,DtComboBox,text,Widget)
258 #define TopItemPosition(w) XmField(w,ipot,DtComboBox,top_item_position,int)
259 #define UpdateLabel(w) XmField(w,ipot,DtComboBox,update_label,Boolean)
260 #define VerticalSpacing(w) XmField(w,ipot,DtComboBox,vertical_spacing,Dimension)
261 #define VisibleItemCount(w) XmField(w,ipot,DtComboBox,visible_item_count,int)
264 * DtComboBoxWidget specific defines.
266 #define PUnitType(w) w->primitive.unit_type
267 #define ShellPoppedUp(w) w->shell.popped_up
268 #define MUnitType(w) w->manager.unit_type
269 #define COMBO_SHADOW(w) w->manager.shadow_thickness
270 #define LayoutDirection(w) w->manager.string_direction
271 #define NavigationType(w) w->manager.navigation_type
272 #define TraversalOn(w) w->manager.traversal_on
273 #define BackgroundGC(w) w->manager.background_GC
274 #define HighlightGC(w) w->manager.highlight_GC
275 #define TopShadowGC(w) w->manager.top_shadow_GC
276 #define BottomShadowGC(w) w->manager.bottom_shadow_GC
277 #define BackgroundPixel(w) w->core.background_pixel
278 #define X(w) w->core.x
279 #define Y(w) w->core.y
280 #define Width(w) w->core.width
281 #define Height(w) w->core.height
282 #define BorderWidth(w) w->core.border_width
283 #define Sensitive(w) w->core.sensitive
284 #define AncestorSensitive(w) w->core.ancestor_sensitive
285 #define Parent(w) w->core.parent
286 #define COMBO_MARGIN_W(w) MarginWidth(w)
287 #define COMBO_MARGIN_H(w) MarginHeight(w)
288 #define COMBO_H_SPACING(w) HorizontalSpacing(w)
289 #define COMBO_V_SPACING(w) VerticalSpacing(w)
291 #define GRAB_POINTER 1 << 0
292 #define GRAB_KEYBOARD 1 << 1
294 #define DtNonePopup 0
295 #define DtPopup 1 << 0
296 #define DtButtonPressPopup 1 << 1
297 #define DtKeyPressPopup 1 << 2
299 #define LIST_EVENTS (ButtonReleaseMask | FocusChangeMask | EnterWindowMask)
300 #define SHELL_EVENTS (ButtonPressMask | ButtonReleaseMask)
301 #define INVALID_DIMENSION (0xFFFF)
304 static char ComboBoxTranslationTable[] = "\
305 <FocusIn>: ComboBoxFocusIn() \n\
306 <FocusOut>: ComboBoxFocusOut() \n\
307 <Key>osfDown: ComboBoxActivate() \n\
308 <Btn1Down>: ComboBoxActivate() \n\
309 <Key>osfSelect: ComboBoxActivate() \n\
310 ~s ~m ~a <Key>space: ComboBoxActivate() \n\
313 static char ComboBoxLabelTranslationTable[] = "\
314 <Key>osfDown: ComboBoxActivate(label) \n\
315 <Btn1Down>: ComboBoxActivate(label) \n\
316 <Key>osfSelect: ComboBoxActivate(label) \n\
317 ~s ~m ~a <Key>space: ComboBoxActivate(label) \n\
320 /* Keyboard Only Traversing During Editable-Mode */
321 static char ComboBoxTextTranslationTable[] = "\
322 <Key>osfUp: ComboBoxActivate(label) \n\
323 <Key>osfDown: ComboBoxActivate(label) \n\
326 static char ComboBoxButtonTranslationTable[] = "\
327 <Key>osfDown: ComboBoxActivate(label) \n\
328 <Btn1Down>: ComboBoxActivate(label) \n\
329 ~s ~m ~a <Key>space: ComboBoxActivate(label) \n\
330 s ~m ~a <Key>Tab: ComboBoxPrevTabGroup()\n\
331 ~m ~a <Key>Tab: ComboBoxNextTabGroup()\n\
334 static char ComboBoxListTranslationTable[] = "\
335 <Key>osfCancel: ListKbdCancel() ComboBoxKbdCancel() \n\
338 static XtActionsRec ComboBoxActionTable[] = {
339 {"ComboBoxFocusIn", (XtActionProc)_ComboBoxFocusIn},
340 {"ComboBoxFocusOut", (XtActionProc)_ComboBoxFocusOut},
341 {"ComboBoxActivate", (XtActionProc)_ComboBoxActivate},
342 {"ComboBoxKbdCancel", (XtActionProc)_ComboBoxKbdCancel},
343 {"ComboBoxPrevTabGroup", (XtActionProc)_ComboBoxPrevTabGroup},
344 {"ComboBoxNextTabGroup", (XtActionProc)_ComboBoxNextTabGroup},
349 * DtComboBoxWidget resources
351 #define offset(field) XtOffset(DtComboBoxWidget, field)
352 #define DtOffset(field) XmPartOffset(DtComboBox,field)
353 static XmPartResource resources[] = {
354 {XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension,
355 sizeof(Dimension), offset(manager.shadow_thickness),
356 XmRImmediate, (XtPointer)TEXT_FIELD_SHADOW},
359 * ComboBox specific resources
361 {DtNactivateCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
362 DtOffset(activate_callback), XmRCallback,
364 {DtNalignment, DtCAlignment, XmRAlignment, sizeof(unsigned char),
365 DtOffset(alignment), XmRImmediate,
366 (XtPointer)DtALIGNMENT_END},
367 {DtNarrowSpacing, DtCArrowSpacing, XmRHorizontalDimension,
368 sizeof(Dimension), DtOffset(arrow_spacing),
369 XmRImmediate, (XtPointer)0},
370 {DtNarrowType, DtCArrowType, DtRArrowType, sizeof(unsigned char),
371 DtOffset(arrow_type), XmRImmediate, (XtPointer)DtMOTIF},
372 {DtNcolumns, DtCColumns, XmRShort, sizeof(short),
373 DtOffset(text_columns), XmRImmediate, (XtPointer)20},
374 {DtNfocusCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
375 DtOffset(focus_callback), XmRCallback,
377 {DtNhorizontalSpacing, DtCHorizontalSpacing, XmRHorizontalDimension,
378 sizeof(Dimension), DtOffset(horizontal_spacing),
379 XmRImmediate, (XtPointer)INVALID_DIMENSION},
380 {DtNitemCount, DtCItemCount, XmRInt, sizeof(int),
381 DtOffset(item_count), XmRImmediate, (XtPointer)0},
383 * items is used only for seeing if the user changed the list. It
384 * is only a pointer that reflects the current list's items.
386 {DtNitems, DtCItems, XmRXmStringTable, sizeof(XmStringTable),
387 DtOffset(items), XmRImmediate, (XtPointer)NULL},
388 {DtNlabelString, DtCXmString, XmRXmString, sizeof(XmString),
389 DtOffset(label_string), XmRImmediate, (XtPointer)NULL},
390 {DtNlist, DtCList, XmRWidget, sizeof(Widget),
391 DtOffset(list), XmRImmediate, (XtPointer)NULL},
392 {DtNlistFontList, DtCListFontList, XmRFontList, sizeof(XmFontList),
393 DtOffset(list_font_list), XmRImmediate, (XtPointer)NULL},
394 {DtNlistMarginHeight, DtCListMarginHeight, XmRVerticalDimension,
395 sizeof(Dimension), DtOffset(list_margin_height),
396 XmRImmediate, (XtPointer)MARGIN},
397 {DtNlistMarginWidth, DtCListMarginWidth, XmRHorizontalDimension,
398 sizeof(Dimension), DtOffset(list_margin_width),
399 XmRImmediate, (XtPointer)MARGIN},
400 {DtNlistSpacing, DtCListSpacing, XmRVerticalDimension,sizeof(Dimension),
401 DtOffset(list_spacing), XmRImmediate, (XtPointer)0},
402 {DtNlosingFocusCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
403 DtOffset(losing_focus_callback), XmRCallback,
405 {DtNmarginHeight, DtCMarginHeight, XmRVerticalDimension,
406 sizeof(Dimension), DtOffset(margin_height),
407 XmRImmediate, (XtPointer)MARGIN},
408 {DtNmarginWidth, DtCMarginWidth, XmRHorizontalDimension, sizeof(Dimension),
409 DtOffset(margin_width), XmRImmediate, (XtPointer)MARGIN},
410 {DtNmaxLength, DtCMaxLength, XmRInt, sizeof(unsigned int),
411 DtOffset(text_max_length), XmRImmediate, (XtPointer)INT_MAX},
412 {DtNmenuPostCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
413 DtOffset(menu_post_callback), XmRCallback, (XtPointer)NULL},
414 {DtNorientation, DtCOrientation, XmROrientation, sizeof(unsigned char),
415 DtOffset(orientation), XmRImmediate, (XtPointer)DtRIGHT},
416 {DtNpoppedUp, DtCPoppedUp, XmRBoolean, sizeof(Boolean),
417 DtOffset(popped_up), XmRImmediate, (XtPointer)FALSE},
418 {DtNrecomputeSize, DtCRecomputeSize, XmRBoolean, sizeof(Boolean),
419 DtOffset(recompute_size), XmRImmediate, (XtPointer)TRUE},
420 {DtNselectedItem, DtCXmString, XmRXmString, sizeof(XmString),
421 DtOffset(selected_item), XmRImmediate, (XtPointer)NULL},
422 {DtNselectedPosition, DtCSelectedPosition, XmRInt, sizeof(int),
423 DtOffset(selected_position), XmRImmediate, (XtPointer)0},
424 {DtNselectionCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
425 DtOffset(selection_callback), XmRCallback, (XtPointer)NULL},
426 {DtNtextField, DtCTextField, XmRWidget, sizeof(Widget),
427 DtOffset(text), XmRImmediate, (XtPointer)NULL},
428 {DtNtopItemPosition, DtCTopItemPosition, XmRInt, sizeof(int),
429 DtOffset(top_item_position), XmRImmediate, (XtPointer)1},
430 {DtNcomboBoxType, DtCComboBoxType, DtRComboBoxType, sizeof(unsigned char),
431 DtOffset(type), XmRImmediate,(XtPointer)DtDROP_DOWN_LIST},
432 {DtNupdateLabel, DtCUpdateLabel, XmRBoolean, sizeof(Boolean),
433 DtOffset(update_label), XmRImmediate, (XtPointer)TRUE},
434 {DtNvisibleItemCount, DtCVisibleItemCount, XmRInt, sizeof(int),
435 DtOffset(visible_item_count), XmRImmediate, (XtPointer)10},
436 {DtNverticalSpacing, DtCVerticalSpacing, XmRVerticalDimension,
437 sizeof(Dimension), DtOffset(vertical_spacing),
438 XmRImmediate, (XtPointer)INVALID_DIMENSION},
442 * List resources (used for GetValues).
444 static XmSyntheticResource syn_resources[] = {
445 {DtNarrowSpacing, sizeof(Dimension), DtOffset(arrow_spacing),
446 XmeFromHorizontalPixels, XmeToHorizontalPixels},
447 {DtNhorizontalSpacing, sizeof(Dimension), DtOffset(horizontal_spacing),
448 XmeFromHorizontalPixels, XmeToHorizontalPixels},
449 {DtNverticalSpacing, sizeof(Dimension), DtOffset(vertical_spacing),
450 XmeFromVerticalPixels, XmeToVerticalPixels},
451 {DtNmarginWidth, sizeof(Dimension), DtOffset(margin_width),
452 XmeFromHorizontalPixels, XmeToHorizontalPixels},
453 {DtNmarginHeight, sizeof(Dimension), DtOffset(margin_height),
454 XmeFromVerticalPixels, XmeToVerticalPixels},
455 {DtNarrowSize, sizeof(Dimension), DtOffset(arrow_size),
456 _DtComboBoxGetArrowSize, XmeToHorizontalPixels},
457 {DtNlabelString, sizeof(XmString), DtOffset(label_string),
458 _DtComboBoxGetLabelString, _XmSetSyntheticResForChild},
459 {DtNitemCount, sizeof(int), DtOffset(item_count),
460 _DtComboBoxGetListItemCount, _XmSetSyntheticResForChild},
461 {DtNitems, sizeof(XmStringTable), DtOffset(items),
462 _DtComboBoxGetListItems, _XmSetSyntheticResForChild},
463 {DtNlistFontList, sizeof(XmFontList), DtOffset(list_font_list),
464 _DtComboBoxGetListFontList, _XmSetSyntheticResForChild},
465 {DtNlistMarginHeight, sizeof(Dimension),
466 DtOffset(list_margin_height),
467 _DtComboBoxGetListMarginHeight, XmeToVerticalPixels},
468 {DtNlistMarginWidth, sizeof(Dimension),DtOffset(list_margin_width),
469 _DtComboBoxGetListMarginWidth, XmeToHorizontalPixels},
470 {DtNlistSpacing, sizeof(Dimension), DtOffset(list_spacing),
471 _DtComboBoxGetListSpacing, XmeToVerticalPixels},
472 {DtNtopItemPosition, sizeof(int), DtOffset(top_item_position),
473 _DtComboBoxGetListTopItemPosition, _XmSetSyntheticResForChild},
474 {DtNvisibleItemCount, sizeof(int), DtOffset(visible_item_count),
475 _DtComboBoxGetListVisibleItemCount, _XmSetSyntheticResForChild},
480 /* Need Class Extension for widget navigation */
481 static XmBaseClassExtRec baseClassExtRec = {
484 XmBaseClassExtVersion,
485 sizeof(XmBaseClassExtRec),
486 (XtInitProc)NULL, /* InitializePrehook */
487 (XtSetValuesFunc)NULL, /* SetValuesPrehook */
488 (XtInitProc)NULL, /* InitializePosthook */
489 (XtSetValuesFunc)NULL, /* SetValuesPosthook */
490 NULL, /* secondaryObjectClass */
491 (XtInitProc)NULL, /* secondaryCreate */
492 (XmGetSecResDataFunc)NULL, /* getSecRes data */
493 { 0 }, /* fastSubclass flags */
494 (XtArgsProc)NULL, /* getValuesPrehook */
495 (XtArgsProc)NULL, /* getValuesPosthook */
496 (XtWidgetClassProc)NULL, /* classPartInitPrehook */
497 (XtWidgetClassProc)NULL, /* classPartInitPosthook*/
498 NULL, /* ext_resources */
499 NULL, /* compiled_ext_resources*/
500 0, /* num_ext_resources */
501 FALSE, /* use_sub_resources */
502 (XmWidgetNavigableProc)WidgetNavigable,
503 /* widgetNavigable */
504 (XmFocusChangeProc)NULL, /* focusChange */
505 (XmWrapperData)NULL /* wrapperData */
509 * Define Class Record.
511 externaldef(dtcomboBoxclassrec) DtComboBoxClassRec dtComboBoxClassRec =
513 { /* core_class fields */
514 (WidgetClass)&(xmManagerClassRec), /* superclass */
515 (String)"DtComboBox", /* class_name */
516 (Cardinal)sizeof(DtComboBoxPart), /* widget_size */
517 (XtProc)ClassInitialize, /* class_initialize */
518 (XtWidgetClassProc)NULL, /* class_part_init */
519 (XtEnum)FALSE, /* class_inited */
520 (XtInitProc)Initialize, /* initialize */
521 (XtArgsProc)NULL, /* initialize_hook */
522 (XtRealizeProc)XtInheritRealize, /* realize */
523 (XtActionList)ComboBoxActionTable, /* actions */
524 (Cardinal)XtNumber(ComboBoxActionTable), /* num_actions */
525 (XtResourceList)resources, /* resources */
526 (Cardinal)XtNumber(resources), /* num_resources */
527 (XrmClass)NULLQUARK, /* xrm_class */
528 (Boolean)TRUE, /* compress_motion */
529 (XtEnum)XtExposeCompressMaximal, /* compress_exposure */
530 (Boolean)TRUE, /* compress_enterleave*/
531 (Boolean)FALSE, /* visible_interest */
532 (XtWidgetProc)Destroy, /* destroy */
533 (XtWidgetProc)Resize, /* resize */
534 (XtExposeProc)Redisplay, /* expose */
535 (XtSetValuesFunc)SetValues, /* set_values */
536 (XtArgsFunc)NULL, /* set values hook */
537 (XtAlmostProc)XtInheritSetValuesAlmost, /* set values almost */
538 (XtArgsProc)NULL, /* get values hook */
539 (XtAcceptFocusProc)NULL, /* accept_focus */
540 (XtVersionType)XtVersionDontCheck, /* Version */
541 (XtPointer)NULL, /* PRIVATE cb list */
542 (String)XtInheritTranslations, /* tm_table */
543 (XtGeometryHandler)XtInheritQueryGeometry, /* query_geom */
544 (XtStringProc)XtInheritDisplayAccelerator, /* display_accelerator*/
545 (XtPointer)&baseClassExtRec /* extension */
547 { /* composite_class fields */
548 (XtGeometryHandler)GeometryManager, /* geometry_manager */
549 (XtWidgetProc)XtInheritChangeManaged, /* change_managed */
550 (XtWidgetProc)XtInheritInsertChild, /* insert_child */
551 (XtWidgetProc)XtInheritDeleteChild, /* delete_child */
552 (XtPointer)NULL /* extension */
554 { /* constraint_class fields */
555 (XtResourceList)NULL, /* resources */
556 (Cardinal)0, /* num_resources */
557 (Cardinal)0, /* constraint_size */
558 (XtInitProc)NULL, /* initialize */
559 (XtWidgetProc)NULL, /* destroy */
560 (XtSetValuesFunc)NULL, /* set_values */
561 (XtPointer)NULL /* extension */
563 { /* manager class */
564 (String)XtInheritTranslations, /* translations */
565 (XmSyntheticResource*)syn_resources, /* syn resources */
566 (int)XtNumber(syn_resources), /* num syn_resources */
567 (XmSyntheticResource*)NULL, /* get_cont_resources */
568 (int)0, /* num_get_cont_resources */
569 (XmParentProcessProc)XmInheritParentProcess,/* parent_process */
570 (XtPointer)NULL /* extension */
572 { /* combo_box_class fields */
577 externaldef(dtcomboBoxwidgetclass) WidgetClass dtComboBoxWidgetClass =
578 (WidgetClass)&dtComboBoxClassRec;
579 /* Parse the translation tables only once for the whole class
581 static XtTranslations trans;
582 static XtTranslations list_trans;
583 static XtTranslations label_trans;
584 static XtTranslations text_trans;
585 static XtTranslations button_trans;
588 * Must set up the record type for the class extensions to work.
591 ClassInitialize(void)
593 baseClassExtRec.record_type = XmQmotif;
597 XmResolveAllPartOffsets(dtComboBoxWidgetClass, &ipot, &cpot);
598 /* Parse the translation tables here
600 trans = XtParseTranslationTable(ComboBoxTranslationTable);
601 list_trans = XtParseTranslationTable(ComboBoxListTranslationTable);
602 label_trans = XtParseTranslationTable(ComboBoxLabelTranslationTable);
603 text_trans = XtParseTranslationTable(ComboBoxTextTranslationTable);
604 button_trans =XtParseTranslationTable(ComboBoxButtonTranslationTable);
606 /* Add a type converter for String to DtRComboBoxType
608 XtSetTypeConverter("String","ComboBoxType", _CvtStringToType, NULL, 0,
611 InitLabel = XmStringCreateLocalized(CB_LABEL);
615 * ComboBox initialization function. This builds the widgets inside
616 * our widget, to get the correct layout. If the type resource
617 * is DtDROP_DOWN_COMBO_BOX, we create a textField; if FALSE, we create a
618 * label. If the user changes this resource later, we will create the
619 * other widget (textField or Label). We don't want to carry backage from
620 * both widgets if the user never changes the type resource.
623 Initialize( DtComboBoxWidget request,
624 DtComboBoxWidget new,
628 /* use the address of the first element of DtComboBoxPart structure
629 * as of DtComboBoxPart
631 DtComboBoxPart *combo_p = (DtComboBoxPart*)
632 &(XmField(new,ipot,DtComboBox,arrow,Widget));
633 Boolean force_label_string = FALSE;
636 /* Resolution Independent */
637 unsigned char unit_type = MUnitType(new);
639 /* Overwrite the manager's focusIn and focusOut translations */
640 XtOverrideTranslations((Widget)new, trans);
644 * force_label_string usage if it is specified and items is not.
645 * This will be the perminant label string only if update-label
646 * is false, else it is only used until the user picks something
649 if (LabelString(new) == NULL)
650 LabelString(new) = InitLabel;
651 else if (!Items(new))
652 force_label_string = TRUE;
654 /* Copy given label-string. */
655 if (LabelString(new))
656 LabelString(new) = XmStringCopy(LabelString(new));
658 Text(new) = (Widget)NULL;
659 Label(new) = (Widget)NULL;
660 Sep(new) = (Widget)NULL;
667 * Create the text or label depending on the type resource.
668 * When part of X-Designer, we create both at initialization to
669 * avoid later crashes.
671 if (Type(new) == DtDROP_DOWN_COMBO_BOX)
674 XtSetArg(args[n], XmNcolumns, TextColumns(new)); n++;
675 XtSetArg(args[n], XmNmaxLength, TextMaxLength(new)); n++;
676 XtSetArg(args[n], XmNmarginWidth, TEXT_CONTEXT_MARGIN); n++;
677 XtSetArg(args[n], XmNmarginHeight, 2); n++;
678 /* Resolution Independent */
679 if (unit_type != XmPIXELS) {
680 XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
682 Text(new) = XtCreateManagedWidget("Text",
683 xmTextFieldWidgetClass,
684 (Widget)new, args, n);
685 XtAddCallback(Text(new), XmNlosingFocusCallback,
686 text_losing_focus_cb, (XtPointer)new);
687 XtAddCallback(Text(new), XmNactivateCallback,
688 text_activate_cb, (XtPointer)new);
689 XtAddCallback(Text(new), XmNfocusCallback,
690 text_focus_cb, (XtPointer)new);
692 XtOverrideTranslations(Text(new), text_trans);
694 if (HorizontalSpacing(new) == INVALID_DIMENSION)
695 HorizontalSpacing(new) = 0;
696 if (VerticalSpacing(new) == INVALID_DIMENSION)
697 VerticalSpacing(new) = 0;
698 if (unit_type != XmPIXELS) {
699 XtSetArg(args[0], XmNunitType, unit_type);
700 XtSetValues(Text(new), args, 1);
705 XmStringDirection new_direction =
706 XmDirectionToStringDirection(LayoutDirection(new));
708 COMBO_SHADOW(new) = LABEL_SHADOW;
710 XtSetArg(args[n], XmNalignment, Alignment(new)); n++;
711 XtSetArg(args[n], XmNrecomputeSize, FALSE); n++;
712 XtSetArg(args[n], XmNlabelString, InitLabel); n++;
713 XtSetArg(args[n], XmNmarginLeft, LABEL_PADDING); n++;
714 XtSetArg(args[n], XmNmarginRight, LABEL_PADDING); n++;
715 XtSetArg(args[n], XmNmarginWidth, TEXT_CONTEXT_MARGIN); n++;
716 XtSetArg(args[n], XmNmarginHeight, 0); n++;
717 XtSetArg(args[n], XmNstringDirection, new_direction); n++;
718 /* Resolution Independent */
719 if (unit_type != XmPIXELS) {
720 XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
722 Label(new) = XtCreateManagedWidget("Label",
724 (Widget)new, args, n);
725 XtOverrideTranslations(Label(new), label_trans);
726 if (HorizontalSpacing(new) == INVALID_DIMENSION)
727 HorizontalSpacing(new) = 1;
728 if (VerticalSpacing(new) == INVALID_DIMENSION)
729 VerticalSpacing(new) = 2;
730 if (unit_type != XmPIXELS) {
731 XtSetArg(args[0], XmNunitType, unit_type);
732 XtSetValues(Label(new), args, 1);
737 * Create the separator used if non-editable combo-box.
739 if (Type(new) == DtDROP_DOWN_LIST)
742 XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
743 /* Resolution Independent */
744 if (unit_type != XmPIXELS) {
745 XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
747 Sep(new) = XtCreateManagedWidget("ComboBoxSeparator",
748 xmSeparatorWidgetClass,
749 (Widget)new, args, n);
751 XtOverrideTranslations((Widget)Sep(new), button_trans);
752 if (unit_type != XmPIXELS) {
753 XtSetArg(args[0], XmNunitType, unit_type);
754 XtSetValues(Sep(new), args, 1);
759 * Create the ArrowWidget.
762 XtSetArg(args[n], XmNtraversalOn, FALSE); n++;
763 XtSetArg(args[n], XmNhighlightThickness, 0); n++;
764 XtSetArg(args[n], XmNshadowThickness, 0); n++;
765 if (ArrowType(new) == DtMOTIF) {
766 XtSetArg(args[n], XmNarrowDirection, XmARROW_DOWN); n++;
767 XtSetArg(args[n], XmNforeground, BackgroundPixel(new)); n++;
768 Arrow(new) = XtCreateManagedWidget("ComboBoxArrow",
769 xmArrowButtonWidgetClass,
770 (Widget)new, args, n);
773 Arrow(new) = XtCreateManagedWidget("ComboBoxArrow",
774 xmDrawnButtonWidgetClass,
775 (Widget)new, args, n);
776 XtAddCallback(Arrow(new), XmNexposeCallback, arrow_expose_cb,
779 XtAddCallback(Arrow(new), XmNactivateCallback, activate_cb,
782 XtOverrideTranslations((Widget)Arrow(new), button_trans);
785 * Create the shell and associated list widgets.
788 XtSetArg(args[n], XtNoverrideRedirect, TRUE); n++;
789 XtSetArg(args[n], XtNallowShellResize, TRUE); n++;
790 XtSetArg(args[n], XtNsaveUnder, TRUE); n++;
791 Shell(new) = XtCreatePopupShell("ComboBoxMenuShell",
792 topLevelShellWidgetClass,
793 (Widget)new, args, n);
796 Frame(new) = XtCreateManagedWidget("ComboBoxRowColumn",
798 Shell(new), args, n);
801 /* Store combo widget in list for later use */
802 XtSetArg(args[n], XmNuserData, (XtPointer)new); n++;
803 if (ListFontList(new)) {
804 XtSetArg(args[n], XmNfontList, ListFontList(new)); n++;
806 /* to disable double click */
807 XtSetArg(args[n], XmNdoubleClickInterval, 0); n++;
808 XtSetArg(args[n], XmNitemCount, ItemCount(new)); n++;
809 XtSetArg(args[n], XmNitems, Items(new)); n++;
810 XtSetArg(args[n], XmNlistMarginHeight, ListMarginHeight(new)); n++;
811 XtSetArg(args[n], XmNlistMarginWidth, ListMarginWidth(new)); n++;
812 XtSetArg(args[n], XmNlistSpacing, ListSpacing(new)); n++;
814 XmStringDirection new_direction =
815 XmDirectionToStringDirection(LayoutDirection(new));
816 XtSetArg(args[n], XmNstringDirection, new_direction); n++;
818 XtSetArg(args[n], XmNtopItemPosition, TopItemPosition(new)); n++;
819 XtSetArg(args[n], XmNvisibleItemCount, VisibleItemCount(new)); n++;
820 XtSetArg(args[n], XmNlistSizePolicy, XmRESIZE_IF_POSSIBLE); n++;
821 XtSetArg(args[n], XmNselectionPolicy, XmBROWSE_SELECT); n++;
822 /* Resolution Independent */
823 if (unit_type != XmPIXELS) {
824 XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
826 List(new) = XmCreateScrolledList(Frame(new), "List", args, n);
827 XtOverrideTranslations((Widget)List(new), list_trans);
830 XtSetArg(args[n], XmNshadowThickness, (XtArgVal) 0); n++;
831 XtSetValues(XtParent(List(new)), args, n);
833 /* selected_item resource used before selected_position */
834 if (SelectedItem(new) && XmeStringIsValid(SelectedItem(new)) ) {
835 SelectedItem(new) =XmStringCopy(SelectedItem(new));
836 DtComboBoxSelectItem((Widget)new, SelectedItem(new));
839 SelectedItem(new) = (XmString) NULL;
840 if (SelectedPosition(new)<0 || SelectedPosition(new)>=ItemCount(new))
841 SelectedPosition(new) = 0;
843 XmListSelectPos(List(new), SelectedPosition(new) + 1, FALSE);
845 if (unit_type != XmPIXELS) {
846 XtSetArg(args[0], XmNunitType, unit_type);
847 XtSetValues(List(new), args, 1);
850 SyncWithList(combo_p);
851 XtManageChild(List(new));
852 XtRealizeWidget(Shell(new));
854 MaxShellWidth(new) = Width(((Widget) Shell(new)));
855 MaxShellHeight(new) = Height(((Widget) Shell(new)));
857 XtAddCallback(List(new), XmNdefaultActionCallback, select_cb, new);
858 XtAddCallback(List(new), XmNbrowseSelectionCallback, select_cb, new);
861 * Set up event handlers needed for handling grab states.
863 XtInsertEventHandler(List(new), LIST_EVENTS, TRUE,
864 (XtEventHandler)list_event_handler,
865 (XtPointer)new, XtListHead);
866 XtInsertEventHandler(Shell(new), SHELL_EVENTS, TRUE,
867 (XtEventHandler)shell_event_handler,
868 (XtPointer)new, XtListHead);
871 * Set initial value in text or label if items was specified
873 if (Type(new) == DtDROP_DOWN_LIST) {
874 SetMaximumLabelSize(combo_p);
875 SetLabelData(combo_p, NULL, force_label_string);
878 SetTextFieldData(combo_p, NULL);
880 SetComboBoxSize(new);
886 * Allow the manager to gain focus if not editable. If editable (using
887 * text-field), then let the toolkit give focus to the text-field.
889 static XmNavigability
890 WidgetNavigable(DtComboBoxWidget combo)
892 XmNavigationType nav_type = NavigationType(((XmManagerWidget)combo));
894 if (Sensitive(combo) && AncestorSensitive(combo) &&
895 TraversalOn(((XmManagerWidget)combo))) {
896 if ((nav_type == XmSTICKY_TAB_GROUP) ||
897 (nav_type == XmEXCLUSIVE_TAB_GROUP) ||
898 ((nav_type == XmTAB_GROUP) &&
899 !_XmShellIsExclusive((Widget)combo))) {
900 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
901 return(XmDESCENDANTS_TAB_NAVIGABLE);
903 return(XmTAB_NAVIGABLE);
905 return(XmDESCENDANTS_NAVIGABLE);
907 return(XmNOT_NAVIGABLE);
911 * The combo_box gets focus.
914 _ComboBoxFocusIn( DtComboBoxWidget combo,
917 Cardinal *num_params)
919 DrawHighlight(combo, FALSE);
923 * The combo_box loses focus. Only happens if not editable.
926 _ComboBoxFocusOut( DtComboBoxWidget combo,
929 Cardinal *num_params)
931 DrawHighlight(combo, TRUE);
935 * This function gets called whenever we draw or clear the shadow (to
936 * redraw highlight during resize, etc), as well as during focus_in
937 * and focus_out events.
940 DrawHighlight( DtComboBoxWidget combo,
945 if (XtIsRealized((Widget)combo)) {
947 rect[0].x = rect[1].x = rect[2].x = 0;
948 rect[3].x = OldWidth(combo) - COMBO_MARGIN_W(combo);
949 rect[0].y = rect[2].y = rect[3].y = 0 ;
950 rect[1].y = OldHeight(combo) - COMBO_MARGIN_H(combo);
951 rect[0].width = rect[1].width = OldWidth(combo);
952 rect[2].width = rect[3].width = COMBO_MARGIN_W(combo);
953 rect[0].height = rect[1].height = COMBO_MARGIN_H(combo);
954 rect[2].height = rect[3].height = OldHeight(combo);
955 XFillRectangles(XtDisplayOfObject((Widget)combo),
956 XtWindowOfObject((Widget)combo),
957 BackgroundGC(combo), rect, 4);
959 else if (XmGetFocusWidget((Widget)combo) == (Widget)combo) {
960 rect[0].x = rect[1].x = rect[2].x = 0;
961 rect[3].x = XtWidth(combo) - COMBO_MARGIN_W(combo);
962 rect[0].y = rect[2].y = rect[3].y = 0 ;
963 rect[1].y = XtHeight(combo) - COMBO_MARGIN_H(combo);
964 rect[0].width = rect[1].width = XtWidth(combo);
965 rect[2].width = rect[3].width = COMBO_MARGIN_W(combo);
966 rect[0].height = rect[1].height = COMBO_MARGIN_H(combo);
967 rect[2].height = rect[3].height = XtHeight(combo);
968 XFillRectangles(XtDisplayOfObject((Widget)combo),
969 XtWindowOfObject((Widget)combo),
970 HighlightGC(combo), rect, 4);
975 /* Add a global variable to avoid the handler to process the
976 * the ButtonPress which popup the shell
978 static int popup_shell_init=DtNonePopup;
981 * osfSelect virtual key hit. Simulate hitting the arrow.
984 _ComboBoxActivate( Widget w,
987 Cardinal *num_params)
989 DtComboBoxWidget combo;
990 XmAnyCallbackStruct cb;
992 if (*num_params == 0) /* no params means combo */
993 combo = (DtComboBoxWidget)w;
994 else /* params means label */
996 combo = (DtComboBoxWidget)XtParent(w);
1000 if (event->type == KeyPress)
1001 popup_shell_init = DtKeyPressPopup;
1002 else if (event->type == ButtonPress)
1003 popup_shell_init = DtButtonPressPopup;
1005 popup_shell_init = DtPopup;
1008 cb.reason = XmCR_ACTIVATE;
1010 activate_cb((Widget)Arrow(combo), (XtPointer)combo, (XtPointer)&cb);
1014 * osfCancel virtual key hit.
1017 _ComboBoxKbdCancel( Widget w,
1020 Cardinal *num_params)
1022 DtComboBoxWidget combo;
1027 /* Get combo-box off list data */
1028 XtSetArg(args[0], XmNuserData, &data);
1029 XtGetValues(w, args, 1);
1031 combo = (DtComboBoxWidget)data;
1033 input_ungrab( combo, GRAB_POINTER | GRAB_KEYBOARD );
1037 * Tab Group Action for Buttons
1040 _ComboBoxPrevTabGroup( Widget w,
1043 Cardinal *num_params)
1045 XmProcessTraversal ((Widget)XtParent(w), XmTRAVERSE_PREV_TAB_GROUP);
1048 _ComboBoxNextTabGroup( Widget w,
1051 Cardinal *num_params)
1053 XmProcessTraversal ((Widget)XtParent(w), XmTRAVERSE_NEXT_TAB_GROUP);
1058 * This function goes through most of the resources and makes sure
1059 * they have legal values.
1062 CheckResources( DtComboBoxWidget combo)
1064 if ((Alignment(combo) != DtALIGNMENT_CENTER) &&
1065 (Alignment(combo) != DtALIGNMENT_BEGINNING) &&
1066 (Alignment(combo) != DtALIGNMENT_END)) {
1067 XtWarning(CB_ALIGNMENT);
1068 Alignment(combo) = DtALIGNMENT_CENTER;
1070 if ((Orientation(combo) != DtLEFT) &&
1071 (Orientation(combo) != DtRIGHT)) {
1072 XtWarning(CB_ORIENTATION);
1073 Orientation(combo) = DtRIGHT;
1075 if (ItemCount(combo) < 0) {
1076 XtWarning(CB_ITEM_COUNT);
1077 ItemCount(combo) = 0;
1079 if ((SelectedPosition(combo) < 0) ||
1080 ((SelectedPosition(combo) >= ItemCount(combo)) &&
1081 (ItemCount(combo) > 0))) {
1082 XtWarning(CB_VISIBLE_ITEM);
1083 SelectedPosition(combo) = 0;
1085 /* NEW: to adjust the size of the list to its content *
1086 if (ItemCount(combo) < VisibleItemCount(combo))
1087 VisibleItemCount(combo) = ItemCount(combo); */
1091 * Destroy procedure called by the toolkit. Free local resources
1094 Destroy(DtComboBoxWidget combo)
1096 if (LabelString(combo))
1097 XmStringFree(LabelString(combo));
1098 if (SelectedItem(combo))
1099 XmStringFree( SelectedItem(combo) );
1103 * Resize function called by toolkit. The size of our combo-box
1104 * has already been changed. That is why we must store
1105 * old_width and old_height.
1108 Resize(DtComboBoxWidget combo)
1110 ClearShadow(combo, TRUE);
1111 LayoutChildren(combo);
1113 OldWidth(combo) = Width(combo);
1114 OldHeight(combo) = Height(combo);
1119 * Redisplay function called by toolkit. The widget didn't change size,
1120 * so just redisplay the shadow.
1123 Redisplay( DtComboBoxWidget w,
1132 * GeometryManager function called by toolkit when a child resizes/moves.
1133 * We are not allowing any changes but width/height of the text-field.
1134 * this is because the user can retrieve the text-field and make changes
1135 * that we want to honor. If they mess around with the label or arrow,
1136 * then we won't honor the request.
1137 * If the text-field requests a change, then make the change, and allow
1138 * our SetComboBoxSize() and LayoutChildren() figure out what size will
1140 * Returning GeometryDone was suppose to tell the toolkit
1141 * that we resized the child ourselves, but the text-field had trouble
1142 * with this (its' geometry_manager wasn't called or working right?), so
1143 * we return GeometryYes.
1145 static XtGeometryResult
1146 GeometryManager(Widget w,
1147 XtWidgetGeometry *request,
1148 XtWidgetGeometry *reply)
1150 DtComboBoxWidget combo = (DtComboBoxWidget) Parent(w);
1152 /* Ignore everything but text-field */
1153 if (w != Text(combo))
1154 return(XtGeometryNo);
1156 /* Only allow width/height changes */
1157 if (!(request->request_mode & (CWWidth | CWHeight)))
1158 return(XtGeometryNo);
1160 /* Set the text-field to the requested size */
1161 if (request->request_mode & CWWidth)
1162 Width(w) = request->width;
1163 if (request->request_mode & CWHeight)
1164 Height(w) = request->height;
1165 XtResizeWidget(w, Width(w), Height(w), BorderWidth(w));
1167 ClearShadow(combo, TRUE);
1168 if (RecomputeSize(combo))
1169 SetComboBoxSize(combo);
1170 LayoutChildren(combo);
1172 return(XtGeometryYes);
1176 * This function sets the size of the combo_box widget based on the
1177 * current size of the children. Don't worry if it doesn't work, the
1178 * children will be squeezed in later.
1181 SetComboBoxSize(DtComboBoxWidget combo)
1183 Widget text_holder = ((Type(combo) == DtDROP_DOWN_COMBO_BOX) ?
1184 Text(combo) : Label(combo));
1185 Dimension shadow = COMBO_SHADOW(combo) * 2;
1186 Dimension h_spacing = COMBO_H_SPACING(combo) * 2;
1187 Dimension v_spacing = COMBO_V_SPACING(combo) * 2;
1188 Dimension arrow_width, text_width, text_height;
1189 Dimension sep_width = 0;
1190 XtGeometryResult ResizeResult;
1192 unsigned char unit_type = XmPIXELS;
1194 /* Resolution Independent */
1195 if (MUnitType(combo) != XmPIXELS) {
1196 unit_type = MUnitType(combo);
1197 XtSetArg(args[0], XmNunitType, XmPIXELS);
1198 XtSetValues(text_holder, args, 1);
1199 if (Type(combo) == DtDROP_DOWN_LIST)
1200 XtSetValues((Widget)Sep(combo), args, 1);
1204 * Find out how big the arrow can be (needed to get
1205 * available_width for text_holder).
1208 XtSetArg(args[0], XmNwidth, &text_width);
1209 XtSetArg(args[1], XmNheight, &text_height);
1210 XtGetValues(text_holder, args, 2);
1212 arrow_width = (Dimension)((float)text_height * ARROW_MULT);
1213 arrow_width = (arrow_width < ARROW_MIN) ? ARROW_MIN : arrow_width;
1215 if (Type(combo) == DtDROP_DOWN_LIST) {
1216 XtSetArg(args[0], XmNwidth, &sep_width);
1217 XtGetValues((Widget)Sep(combo), args, 1);
1220 ResizeResult=XtMakeResizeRequest((Widget)combo, arrow_width + sep_width +
1221 ArrowSpacing(combo) +
1222 text_width + shadow + h_spacing +
1223 (COMBO_MARGIN_W(combo) * 2),
1224 text_height + shadow + v_spacing +
1225 (COMBO_MARGIN_H(combo) * 2),
1227 if (ResizeResult==XtGeometryNo || ResizeResult==XtGeometryAlmost) {
1228 XtWarning(CB_RESIZE);
1230 OldWidth(combo) = Width(combo);
1231 OldHeight(combo) = Height(combo);
1233 /* Resolution Independent */
1234 if (unit_type != XmPIXELS) {
1235 XtSetArg(args[0], XmNunitType, unit_type);
1236 XtSetValues(text_holder, args, 1);
1237 if (Type(combo) == DtDROP_DOWN_LIST)
1238 XtSetValues((Widget)Sep(combo), args, 1);
1243 * This function makes the text_holder (label or text-field) smaller
1244 * if the combo_box couldn't grow to the needed full size. It will
1245 * also make the text_holder grow if there is space. The textfield will
1246 * grow with the combo_box, but the label will only grow to its'
1247 * maximum size. The label will also shrink down to nothing, but the
1248 * text-field will always keep its' core height.
1251 ForceChildSizes(DtComboBoxWidget combo)
1253 Dimension full_available_height, available_height, available_width;
1254 Dimension arrow_width;
1255 Dimension sep_width = 0;
1256 Dimension tmp_width, tmp_height, tmp_borderwidth;
1258 unsigned char unit_type = XmPIXELS;
1260 /* Resolution Independent */
1261 if (MUnitType(combo) != XmPIXELS) {
1262 unit_type = MUnitType(combo);
1263 XtSetArg(args[0], XmNunitType, XmPIXELS);
1264 if (Type(combo) == DtDROP_DOWN_LIST) {
1265 XtSetValues(Sep(combo), args, 1);
1266 XtSetValues(Label(combo), args, 1);
1269 XtSetValues(Text(combo), args, 1);
1270 XtSetValues(Arrow(combo), args, 1);
1272 /* Calculate available height for children */
1273 if ((available_height = Height(combo) - (COMBO_SHADOW(combo) * 2) -
1274 (COMBO_MARGIN_H(combo) * 2) - (COMBO_V_SPACING(combo) * 2)) <= 0) {
1275 full_available_height = available_height = 1;
1278 /* Seperator need available_height plus the vertical_spacing */
1279 full_available_height = (available_height +
1280 (COMBO_V_SPACING(combo) * 2));
1283 /* Get initial available width for children */
1284 available_width = (Width(combo) - (COMBO_SHADOW(combo) * 2) -
1285 (COMBO_MARGIN_W(combo) * 2) -
1286 (COMBO_H_SPACING(combo) * 2));
1288 /* label only grows to maximum width needed */
1289 if ((Type(combo) == DtDROP_DOWN_LIST) &&
1290 ((int)available_height > (int)LabelMaxHeight(combo)))
1291 available_height = LabelMaxHeight(combo);
1292 else if (Type(combo) == DtDROP_DOWN_COMBO_BOX) {
1293 XtSetArg(args[0], XmNheight, &available_height);
1294 XtGetValues((Widget)Text(combo), args, 1);
1298 * Find out how big the arrow can be (needed to get
1299 * available_width for text_holder).
1301 arrow_width = (Dimension)((float)available_height * ARROW_MULT);
1302 arrow_width = (arrow_width < ARROW_MIN) ? ARROW_MIN : arrow_width;
1304 if (Type(combo) == DtDROP_DOWN_LIST) {
1305 XtSetArg(args[0], XmNwidth, &sep_width);
1306 XtGetValues((Widget)Sep(combo), args, 1);
1309 /* Make sure width isn't too small or too big */
1310 if ((available_width -=
1311 (arrow_width + sep_width + ArrowSpacing(combo) )) <= (Dimension)0)
1312 available_width = 1;
1315 XtSetArg(args[0], XmNwidth, &tmp_width);
1316 XtSetArg(args[1], XmNheight, &tmp_height);
1317 XtSetArg(args[2], XmNborderWidth, &tmp_borderwidth);
1318 if (Type(combo) == DtDROP_DOWN_LIST) { /** label **/
1319 if ((int)available_width > (int)LabelMaxLength(combo))
1320 available_width = LabelMaxLength(combo);
1323 XtGetValues((Widget)Label(combo), args, 3);
1324 if ((available_width != tmp_width) ||
1325 (available_height != tmp_height))
1326 XtResizeWidget(Label(combo), available_width, available_height,
1329 XtGetValues((Widget)Sep(combo), args, 3);
1330 if (full_available_height != tmp_height)
1331 XtResizeWidget(Sep(combo), tmp_width, full_available_height,
1336 XtGetValues((Widget)Text(combo), args, 3);
1337 if ( Width(((Widget)Text(combo))) != available_width) /** TextField **/
1338 XtResizeWidget(Text(combo), available_width,
1339 tmp_height, tmp_borderwidth);
1343 XtGetValues((Widget)Arrow(combo), args, 3);
1344 if ((arrow_width != tmp_width) || (tmp_height != available_height)) {
1345 available_height = (available_height < ARROW_MIN) ? ARROW_MIN :
1347 XtResizeWidget(Arrow(combo), arrow_width, available_height,
1351 /* Resolution Independent */
1352 if (unit_type != XmPIXELS) {
1353 XtSetArg(args[0], XmNunitType, unit_type);
1354 if (Type(combo) == DtDROP_DOWN_LIST) {
1355 XtSetValues(Sep(combo), args, 1);
1356 XtSetValues(Label(combo), args, 1);
1359 XtSetValues(Text(combo), args, 1);
1360 XtSetValues(Arrow(combo), args, 1);
1365 * This function positions the children within the combo_box widget.
1366 * It calls ForceChildSizes() to make sure the children fit within the
1367 * combo_box widget, but it will not try to resize the combo_box widget.
1370 LayoutChildren(DtComboBoxWidget combo)
1372 Widget text_holder = ((Type(combo) == DtDROP_DOWN_COMBO_BOX)
1373 ? Text(combo) : Label(combo));
1374 Position start_x = (COMBO_SHADOW(combo) + COMBO_MARGIN_W(combo) +
1375 COMBO_H_SPACING(combo));
1376 Position start_y = (COMBO_SHADOW(combo) + COMBO_MARGIN_H(combo) +
1377 COMBO_V_SPACING(combo));
1378 short available_height = Height(combo) - (start_y * 2);
1379 Position y, arrow_y;
1380 unsigned char unit_type = XmPIXELS;
1381 Dimension tmp_width, tmp_height, sep_width;
1384 ForceChildSizes(combo);
1386 /* Resolution Independent */
1387 if (MUnitType(combo) != XmPIXELS) {
1388 unit_type = MUnitType(combo);
1389 XtSetArg(args[0], XmNunitType, XmPIXELS);
1390 XtSetValues(text_holder, args, 1);
1391 XtSetValues(Arrow(combo), args, 1);
1392 if (Type(combo) == DtDROP_DOWN_LIST)
1393 XtSetValues(Sep(combo), args, 1);
1395 /* Center text_holder within combo_box */
1397 XtSetArg(args[0], XmNheight, &tmp_height);
1398 XtGetValues(text_holder, args, 1);
1399 y = available_height - tmp_height;
1400 y = ((y < 0) ? 0 : y)/2 + start_y;
1402 /* Center arrow within combo_box */
1404 XtSetArg(args[1], XmNwidth, &tmp_width);
1405 XtGetValues(Arrow(combo), args, 2);
1406 arrow_y = available_height - tmp_height;
1407 arrow_y = ((arrow_y < 0) ? 0 : arrow_y)/2 + start_y;
1410 if (Type(combo) == DtDROP_DOWN_LIST) {
1411 XtSetArg(args[0], XmNwidth, &sep_width);
1412 XtGetValues(Sep(combo), args, 1);
1414 if (Orientation(combo) == DtLEFT) {
1415 XtMoveWidget(Arrow(combo), start_x, arrow_y);
1416 start_x += tmp_width;
1417 if (Type(combo) == DtDROP_DOWN_LIST) {
1418 XtMoveWidget(Sep(combo), start_x, start_y -
1419 COMBO_V_SPACING(combo));
1420 start_x += sep_width;
1422 start_x += ArrowSpacing(combo);
1423 XtMoveWidget(text_holder, start_x, y);
1426 XtMoveWidget(text_holder, start_x, y);
1428 * We want the arrow at the end of the combo_box, so
1429 * the user can use recompute_size more effectively.
1431 start_x = Width(combo) - start_x - tmp_width;
1432 if (Type(combo) == DtDROP_DOWN_LIST) {
1433 start_x -= sep_width;
1434 XtMoveWidget(Sep(combo), start_x, start_y -
1435 COMBO_V_SPACING(combo));
1436 start_x += sep_width;
1438 XtMoveWidget(Arrow(combo), start_x, arrow_y);
1441 /* Resolution Independent */
1442 if (unit_type != XmPIXELS) {
1443 XtSetArg(args[0], XmNunitType, unit_type);
1444 XtSetValues(text_holder, args, 1);
1445 XtSetValues(Arrow(combo), args, 1);
1446 if (Type(combo) == DtDROP_DOWN_LIST)
1447 XtSetValues(Sep(combo), args, 1);
1452 * SetValues() routine for ComboBox widget.
1455 SetValues( DtComboBoxWidget current,
1456 DtComboBoxWidget request,
1457 DtComboBoxWidget new)
1459 DtComboBoxPart *new_p = (DtComboBoxPart*)
1460 &(XmField(new,ipot,DtComboBox,arrow,Widget));
1461 DtComboBoxPart *cur_p = (DtComboBoxPart*)
1462 &(XmField(current,ipot,DtComboBox,arrow,Widget));
1463 Boolean label_size_changed = FALSE;
1464 Boolean force_label_string = FALSE;
1467 unsigned char new_unit_type = XmPIXELS, curr_unit_type = XmPIXELS;
1469 CheckResources(new);
1471 /* Resolution Independent */
1472 if (MUnitType(new) != XmPIXELS) {
1473 new_unit_type = MUnitType(new);
1474 XtSetArg(args[0], XmNunitType, XmPIXELS);
1475 if (Arrow(new)) XtSetValues(Arrow(new), args, 1);
1476 if (List(new)) XtSetValues(List(new), args, 1);
1477 if (Shell(new)) XtSetValues(Shell(new), args, 1);
1478 if (Label(new)) XtSetValues(Label(new), args, 1);
1479 if (Text(new)) XtSetValues(Text(new), args, 1);
1480 if (Sep(new)) XtSetValues(Sep(new), args, 1);
1482 if (MUnitType(current) != XmPIXELS) {
1483 curr_unit_type = MUnitType(current);
1484 XtSetArg(args[0], XmNunitType, XmPIXELS);
1485 if (Arrow(current)) XtSetValues(Arrow(current), args, 1);
1486 if (List(current)) XtSetValues(List(current), args, 1);
1487 if (Shell(current)) XtSetValues(Shell(current), args, 1);
1488 if (Label(current)) XtSetValues(Label(current), args, 1);
1489 if (Text(current)) XtSetValues(Text(current), args, 1);
1490 if (Sep(current)) XtSetValues(Sep(current), args, 1);
1493 if (Text(new) != Text(current)) {
1495 Text(new) = Text(current);
1499 * Pass any list specific resources on to our List Widget.
1500 * Check each one, since it's too costly to always set them.
1503 if (ItemCount(new) != ItemCount(current)){
1504 if (Items(new) && (ItemCount(new) < 0)) {
1505 XtWarning(CB_ITEM_COUNT);
1508 XtSetArg(args[n], XmNitemCount, ItemCount(new)); n++;
1510 if (Items(new) != ListItems(current)) {
1511 XtSetArg(args[n], XmNitems, Items(new)); n++;
1512 /* Make sure itemCount will get sent to list */
1513 if (ItemCount(new) == ItemCount(current)) {
1514 XtSetArg(args[n], XmNitemCount, ItemCount(new)); n++;
1517 if (ListFontList(new) != ListFontList(current)) {
1518 XtSetArg(args[n], XmNfontList, ListFontList(new)); n++;
1520 if (ListMarginHeight(new) != ListMarginHeight(current)) {
1521 XtSetArg(args[n], XmNlistMarginHeight, ListMarginHeight(new)); n++;
1523 if (ListMarginWidth(new) != ListMarginWidth(current)) {
1524 XtSetArg(args[n], XmNlistMarginWidth, ListMarginWidth(new)); n++;
1526 if (ListSpacing(new) != ListSpacing(current)) {
1527 XtSetArg(args[n], XmNlistSpacing, ListSpacing(new)); n++;
1529 if (LayoutDirection(new) != LayoutDirection(current)) {
1530 XmStringDirection new_direction =
1531 XmDirectionToStringDirection(LayoutDirection(new));
1532 XtSetArg(args[n], XmNstringDirection, new_direction); n++;
1534 if (TopItemPosition(new) != TopItemPosition(current)) {
1535 XtSetArg(args[n], XmNtopItemPosition, TopItemPosition(new)); n++;
1537 if (VisibleItemCount(new) != VisibleItemCount(current)) {
1538 XtSetArg(args[n], XmNvisibleItemCount, VisibleItemCount(new)); n++;
1543 Dimension tmp_width, tmp_height;
1545 XtSetValues(List(new), args, n);
1547 XtSetArg(tmp_arg[0], XmNwidth, &tmp_width);
1548 XtSetArg(tmp_arg[1], XmNheight, &tmp_height);
1549 XtGetValues(((Widget) Shell(new)), tmp_arg, 2);
1550 MaxShellWidth(new) = tmp_width;
1551 MaxShellHeight(new) = tmp_height;
1554 /* If arrow type changes delete the old one and create the new one */
1555 if (ArrowType(new) != ArrowType(current)) {
1556 XtRemoveCallback(Arrow(new), XmNactivateCallback, activate_cb,
1558 if (ArrowType(current) == DtWINDOWS)
1559 XtRemoveCallback(Arrow(new), XmNexposeCallback,
1560 arrow_expose_cb, (XtPointer)new);
1561 XtDestroyWidget(Arrow(new));
1564 XtSetArg(args[n], XmNtraversalOn, FALSE); n++;
1565 XtSetArg(args[n], XmNhighlightThickness, 0); n++;
1566 XtSetArg(args[n], XmNshadowThickness, 0); n++;
1567 if (ArrowType(new) == DtMOTIF) {
1568 XtSetArg(args[n], XmNarrowDirection, XmARROW_DOWN); n++;
1569 XtSetArg(args[n], XmNforeground, BackgroundPixel(new)); n++;
1570 Arrow(new) = XtCreateManagedWidget("ComboBoxArrow",
1571 xmArrowButtonWidgetClass,
1572 (Widget)new, args, n);
1575 Arrow(new) = XtCreateManagedWidget("ComboBoxArrow",
1576 xmDrawnButtonWidgetClass,
1577 (Widget)new, args, n);
1578 XtAddCallback(Arrow(new), XmNexposeCallback, arrow_expose_cb,
1581 XtAddCallback(Arrow(new), XmNactivateCallback, activate_cb,
1586 * Type resource changed. If the widget (textField or Label)
1587 * doesn't exist, then create it. Always reset orientation
1588 * constraint resources when type changes; otherwise, the
1589 * text_holder widget positioning could be screwed up. We don't
1590 * reset both widgets if the orientation changes (because we might
1591 * not have created both widgets).
1592 * If label must be created, also create the separator widget.
1594 if (Type(new) != Type(current)) {
1595 if (Type(new) == DtDROP_DOWN_COMBO_BOX) {
1596 if (Text(new) == NULL) {
1598 XtSetArg(args[n], XmNcolumns, TextColumns(new)); n++;
1599 XtSetArg(args[n], XmNmaxLength, TextMaxLength(new)); n++;
1600 XtSetArg(args[n], XmNmarginWidth, 2); n++;
1601 XtSetArg(args[n], XmNmarginHeight, 2); n++;
1602 Text(new) = XtCreateWidget("ComboBoxTextField",
1603 xmTextFieldWidgetClass,
1604 (Widget)new, args, n);
1605 XtAddCallback(Text(new), XmNlosingFocusCallback,
1606 text_losing_focus_cb, (XtPointer)new);
1607 XtAddCallback(Text(new), XmNactivateCallback,
1608 text_activate_cb, (XtPointer)new);
1609 XtAddCallback(Text(new), XmNfocusCallback,
1610 text_focus_cb, (XtPointer)new);
1611 if (HorizontalSpacing(new) == HorizontalSpacing(current))
1612 HorizontalSpacing(new) = 0;
1613 if (VerticalSpacing(new) == VerticalSpacing(current))
1614 VerticalSpacing(new) = 0;
1616 XtUnmanageChild(Sep(new));
1617 XtUnmanageChild(Label(new));
1618 XtManageChild(Text(new));
1621 if (Label(new) == NULL) {
1622 XmStringDirection new_direction =
1623 XmDirectionToStringDirection(LayoutDirection(new));
1625 XtTranslations label_trans =
1626 XtParseTranslationTable(ComboBoxLabelTranslationTable);
1629 XtSetArg(args[n], XmNalignment, Alignment(new)); n++;
1630 XtSetArg(args[n], XmNrecomputeSize, FALSE); n++;
1631 XtSetArg(args[n], XmNmarginLeft, LABEL_PADDING); n++;
1632 XtSetArg(args[n], XmNmarginRight, LABEL_PADDING); n++;
1633 XtSetArg(args[n], XmNmarginWidth, TEXT_CONTEXT_MARGIN); n++;
1634 XtSetArg(args[n], XmNmarginHeight, 0); n++;
1635 XtSetArg(args[n], XmNstringDirection, new_direction); n++;
1636 Label(new) = XtCreateWidget("ComboBoxLabel",
1638 (Widget)new, args, n);
1639 XtOverrideTranslations((Widget)Label(new), label_trans);
1640 if (HorizontalSpacing(new) == HorizontalSpacing(current))
1641 HorizontalSpacing(new) = 1;
1642 if (VerticalSpacing(new) == VerticalSpacing(current))
1643 VerticalSpacing(new) = 2;
1646 XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
1647 Sep(new) = XtCreateWidget("ComboBoxSeparator",
1648 xmSeparatorWidgetClass,
1649 (Widget)new, args, n);
1651 else if (LayoutDirection(new) != LayoutDirection(current)) {
1652 XmStringDirection new_direction =
1653 XmDirectionToStringDirection(LayoutDirection(new));
1654 XtSetArg(args[0], XmNstringDirection, new_direction);
1655 XtSetValues(Label(new), args, 1);
1657 XtUnmanageChild(Text(new));
1658 XtManageChild(Label(new));
1659 XtManageChild(Sep(new));
1662 * Text-fields and labels have different shadows. Only
1663 * change if user didn't change the shadow resource.
1665 if (COMBO_SHADOW(new) == COMBO_SHADOW(current))
1666 COMBO_SHADOW(new) = ((Type(new) == DtDROP_DOWN_COMBO_BOX) ?
1667 TEXT_FIELD_SHADOW : LABEL_SHADOW);
1670 if (Text(new) && (Text(new) == Text(current))) {
1672 if (TextColumns(new) != TextColumns(current)) {
1673 XtSetArg(args[n], XmNcolumns, TextColumns(new)); n++;
1675 if (TextMaxLength(new) != TextMaxLength(current) ) {
1676 XtSetArg(args[n], XmNmaxLength, TextMaxLength(new)); n++;
1679 XtSetValues(Text(new), args, n);
1683 * LabelWidget alignment has changed.
1685 if (Label(new) && (Alignment(new) != Alignment(current))) {
1686 XtSetArg(args[0], XmNalignment, Alignment(new));
1687 XtSetValues(Label(new), args, 1);
1690 if (Label(new) && ((Items(new) != ListItems(current)) ||
1691 (ItemCount(new) != ItemCount(current)) ||
1692 (Label(new) != Label(current)))) {
1693 SetMaximumLabelSize(new_p);
1694 label_size_changed = TRUE;
1697 /* Copy and free label-string */
1698 if (LabelString(new) != LabelString(current)) {
1699 if (LabelString(new))
1700 LabelString(new) = XmStringCopy(LabelString(new));
1701 if (LabelString(current))
1702 XmStringFree(LabelString(current));
1704 * force_label_string usage if it is specified and items is not.
1705 * This will be the perminant label string only if update-label
1706 * is false, else it is only used until the user picks something
1709 if (Items(new) == ListItems(current))
1710 force_label_string = TRUE;
1713 if ((Items(new) != ListItems(current)) ||
1714 (Alignment(new) != Alignment(current)) ||
1715 (Type(new) != Type(current)) ||
1716 (ItemCount(new) != ItemCount(current)) ||
1717 (SelectedPosition(new) != SelectedPosition(current)) ||
1718 (XmStringByteCompare(SelectedItem(new), SelectedItem(current))!=True) ||
1719 (Label(new) != Label(current)) ||
1720 (UpdateLabel(new) != UpdateLabel(current)) ||
1721 (LabelString(new) != LabelString(current))) {
1723 /* selected_item resource used before selected_position */
1724 if (SelectedItem(new) && XmeStringIsValid(SelectedItem(new)) &&
1725 (XmStringByteCompare(SelectedItem(new),
1726 SelectedItem(current))!=True) ){
1727 if (SelectedItem(current)) {
1728 XmStringFree(SelectedItem(current));
1729 SelectedItem(current) = NULL;
1731 SelectedItem(new) = XmStringCopy(SelectedItem(new));
1732 DtComboBoxSelectItem((Widget)new, SelectedItem(new));
1735 if (SelectedPosition(new)<0||SelectedPosition(new)>=ItemCount(new))
1736 SelectedPosition(new) = 0;
1737 if ((ItemCount(new)) &&
1738 (SelectedPosition(new) != SelectedPosition(current))) {
1740 XmListSelectPos(List(new), SelectedPosition(new) + 1, FALSE);
1741 if (SelectedItem(current)) {
1743 XmStringFree(SelectedItem(current));
1744 SelectedItem(current) = NULL;
1746 SyncWithList(new_p);
1748 XmStringCopy((ListItems(new))[SelectedPosition(new)]);
1751 /* Else, same item selected as last time */
1753 SelectedItem(new) = XmStringCopy(SelectedItem(new));
1754 if ((SelectedItem(new) != NULL) && (ListItems(new) != NULL))
1755 DtComboBoxSelectItem((Widget)new, SelectedItem(new));
1756 if (SelectedItem(current)) {
1757 XmStringFree(SelectedItem(current));
1758 SelectedItem(current) = NULL;
1763 if (Type(new) == DtDROP_DOWN_COMBO_BOX)
1764 SetTextFieldData(new_p, NULL);
1766 SetLabelData(new_p, NULL, force_label_string);
1769 /* Else, same item selected as last time */
1771 SelectedItem(new) = XmStringCopy(SelectedItem(new));
1772 if ((SelectedItem(new) != NULL) && (ListItems(new) != NULL))
1773 DtComboBoxSelectItem((Widget)new, SelectedItem(new));
1774 if (SelectedItem(current)) {
1775 XmStringFree(SelectedItem(current));
1776 SelectedItem(current) = NULL;
1781 * Must recalculate the combo_box and re-layout the children.
1782 * If this is not editable, then set the label to its' maximum
1783 * size; it will get chopped if it is too big. This is needed
1784 * because we shrink the label down, and SetComboBoxSize() uses
1785 * the label's core sizes to figure what size to become.
1787 if ((Type(new) != Type(current)) ||
1788 (ArrowType(new) != ArrowType(current)) ||
1789 (COMBO_MARGIN_W(new) != COMBO_MARGIN_W(current)) ||
1790 (COMBO_MARGIN_H(new) != COMBO_MARGIN_H(current)) ||
1791 (COMBO_H_SPACING(new) != COMBO_H_SPACING(current)) ||
1792 (COMBO_V_SPACING(new) != COMBO_V_SPACING(current)) ||
1793 (COMBO_SHADOW(new) != COMBO_SHADOW(current)) ||
1794 (Orientation(new) != Orientation(current)) ||
1795 (ArrowSpacing(new) != ArrowSpacing(current)) ||
1796 ((Type(new) == DtDROP_DOWN_LIST) && label_size_changed)) {
1797 ClearShadow(current, TRUE);
1798 if (RecomputeSize(new))
1799 SetComboBoxSize(new);
1800 LayoutChildren(new);
1804 SyncWithList(new_p);
1805 /* Resolution Independent */
1806 if (new_unit_type != XmPIXELS) {
1807 XtSetArg(args[0], XmNunitType, new_unit_type);
1808 if (Arrow(new)) XtSetValues(Arrow(new), args, 1);
1809 if (List(new)) XtSetValues(List(new), args, 1);
1810 if (Shell(new)) XtSetValues(Shell(new), args, 1);
1811 if (Label(new)) XtSetValues(Label(new), args, 1);
1812 if (Text(new)) XtSetValues(Text(new), args, 1);
1813 if (Sep(new)) XtSetValues(Sep(new), args, 1);
1815 if (curr_unit_type != XmPIXELS) {
1816 XtSetArg(args[0], XmNunitType, curr_unit_type);
1817 if (Arrow(current)) XtSetValues(Arrow(current), args, 1);
1818 if (List(current)) XtSetValues(List(current), args, 1);
1819 if (Shell(current)) XtSetValues(Shell(current), args, 1);
1820 if (Label(current)) XtSetValues(Label(current), args, 1);
1821 if (Text(current)) XtSetValues(Text(current), args, 1);
1822 if (Sep(current)) XtSetValues(Sep(current), args, 1);
1829 * This function clears the shadow around our widget. If all is TRUE,
1830 * then clear all 4 sides; otherwise, only clear the right and bottom
1831 * sides (during resize).
1834 ClearShadow( DtComboBoxWidget w,
1837 Dimension shadow = COMBO_SHADOW(w);
1838 Dimension margin_w = COMBO_MARGIN_W(w);
1839 Dimension margin_h = COMBO_MARGIN_H(w);
1841 if ((shadow > 0) && XtIsRealized((Widget)w)) {
1843 XClearArea(XtDisplayOfObject((Widget)w),
1844 XtWindowOfObject((Widget)w),
1846 OldWidth(w) - (margin_w * 2),
1848 XClearArea(XtDisplayOfObject((Widget)w),
1849 XtWindowOfObject((Widget)w),
1850 margin_w, margin_h, shadow,
1851 OldHeight(w) - (margin_h * 2), FALSE);
1853 XClearArea(XtDisplayOfObject((Widget)w),
1854 XtWindowOfObject((Widget)w), margin_w,
1855 OldHeight(w) - margin_h - shadow,
1856 OldWidth(w) - (margin_w * 2), shadow, FALSE);
1857 XClearArea(XtDisplayOfObject((Widget)w), XtWindowOfObject((Widget)w),
1858 OldWidth(w) - margin_w - shadow,
1860 OldHeight(w) - (margin_h * 2), FALSE);
1862 DrawHighlight(w, TRUE);
1866 * This functions draws the shadow around our combo-box.
1869 DrawShadow(DtComboBoxWidget w)
1871 Dimension shadow = COMBO_SHADOW(w);
1872 Dimension margin_w = COMBO_MARGIN_W(w);
1873 Dimension margin_h = COMBO_MARGIN_H(w);
1875 if ((shadow > 0) && XtIsRealized((Widget)w)) {
1876 XmeDrawShadows(XtDisplayOfObject((Widget)w),
1877 XtWindowOfObject((Widget)w),
1881 Width(w) - (margin_w * 2),
1882 Height(w) - (margin_h * 2),
1883 shadow, XmSHADOW_OUT);
1885 DrawHighlight(w, FALSE);
1889 * Take the string out of the list and put it into the text-field.
1890 * text-fields don't handle xm-strings, so we must get the char*
1891 * out of it (only getting the first segment). This is slower than
1892 * storing the text-strings (char*) ourselves, but that would take
1893 * up a lot of memory. Since this setting happens during a user
1894 * action, speed isn't a problem.
1897 SetTextFieldData(DtComboBoxPart *combo_p, XmString item)
1899 XmListWidget list = (XmListWidget)combo_p->list;
1900 XmStringContext context;
1901 Boolean done = FALSE;
1903 XmStringComponentType type;
1905 XmStringCharSet charset;
1906 XmStringDirection direction;
1907 XmStringComponentType unknown_tag;
1910 XmStringTable list_items;
1912 Boolean isItemCopied = FALSE;
1915 XtSetArg(args[0], XmNitemCount, &item_count);
1916 XtSetArg(args[1], XmNitems, &list_items);
1917 XtGetValues((Widget)list, args, 2);
1918 if (item_count && item_count>combo_p->selected_position &&
1919 !item && list_items) {
1920 item = XmStringCopy(list_items[combo_p->selected_position]);
1921 isItemCopied = TRUE;
1925 combo_p->selected_item = NULL;
1926 XtSetArg(args[0], XmNvalue, "");
1927 XtSetValues(combo_p->text, args, 1);
1930 if (combo_p->selected_item != item)
1932 if (combo_p->selected_item)
1933 XmStringFree (combo_p->selected_item);
1934 combo_p->selected_item = XmStringCopy(item);
1936 XmStringInitContext(&context, item);
1938 /* Loop until 1st char* found */
1940 type = XmStringGetNextComponent(context, &text, &charset,
1941 &direction, &unknown_tag,
1944 case XmSTRING_COMPONENT_END:
1947 case XmSTRING_COMPONENT_TEXT:
1948 case XmSTRING_COMPONENT_LOCALE_TEXT:
1949 XtSetArg(args[0], XmNvalue, text);
1950 XtSetValues(combo_p->text, args, 1);
1958 XmStringFreeContext(context);
1966 * Set the maximum size of the label, depending on the
1967 * characteristics of the list of items.
1970 SetMaximumLabelSize(DtComboBoxPart *combo_p)
1972 XmListWidget list = (XmListWidget)combo_p->list;
1973 XmFontList font_list;
1974 Dimension width, height, border_width;
1975 Dimension longest = 0;
1976 Dimension highest = 0;
1979 XmStringTable list_items;
1980 unsigned char unit_type = XmPIXELS;
1982 /* Resolution Independent */
1983 XtSetArg(args[0], XmNunitType, &unit_type);
1984 XtGetValues(combo_p->list, args, 1); /* Assume list/Combo has same uniType*/
1985 if (unit_type != XmPIXELS) {
1986 XtSetArg(args[0], XmNunitType, XmPIXELS);
1987 XtSetValues(combo_p->label, args, 1);
1988 XtSetValues(combo_p->list, args, 1);
1991 /* Get font info from the widget */
1992 XtSetArg(args[0], XmNfontList, &font_list);
1993 XtGetValues(combo_p->label, args, 1);
1996 XtSetArg(args[0], XmNitems, &list_items);
1997 XtSetArg(args[1], XmNitemCount, &item_count);
1998 XtGetValues((Widget)list, args, 2);
2000 if ( item_count && item_count >= combo_p->item_count &&
2001 list_items && combo_p->update_label) {
2003 * Loop through all the items to find the biggest dimensions
2005 for (i = 0; i < combo_p->item_count; i++) {
2006 XmStringExtent(font_list, list_items[i], &width, &height);
2007 longest = (width > longest) ? width : longest;
2008 highest = (height > highest) ? height : highest;
2012 XmStringExtent(font_list, combo_p->label_string, &longest, &highest);
2015 combo_p->label_max_length = longest + ((LABEL_PADDING+TEXT_CONTEXT_MARGIN) * 2);
2016 combo_p->label_max_height = highest;
2018 XtSetArg(args[0], XmNborderWidth, &border_width);
2019 XtGetValues(combo_p->label, args, 1);
2020 XtResizeWidget(combo_p->label, combo_p->label_max_length, highest,
2023 /* Resolution Independent */
2024 if (unit_type != XmPIXELS) {
2025 XtSetArg(args[0], XmNunitType, unit_type);
2026 XtSetValues(combo_p->label, args, 1);
2027 XtSetValues(combo_p->list, args, 1);
2033 * Put the current list item into the label.
2034 * This could probably be faster if we see if the label is the
2035 * same as the new item?
2038 SetLabelData( DtComboBoxPart *combo_p,
2040 Boolean force_label_string)
2042 XmListWidget list = (XmListWidget)combo_p->list;
2043 int index = combo_p->selected_position;
2045 XmStringTable list_items;
2049 * If the item is empty, get the current item from the list, or
2050 * use label_string if update_label is FALSE. If that is empty,
2053 if (force_label_string || (combo_p->update_label == FALSE))
2054 item = combo_p->label_string ? combo_p->label_string : InitLabel;
2059 XtSetArg(args[0], XmNitemCount, &item_count);
2060 XtSetArg(args[1], XmNitems, &list_items);
2061 XtGetValues((Widget)list, args, 2);
2062 if (item_count && item_count>index && list_items)
2063 item = list_items[index];
2068 /* Keep label_string in sync with item picked */
2069 if (combo_p->label_string)
2070 XmStringFree(combo_p->label_string);
2071 combo_p->label_string = XmStringCopy(item);
2074 combo_p->selected_item = XmStringCopy(item);
2075 XtSetArg(args[0], XmNlabelString, item);
2076 XtSetValues(combo_p->label, args, 1);
2080 * This is the browseSelect and defaultAction callback handler for the
2081 * ListWidget. If using the textWidget, we only take the first
2082 * segment of the XmString (TextWidgets don't handle XmStrings). If we
2083 * are using a label, then just set the labelString resource.
2086 select_cb( Widget w,
2087 XtPointer client_data,
2088 XtPointer call_data)
2090 DtComboBoxWidget combo_w = (DtComboBoxWidget)client_data;
2091 DtComboBoxPart *combo_p = (DtComboBoxPart*)
2092 &(XmField(combo_w,ipot,DtComboBox,arrow,Widget));
2093 XmListCallbackStruct *info = (XmListCallbackStruct*)call_data;
2094 DtComboBoxCallbackStruct cb;
2096 SelectedPosition(combo_w) = info->item_position - 1;
2097 if (SelectedItem(combo_w))
2098 XmStringFree(SelectedItem(combo_w));
2099 SelectedItem(combo_w) = XmStringCopy(info->item);
2100 if (Type(combo_w) == DtDROP_DOWN_COMBO_BOX) {
2101 SetTextFieldData(combo_p, SelectedItem(combo_w));
2103 else { /* Set the labelWidget string */
2104 SetLabelData(combo_p, SelectedItem(combo_w), FALSE);
2108 * Only popdown if this is the defaultAction callback. We don't
2109 * want to popdown with browseSelect callback; that would cause the
2110 * menu to popdown when the user moved selection with the keyboard.
2111 * Doing it this way, allows the menu to stay up during
2112 * keyboard navigation. When menu goes away, make sure input
2113 * focus goes back into the textField (if editable).
2115 /* This is one of three places to popdown the menu and here is
2116 * to pop it down by Keyboard input: KSelect
2117 * Another place using keyboard input to popdown the menu is
2118 * in _ComboBoxKbdCancel() by <Key>osfEsc
2119 * the last place is in shell_event_handler and that is for
2120 * poping down through Button operation: BSelect
2122 if (info->reason == XmCR_DEFAULT_ACTION)
2123 input_ungrab( combo_w, GRAB_POINTER | GRAB_KEYBOARD );
2125 if ( ShellPoppedUp(((ShellWidget)Shell(combo_w))) == FALSE) {
2126 /* The list will free info->item */
2127 /* The semantic of a DtNselectionCallback is:
2128 * a callback to here + ShellPoppedUp==False
2129 * In reality, there are two scenario for this:
2130 * 1. XmList's XmNdefaultActionCallback which is activated by
2131 * KSelect, will first pop down the shell (see above) and
2132 * and then get here.
2133 * 2. BSelect on XmList, which first call the list_event_handler()
2134 * (for the handler is registered as LIST_HEAD) to pop down
2135 * the shell, and then call XmList's XmNbrowseSelectionCallback
2136 * which in turn get here
2138 cb.reason = DtCR_SELECT;
2139 cb.event = info->event;
2140 cb.item_or_text = XmStringCopy(info->item);
2141 cb.item_position = SelectedPosition(combo_w);
2142 XtCallCallbackList((Widget)combo_w, SelectionCallback(combo_w),
2144 if (cb.item_or_text != NULL) {
2145 XmStringFree(cb.item_or_text);
2146 cb.item_or_text = NULL;
2153 * This is the event_handler for our shell widget. The grab happens
2154 * on the shell while the user is not doing anything inside the list.
2155 * This allows us to know if the user pressed a button outside our
2156 * application. If the user pressed a button anywhere but inside
2157 * the shell, then popdown the menu and ungrab everything.
2161 shell_event_handler( Widget widget,
2162 XtPointer client_data,
2166 DtComboBoxWidget combo_w = (DtComboBoxWidget)client_data;
2167 XmScrolledWindowWidget sw = (XmScrolledWindowWidget)XtParent(List(combo_w));
2168 XmScrollBarWidget v_scrollbar;
2169 XmScrollBarWidget h_scrollbar;
2170 Window window = event->xbutton.window;
2174 if (popup_shell_init) {
2175 if (popup_shell_init != DtKeyPressPopup) {
2176 /* Menu popped up by ButtonPress */
2177 popup_shell_init = DtNonePopup;
2182 /* Menu popped up by KActivate */
2183 popup_shell_init = DtNonePopup;
2188 XtSetArg(args[0], XmNverticalScrollBar, &v_scrollbar);
2189 XtSetArg(args[1], XmNhorizontalScrollBar, &h_scrollbar);
2190 XtGetValues((Widget)sw, args, 2);
2192 /* condition : Shell is popped up;
2193 * ButtonPress event;
2194 * the cursor is Not inside the XmList area,
2195 * the horizontal scrollbar or the vertical one;
2196 * action: remove all the grabs by DtComboBox
2198 if ( ShellPoppedUp(((ShellWidget)Shell(combo_w))) &&
2199 (event->type == ButtonPress &&
2200 (window != XtWindowOfObject(List(combo_w))) &&
2201 !(ScrollBarVisible((Widget)h_scrollbar) &&
2202 (window == XtWindowOfObject((Widget)h_scrollbar))) &&
2203 !(ScrollBarVisible((Widget)v_scrollbar) &&
2204 (window == XtWindowOfObject((Widget)v_scrollbar))))
2206 input_ungrab( combo_w, GRAB_POINTER | GRAB_KEYBOARD );
2208 /* condition : ButtonRelease event
2209 * the cursor is outside the scrollbar(horizontal or vertical)
2210 * action: call action routine "Release" of ScrollBar to release
2211 * possible pressed slider arrow (up/down)
2213 if (event->type == ButtonRelease) {
2214 if ( ScrollBarVisible((Widget)h_scrollbar) &&
2215 window != XtWindowOfObject((Widget)h_scrollbar) )
2216 XtCallActionProc((Widget)h_scrollbar, "Release", event,NULL,0);
2217 if ( ScrollBarVisible((Widget)v_scrollbar) &&
2218 window != XtWindowOfObject((Widget)v_scrollbar) )
2219 XtCallActionProc((Widget)v_scrollbar, "Release", event,NULL,0);
2225 * This is the event_handler for our list widget. Getting the pointer
2226 * grabbing to work correctly was not very easy. In order for everything
2227 * to work correctly, we only do grab-pointer, for the shell, while not
2228 * doing anything inside the list. If doing something inside the list
2229 * we remove the grab on the shell. This is the only way that the
2230 * list will get the ButtonRelease if doing browse while outside the
2231 * list. The toolkit automatically does a grab in between ButtonPress
2232 * and ButtonRelease; therefore, the shell ungrab can't be done inside
2233 * the ButtonPress event.
2236 list_event_handler( Widget widget,
2237 XtPointer client_data,
2239 Boolean *dispatch) /* call remaining event handlers */
2241 DtComboBoxWidget combo_w = (DtComboBoxWidget)client_data;
2244 int top_item_position;
2245 int visible_item_count;
2247 XmScrolledWindowWidget sw = (XmScrolledWindowWidget)XtParent(widget);
2248 XmScrollBarWidget v_scrollbar;
2249 XmScrollBarWidget h_scrollbar;
2251 switch (event->type) {
2254 * Pop down the menu when Button is released inside the menu.
2256 /* Doing the popdown here upon receiving ButtonRelease event,
2257 * rather than in shell_even_hanlder(), is
2258 * essential to allow select_cb() to recognize that this
2259 * XmNbrowseSelectionCallback is the last one in this popup session
2260 * and must treat it as a DtNselectionCallback
2262 input_ungrab( combo_w, GRAB_KEYBOARD );
2264 /* condition : ButtonRelease event
2265 * cursor is outside the scrollbar(horizontal or vertical)
2266 * action: call action routine "Release" of ScrollBar to release
2267 * possible pressed slider arrow (up/down)
2270 XtSetArg(args[0], XmNverticalScrollBar, &v_scrollbar);
2271 XtSetArg(args[1], XmNhorizontalScrollBar, &h_scrollbar);
2272 XtGetValues((Widget)sw, args, 2);
2273 if ( ScrollBarVisible((Widget)h_scrollbar) )
2274 XtCallActionProc((Widget)h_scrollbar, "Release", event,NULL,0);
2275 if ( ScrollBarVisible((Widget)v_scrollbar) )
2276 XtCallActionProc((Widget)v_scrollbar, "Release", event,NULL,0);
2281 * There is interaction conflict between the list and the
2282 * scrollbars in terms of Focus. We always want our list
2283 * to have focus, so grab it back if we lose it.
2285 if ( ShellPoppedUp(((ShellWidget)(Shell(combo_w)))) ) {
2286 _XmGrabKeyboard(widget, False, GrabModeAsync, GrabModeAsync,
2288 XtSetKeyboardFocus(List(combo_w), RevertToNone);
2292 /* call ListBeginSelect() action directly to simulate Btn1Down*/
2293 {Display *disp = XtDisplay(List(combo_w));
2294 Window win = XtWindow(List(combo_w));
2298 int root_x, root_y, win_x, win_y, item_pos;
2299 unsigned int keys_buttons;
2300 unsigned char unit_type = XmPIXELS;
2302 /* Resolution Independent */
2303 if ( MUnitType(combo_w) != XmPIXELS) {
2304 unit_type = MUnitType(combo_w);
2305 XtSetArg(args[0], XmNunitType, XmPIXELS);
2306 XtSetValues(List(combo_w), args, 1);
2308 root = XDefaultRootWindow( disp );
2309 XQueryPointer ( disp, win, &root,
2310 &child, &root_x, &root_y,
2311 &win_x, &win_y, &keys_buttons );
2312 if ( keys_buttons & Button1Mask ) {
2313 item_pos = XmListYToPos(List(combo_w), event->xbutton.y);
2314 list = (XmListWidget)List(combo_w);
2318 XtSetArg(args[num_args],XmNtopItemPosition,&top_item_position);
2320 XtSetArg(args[num_args], XmNvisibleItemCount,
2321 &visible_item_count);
2323 XtSetArg(args[num_args], XmNitemCount, &item_count);
2325 XtGetValues((Widget)list, args, num_args);
2326 /* Adjust top_item_position value to its' internal form */
2327 if (top_item_position)
2328 top_item_position--;
2330 top_item_position = item_count - 1;
2333 (item_pos>=(top_item_position + visible_item_count))||
2334 (item_pos < top_item_position) ||
2335 (item_pos >= item_count) )
2337 Position item_x, item_y;
2338 Dimension item_height, item_width;
2340 XmListPosToBounds((Widget)list,
2341 ((top_item_position + visible_item_count )>
2342 item_count)? item_count:
2343 (top_item_position + visible_item_count ),
2344 &item_x, &item_y, &item_width, &item_height);
2346 if ( item_pos ==0 && event->xbutton.y<(int)(item_height/2) )
2347 event->xbutton.y = item_height/2;
2349 event->xbutton.y = item_y + item_height/2;
2350 event->xbutton.x = item_x;
2353 XtCallActionProc(List(combo_w), "ListBeginSelect",
2358 /* Resolution Independent */
2359 if ( unit_type != XmPIXELS) {
2360 XtSetArg(args[0], XmNunitType, unit_type);
2361 XtSetValues(List(combo_w), args, 1);
2369 /* Caller must free string */
2371 GetTextString(XmString xm_string)
2373 XmStringContext context;
2374 XmStringComponentType type;
2375 XmStringCharSet charset;
2376 XmStringDirection direction;
2377 XmStringComponentType unknown_tag;
2381 Boolean done = FALSE;
2383 XmStringInitContext(&context, xm_string);
2385 /* Loop until 1st char* found */
2387 type = XmStringGetNextComponent(context, &text, &charset,
2388 &direction, &unknown_tag,
2391 case XmSTRING_COMPONENT_END:
2394 case XmSTRING_COMPONENT_TEXT:
2395 case XmSTRING_COMPONENT_LOCALE_TEXT:
2402 XmStringFreeContext(context);
2407 TextFieldActivate(DtComboBoxPart *combo_p, XtPointer call_data)
2409 XmTextFieldWidget w = (XmTextFieldWidget)(combo_p->text);
2410 XmListWidget list = (XmListWidget)combo_p->list;
2411 XmAnyCallbackStruct cb;
2415 XmStringTable list_items;
2417 XtSetArg(arg, XmNvalue, &data);
2418 XtGetValues((Widget)w, &arg, 1);
2421 XtSetArg(arg, XmNitems, &list_items);
2422 XtGetValues((Widget)list, &arg, 1);
2425 text = GetTextString(list_items[combo_p->selected_position]);
2427 if (text && data && (strcmp(text, data) == 0)) {
2430 /* Only send callback if both are not NULL */
2431 else if (!((text == NULL) && (data == NULL))) {
2432 XmAnyCallbackStruct *local_cb = (XmAnyCallbackStruct *)call_data;
2434 cb.reason = XmCR_ACTIVATE;
2435 cb.event = local_cb ? local_cb->event : NULL;
2438 if (XtHasCallbacks((Widget)w, XmNactivateCallback)==XtCallbackHasSome)
2439 XtCallCallbacks((Widget)w, XmNactivateCallback,
2450 * This is the activate callback for the arrow button. This
2451 * sets the shell position and width, does the correct grabs, and
2452 * puts the shell on the screen.
2455 activate_cb( Widget w,
2456 XtPointer client_data,
2457 XtPointer call_data)
2459 DtComboBoxWidget combo_w = (DtComboBoxWidget)client_data;
2460 DtComboBoxPart *combo_p = (DtComboBoxPart*)
2461 &(XmField(combo_w,ipot,DtComboBox,arrow,Widget));
2462 Display *disp = XtDisplayOfObject((Widget)combo_w);
2463 XmDisplay xmdisp = (XmDisplay) XmGetXmDisplay(disp);
2465 Dimension width, height;
2466 Dimension disp_width, disp_height;
2467 Position root_x, root_y, root_y0;
2470 XmStringTable list_items;
2471 unsigned char unit_type = XmPIXELS;
2473 /* Resolution Independent Handling */
2474 XtSetArg(args[0], XmNunitType, &unit_type);
2475 XtGetValues((Widget)combo_w, args, 1);
2477 if ( !_XmFocusIsHere( (Widget)combo_w) )
2478 XmProcessTraversal((Widget)combo_w,
2479 (XmTraversalDirection) XmTRAVERSE_CURRENT);
2481 if (Type(combo_w) == DtDROP_DOWN_COMBO_BOX)
2482 TextFieldActivate(combo_p, call_data);
2485 * Don't popup if no items in the list.
2489 XtSetArg(args[0], XmNitemCount, &n);
2490 XtGetValues(((Widget)List(combo_w)), args, 1);
2491 if ( n != ItemCount(combo_w) )
2492 SyncWithList(combo_p);
2496 screen = DefaultScreen(disp);
2497 disp_width = DisplayWidth(disp, screen);
2498 disp_height = DisplayHeight(disp, screen);
2501 * Call the menu-post callback if requested. This allows the
2502 * user to change the items, instead of using the losing-focus callback.
2503 * If the user used the losing-focus callback to change the items, the
2504 * size of the list/shell will change while it is popped up. We
2505 * could disallow SetValues while the menu is posted, but let's see
2506 * how things go first.
2508 if (MenuPostCallback(combo_w)) {
2509 XmAnyCallbackStruct info;
2511 info.reason = DtCR_MENU_POST;
2512 info.event = (XEvent*)NULL;
2513 XtCallCallbackList((Widget)combo_w, MenuPostCallback(combo_w),
2517 width = MaxShellWidth(combo_w);
2518 height = MaxShellHeight(combo_w);
2521 /* Get root coords of ComboBox */
2522 XtTranslateCoords((Widget)combo_w, X(combo_w), Y(combo_w),
2527 * Make necessary adjustments for offset of our widget
2528 * inside its' parent. Calculate the width of the shell.
2529 * This must be done every time the shell gets popped up, because
2530 * the x/y can change as well as the width (from list's visibleItemCount
2531 * or geometry management changes).
2533 root_x -= X(combo_w);
2534 root_y -= Y(combo_w);
2535 root_y += (Height(combo_w) - COMBO_MARGIN_H(combo_w));
2538 * Make sure the shell is at least as big as our combo-box, and
2539 * make sure it stays on the screen.
2541 /* to enforce a scrollbar with Shell */
2542 if (width < Width(combo_w))
2544 Dimension sb_width, spacing, list_width;
2547 XtSetArg(args[n], XmNverticalScrollBar, &sb); n++;
2548 XtSetArg(args[n], XmNspacing, &spacing); n++;
2549 XtGetValues(XtParent(List(combo_w)), args, n);
2550 /* Resolution Independent Resource */
2551 if ( unit_type != XmPIXELS) {
2552 n = XmConvertUnits(List(combo_w), XmHORIZONTAL,
2553 (int)unit_type, spacing, XmPIXELS);
2556 if (sb && XtIsWidget(sb) ) {
2558 XtSetArg(args[n], XmNwidth, &sb_width); n++;
2559 XtGetValues(sb, args, n);
2560 /* Resolution Independent Resource */
2561 if (unit_type != XmPIXELS) {
2562 n = XmConvertUnits(sb, XmHORIZONTAL,
2563 (int)unit_type, sb_width, XmPIXELS);
2571 width = Width(combo_w);
2572 list_width = ( ScrollBarVisible(sb) ?
2573 (width - sb_width - spacing)
2574 :(width - spacing) );
2576 if (unit_type != XmPIXELS) {
2577 n = XmConvertUnits(sb, XmHORIZONTAL,
2578 XmPIXELS, list_width, (int)unit_type);
2579 list_width = n; n=0;
2581 XtSetArg(args[n], XmNwidth, list_width); n++;
2582 XtSetValues(List(combo_w), args, n);
2584 if ((int)(root_x + width) > (int)disp_width)
2585 root_x = (disp_width - width);
2586 else if (root_x <=0)
2591 if ((int)(root_y + height) > (int)disp_height)
2592 root_y = root_y0 - Y(combo_w) - height;
2594 if (unit_type != XmPIXELS) {
2595 XtSetArg(args[0], XmNunitType, XmPIXELS);
2596 XtSetValues(Shell(combo_w), args, 1);
2599 XtSetArg(args[n], XmNx, root_x); n++;
2600 XtSetArg(args[n], XmNy, root_y); n++;
2601 XtSetValues(Shell(combo_w), args, n);
2602 if (unit_type != XmPIXELS) {
2603 XtSetArg(args[0], XmNunitType, unit_type);
2604 XtSetValues(Shell(combo_w), args, 1);
2608 PoppedUp(combo_w) = TRUE;
2609 XtPopup(Shell(combo_w), XtGrabNone);
2612 * Set up the grab for the shell and list. The shell gets the
2613 * pointer grab so that events will go into the list and scrollbars
2614 * correctly, but events outside the shell will go to the shell.
2615 * See shell and list event handlers for details about grabs.
2617 _XmAddGrab(Shell(combo_w), True, True);
2618 _XmGrabPointer(Shell(combo_w), True, ButtonPressMask |ButtonReleaseMask,
2619 GrabModeAsync, GrabModeAsync, None,
2620 XmGetMenuCursor(disp), CurrentTime);
2621 _XmGrabKeyboard(List(combo_w), False, GrabModeAsync, GrabModeAsync,
2623 xmdisp->display.userGrabbed = True;
2626 * Where to define the cursor for the list widget. It would be
2627 * nice to do it in the list's realize function, but that's not
2628 * possible. We can't use the ComboBox realize function, because
2629 * the list isn't realized at that point. This is the simpliest
2630 * way to get this done. This is needed to make sure the list has the
2631 * correct menu during browse scrolling, etc.
2633 XDefineCursor(disp, XtWindowOfObject(Shell(combo_w)),
2634 XmGetMenuCursor(disp));
2639 * Make sure arrow is symetrical. 45 degree angle. I'm not sure how
2640 * inefficient get/releasing the GC every time is (they are cached by
2644 arrow_expose_cb(Widget w,
2645 XtPointer client_data,
2646 XtPointer call_data)
2648 DtComboBoxWidget combo_w = (DtComboBoxWidget)client_data;
2649 Display *disp = XtDisplayOfObject(w);
2650 Window win = XtWindowOfObject(w);
2658 Dimension arrow_width, arrow_height;
2659 unsigned char unit_type = XmPIXELS;
2661 /* Resolution Independent */
2662 if ( MUnitType(combo_w) != XmPIXELS ) {
2663 unit_type = MUnitType(combo_w);
2664 XtSetArg(args[0], XmNunitType, XmPIXELS);
2665 XtSetValues(w, args, 1);
2668 XtSetArg(args[0], XmNwidth, &arrow_width);
2669 XtSetArg(args[1], XmNheight, &arrow_height);
2670 XtSetArg(args[2], XmNforeground, &(values.foreground));
2671 XtGetValues(w, args, 3);
2672 center_w = arrow_width/2;
2673 center_h = (int) (arrow_height -3.)/2;
2675 values.line_width = 0;
2676 values.line_style = LineSolid;
2677 values.fill_style = FillSolid;
2678 gc = XtGetGC(w, GCForeground | GCFillStyle | GCLineStyle | GCLineWidth,
2681 XDrawLine(disp, win, gc, 1, center_h + center_w + 1, Width(w) - 2,
2682 center_h + center_w + 1);
2684 /* A - bottom point */
2685 points[0].x = center_w;
2686 points[0].y = center_h + (int)(center_w * .8);
2688 /* B - far left point */
2689 points[1].x = center_w - (int)(center_w * .8);
2690 points[1].y = center_h;
2692 /* C - inner left point */
2693 points[2].x = center_w - (int)(center_w * .3);
2694 points[2].y = points[1].y;
2696 /* D - top left point */
2697 points[3].x = points[2].x;
2698 points[3].y = center_h - (int)(center_w * .8);
2700 /* E - top right point */
2701 points[4].x = center_w + (int)(center_w * .3);
2702 points[4].y = points[3].y;
2704 /* F - inner right point */
2705 points[5].x = points[4].x;
2706 points[5].y = points[1].y;
2708 /* G - far right point */
2709 points[6].x = center_w + (int)(center_w * .8);
2710 points[6].y = points[1].y;
2712 /* A - bottom point */
2713 points[7].x = points[0].x;
2714 points[7].y = points[0].y;
2716 XDrawLines(disp, win, gc, points, 8, CoordModeOrigin);
2717 XFillPolygon(disp, win, gc, points, 8, Convex, CoordModeOrigin);
2720 /* Resolution Independent */
2721 if ( unit_type != XmPIXELS ) {
2722 XtSetArg(args[0], XmNunitType, unit_type);
2723 XtSetValues(w, args, 1);
2728 * We get the text-field losing-focus callback, so pass it on to
2729 * the user if they requested it. Our losing-focus callback
2730 * is just a convenience callback, so that the user doesn't
2731 * have to get the text-field first. This make our integration
2732 * with XDesigner a little easier.
2735 text_losing_focus_cb( Widget w,
2736 XtPointer client_data,
2737 XtPointer call_data)
2739 DtComboBoxWidget combo = (DtComboBoxWidget)client_data;
2740 DtComboBoxPart *combo_p = (DtComboBoxPart*)
2741 &(XmField(combo,ipot,DtComboBox,arrow,Widget));
2742 XmTextFieldWidget wt=(XmTextFieldWidget) Text(combo);
2746 int i, need_sync_flag=1;
2749 XtSetArg(arg, XmNvalue, &text_string);
2750 XtGetValues((Widget)wt, &arg, 1);
2751 xmStr = (XmString) XmStringCreateLocalized(text_string?text_string:"");
2753 XtFree (text_string);
2755 if (LosingFocusCallback(combo))
2756 XtCallCallbackList((Widget)combo, LosingFocusCallback(combo),
2757 (XtPointer)call_data);
2759 /* To synchronize the ComboBox record with XmList */
2760 XtVaGetValues(List(combo), XmNitemCount, &i, NULL);
2761 if (i != ItemCount(combo) ) {
2762 SyncWithList(combo_p);
2766 for (i = 0; i < ItemCount(combo); i++) {
2767 if ( need_sync_flag &&
2768 !( (ListItems(combo))[i] && XmeStringIsValid((ListItems(combo))[i]) )) {
2769 SyncWithList(combo_p);
2772 if (XmStringCompare(xmStr, (ListItems(combo))[i]))
2776 if (i < ItemCount(combo) && i != SelectedPosition(combo) ) {
2777 SelectedPosition(combo) = i;
2778 if (SelectedItem(combo))
2779 XmStringFree(SelectedItem(combo));
2780 SelectedItem(combo) = xmStr;
2781 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
2782 SetTextFieldData(combo_p, NULL);
2784 SetLabelData(combo_p, NULL, FALSE);
2785 XmListSetPos(List(combo), SelectedPosition(combo) + 1);
2786 XmListSelectPos(List(combo), SelectedPosition(combo) + 1, True);
2788 XtVaGetValues(List(combo), XmNtopItemPosition,
2789 &(combo_p->top_item_position), NULL);
2792 XmStringFree( xmStr );
2796 * We get the text-field activate callback, so pass it on to
2797 * the user if they requested it. Our activate callback
2798 * is just a convenience callback, so that the user doesn't
2799 * have to get the text-field first. This make our integration
2800 * with XDesigner a little easier.
2803 text_activate_cb( Widget w,
2804 XtPointer client_data,
2805 XtPointer call_data)
2807 DtComboBoxWidget combo = (DtComboBoxWidget)client_data;
2808 DtComboBoxPart *combo_p = (DtComboBoxPart*)
2809 &(XmField(combo,ipot,DtComboBox,arrow,Widget));
2810 XmTextFieldWidget wt=(XmTextFieldWidget) Text(combo);
2814 int i, need_sync_flag=1;
2817 XtSetArg(arg, XmNvalue, &text_string);
2818 XtGetValues((Widget)wt, &arg, 1);
2819 xmStr = (XmString) XmStringCreateLocalized(text_string?text_string:"");
2821 XtFree (text_string);
2823 if (ActivateCallback(combo))
2824 XtCallCallbackList((Widget)combo,
2825 ActivateCallback(combo),
2826 (XtPointer)call_data);
2828 /* To synchronize the ComboBox record with XmList */
2829 XtVaGetValues(List(combo), XmNitemCount, &i, NULL);
2830 if (i != ItemCount(combo) ) {
2831 SyncWithList(combo_p);
2835 for (i = 0; i < ItemCount(combo); i++) {
2836 if ( need_sync_flag &&
2837 !( (ListItems(combo))[i] &&
2838 XmeStringIsValid((ListItems(combo))[i]) )) {
2839 SyncWithList(combo_p);
2842 if (XmStringCompare(xmStr, (ListItems(combo))[i]))
2846 if (i < ItemCount(combo) && i != SelectedPosition(combo) ) {
2847 SelectedPosition(combo) = i;
2848 if (SelectedItem(combo))
2849 XmStringFree(SelectedItem(combo));
2850 SelectedItem(combo) = xmStr;
2851 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
2852 SetTextFieldData(combo_p, NULL);
2854 SetLabelData(combo_p, NULL, FALSE);
2855 XmListSetPos(List(combo), SelectedPosition(combo) + 1);
2856 XmListSelectPos(List(combo), SelectedPosition(combo) + 1, True);
2857 XtVaGetValues(List(combo), XmNtopItemPosition,
2858 &(combo_p->top_item_position), NULL);
2861 XmStringFree( xmStr );
2866 * We get the text-field focus callback, so pass it on to
2867 * the user if they requested it. Our focus callback
2868 * is just a convenience callback, so that the user doesn't
2869 * have to get the text-field first. This make our integration
2870 * with XDesigner a little easier.
2873 text_focus_cb( Widget w,
2874 XtPointer client_data,
2875 XtPointer call_data)
2877 DtComboBoxWidget combo = (DtComboBoxWidget)client_data;
2879 if (FocusCallback(combo))
2880 XtCallCallbackList((Widget)combo, FocusCallback(combo),
2881 (XtPointer)call_data);
2885 * Try and keep our list related rsources in sync with the list widget.
2886 * This is not always possible, depending on if the programmer makes
2887 * list widget calls directly. If we get out of sync with the
2888 * list widget, our SetValues() may not work correctly (when the
2889 * comparisons are done). Should do get values in case list widget
2890 * names are changed?
2893 SyncWithList(DtComboBoxPart *combo_p)
2895 XmListWidget list = (XmListWidget)combo_p->list;
2898 unsigned char unit_type = XmPIXELS;
2900 /* Resolution Independent */
2901 XtSetArg(args[0],XmNunitType,&unit_type);
2902 XtGetValues((Widget)list, args, 1);
2903 if (unit_type != XmPIXELS) {
2904 XtSetArg(args[0],XmNunitType,XmPIXELS);
2905 XtSetValues((Widget)list, args, 1);
2910 XtSetArg(args[num_args],XmNitems,&(combo_p->list_items)); num_args ++;
2911 XtSetArg(args[num_args],XmNitems,&(combo_p->items)); num_args ++;
2912 XtSetArg(args[num_args],XmNitemCount,&(combo_p->item_count)); num_args ++;
2913 XtSetArg(args[num_args],XmNfontList,&(combo_p->list_font_list));
2915 XtSetArg(args[num_args],XmNlistMarginHeight,&(combo_p->list_margin_height));
2917 XtSetArg(args[num_args],XmNlistMarginWidth,&(combo_p->list_margin_width));
2919 XtSetArg(args[num_args],XmNlistSpacing,&(combo_p->list_spacing));
2921 XtSetArg(args[num_args],XmNtopItemPosition,&(combo_p->top_item_position));
2923 XtSetArg(args[num_args],XmNvisibleItemCount,&(combo_p->visible_item_count));
2925 XtGetValues((Widget)list, args, num_args);
2926 /* Adjustment with empty list */
2927 if (! combo_p->item_count) {
2928 combo_p->items = NULL;
2929 combo_p->list_items = NULL;
2932 /* Resolution Independent */
2933 if (unit_type != XmPIXELS) {
2934 XtSetArg(args[0],XmNunitType,unit_type);
2935 XtSetValues((Widget)list, args, 1);
2940 * Routines which manipulate the ComboBox list. These are external
2941 * for use by users of our widget.
2944 DtCreateComboBox(Widget parent,
2949 return(XtCreateWidget(name, dtComboBoxWidgetClass, parent,
2950 arglist, num_args));
2954 DtComboBoxAddItem( Widget combow,
2959 DtComboBoxWidget combo = (DtComboBoxWidget)combow;
2960 DtComboBoxPart *combo_p = (DtComboBoxPart*)
2961 &(XmField(combo,ipot,DtComboBox,arrow,Widget));
2962 XmStringTable list_items;
2965 _DtWidgetToAppContext(combow);
2968 /* Try to help confused applications. */
2969 if (XmIsComboBox(combow))
2971 XmComboBoxAddItem(combow, item, pos, unique);
2978 XtSetArg(arg, XmNitems, &list_items);
2979 XtGetValues(((Widget)List(combo)), &arg, 1);
2981 if (item && list_items) {
2982 for (i = 0; i < ItemCount(combo); i++)
2983 if (XmStringCompare(item, list_items[i]))
2985 if ((i < ItemCount(combo)) && unique)
2992 XmListAddItemUnselected(List(combo), item, pos);
2993 SyncWithList(combo_p);
2996 SetMaximumLabelSize(combo_p);
2997 if (Type(combo) == DtDROP_DOWN_LIST) {
2998 ClearShadow(combo, TRUE);
2999 if (RecomputeSize(combo))
3000 SetComboBoxSize(combo);
3001 LayoutChildren(combo);
3005 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
3006 SetTextFieldData(combo_p, NULL);
3008 SetLabelData(combo_p, NULL, FALSE);
3016 DtComboBoxDeletePos( Widget combow,
3019 DtComboBoxWidget combo = (DtComboBoxWidget)combow;
3020 DtComboBoxPart *combo_p = (DtComboBoxPart*)
3021 &(XmField(combo,ipot,DtComboBox,arrow,Widget));
3022 int selection_changed = 0;
3023 _DtWidgetToAppContext(combow);
3026 /* Try to help confused applications. */
3027 if (XmIsComboBox(combow))
3029 XmComboBoxDeletePos(combow, pos);
3034 if ( pos <= 0 || pos >combo_p->item_count ) {
3035 XtWarning(CB_DEL_POS);
3040 XmListDeletePos(List(combo), pos);
3041 if ( pos == (combo_p->selected_position+1) ) {
3042 /* Since we delete the current item, we have to set one */
3043 if ( pos == combo_p->item_count && combo_p->selected_position>0) {
3044 combo_p->selected_position--;
3045 selection_changed ++;
3047 XmListSelectPos(List(combo), combo_p->selected_position+1, True);
3049 else if ( pos <= combo_p->selected_position) {
3050 combo_p->selected_position--;
3051 selection_changed ++;
3053 SyncWithList(combo_p);
3054 if ( selection_changed ) {
3055 if ( combo_p->selected_item )
3056 XmStringFree(combo_p->selected_item );
3057 combo_p->selected_item =
3059 XmStringCopy(combo_p->list_items[combo_p->selected_position]):
3064 SetMaximumLabelSize(combo_p);
3065 if (Type(combo) == DtDROP_DOWN_LIST) {
3066 ClearShadow(combo, TRUE);
3067 if (RecomputeSize(combo))
3068 SetComboBoxSize(combo);
3069 LayoutChildren(combo);
3073 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
3074 SetTextFieldData(combo_p, NULL);
3076 SetLabelData(combo_p, NULL, FALSE);
3082 DtComboBoxSetItem( Widget combow,
3085 DtComboBoxWidget combo = (DtComboBoxWidget)combow;
3086 DtComboBoxPart *combo_p = (DtComboBoxPart*)
3087 &(XmField(combo,ipot,DtComboBox,arrow,Widget));
3088 XmStringTable list_items;
3091 _DtWidgetToAppContext(combow);
3094 /* Try to help confused applications. */
3095 if (XmIsComboBox(combow))
3097 XmComboBoxSetItem(combow, item);
3104 XtSetArg(arg, XmNitems, &list_items);
3105 XtGetValues(((Widget)List(combow)), &arg, 1);
3107 if (item && list_items) {
3108 for (i = 0; i < ItemCount(combo); i++)
3109 if (XmStringCompare(item, list_items[i]))
3111 if (i < ItemCount(combo)) {
3112 SelectedPosition(combo) = i;
3113 if (SelectedItem(combo))
3114 XmStringFree(SelectedItem(combo));
3115 SelectedItem(combo) = XmStringCopy(item);
3116 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
3117 SetTextFieldData(combo_p, NULL);
3119 SetLabelData(combo_p, NULL, FALSE);
3120 XmListSetItem(List(combo), item);
3121 XmListSelectItem(List(combo), item, FALSE);
3122 SyncWithList(combo_p);
3125 XtWarning(CB_SET_ITEM);
3128 XtWarning(CB_SET_ITEM);
3134 DtComboBoxSelectItem( Widget combow,
3137 DtComboBoxWidget combo = (DtComboBoxWidget)combow;
3138 DtComboBoxPart *combo_p = (DtComboBoxPart*)
3139 &(XmField(combo,ipot,DtComboBox,arrow,Widget));
3140 XmStringTable list_items;
3144 _DtWidgetToAppContext(combow);
3147 /* Try to help confused applications. */
3148 if (XmIsComboBox(combow))
3150 XmComboBoxSelectItem(combow, item);
3157 XtSetArg(arg, XmNitems, &list_items);
3158 XtGetValues(((Widget)List(combo)), &arg, 1);
3160 if (item && list_items) {
3161 for (i = 0; i < ItemCount(combo); i++)
3162 if (XmStringCompare(item, list_items[i]))
3164 if (i < ItemCount(combo)) {
3165 SelectedPosition(combo) = i;
3166 tmpStr=SelectedItem(combo);
3167 SelectedItem(combo) = XmStringCopy(item);
3168 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
3169 SetTextFieldData(combo_p, NULL);
3171 SetLabelData(combo_p, NULL, FALSE);
3172 XmListDeselectAllItems(List(combo));
3173 XmListSelectItem(List(combo), item, FALSE);
3175 XmStringFree(tmpStr);
3176 SyncWithList(combo_p);
3179 XtWarning(CB_SELECT_ITEM);
3182 XtWarning(CB_SELECT_ITEM);
3189 * Synthetic GetValues for List resources.
3192 static XmImportOperator
3193 _XmSetSyntheticResForChild( Widget widget,
3197 return(XmSYNTHETIC_LOAD);
3201 _DtComboBoxGetArrowSize(Widget w,
3202 int resource_offset,
3205 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3209 XtSetArg(arg, XmNheight, &data);
3210 XtGetValues(Arrow(combo), &arg, 1);
3211 *value = (XtArgVal)data;
3215 _DtComboBoxGetLabelString( Widget w,
3216 int resource_offset,
3219 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3221 if (LabelString(combo))
3222 *value = (XtArgVal)XmStringCopy(LabelString(combo));
3224 *value = (XtArgVal)NULL;
3228 _DtComboBoxGetListItemCount( Widget w,
3229 int resource_offset,
3232 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3236 XtSetArg(arg, XmNitemCount, &data);
3237 XtGetValues(List(combo), &arg, 1);
3238 *value = (XtArgVal)data;
3242 _DtComboBoxGetListItems(Widget w,
3243 int resource_offset,
3246 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3250 XtSetArg(arg, XmNitems, &data);
3251 XtGetValues(List(combo), &arg, 1);
3252 *value = (XtArgVal)data;
3256 _DtComboBoxGetListFontList( Widget w,
3257 int resource_offset,
3260 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3264 XtSetArg(arg, XmNfontList, &data);
3265 XtGetValues(List(combo), &arg, 1);
3266 *value = (XtArgVal)data;
3270 _DtComboBoxGetListMarginHeight( Widget w,
3271 int resource_offset,
3274 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3278 XtSetArg(arg, XmNmarginHeight, &data);
3279 XtGetValues(List(combo), &arg, 1);
3280 *value = (XtArgVal)data;
3284 _DtComboBoxGetListMarginWidth( Widget w,
3285 int resource_offset,
3288 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3292 XtSetArg(arg, XmNmarginWidth, &data);
3293 XtGetValues(List(combo), &arg, 1);
3294 *value = (XtArgVal)data;
3298 _DtComboBoxGetListSpacing( Widget w,
3299 int resource_offset,
3302 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3306 XtSetArg(arg, XmNspacing, &data);
3307 XtGetValues(List(combo), &arg, 1);
3308 *value = (XtArgVal)data;
3312 _DtComboBoxGetListTopItemPosition( Widget w,
3313 int resource_offset,
3316 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3320 XtSetArg(arg, XmNtopItemPosition, &data);
3321 XtGetValues(List(combo), &arg, 1);
3322 *value = (XtArgVal)data;
3326 _DtComboBoxGetListVisibleItemCount( Widget w,
3327 int resource_offset,
3330 DtComboBoxWidget combo = (DtComboBoxWidget)w;
3334 XtSetArg(arg, XmNvisibleItemCount, &data);
3335 XtGetValues(List(combo), &arg, 1);
3336 *value = (XtArgVal)data;
3349 static unsigned char to_value;
3351 if(*num_args !=0 ) {
3352 XtError(CB_CVTSTRING);
3355 from_str = (char *)from->addr;
3356 if(strcmp(from_str, "DROP_DOWN_LIST")==0 ||
3357 strcmp(from_str, "drop_down_list")==0 ||
3358 strcmp(from_str, "DtDROP_DOWN_LIST")==0)
3359 to_value = DtDROP_DOWN_LIST;
3360 else if (strcmp(from_str, "DROP_DOWN_COMBO_BOX")==0 ||
3361 strcmp(from_str, "drop_down_combo_box")==0 ||
3362 strcmp(from_str, "DtDROP_DOWN_COMBO_BOX")==0)
3363 to_value = DtDROP_DOWN_COMBO_BOX;
3365 XtDisplayStringConversionWarning(dpy, from->addr, "ComboBoxType");
3369 if (to->addr == NULL) to->addr = (caddr_t) &to_value;
3370 else if (to->size <sizeof(unsigned char)) {
3371 XtDisplayStringConversionWarning(dpy, from->addr, "ComboBoxType");
3375 *(unsigned char *) to->addr = to_value;
3377 to->size = sizeof(unsigned char);
3383 input_ungrab ( DtComboBoxWidget combo, int ungrab_mask)
3385 XmDisplay disp = (XmDisplay) XmGetXmDisplay(XtDisplay(combo));
3387 if ( ungrab_mask & GRAB_POINTER )
3388 XtUngrabPointer(Shell(combo), CurrentTime);
3389 if ( ungrab_mask & GRAB_KEYBOARD )
3390 XtUngrabKeyboard(List(combo), CurrentTime);
3391 _XmRemoveGrab(Shell(combo));
3393 /* We move XtPopdown() here and do _XmRemoveGrab first.
3394 * This is a fix to solve an MR in Desktop which over a time period
3395 * develope a possible core-dump due to duplicated removeGrab() calls
3397 PoppedUp(combo) = FALSE;
3398 XtPopdown(Shell(combo));
3399 if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
3400 XmProcessTraversal(Text(combo), XmTRAVERSE_CURRENT);
3402 /* This is to enable the Drag-and-Drop operation */
3403 disp->display.userGrabbed = False;