2 * ComboBox.c - Das schon lange schmerzlich vermisste Combo-Box-
3 * Widget -- nun endlich auf fuer Motif!
5 * Version 1.32a -- 04.10.95
8 * 04.10.1995 Layoutfehler behoben, der bei angezeigter horizontaler Liste
9 * dazu fuehrt, dass das Listenfeld schrumpft. Daneben wird
10 * jetzt auch der Fall beruecksichtigt, dass das Listenfeld am
11 * unteren Bildschirmrand abgeschnitten wuerde. In diesem Fall
12 * erscheint das Listenfeld oberhalb des Eingabefeldes.
13 * 20.03.1995 XmNscrollbarDisplayPolicy,... koennen nun immer vom Pro-
14 * grammierer gesetzt werden, statische Liste hin und her.
15 * 21.10.1994 Fehler in SetValues behoben, der auftritt, wenn man versucht,
16 * XmNitems und XmNitemCount zu setzen.
17 * 01.10.1994 Externe Sortierung wird nun unterstuetzt sowie seitenweises
18 * Rollen in der Liste mittels PgUp und PgDn.
19 * 25.09.1994 Unterstuetzung fuer XmNautomaticSelection implementiert.
20 * Damit wird die Sache noch ein bischen runder in der Bedienung.
21 * Des weiteren sind etliche Callbacks neu hinzugekommen.
22 * 04.09.1994 Erweiterungen fuer XmSINGLE_SELECT eingebaut. Ausserdem
23 * kann die Liste jetzt auch statisch unterhalb des Eingabe-
24 * felds erscheinen. Damit sind wir nun noch kompatibler ge-
25 * worden -- fragt sich nur, zu was?!
26 * 29.08.1994 Alle Mirror-Ressourcen tauchen nun auch in der Ressourcen-
27 * liste der ComboBox-Klasse auf. Allerdings stehen keine
28 * sinnvollen Werte fuer die Initialisierung 'drin. Weiterhin
29 * den GeometryManager so veraendert, dass ab sofort das
30 * Label in der Breite wachsen oder schrumpfen darf.
31 * 07.06.1994 XmNmnemonic und XmNmnemonicCharSet implementiert.
32 * 29.05.1994 XmNsensitive angepasst. XmNcursorPositionVisible ist nun
33 * False, falls die ComboBox nicht editierbar ist.
34 * 07.05.1994 Drag'n'Drop funktioniert endlich!!! Zudem Anpassung an
35 * den fvwm ausgefuehrt ('st vom Focus-Verhalten ja ein halber
36 * twm). Hach', so'ne Linux-Box mit Motif 1.2 macht doch
37 * einfach Spass... vor allem geht hier so richtig die Post ab.
38 * Das kann man ja von M$ Windoze (Windoze for Mondays) nicht
40 * 14.04.1994 Ein paar Speicherlecks korrigiert.
41 * 21.02.1994 Die Resourcen XmNitems und XmNitemCount lassen sich nun
42 * auch von einer Resourcendatei aus initialisieren. ACHTUNG:
43 * diese beiden Resourcen mussen immer beide beim Aufruf von
44 * XtSetValues zugleich angegeben werden, ansonsten werden
45 * diese Angaben ignoriert.
46 * 03.02.1994 Convenience-Funktionen auf Vordermann gebracht und noch
47 * einen Callback eingebaut, der immer dann aufgerufen wird,
48 * wenn die List angezeigt oder wieder versteckt wird.
49 * 01.02.1994 Motif 1.2-fest!!! Das wird aber heute abend gefeiert!!
50 * Endlich EIN Alptraum weniger! Naja, Drag'n'Drop bleibt
51 * noch zu loesen. Spaeter...
52 * 31.01.1994 VAX-fest (mit Hilfe von Vincenct Li)
53 * owlm sollte man abschaffen! Aber es scheint so, als ob
54 * ich jetzt doch noch das FocusOut-Problem geknackt habe.
55 * Ebenso die OSF...mit viel Arbeit habe ich nun auch noch
56 * eine anstaendige Initialisierung der Fontliste des Label-
58 * 12.01.1994 Revisionsstand: 1.10a
59 * nun wirklich voll ANSI-faehiger C-Code
60 * Pixmaps werden ggf. aufgeraeumt; Druckrichtung
61 * wird vom Vater erfragt und an das Label weiter-
63 * ESC-Behandlung implementiert.
64 * Spiegel-Ressourcen-Initialisierung aus Ressourcen-Daten-
66 * Weitergabe von neu gesetzten Farben an die Kinder
68 * Combo-Box kann jetzt wahlweise auch links neben dem
69 * Eingabefeld ein Label anzeigen.
70 * 09.12.1993 Revisionsstand: 1.00
71 * erste oeffentlich zugaengliche Version der Combo-Box
73 * (c) 1993, 1994, 1995 Harald Albrecht
74 * Institut fuer Geometrie und Praktische Mathematik
75 * RWTH Aachen, Germany
76 * albrecht@igpm.rwth-aachen.de
78 * This program is free software; you can redistribute it and/or modify
79 * it under the terms of the GNU General Public License as published by
80 * the Free Software Foundation; either version 2 of the License, or
81 * (at your option) any later version.
83 * This program is distributed in the hope that it will be useful,
84 * but WITHOUT ANY WARRANTY; without even the implied warranty of
85 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
86 * GNU General Public License for more details.
88 * You should have received a copy of the GNU General Public License
89 * along with this program (see the file COPYING for more details);
90 * if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
91 * Cambridge, MA 02139, USA.
95 /* vms_x_fix.h should be included before any of the X11/Motif headers */
96 #include <wx/vms_x_fix.h>
105 /* get XmVersion definition */
108 #if (XmVersion < 2000)
110 #include <X11/IntrinsicP.h>
111 #include <X11/StringDefs.h>
112 #include <X11/cursorfont.h>
113 #include <X11/Shell.h>
114 #ifdef VMS /* Huch, wo gibt's denn noch sowas ... ?! */
115 /* Bitte keine Mail bzgl. dieser Bemerkung schicken...
116 * Ich weiss, das ist ein Vorurteil...aber es gibt
117 * ja auch wahre Vorurteile....
119 #include <Xmu/Converters.h>
121 #include <X11/Xmu/Converters.h>
123 #include <Xm/ArrowB.h>
124 #include <Xm/TextF.h>
126 #include <Xm/LabelP.h>
129 #include <ctype.h> /* define toupper */
134 /* --- Systemspezifische Definitionen */
136 #define strcasecmp(s1, s2) strcmp(s1, s2)
137 #elif defined(__EMX__)
138 #define strcasecmp stricmp
141 /* --- sonstiger Quark */
144 #define LOG(p1) fprintf(stderr, p1);
145 #define LOG2(p1, p2) fprintf(stderr, p1, p2);
146 #define LOG3(p1, p2, p3) fprintf(stderr, p1, p2, p3);
150 #define LOG3(p1, p2, p3)
153 /* ---------------------------------------------------------------------------
155 * Hier werden diejenigen Resourcen definiert, die von "aussen" - also fuer
156 * den Programmierer oder Anwender - benutzbar und veraenderbar sind.
158 * Der Aufbau der einzelnen Eintraege ist immer wieder gleich:
159 * Resourcen-Name XmN... oder XtN
160 * Resourcen-Klasse XmC... oder XtC
161 * Resourcen-Type XmR... oder XtR (Datentyp der Variable in der
162 * struct der jeweiligen Widgetinstanz)
163 * Resourcen-Groesse aktuelle Groesse dieses Datentyps
164 * Resourcen-Offset Lage der Variable innerhalb der struct der
166 * Defaultwert-Type Typ des Defaultwertes
167 * Defaultwert (normalerweise) Zeiger auf den Defaultwert
169 #define offset(field) XtOffsetOf(XmComboBoxRec, field)
170 static XtResource resources
[] = {
171 { /* Eingabefeld kann veraendert werden, oder aber es sind nur
172 * die Vorgaben aus der Liste auswaehlbar.
174 XmNeditable
, XmCEditable
, XmRBoolean
, sizeof(Boolean
),
175 offset(combobox
.Editable
), XmRString
, "False"
177 { /* Liste wird automatisch sortiert -- wie konnten die bei
178 * der OSF denn SOETWAS nur vergessen ??
180 XmNsorted
, XmCSorted
, XmRBoolean
, sizeof(Boolean
),
181 offset(combobox
.Sorted
), XmRString
, "False"
183 { /* externe Sortierreihenfolge */
184 XmNsortingCallback
, XmCSortingCallback
, XmRCallback
,
185 sizeof(XtCallbackList
),
186 offset(combobox
.SortingCBL
), XmRCallback
, NULL
188 { /* Anzahl auf einmal sichtbarer Eintraege in der Liste (ent-
189 * spricht damit der Listenhoehe.
191 XmNvisibleItemCount
, XmCVisibleItemCount
, XmRInt
, sizeof(int),
192 offset(combobox
.VisibleItemCount
), XmRImmediate
, (caddr_t
) 8
194 { /* Fuer das Eingabefeld sowie die Liste verwandte Fonts */
195 XmNfontList
, XmCFontList
, XmRFontList
, sizeof(XmFontList
),
196 offset(combobox
.Font
), XmRImmediate
, NULL
198 { /* Rueckruf bei Anwahl */
199 XmNselectionCallback
, XmCSelectionCallback
, XmRCallback
,
200 sizeof(XtCallbackList
),
201 offset(combobox
.SelectionCBL
), XmRCallback
, NULL
203 { /* Gegenteil zum vorherigen Callback! */
204 XmNunselectionCallback
, XmCUnselectionCallback
, XmRCallback
,
205 sizeof(XtCallbackList
),
206 offset(combobox
.UnselectionCBL
), XmRCallback
, NULL
208 { /* Doppelklick in der Liste */
209 XmNdefaultActionCallback
, XmCCallback
, XmRCallback
,
210 sizeof(XtCallbackList
),
211 offset(combobox
.DefaultActionCBL
), XmRCallback
, NULL
213 { /* Rueckruf bei Liste ausklappen/verstecken */
214 XmNdropDownCallback
, XmCDropDownCallback
, XmRCallback
,
215 sizeof(XtCallbackList
),
216 offset(combobox
.DropDownCBL
), XmRCallback
, NULL
218 { /* Eingabe abchecken... */
219 XmNmodifyVerifyCallback
, XmCCallback
, XmRCallback
,
220 sizeof(XtCallbackList
),
221 offset(combobox
.ModifyVerifyCBL
), XmRCallback
, NULL
224 XmNvalueChangedCallback
, XmCCallback
, XmRCallback
,
225 sizeof(XtCallbackList
),
226 offset(combobox
.ValueChangedCBL
), XmRCallback
, NULL
229 XmNactivateCallback
, XmCCallback
, XmRCallback
,
230 sizeof(XtCallbackList
),
231 offset(combobox
.ActivateCBL
), XmRCallback
, NULL
234 XmNmotionVerifyCallback
, XmCCallback
, XmRCallback
,
235 sizeof(XtCallbackList
),
236 offset(combobox
.MotionVerifyCBL
), XmRCallback
, NULL
238 { /* Verhalten der ausgeklappten Liste bei Focus-Out */
239 XmNpersistentDropDown
, XmCPersistentDropDown
, XmRBoolean
,
241 offset(combobox
.Persistent
), XmRString
, "False"
243 { /* Wie verhaelt sich der Window-Manager? */
244 XmNtwmHandlingOn
, XmCTwmHandlingOn
, XmRBoolean
, sizeof(Boolean
),
245 offset(combobox
.TwmHandlingOn
), XmRString
, "False"
247 { /* Label anzeigen oder nicht? */
248 XmNshowLabel
, XmCShowLabel
, XmRBoolean
, sizeof(Boolean
),
249 offset(combobox
.ShowLabel
), XmRString
, "False"
251 { /* Abstand zw. linkem Rand Eingabefeld und linkem Rand Liste */
252 XmNdropDownOffset
, XmCDropDownOffset
, XmRPosition
,
253 sizeof(Position
), offset(combobox
.DropDownOffset
),
254 XmRImmediate
, (caddr_t
) -1
256 { /* Neue Voreinstellung bzgl. des Randes */
257 XmNborderWidth
, XmCBorderWidth
, XmRDimension
, sizeof(Dimension
),
258 offset(core
.border_width
), XmRImmediate
, (caddr_t
) 0
260 { /* welcher Cursor soll in der Dropdown-Liste benutzt werden? */
261 XmNdropDownCursor
, XmCDropDownCursor
, XmRCursor
, sizeof(Cursor
),
262 offset(combobox
.ArrowCursor
), XmRString
, "center_ptr"
264 { /* wie lassen sich Eintraege auswaehlen? */
265 XmNselectionPolicy
, XmCSelectionPolicy
, XmRSelectionPolicy
, sizeof(unsigned char),
266 offset(combobox
.SelectionPolicy
), XmRImmediate
, (caddr_t
) XmBROWSE_SELECT
268 { /* Wann werden die Callbacks aufgerufen? */
269 XmNautomaticSelection
, XmCAutomaticSelection
, XmRBoolean
, sizeof(Boolean
),
270 offset(combobox
.AutomaticSelection
), XmRString
, "False"
272 { /* erscheint die Liste staendig? */
273 XmNstaticList
, XmCStaticList
, XmRBoolean
, sizeof(Boolean
),
274 offset(combobox
.StaticList
), XmRString
, "False"
277 XmNscrollBarDisplayPolicy
, XmCScrollBarDisplayPolicy
, XmRScrollBarDisplayPolicy
, sizeof(unsigned char),
278 offset(combobox
.ScrollBarDisplayPolicy
), XmRImmediate
, (caddr_t
) XmAS_NEEDED
281 XmNlistSizePolicy
, XmCListSizePolicy
, XmRListSizePolicy
, sizeof(unsigned char),
282 offset(combobox
.ListSizePolicy
), XmRImmediate
, (caddr_t
) XmVARIABLE
285 XmNsquareArrow
, XmCSquareArrow
, XmRBoolean
, sizeof(Boolean
),
286 offset(combobox
.SquareArrow
), XmRString
, "False"
289 XmNarrowSpacingOn
, XmCArrowSpacingOn
, XmRBoolean
, sizeof(Boolean
),
290 offset(combobox
.ArrowSpacingOn
), XmRString
, "True"
292 #ifndef DONT_LOOK_IN_THE_MIRROR
293 /* Mirror-Ressourcen, Adressen sind ungueltig!!!! */
295 XmNalignment
, XmCAlignment
, XmRAlignment
, sizeof(unsigned char),
296 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
299 XmNblinkRate
, XmCBlinkRate
, XmRInt
, sizeof(int),
300 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
303 XmNcolumns
, XmCColumns
, XmRShort
, sizeof(short),
304 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
307 XmNcursorPosition
, XmCCursorPosition
, XmRTextPosition
, sizeof(XmTextPosition
),
308 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
311 XmNitemCount
, XmCItemCount
, XmRInt
, sizeof(int),
312 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
315 XmNitems
, XmCItems
, XmRXmStringTable
, sizeof(XmStringTable
),
316 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
319 XmNlabelFontList
, XmCLabelFontList
, XmRFontList
, sizeof(XmFontList
),
320 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
323 XmNlabelInsensitivePixmap
, XmCLabelInsensitivePixmap
, XmRPixmap
, sizeof(Pixmap
),
324 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
327 XmNlabelMarginBottom
, XmCLabelMarginBottom
, XmRDimension
, sizeof(Dimension
),
328 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
331 XmNlabelMarginHeight
, XmCLabelMarginHeight
, XmRDimension
, sizeof(Dimension
),
332 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
335 XmNlabelMarginLeft
, XmCLabelMarginLeft
, XmRDimension
, sizeof(Dimension
),
336 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
339 XmNlabelMarginRight
, XmCLabelMarginRight
, XmRDimension
, sizeof(Dimension
),
340 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
343 XmNlabelMarginTop
, XmCLabelMarginTop
, XmRDimension
, sizeof(Dimension
),
344 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
347 XmNlabelMarginWidth
, XmCLabelMarginWidth
, XmRDimension
, sizeof(Dimension
),
348 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
351 XmNlabelPixmap
, XmCLabelPixmap
, XmRPixmap
, sizeof(Pixmap
),
352 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
355 XmNlabelString
, XmCLabelString
, XmRString
, sizeof(XmString
),
356 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
359 XmNlabelType
, XmCLabelType
, XmRLabelType
, sizeof(unsigned char),
360 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
363 XmNlistMarginHeight
, XmCListMarginHeight
, XmRDimension
, sizeof(Dimension
),
364 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
367 XmNlistMarginWidth
, XmCListMarginWidth
, XmRDimension
, sizeof(Dimension
),
368 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
371 XmNlistSpacing
, XmCListSpacing
, XmRDimension
, sizeof(Dimension
),
372 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
375 XmNmarginHeight
, XmCMarginHeight
, XmRDimension
, sizeof(Dimension
),
376 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
379 XmNmarginWidth
, XmCMarginWidth
, XmRDimension
, sizeof(Dimension
),
380 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
383 XmNmaxLength
, XmCMaxLength
, XmRInt
, sizeof(int),
384 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
387 XmNselectThreshold
, XmCSelectThreshold
, XmRInt
, sizeof(int),
388 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
391 XmNstringDirection
, XmCStringDirection
, XmRStringDirection
, sizeof(XmStringDirection
),
392 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
395 XmNtopItemPosition
, XmCTopItemPosition
, XmRInt
, sizeof(int),
396 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
399 XmNvalue
, XmCValue
, XmRString
, sizeof(String
),
400 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
403 XmNvalue
, XmCValue
, XmRInt
, sizeof(int),
404 offset(combobox
.Dummy
), XmRImmediate
, (caddr_t
) 0
409 /* ---------------------------------------------------------------------------
410 * Funktions-Prototypen fuer die 'Methoden' des ComboBox-Widgets. Diese
411 * 'Methoden' werden vom Xt-Toolkit aufgerufen und sorgen dafuer, dass eine
412 * ComboBox sich wie ein anstaendiges Widget verhaelt.
414 static void Initialize (Widget
, XmComboBoxWidget
, ArgList
,
416 static void Destroy (XmComboBoxWidget
);
417 static void Resize (XmComboBoxWidget
);
418 static Boolean
SetValues (XmComboBoxWidget
, XmComboBoxWidget
,
419 XmComboBoxWidget
, ArgList
, Cardinal
*);
420 static void GetValuesAlmost(XmComboBoxWidget
, ArgList
, Cardinal
*);
421 static XtGeometryResult
QueryGeometry (XmComboBoxWidget
, XtWidgetGeometry
*,
423 static XtGeometryResult
GeometryManager(Widget
, XtWidgetGeometry
*,
425 static void ClassInit ();
426 static void Realize (XmComboBoxWidget
, Mask
*,
427 XSetWindowAttributes
*);
428 /* ---------------------------------------------------------------------------
429 * diverse restliche Prototypen... naja, hier halt etwas mager! Hierbei
431 static void ShowHideDropDownList (XmComboBoxWidget w
, XEvent
*event
,
433 static void ShellCallback (Widget w
, XtPointer cbw
,
434 XEvent
*event
, Boolean
*ContDispatch
);
435 static void DoLayout (XmComboBoxWidget w
);
436 /* --------------------------------------------------------------------
439 XmComboBoxClassRec xmComboBoxClassRec
= {
440 { /*** core-Klasse ***/
441 /* superclass */ (WidgetClass
) &xmManagerClassRec
,
442 /* class_name */ "XmComboBox",
443 /* widget_size */ sizeof(XmComboBoxRec
),
444 /* class_initialize */ (XtProc
) ClassInit
,
445 /* class_part_initialize */ NULL
,
446 /* class_inited */ False
, /* IMMER mit FALSE initialisieren !! */
447 /* initialize */ (XtInitProc
) Initialize
,
448 /* initialize_hook */ NULL
,
449 /* realize */ (XtRealizeProc
) Realize
,
452 /* resources */ resources
,
453 /* num_resources */ XtNumber(resources
),
454 /* xrm_class */ NULLQUARK
,
455 /* compress_motion */ True
,
456 /* compress_exposure */ XtExposeCompressMultiple
,
457 /* compress_enterleave */ True
,
458 /* visible_interest */ False
,
459 /* destroy */ (XtWidgetProc
) Destroy
,
460 /* resize */ (XtWidgetProc
) Resize
,
462 /* set_values */ (XtSetValuesFunc
) SetValues
,
463 /* set_values_hook */ NULL
,
464 /* set_values_almost */ XtInheritSetValuesAlmost
,
465 /* get_values_hook */ (XtArgsProc
) GetValuesAlmost
,
466 /* accept_focus */ NULL
,
467 /* version */ XtVersion
,
468 /* callback_private */ NULL
,
469 /* tm_table */ XtInheritTranslations
, /* Changed from NULL: Bug #406153 */
470 /* query_geometry */ (XtGeometryHandler
) QueryGeometry
,
471 /* display_accelerator */ XtInheritDisplayAccelerator
,
474 { /*** composite-Klasse ***/
475 /* geometry_manager */ (XtGeometryHandler
) GeometryManager
,
476 /* change_managed */ XtInheritChangeManaged
,
477 /* insert_child */ XtInheritInsertChild
,
478 /* delete_child */ XtInheritDeleteChild
,
481 { /*** constraint-Klasse ***/
482 /* resources */ NULL
,
483 /* num_resources */ 0,
484 /* constraint_size */ sizeof(XmManagerConstraintPart
),
485 /* initialize */ NULL
,
487 /* set_values */ NULL
,
490 { /*** xmManager-Klasse ***/
491 /* translations */ XtInheritTranslations
,
492 /* syn_resources */ NULL
,
493 /* num_syn_resources */ 0,
494 /* syn_constraint_resources */ NULL
,
495 /* num_syn_constraint_resources */ 0,
496 /* parent_process */ XmInheritParentProcess
,
499 { /*** combobox-Klasse ***/
502 }; /* xmComboBoxClassRec */
503 WidgetClass xmComboBoxWidgetClass
= (WidgetClass
) &xmComboBoxClassRec
;
505 /* --------------------------------------------------------------------
506 * --------------------------------------------------------------------
507 * Translation-Tabelle (hier allerdings fuer das Eingabefeld!)
508 * Tjaja....mit der Reihenfolge von Translations ist das schon so eine
509 * ziemlich boese Sache!
511 static char newEditTranslations
[] =
512 "Alt<Key>osfDown: ComboBox-Manager(show-hide-list) \n\
513 Meta<Key>osfDown: ComboBox-Manager(show-hide-list) \n\
514 Alt<Key>osfUp: ComboBox-Manager(hide-list) \n\
515 Meta<Key>osfUp: ComboBox-Manager(hide-list) \n\
516 <Key>osfUp: ComboBox-Manager(up) \n\
517 <Key>osfDown: ComboBox-Manager(down) \n\
518 <Key>osfPageUp: ComboBox-Manager(page-up) \n\
519 <Key>osfPageDown: ComboBox-Manager(page-down) \n\
520 <Key>osfCancel: ComboBox-Manager(cancel) \n\
521 <Key>Return: ComboBox-Manager(activate) activate()"
523 /* speziell bei der nicht editierbaren Combo-Box sind noch einige
524 * andere Tasten belegt, die sonst dem Eingabefeld alleine gehoeren.
525 * Die dazugehoerigen neuen Translations befinden sich in dieser
526 * zusaetzlichen Tabelle, das Anhaengsel ...NE ist dabei die Ab-
527 * kuerzung fuer "non editable".
529 static char newEditTranslationsNE
[] =
530 "<Key>osfDelete: ComboBox-Manager(wipe-out) \n\
531 <Key>osfBeginLine: ComboBox-Manager(top) \n\
532 <Key>osfEndLine: ComboBox-Manager(bottom) "
534 /* Momentan gibt es noch Aerger mit dem Drag'n'Drop-Mechanismus
535 * von Motif 1.2. Legen wir ihn deshalb erst einmal still, solange
536 * bis ich weiss, warum, und eine Loesung parat habe. NEU: Nur wenn
537 * Sie mit einer libXm geschlagen sind, die partout nicht funktionieren
538 * will, muessen Sie Drag'n'Drop stillegen, ansonsten klappts doch!
541 static char newListTranslations
[] =
542 "<Btn2Down>: ComboBox-Manager(no-operation) ";
544 static char newListTranslationsE
[] =
545 "<Key>osfPageUp: ComboBox-Manager(page-up) \n\
546 <Key>osfPageDown: ComboBox-Manager(page-down) ";
548 /* ---------------------------------------------------------------------------
549 * ---------------------------------------------------------------------------
550 * Aktionen-Tabelle: Hierdurch werden den einzelnen Translations die dazuge-
551 * hoerigen C-Routinen zugeordnet. Da wir hier ein anstaendiges ANSI-C be-
552 * nutzen, werden hier zuerst einmal die Prototypen faellig... Ach ja, noch
553 * ein Hinweis in eigener Sache... der ComboBox-Manager muss applikationsweit
554 * registriert werden, da er auch von Translationen in den Kindern der Combo-
555 * Box aktiviert wird. Bei diesem Namen der 'Aktion' steht aber nicht zu be-
556 * fuerchten, dass er anderweitig bereits in Anwendung ist.
558 static void CBoxManager(Widget w
, XEvent
*event
, String
*params
,
559 Cardinal
*num_params
);
561 static XtActionsRec actions
[] = {
562 { "ComboBox-Manager", CBoxManager
},
567 /* --------------------------------------------------------------------
568 * Eine Instanz dieser Widget-Klasse wird erstmalig in Betrieb ge-
569 * nommen, daher sind noch Vorbereitungen notwendig, die nun hier
570 * durchgefuehrt werden.
572 static XtTranslations NewEditTranslations
, NewEditTranslationsNE
,
576 NewListTranslationsE
;
578 static XtConvertArgRec ConverterScreenConvertArg
[] = {
579 { XtBaseOffset
, (XtPointer
) XtOffset(Widget
, core
.screen
),
583 static void ClassInit()
585 NewEditTranslations
=
586 XtParseTranslationTable(newEditTranslations
);
587 NewEditTranslationsNE
=
588 XtParseTranslationTable(newEditTranslationsNE
);
590 NewListTranslations
=
591 XtParseTranslationTable(newListTranslations
);
593 NewListTranslationsE
=
594 XtParseTranslationTable(newListTranslationsE
);
595 XtAddConverter(XtRString
, XtRBitmap
,
596 XmuCvtStringToBitmap
,
597 ConverterScreenConvertArg
,
598 XtNumber(ConverterScreenConvertArg
));
601 /* ---------------------------------------------------------------------------
602 * Weil es sich bei diesem Widget um ein etwas komplizierteres zusammengesetz-
603 * tes Widget handelt, muessen wir hier - wo eigentlich nur das die Combobox
604 * bildende Fenster auf dem X-Server erzeugt wird - noch einmal das Layout
605 * auf Vordermann bringen. Den Aerger loest dabei das Listenfeld der OSF aus,
606 * das einfach keine Geometrie-Nachfragen verschickt, solange es nicht
607 * 'realized' ist!!! Nicht, dass ich mich ueber so einen Sauhaufen aufregen
608 * wuerde...ich doch nicht! ABER MACHT IHR DENN NUR SO'N MIST...? WARUM KOENNT
609 * IHR DENN NICHT EINMAL DIESES ****(BIEP)**** MOTIF TOOLKIT ANSTAENDIG
610 * DOKUMENTIEREN! Ich glaub', ich kann mich nach dem Chaos eigentlich nur noch
611 * hemmungslos besaufen... Die Suche nach der Ursache (bzw. Urheber = OSF) hat
612 * mich doch einige Tage gekostet (jaja...die Mannstunden!).
614 static void Realize(XmComboBoxWidget w
, Mask
*ValueMask
,
615 XSetWindowAttributes
*Attributes
)
618 * Also: wenn die Liste staendig sichtbar ist, dann zuerst noch einmal
619 * das Layout berechnen. Sonst wird vorne und hinten 'was abgeschnitten.
621 if ( w
->combobox
.StaticList
)
623 (*w
->core
.widget_class
->core_class
.superclass
->core_class
.realize
)
624 ((Widget
) w
, ValueMask
, Attributes
);
627 /* ---------------------------------------------------------------------------
628 * Suche dasjenige Fenster, in dem unsere Shell liegt, in der wiederum die
629 * Combo-Box steckt. Diese Information wird benoetigt, um die Drop-Down-Liste
630 * innerhalb des Fensterstacks immer direkt oberhalb der Shell mit der Combo-
631 * Box zu halten. Jajaja -- ich muss halt davon ausgehen, dass der Fenster-
632 * manager ein sog. "reparenting wm" ist; also die Dekorationen in einem
633 * Fenster dargestellt werden und unsere Shell in dieses Fenster hineingepackt
634 * ist. Die Dekoration ist damit ein Kind des 'root window' - wie die Shell,
635 * in der die Drop-Down-Liste steckt. Und da nur Geschwisterfenster (sibling
636 * windows) im gleichen Stapel stecken, reicht das Shellfenster nicht aus.
637 * Alle gaengigen Fenstermanager sind solche "reparenting wm's", so dass ich
638 * hier zu diesem Trick greifen kann, um die Drop-Down-Liste immer ueber der
639 * ComboBox zu halten.
642 * w Diejenige Combo-Box, fuer die wir dasjenige
643 * Fenster des Window-Managers ermitteln sollen,
644 * dass direkt unterhalb des Root-Fensters liegt.
646 * besagtes zu suchendes Fenster, dass die Dekoration enthaelt (hoffentlich
647 * nur echte Bruesseler Spitze!)
649 static Window
GetDecorationWindow(XmComboBoxWidget w
)
651 Window Root
, Parent
, AWindow
;
653 unsigned int NumChildren
;
655 Parent
= XtWindow((Widget
) w
);
656 /* Suche nach dem Dekorationsfenster des Window-Managers */
659 XQueryTree(XtDisplay((Widget
) w
), AWindow
,
660 &Root
, &Parent
, &Children
, &NumChildren
);
661 XFree((char *) Children
);
662 } while ( Parent
!= Root
);
664 } /* GetDecorationWindow */
666 /* --------------------------------------------------------------------
667 * Eine Combo-Box aus dem Wege raeumen...
668 * Momentan muessen wir hier nur den Cursor wieder los werden sowie
669 * eventuell reservierte Pixmaps.
670 * Ups -- natuerlich muss auch wieder der Callback entfernt werden,
671 * der noch an der Shell haengt.
673 static void Destroy(XmComboBoxWidget w
)
675 /* fprintf(stderr, "Destroy: %08X\n", w->core.window);*/
676 if ( w
->combobox
.ConvertBitmapToPixmap
)
677 XFreePixmap(XtDisplay((Widget
) w
),
678 w
->combobox
.LabelPixmap
);
679 if ( w
->combobox
.ConvertBitmapToPixmapInsensitive
)
680 XFreePixmap(XtDisplay((Widget
) w
),
681 w
->combobox
.LabelInsensitivePixmap
);
682 if ( w
->combobox
.PendingFocusOut
)
683 XtRemoveWorkProc(w
->combobox
.WorkProcID
);
684 XtRemoveEventHandler(w
->combobox
.MyNextShell
,
685 StructureNotifyMask
| FocusChangeMask
,
686 True
, (XtEventHandler
) ShellCallback
,
690 /* ---------------------------------------------------------------------------
691 * Ueberpruefe, ob fuer die Ressource "DropDownOffset" ein gueltiger Wert vom
692 * Benutzer angegeben wurde. Diese Ressource gibt an, wie weit die Drop-Down-
693 * Liste nach rechts gegenueber dem Eingabefeld eingerueckt sein soll. Wenn
694 * hierfuer ein negativer Wert angegeben ist, so berechne statt dessen einen
695 * Standardwert: dieser entspricht der Breite der Pfeilschaltflaeche, was
696 * optisch ganz gut wirkt (jedenfall nach meinem Dafuerhalten).
698 static void CheckDropDownOffset(XmComboBoxWidget w
)
700 if ( w
->combobox
.DropDownOffset
< 0 ) {
701 XtWidgetGeometry ArrowGeom
;
703 XtQueryGeometry(w
->combobox
.ArrowCtrl
, NULL
, &ArrowGeom
);
704 w
->combobox
.DropDownOffset
= ArrowGeom
.width
;
706 } /* CheckDropDownOffset */
708 /* --------------------------------------------------------------------
709 * Berechne die voreinzustellende Groesse, die diese Combo-Box be-
710 * sitzen muss, um ausreichenden Raum fuer das Eingabefeld und den
711 * Pfeil rechts daneben zur Verfuegung zu stellen. Bei einer
712 * editierbaren Combo-Box ist zwischen dem Eingabefeld und dem Pfeil
713 * noch ein Angst-Rasen von der halben Breite eines Pfeiles vorhanden.
714 * Wird das Listenfeld staendig dargestellt, so entfallen sowohl Pfeil
715 * als auch der Angstrasen, dafuer muss aber die Hoehe des Listenfelds
716 * beruecksichtigt werden.
718 static void DefaultGeometry(XmComboBoxWidget w
,
719 Dimension
*TotalWidth
,
720 Dimension
*TotalHeight
,
721 Dimension
*EditCtrlWidth
,
722 Dimension
*LabelCtrlWidth
)
724 XtWidgetGeometry EditGeom
, ArrowGeom
, LabelGeom
, ListGeom
;
726 XtQueryGeometry(w
->combobox
.EditCtrl
, NULL
, &EditGeom
);
727 XtQueryGeometry(w
->combobox
.ArrowCtrl
, NULL
, &ArrowGeom
);
728 XtQueryGeometry(w
->combobox
.LabelCtrl
, NULL
, &LabelGeom
);
731 * Soll die Pfeilschaltflaeche quadratisch, praktisch, gut sein?
733 if ( w
->combobox
.SquareArrow
)
734 ArrowGeom
.width
= ArrowGeom
.height
;
736 ArrowGeom
.width
= (ArrowGeom
.height
* 4) / 5;
739 * Zuerst einmal ein paar einfache Werte ermitteln und zurueckgeben...
741 *TotalHeight
= EditGeom
.height
;
742 *EditCtrlWidth
= EditGeom
.width
;
743 *LabelCtrlWidth
= LabelGeom
.width
;
746 * Ermittele nun die Breite, welche die Combobox benoetigt. Je nach-
747 * dem, ob das Eingabefeld oder die Liste breiter sind, wird der
748 * entsprechende Wert genommen. Diese Auswahl zwischen der Breite von
749 * Eingabefeld und Liste findet aber nur statt, wenn die Liste auch
750 * wirklich staendig sichtbar ist. Waehrend der Initialisierung hat
751 * allerdings XmNcolumns, so dass in diesem Moment die List nicht
752 * mehr die Breite kontrollieren kann!
754 if ( w
->combobox
.StaticList
) {
756 * Beachte: Frage nicht die Listbox, sondern das ScrolledWindow,
757 * in welchem die Liste eingebettet ist.
759 CheckDropDownOffset(w
);
760 XtQueryGeometry(XtParent(w
->combobox
.ListCtrl
), NULL
, &ListGeom
);
761 if ( w
->combobox
.InInit
) {
762 *TotalWidth
= EditGeom
.width
;
764 if ( EditGeom
.width
< (Dimension
)
765 (ListGeom
.width
+ w
->combobox
.DropDownOffset
) )
766 *TotalWidth
= ListGeom
.width
+ w
->combobox
.DropDownOffset
;
768 *TotalWidth
= EditGeom
.width
;
770 *TotalHeight
+= ListGeom
.height
;
773 * Das Listenfeld interessiert uns hier nicht. Degegen sollte noch
774 * die Breite fuer den Pfeil und ein evtl. Angstrasen beachtet
777 *TotalWidth
= EditGeom
.width
+ ArrowGeom
.width
;
778 if ( w
->combobox
.Editable
&& w
->combobox
.ArrowSpacingOn
)
779 *TotalWidth
+= ArrowGeom
.width
/2;
783 * Vergiss nicht, auch noch ein evtl. sichtbares Schriftfeld zu berueck-
786 if ( w
->combobox
.ShowLabel
)
787 *TotalWidth
+= LabelGeom
.width
;
789 } /* DefaultGeometry */
791 /* --------------------------------------------------------------------
792 * Anhand eines Widgets ermittele darueber die Screennummer desjenigen
793 * Screens, auf dem das Widget erscheint.
795 * w betroffenes Widget.
797 * Nummer desjenigen Screens, auf dem das Widget angezeigt wird.
799 static int WidgetToScreen(Widget w
)
805 screen
= XtScreen(w
); NumScreens
= ScreenCount(XtDisplay(w
));
806 display
= DisplayOfScreen(screen
);
807 for ( i
= 0; i
< NumScreens
; ++i
)
808 if ( ScreenOfDisplay(display
, i
) == screen
)
810 XtError("WidgetToScreen: data structures are destroyed.");
811 return 0; /* to avoid a compiler warning */
812 } /* WidgetToScreen */
814 /* --------------------------------------------------------------------
815 * Positioniere die DropDown-Liste (soweit sie natuerlich auch momentan
816 * sichtbar ist) so auf dem Bildschirm, dass sie sich unterhalb des
817 * Eingabefeldes anschliesst.
819 static void DoDropDownLayout(XmComboBoxWidget w
)
821 Position abs_x
, abs_y
;
822 Dimension ArrowWidth
, ListWidth
, ListHeight
;
823 Dimension ScreenHeight
, LabelWidth
;
824 XWindowChanges WindowChanges
;
827 * etwa nicht sichtbar ?!! Oder etwa immer sichtbar ?!!
828 * Dann sind wir jetzt sofort fertig.
830 if ( !w
->combobox
.ListVisible
|| w
->combobox
.StaticList
) return;
832 * Finde zuerst einmal heraus, wo wir uns denn auf dem Bildschirm be-
833 * finden sollen... Beachte dabei auch, dass eventuell die Liste zu schmal
834 * werden koennte und gib' ihr dann ggf. eine Mindestbreite, damit es
835 * keinen core-Dump gibt.
837 XtVaGetValues(w
->combobox
.ArrowCtrl
, XmNwidth
, &ArrowWidth
, NULL
);
838 XtTranslateCoords((Widget
) w
, 0, w
->core
.height
, &abs_x
, &abs_y
);
839 CheckDropDownOffset(w
);
840 ListWidth
= w
->core
.width
- w
->combobox
.DropDownOffset
- 2;
841 abs_x
+= w
->combobox
.DropDownOffset
;
842 if ( w
->combobox
.ShowLabel
) {
843 XtVaGetValues(w
->combobox
.LabelCtrl
, XmNwidth
, &LabelWidth
, NULL
);
844 ListWidth
-= LabelWidth
;
847 if ( ListWidth
< 20 ) ListWidth
= 20;
848 XtVaGetValues(XtParent(w
->combobox
.ListCtrl
), XmNheight
, &ListHeight
, NULL
);
850 * Hier ueberpruefen wir noch, ob die Liste unten aus dem Bildschirm
851 * herausfallen wuerde. In dem Fall klappen wir die Liste oberhalb des
854 ScreenHeight
= DisplayHeight(XtDisplay((Widget
) w
),
855 WidgetToScreen((Widget
) w
));
856 if ( abs_y
+ ListHeight
+ 2 > ScreenHeight
) {
859 y
= ((int) abs_y
) - ListHeight
- w
->core
.height
- 1;
861 abs_y
= (Position
) y
;
863 XtConfigureWidget(w
->combobox
.PopupShell
,
864 abs_x
, abs_y
, ListWidth
, ListHeight
, 1);
866 * So...das hier dient der Kosmetik: hier sorgen wir dafuer, dass die
867 * Liste auch wirklich immer direkt ueber der ComboBox innerhalb des
868 * Fensterstapels schwebt. Siehe dazu auch die Erlaeuterungen und An-
869 * merkungen in GetDecorationWindow().
871 if ( XtIsRealized((Widget
) w
) ) {
872 WindowChanges
.sibling
= GetDecorationWindow(w
);
873 WindowChanges
.stack_mode
= Above
;
874 XReconfigureWMWindow(XtDisplay((Widget
) w
),
875 XtWindow(w
->combobox
.PopupShell
),
876 WidgetToScreen(w
->combobox
.PopupShell
),
877 CWSibling
| CWStackMode
, &WindowChanges
);
879 } /* DoDropDownLayout */
881 /* --------------------------------------------------------------------
882 * Naja... diese Routine scheint ja bereits zu einer Institution beim
883 * Schreiben von Composite-Widgets geworden zu sein.
885 * Hier beim ComboBox-Widget ist die Aufgabe ziemlich einfach: es
886 * genuegt, die Eingabezeile und den Pfeil-Button entsprechend inner-
887 * halb des ComboBox-Widgets zu plazieren. Seit allerdings noch das
888 * Textlabel hinzukommt, wird's langsam aufwendiger. Nun ja - da sich
889 * das Listenfeld wahlweise auch statisch einblenden laesst, ist nun
890 * noch mehr zu beruecksichtigen, wenn die Kinder-Widgets an ihre
891 * Plaetze geschoben werden.
893 static void DoLayout(XmComboBoxWidget w
)
895 Dimension EditCtrlWidth
, ArrowCtrlWidth
, LabelCtrlWidth
;
896 Dimension ComboBoxHeight
;
897 Dimension BorderWidth
;
898 Dimension HighlightThickness
;
901 XtVaGetValues(w
->combobox
.ArrowCtrl
,
902 XmNheight
, &ArrowCtrlWidth
, NULL
);
903 if ( !w
->combobox
.SquareArrow
)
904 ArrowCtrlWidth
= (ArrowCtrlWidth
* 4) / 5;
905 XtVaGetValues(w
->combobox
.LabelCtrl
,
906 XmNwidth
, &LabelCtrlWidth
, NULL
);
909 * In Abhaengigkeit davon, ob die ComboBox editierbar ist und ob das
910 * Listenfeld staendig sichtbar sein soll, hier die Breite einzelner
913 if ( w
->combobox
.StaticList
) {
914 ComboBoxHeight
= w
->combobox
.EditCtrl
->core
.height
;
915 EditCtrlWidth
= w
->core
.width
;
917 ComboBoxHeight
= w
->core
.height
;
918 EditCtrlWidth
= w
->core
.width
- ArrowCtrlWidth
;
919 if ( w
->combobox
.Editable
&& w
->combobox
.ArrowSpacingOn
)
920 EditCtrlWidth
-= ArrowCtrlWidth
/2;
922 /* Beruecksichtige noch ein evtl. ebenfalls anzuzeigendes Schriftfeld
923 * neben dem Eingabefeld.
925 if ( w
->combobox
.ShowLabel
) {
926 EditX
= LabelCtrlWidth
;
927 EditCtrlWidth
-= LabelCtrlWidth
;
930 if ( EditCtrlWidth
< 20 ) EditCtrlWidth
= 20;
931 /* Plaziere nun das Eingabefeld... */
932 XtVaGetValues(w
->combobox
.EditCtrl
,
933 XmNborderWidth
, &BorderWidth
,
934 XmNhighlightThickness
, &HighlightThickness
,
936 XtConfigureWidget(w
->combobox
.EditCtrl
,
938 EditCtrlWidth
, ComboBoxHeight
, BorderWidth
);
939 /* ...und nun den Pfeil... */
940 XtVaGetValues(w
->combobox
.ArrowCtrl
,
941 XtNborderWidth
, &BorderWidth
, NULL
);
942 XtConfigureWidget(w
->combobox
.ArrowCtrl
,
943 w
->core
.width
-ArrowCtrlWidth
, HighlightThickness
,
945 ComboBoxHeight
- 2 * HighlightThickness
,
947 /* ...und ggf. das Textlabel. */
948 if ( w
->combobox
.ShowLabel
) {
949 XtVaGetValues(w
->combobox
.LabelCtrl
,
950 XmNborderWidth
, &BorderWidth
,
952 XtConfigureWidget(w
->combobox
.LabelCtrl
,
954 LabelCtrlWidth
, ComboBoxHeight
,
957 /* Falls da noch die Liste herumgurkt... */
958 if ( w
->combobox
.StaticList
) {
959 Dimension Width
, Height
;
961 if ( w
->core
.height
> ComboBoxHeight
)
962 Height
= w
->core
.height
- ComboBoxHeight
;
966 if ( w
->core
.width
> (Dimension
)(ArrowCtrlWidth
+ EditX
) )
967 Width
= w
->core
.width
- ArrowCtrlWidth
- EditX
;
971 XtConfigureWidget(XtParent(w
->combobox
.ListCtrl
),
972 EditX
+ ArrowCtrlWidth
, ComboBoxHeight
, Width
, Height
, 0);
973 } else if ( w
->combobox
.ListVisible
)
977 /* --------------------------------------------------------------------
978 * Pappi fragt nach, wie gross wir denn sein wollen.
979 * Die hier benutzte Vorgehensweise zur Ermittlung der Groesse:
980 * Sobald der Vater uns eine Breite (oder aber Hoehe) vorschlaegt,
981 * die fuer uns eigentlich zu klein ist, meckern wir und schlagen
982 * die von uns benoetigte Breite (Hoehe) vor.
983 * Soweit also zur Theorie... leider sieht es beispielsweise das
984 * Motif Form-Widget ueberhaupt nicht ein, uns auch nur ein einziges
985 * Mal nach unseren Wuenschen zu fragen! Damit es bei derart unum-
986 * gaenglichen Widgets dann doch noch geht, muss ChangedManaged die
987 * Kohlen wieder aus dem Feuer holen mit einer Sondertour.
989 * *Request Vom Vater vorgeschlagene Geometrie
991 * *Reply Unsere Antwort auf die vorgeschlagene Geometrie
992 * sowie XtGeometryYes oder XtGeometryAlmost, je nachdem, wie gut
993 * uns Pappis Vorschlag in den Kram passt.
995 static XtGeometryResult
QueryGeometry(XmComboBoxWidget w
,
996 XtWidgetGeometry
*Request
,
997 XtWidgetGeometry
*Reply
)
999 XtGeometryResult result
= XtGeometryYes
;
1000 Dimension minW
, minH
, editW
, labelW
;
1002 /* Elternteil will nichts weiter aendern, also ist uns das
1005 Request
->request_mode
&= CWWidth
| CWHeight
;
1006 if ( Request
->request_mode
== 0 ) return result
;
1008 DefaultGeometry(w
, &minW
, &minH
, &editW
, &labelW
);
1010 /* Ueberpruefe, ob uns das in der Breite passt, was Pappi moechte... */
1011 if ( Request
->request_mode
& CWWidth
) {
1012 if ( Request
->width
< minW
) {
1013 /* Wenn Pappi uns etwas vorschlaegt, was im wahrsten Sinne des Wortes
1014 * vorn und hinten nicht reicht, dann versuchen wir ihn entsprechend
1015 * zu korrigieren. ("Versuchen" deshalb, weil er diesen Vorschlag auch
1016 * voellig ignorieren kann.)
1018 result
= XtGeometryAlmost
;
1019 Reply
->width
= minW
;
1020 Reply
->request_mode
|= CWWidth
;
1023 /* Die ganze Chose nun noch vertikal */
1024 if ( Request
->request_mode
& CWHeight
) {
1025 if ( Request
->height
< minH
) {
1026 result
= XtGeometryAlmost
;
1027 Reply
->height
= minH
;
1028 Reply
->request_mode
|= CWHeight
;
1032 } /* QueryGeometry */
1034 /* --------------------------------------------------------------------
1035 * Die Groesse des ComboBox-Widgets hat sich veraendert und deshalb
1036 * mussen alle Kinder neu positioniert werden.
1037 * Letzten Endes laeuft hier alles auf ein ordinaeres DoLayout()
1038 * hinaus, um die Kinder umher zu schieben.
1040 * w Die bereits hinlaenglich bekannte Instanz dieses
1043 static void Resize(XmComboBoxWidget w
)
1048 /* --------------------------------------------------------------------
1049 * Dieses Widget hat sich in irgendeiner Form bewegt (und das nicht
1050 * nur relativ zum Vater, sondern moeglicherweise auch der Vater
1051 * selbst!) bzw. die Shell, in der sich irgendwo unsere Combo-Box
1052 * befindet, hat soeben den Fokus verschusselt und kann ihn nicht
1053 * mehr wiederfinden. Daneben kann es auch sein, dass die Shell
1054 * ikonisiert wurde. (Welch' Vielfalt! Dieses ist hier halt eine
1055 * multifunktionale Routine.)
1058 * w Die naechste Shell in Reichweite ueber unserer
1060 * cbw Diese Combo-Box.
1061 * event ^ auf den Event, enthaelt genauerere Informationen
1062 * (naja... sieht so aus, als ob Motif hier auch
1063 * schon 'mal Schrott 'reinpackt...)
1064 * ContDispatch Auf True setzen, damit dieser Event noch weiter-
1065 * gereicht wird an all' die anderen, die auch noch
1068 static void ShellCallback(Widget w
, XtPointer pClientData
,
1069 XEvent
*event
, Boolean
*ContDispatch
)
1071 XmComboBoxWidget cbw
= (XmComboBoxWidget
) pClientData
;
1073 switch ( event
->type
) {
1074 case ConfigureNotify
:
1075 case CirculateNotify
:
1076 DoDropDownLayout((XmComboBoxWidget
) cbw
);
1079 LOG3("ShellCallback: FocusOut, mode: %i, detail: %i\n",
1080 (int)event
->xfocus
.mode
, (int)event
->xfocus
.detail
);
1081 if ( cbw
->combobox
.Persistent
)
1082 cbw
->combobox
.IgnoreFocusOut
= True
;
1083 else if ( (event
->xfocus
.mode
== NotifyGrab
) &&
1084 cbw
->combobox
.ListVisible
)
1085 cbw
->combobox
.IgnoreFocusOut
= True
;
1088 ShowHideDropDownList((XmComboBoxWidget
) cbw
,
1092 *ContDispatch
= True
;
1093 } /* ShellCallback */
1095 /* --------------------------------------------------------------------
1096 * Diese Routine sorgt dafuer, dass die Liste nicht irrtuemlich bei
1097 * manchen Window Managern vom Bildschirm genommen wird, bloss weil
1098 * diese der OverrideShell den Tastaturfocus schenken bzw. diesen
1099 * dem Combo-Box-Widget wegnehmen, sobald der Mauszeiger in die Liste
1102 static void OverrideShellCallback(Widget w
, XtPointer pClientData
,
1103 XEvent
*event
, Boolean
*ContDispatch
)
1106 XmComboBoxWidget cbw
= (XmComboBoxWidget
) pClientData
;
1107 switch ( event
->type
) {
1109 LOG2("OverrideShellCallback: EnterNotify, PendingFO: %s\n",
1110 cbw
->combobox
.PendingFocusOut
? "True" : "False");
1111 if ( cbw
->combobox
.PendingFocusOut
)
1112 cbw
->combobox
.IgnoreFocusOut
= True
;
1113 if ( cbw
->combobox
.TwmHandlingOn
)
1114 cbw
->combobox
.PendingOverrideInOut
= True
;
1117 LOG("OverrideShellCallback: LeaveNotify\n");
1118 if ( cbw
->combobox
.TwmHandlingOn
)
1119 cbw
->combobox
.PendingOverrideInOut
= True
;
1122 } /* OverrideShellCallback */
1124 /* --------------------------------------------------------------------
1125 * Ha! Anscheinend kann man das Problem mit der einklappenden Liste,
1126 * sobald man den Arrow-Button anklickt, doch loesen! Allerdings geht
1127 * das auch nur von hinten durch die Brust in's Auge. Hier war die
1128 * Reihenfolge der Events bislang das Problem: Klickt man den Arrow-
1129 * Button an, so verliert das Eingabefeld den Focus, dann wird leider
1130 * schon die WorkProc aktiviert und laesst die Liste verschwinden.
1131 * Danach erst kommt der Arrow-Button-Callback an die Reihe. Um dieses
1132 * Dilemma doch noch zu loesen, wird hier darauf gelauert, wann und
1133 * welcher LeaveNotify kommt. Klickt der Benutzer den Pfeil an, so
1134 * kommt hier noch rechtzeitig ein LeaveNotify vorbei, der aber durch
1135 * einen Grab ausgeloest wurde. Und das ist eben nur beim Anklicken
1136 * der Fall. Damit wissen wir, das der FocusOut getrost ignoriert
1138 * Puhhh -- ist das ein kompliziertes Chaos.
1139 * Uebrigends...auch wenn manche Befehle zuerst ueberfluessig er-
1140 * scheinen...sie sind erforderlich, damit die ComboBox auch mit unter-
1141 * schiedlichen Window Managern zurechtkommt!
1143 static void ArrowCrossingCallback(Widget w
, XtPointer pClientData
,
1144 XEvent
*event
, Boolean
*ContDispatch
)
1147 XmComboBoxWidget cbw
= (XmComboBoxWidget
) pClientData
;
1148 switch ( event
->type
) {
1150 LOG2("ArrowCrossingCallback: LeaveNotify, mode: %i\n",
1151 event
->xcrossing
.mode
);
1152 if ( event
->xcrossing
.mode
== NotifyGrab
)
1153 cbw
->combobox
.IgnoreFocusOut
= True
;
1155 cbw
->combobox
.IgnoreFocusOut
= False
;
1158 } /* ArrowCrossingCallback */
1160 /* --------------------------------------------------------------------
1161 * Alle Hilfeaufrufe innerhalb der Kinder gehen an das eigentliche
1162 * Combo-Box-Widget weiter, so dass auch hier nach aussen hin die
1163 * Kinder-Widgets nicht in Erscheinung treten.
1165 static void HelpCallback(Widget w
, XtPointer cbw
, XtPointer CallData
)
1167 XtCallCallbacks((Widget
) cbw
, XmNhelpCallback
, CallData
);
1168 } /* HelpCallback */
1170 /* --------------------------------------------------------------------
1171 * Wenn der Benutzer im Eingabefeld osfActivate drueckt, dann dieses
1172 * Ereignis offiziell bekanntgeben.
1174 static void ActivateCallback(Widget w
, XtPointer cbw
, XtPointer CallData
)
1176 XtCallCallbacks((Widget
) cbw
, XmNactivateCallback
, CallData
);
1177 } /* ActivateCallback */
1179 /* --------------------------------------------------------------------
1180 * Ein Kind moechte sein Groesse veraendern und fragt deshalb hier bei
1184 * *Request Vorschlag des Kindes
1186 * *Reply Unsere Antwort darauf
1187 * XtGeometryNo, da es uns bislang grundsaetzlich nie passt, es sei
1188 * denn, es ist das Label... Naja, jetzt darf auch schon einmal das
1189 * Listenfeld quengeln (aber nur, wenn es staendig sichtbar ist,
1190 * ansonsten wird es nicht beruecksichtigt!).
1192 static XtGeometryResult
GeometryManager(Widget w
,
1193 XtWidgetGeometry
*Request
,
1194 XtWidgetGeometry
*Reply
)
1196 XmComboBoxWidget cbw
= (XmComboBoxWidget
) XtParent(w
);
1197 XtGeometryResult Result
= XtGeometryNo
;
1200 * Falls das Listenfeld statisch dargestellt wird, muessen wir seine
1201 * Wuensche doch beruecksichtigen. Was fuer ein Aufwand...
1203 if ( (w
== XtParent(cbw
->combobox
.ListCtrl
)) && cbw
->combobox
.StaticList
) {
1204 Dimension TotalWidth
, TotalHeight
, EditWidth
, LabelWidth
;
1205 XtWidgetGeometry MyRequest
, YourReply
, EditGeom
;
1207 XtQueryGeometry(cbw
->combobox
.EditCtrl
, NULL
, &EditGeom
);
1208 DefaultGeometry(cbw
, &TotalWidth
, &TotalHeight
,
1209 &EditWidth
, &LabelWidth
);
1210 CheckDropDownOffset(cbw
);
1212 if ( Request
->request_mode
&& CWWidth
)
1213 if ( (Dimension
)(LabelWidth
+ cbw
->combobox
.DropDownOffset
+
1214 Request
->width
) > TotalWidth
)
1215 TotalWidth
= LabelWidth
+ cbw
->combobox
.DropDownOffset
+
1218 if ( Request
->request_mode
&& CWHeight
)
1219 TotalHeight
= EditGeom
.height
+ Request
->height
;
1221 * Bastele nun eine Anfrage an Pappi zusammen und geh' ihm damit auf den
1222 * Keks. Wenn er zustimmt, ist sofort alles gut, wir muessen dann nur
1223 * noch das Layout aufpolieren, damit das Listenfeld die neue Groesse
1224 * bekommt. Wenn Pappi nur halb zustimmt, akzeptieren wir das und fragen
1225 * ihn damit noch einmal....
1227 MyRequest
.request_mode
= CWWidth
| CWHeight
;
1228 MyRequest
.width
= TotalWidth
;
1229 MyRequest
.height
= TotalHeight
;
1230 Result
= XtMakeGeometryRequest((Widget
) cbw
, &MyRequest
, &YourReply
);
1231 if ( Result
== XtGeometryAlmost
) {
1232 MyRequest
.width
= YourReply
.width
;
1233 MyRequest
.height
= YourReply
.height
;
1234 Result
= XtMakeGeometryRequest((Widget
) cbw
, &MyRequest
, &YourReply
);
1236 if ( Result
== XtGeometryYes
)
1240 * Ansonsten darf nur noch das Schriftfeld Ansprueche anmelden.
1242 if ( w
!= cbw
->combobox
.LabelCtrl
)
1243 return XtGeometryNo
; /* Was ICH hier vorgegeben habe, gilt! */
1244 else if ( cbw
->combobox
.ShowLabel
) { /* Naja, 'mal schauen! */
1245 Dimension TotalWidth
, TotalHeight
, EditWidth
, LabelWidth
;
1246 XtWidgetGeometry MyRequest
;
1248 if ( Request
->request_mode
& CWWidth
) {
1249 DefaultGeometry(cbw
, &TotalWidth
, &TotalHeight
,
1250 &EditWidth
, &LabelWidth
);
1251 TotalWidth
= TotalWidth
- LabelWidth
+
1254 MyRequest
.request_mode
= CWWidth
;
1255 MyRequest
.width
= TotalWidth
;
1256 Result
= XtMakeGeometryRequest((Widget
) cbw
, &MyRequest
, NULL
);
1258 if ( Result
== XtGeometryYes
)
1263 } /* GeometryManager */
1265 /* --------------------------------------------------------------------
1266 * Hier werden auf Wunsch diejenigen Farben, die bei der Combo-Box neu
1267 * gesetzt wurden, an alle Kinder weitergegeben.
1269 #define BOTTOMSHADOWCOLOR 0x0001
1270 #define TOPSHADOWCOLOR 0x0002
1271 #define FOREGROUND 0x0004
1272 #define BACKGROUND 0x0008
1274 static struct { String Resource
; int Flag
; }
1275 ColorResources
[] = {
1276 { XmNbottomShadowColor
, BOTTOMSHADOWCOLOR
},
1277 { XmNtopShadowColor
, TOPSHADOWCOLOR
},
1278 { XmNforeground
, FOREGROUND
},
1279 { XmNbackground
, BACKGROUND
}
1282 static int UpdateColors(XmComboBoxWidget w
, int flags
)
1284 Pixel Color
, White
, Black
, EditCol
;
1285 int i
, size
= XtNumber(ColorResources
);
1286 Widget ScrolledWin
, ScrollBar
;
1288 ScrolledWin
= XtParent(w
->combobox
.ListCtrl
);
1289 XtVaGetValues(ScrolledWin
, XmNverticalScrollBar
, &ScrollBar
, NULL
);
1290 White
= WhitePixel(XtDisplay(w
), WidgetToScreen((Widget
) w
));
1291 Black
= BlackPixel(XtDisplay(w
), WidgetToScreen((Widget
) w
));
1292 for ( i
=0; i
<size
; i
++ )
1293 if ( flags
& ColorResources
[i
].Flag
) {
1294 if ( ColorResources
[i
].Flag
== BACKGROUND
)
1296 else if ( ColorResources
[i
].Flag
== FOREGROUND
)
1300 XtVaGetValues((Widget
) w
, ColorResources
[i
].Resource
, &Color
,
1302 XtVaSetValues(ScrollBar
,
1303 ColorResources
[i
].Resource
, Color
, NULL
);
1304 XtVaSetValues(w
->combobox
.ListCtrl
,
1305 ColorResources
[i
].Resource
, EditCol
, NULL
);
1306 XtVaSetValues(w
->combobox
.EditCtrl
,
1307 ColorResources
[i
].Resource
, EditCol
, NULL
);
1308 XtVaSetValues(ScrolledWin
,
1309 ColorResources
[i
].Resource
, Color
, NULL
);
1310 XtVaSetValues(w
->combobox
.LabelCtrl
,
1311 ColorResources
[i
].Resource
, Color
, NULL
);
1312 XtVaSetValues(w
->combobox
.ArrowCtrl
,
1313 ColorResources
[i
].Resource
, Color
, NULL
);
1314 if ( ColorResources
[i
].Flag
& BACKGROUND
)
1315 XtVaSetValues(ScrollBar
, XmNtroughColor
, Color
, NULL
);
1319 } /* UpdateColors */
1321 /* --------------------------------------------------------------------
1322 * Liste aller vorgespiegelten Resourcen, die automatisch verarbeitet
1323 * werden koennen, ohne weiter darueber nachdenken zu muessen...
1325 typedef enum { EDITCTRL
, LISTCTRL
, LABELCTRL
} CHILDCTRL
;
1326 typedef enum { RO
, RW
, RWS
, RWL
, RWI
, RWIGNORE
} aUniqueName
;
1330 /* enum { RO, RW, RWS, RWL, RWI, RWIGNORE } dir; */
1332 /* nur lesen, lesen&schreiben, lesen&schreiben spezial,
1333 lesen&schreiben label, lesen&schreiben items */
1336 /* Alle mit !!! gekennzeichneten Eintraege werden auf die richtigen
1337 * Namen des entsprechenden Widgets umgesetzt.
1339 static MIRROR MirroredResources
[] = {
1340 { XmNitems
, LISTCTRL
, RWI
}, /* Urgs! */
1341 { XmNitemCount
, LISTCTRL
, RWIGNORE
}, /* dto. */
1342 { XmNlistMarginHeight
, LISTCTRL
, RW
},
1343 { XmNlistMarginWidth
, LISTCTRL
, RW
},
1344 { XmNlistSpacing
, LISTCTRL
, RW
},
1345 { XmNstringDirection
, LISTCTRL
, RO
}, /* Naja? */
1346 { XmNtopItemPosition
, LISTCTRL
, RO
},
1348 { XmNblinkRate
, EDITCTRL
, RW
},
1349 { XmNcolumns
, EDITCTRL
, RW
},
1350 { XmNcursorPosition
, EDITCTRL
, RW
},
1351 { XmNcursorPositionVisible
, EDITCTRL
, RW
},
1352 { XmNmarginHeight
, EDITCTRL
, RW
},
1353 { XmNmarginWidth
, EDITCTRL
, RW
},
1354 { XmNmaxLength
, EDITCTRL
, RW
},
1355 { XmNselectThreshold
, EDITCTRL
, RW
},
1356 { XmNvalue
, EDITCTRL
, RWS
},
1358 { XmNalignment
, LABELCTRL
, RW
},
1359 { XmNmnemonic
, LABELCTRL
, RW
},
1360 { XmNmnemonicCharSet
, LABELCTRL
, RW
},
1361 { XmNlabelPixmap
, LABELCTRL
, RW
},
1362 { XmNlabelInsensitivePixmap
, LABELCTRL
, RW
},
1363 { XmNlabelString
, LABELCTRL
, RW
},
1364 { XmNlabelType
, LABELCTRL
, RW
},
1365 { XmNlabelMarginBottom
, LABELCTRL
, RWL
}, /* !!! */
1366 { XmNlabelMarginHeight
, LABELCTRL
, RWL
}, /* !!! */
1367 { XmNlabelMarginLeft
, LABELCTRL
, RWL
}, /* !!! */
1368 { XmNlabelMarginRight
, LABELCTRL
, RWL
}, /* !!! */
1369 { XmNlabelMarginTop
, LABELCTRL
, RWL
}, /* !!! */
1370 { XmNlabelMarginWidth
, LABELCTRL
, RWL
}, /* !!! */
1371 { XmNlabelFontList
, LABELCTRL
, RWL
}, /* !!! */
1377 static TRANSFORMATION Transformations
[] = {
1378 { XmNlabelMarginBottom
, XmNmarginBottom
},
1379 { XmNlabelMarginHeight
, XmNmarginHeight
},
1380 { XmNlabelMarginLeft
, XmNmarginLeft
},
1381 { XmNlabelMarginRight
, XmNmarginRight
},
1382 { XmNlabelMarginTop
, XmNmarginTop
},
1383 { XmNlabelMarginWidth
, XmNmarginWidth
},
1384 { XmNlabelFontList
, XmNfontList
},
1387 /* --------------------------------------------------------------------
1388 * Sobald irgendeine Resource veraendert wird, erfolgt der Aufruf
1389 * hierin als Benachrichtigung, einmal nach dem rechten zu sehen.
1391 * current Kopie der Widget-Instanz, bevor irgendwelche
1392 * Resourcen veraendert oder set_values()-Methoden
1393 * aufgerufen wurden.
1394 * req Kopie der Widget-Instanz, aber bereits mit den
1395 * durch XtSetValues veraenderten Werten
1396 * new aktuellster Zustand der Widget-Instanz mit
1397 * veraenderten Werten (entweder durch XtSetValues
1398 * oder set_values()-Methoden der Superklasse)
1399 * args Argumentenliste beim Aufruf von XtSetValues()
1400 * NumArgs Anzahl der Argumente in der Liste
1402 * True, falls Widget neu gezeichnet werden soll.
1404 static Boolean
SetValues(XmComboBoxWidget current
, XmComboBoxWidget req
,
1405 XmComboBoxWidget newW
,
1406 ArgList args
, Cardinal
*NumArgs
)
1408 Boolean Update
= False
;
1409 int i
, j
, MirrorSize
= XtNumber(MirroredResources
);
1410 int k
, TransformationSize
= XtNumber(Transformations
);
1415 * Alle Resourcen, die nicht mehr nach dem Erstellen der Widget-Instanz
1416 * veraendert werden koennen.
1418 newW
->combobox
.Editable
= current
->combobox
.Editable
;
1419 newW
->combobox
.ListCtrl
= current
->combobox
.ListCtrl
;
1420 newW
->combobox
.EditCtrl
= current
->combobox
.EditCtrl
;
1421 newW
->combobox
.LabelCtrl
= current
->combobox
.LabelCtrl
;
1422 newW
->combobox
.SelectionPolicy
= current
->combobox
.SelectionPolicy
;
1423 newW
->combobox
.ListSizePolicy
= current
->combobox
.ListSizePolicy
;
1424 newW
->combobox
.StaticList
= current
->combobox
.StaticList
;
1427 * Kontrolliere nun alle Resourcen, die sich veraendert haben koennten
1428 * und gebe die neuen Einstellungen entsprechend weiter...
1430 * Hat sich der Sensitive-Zustand veraendert? Dann muessen wir hier dafuer
1431 * sorgen, dass alle Kinder ebenfalls den neuen Zustand annehmen.
1433 if ( current
->core
.sensitive
!= newW
->core
.sensitive
) {
1434 XtSetSensitive(newW
->combobox
.ListCtrl
, newW
->core
.sensitive
);
1435 XtSetSensitive(newW
->combobox
.EditCtrl
, newW
->core
.sensitive
);
1436 XtSetSensitive(newW
->combobox
.ArrowCtrl
, newW
->core
.sensitive
);
1437 XtSetSensitive(newW
->combobox
.ListCtrl
, newW
->core
.sensitive
);
1438 if ( !newW
->core
.sensitive
)
1439 ShowHideDropDownList(newW
, NULL
, False
);
1442 * Die ScrollBarPolicy kann nur dann geaendert werden, wenn das Listenfeld
1443 * dauerhaft dargestellt wird.
1445 if ( newW
->combobox
.ScrollBarDisplayPolicy
!=
1446 current
->combobox
.ScrollBarDisplayPolicy
) {
1447 if ( newW
->combobox
.StaticList
)
1448 XtVaSetValues(newW
->combobox
.ListCtrl
,
1449 XmNscrollBarDisplayPolicy
, newW
->combobox
.ScrollBarDisplayPolicy
,
1453 "XmComboBox: ScrollBarDisplayPolicy can not be changed when StaticList == False."
1456 /* Anzahl der in der Liste gleichzeitig darstellbaren Eintraege */
1457 if ( current
->combobox
.VisibleItemCount
!=
1458 newW
->combobox
.VisibleItemCount
) {
1459 XtVaSetValues(newW
->combobox
.ListCtrl
,
1460 XmNvisibleItemCount
, newW
->combobox
.VisibleItemCount
,
1464 if ( current
->combobox
.AutomaticSelection
!=
1465 newW
->combobox
.AutomaticSelection
) {
1466 XtVaSetValues(newW
->combobox
.ListCtrl
,
1467 XmNautomaticSelection
, newW
->combobox
.AutomaticSelection
,
1471 * benutzter Font: hier erhalten Liste und Eingabefeld jeweils die
1472 * gleiche Fontliste, wohingegen das Label getrennt behandelt wird.
1473 * Das macht auch Sinn, denn Liste und Eingabefeld beinhalten gleich-
1474 * artigen Text, so dass hier auch tunlichst der gleiche Font zu
1477 if ( current
->combobox
.Font
!= newW
->combobox
.Font
) {
1478 XtVaSetValues(newW
->combobox
.ListCtrl
,
1479 XmNfontList
, newW
->combobox
.Font
, NULL
);
1480 XtVaSetValues(newW
->combobox
.EditCtrl
,
1481 XmNfontList
, newW
->combobox
.Font
, NULL
);
1486 if ( newW
->manager
.top_shadow_color
!=
1487 current
->manager
.top_shadow_color
) Flags
|= TOPSHADOWCOLOR
;
1488 if ( newW
->manager
.bottom_shadow_color
!=
1489 current
->manager
.bottom_shadow_color
) Flags
|= BOTTOMSHADOWCOLOR
;
1490 if ( newW
->manager
.foreground
!=
1491 current
->manager
.foreground
) Flags
|= FOREGROUND
;
1492 if ( newW
->core
.background_pixel
!=
1493 current
->core
.background_pixel
) Flags
|= BACKGROUND
;
1494 if ( Flags
) { UpdateColors(newW
, Flags
); Update
= True
; }
1497 if ( newW
->combobox
.ArrowCursor
!= current
->combobox
.ArrowCursor
) {
1498 if ( newW
->combobox
.ListVisible
)
1499 XDefineCursor(XtDisplay(newW
->combobox
.PopupShell
),
1500 XtWindow(newW
->combobox
.PopupShell
),
1501 newW
->combobox
.ArrowCursor
);
1503 /* Hier werden die vorgespiegelten Resourcen verwaltet, die in
1504 * Wirklichkeit zu einem unserer Kinder gehoeren.
1506 for ( i
= 0; i
< *NumArgs
; i
++ ) {
1507 /* Ist es eine vorgespiegelte Resource ? Wenn ja, dann leite die
1508 * Anfrage an das entsprechende Kind-Widget weiter.
1510 for ( j
= 0; j
< MirrorSize
; j
++ ) {
1511 if ( (strcmp(args
[i
].name
, MirroredResources
[j
].rsc
) == 0) ) {
1512 switch ( MirroredResources
[j
].dir
) {
1513 case RW
: /* schreibender Zugriff erlaubt */
1514 XtSetValues(MirroredResources
[j
].ctrl
== LISTCTRL
?
1515 newW
->combobox
.ListCtrl
:
1516 (MirroredResources
[j
].ctrl
== EDITCTRL
?
1517 newW
->combobox
.EditCtrl
:
1518 newW
->combobox
.LabelCtrl
),
1521 case RWS
: /* schreibender Zugriff unter Kontrolle */
1522 if ( strcmp(args
[i
].name
, XmNvalue
) == 0 ) {
1523 if ( newW
->combobox
.Editable
)
1524 XtSetValues(newW
->combobox
.EditCtrl
,
1528 case RWL
: /* Transformation in andere Resource beim
1530 for ( k
= 0; k
< TransformationSize
; k
++ )
1531 if ( strcmp(args
[i
].name
, Transformations
[k
].from
) == 0 ) {
1532 arg
.value
= args
[i
].value
;
1533 arg
.name
= Transformations
[k
].to
;
1534 XtSetValues(newW
->combobox
.LabelCtrl
,
1539 case RWIGNORE
: /* Zugriff auf XmNitemCount */
1540 /* Wird von XmNitems erledigt! */
1542 case RWI
: /* Zugriff auf XmNitems */
1543 for ( k
= 0; k
< *NumArgs
; k
++ )
1544 if ( strcmp(args
[k
].name
, XmNitemCount
) == 0 ) {
1547 MyArgs
[0].name
= XmNitems
;
1548 MyArgs
[0].value
= args
[i
].value
;
1549 MyArgs
[1].name
= XmNitemCount
;
1550 MyArgs
[1].value
= args
[k
].value
;
1551 XtSetValues(newW
->combobox
.ListCtrl
,
1553 /*XtVaSetValues(newW->combobox.ListCtrl,
1554 XmNitems, args[i].value,
1555 XmNitemCount, args[k].value,
1562 } /* case write mode */
1563 goto ScanForNextResource
;
1564 } /* if entry found */
1565 } /* for every mirrored entry */
1566 ScanForNextResource
: ;
1567 } /* for every Arg */
1569 if ( (newW
->combobox
.SquareArrow
!= current
->combobox
.SquareArrow
) ||
1570 (newW
->combobox
.ArrowSpacingOn
!= current
->combobox
.ArrowSpacingOn
) ) {
1578 /* --------------------------------------------------------------------
1579 * Werden irgendwelche Resourcen abgefragt, so muessen wir hier erst
1580 * noch vor der Rueckkehr zum Frager klaeren, ob davon eine Resource
1581 * betroffen ist, die nur vorgespiegelt ist, da sie eigentlich einem
1582 * der Widgets gehoert, die von uns hier verwaltet werden, um daraus
1583 * eine ordentliche Combo-Box zu machen.
1586 * args Abgefragte Resourcen
1587 * NumArgs Anzahl der abgefragten Resourcen
1589 static void GetValuesAlmost(XmComboBoxWidget w
, ArgList args
,
1592 int i
, j
, MirrorSize
= XtNumber(MirroredResources
);
1593 int k
, TransformationSize
= XtNumber(Transformations
);
1596 for ( i
= 0; i
< *NumArgs
; i
++ ) {
1597 /* Ist es eine vorgespiegelte Resource ? Wenn ja, dann leite die
1598 * Anfrage an das entsprechende Kind-Widget weiter.
1600 for ( j
= 0; j
< MirrorSize
; j
++ ) {
1601 if ( strcmp(args
[i
].name
, MirroredResources
[j
].rsc
) == 0 ) {
1602 switch ( MirroredResources
[j
].dir
) {
1607 XtGetValues(MirroredResources
[j
].ctrl
== LISTCTRL
?
1608 w
->combobox
.ListCtrl
:
1609 MirroredResources
[j
].ctrl
== EDITCTRL
?
1610 w
->combobox
.EditCtrl
:
1611 w
->combobox
.LabelCtrl
,
1614 case RWL
: /* Umzuleitende Resource bei Label-Widget */
1615 for ( k
= 0; k
< TransformationSize
; k
++ )
1616 if ( strcmp(args
[i
].name
, Transformations
[k
].from
) == 0 ) {
1617 arg
.value
= args
[i
].value
;
1618 arg
.name
= Transformations
[k
].to
;
1619 XtGetValues(w
->combobox
.LabelCtrl
,
1626 } /* case read mode */
1627 } /* if entry found */
1628 } /* for every mirrored entry */
1629 } /* for every Arg */
1630 } /* GetValuesAlmost */
1632 /* --------------------------------------------------------------------
1633 * Zeige beziehungsweise verstecke die Drop-Down-Liste der Combo-Box.
1634 * Falls die Liste bereits den entsprechenden Zustand hat, geht's
1635 * sofort zum Aufrufer zurueck.
1637 * w Her Royal Majesty ComboBox
1638 * Show True, falls anzuzeigen, andernfalls False
1640 static void ShowHideDropDownList(XmComboBoxWidget w
, XEvent
*event
,
1643 XmComboBoxDropDownCallbackStruct info
;
1645 if ( w
->combobox
.StaticList
||
1646 (Show
== w
->combobox
.ListVisible
) ) return;
1647 w
->combobox
.ListVisible
= Show
;
1648 if ( Show
) { /* Klapp' die Liste aus! */
1649 DoDropDownLayout(w
);
1650 info
.reason
= XmCR_SHOW_LIST
;
1652 XtCallCallbacks((Widget
) w
, XmNdropDownCallback
,
1654 XDefineCursor(XtDisplay(w
->combobox
.PopupShell
),
1655 XtWindow(w
->combobox
.PopupShell
),
1656 w
->combobox
.ArrowCursor
);
1657 XtPopup(w
->combobox
.PopupShell
, XtGrabNone
);
1658 XtVaSetValues(w
->combobox
.ArrowCtrl
,
1659 XmNarrowDirection
, XmARROW_UP
, NULL
);
1660 } else { /* Klapp' die Liste wieder ein... */
1661 XtPopdown(w
->combobox
.PopupShell
);
1662 XtVaSetValues(w
->combobox
.ArrowCtrl
,
1663 XmNarrowDirection
, XmARROW_DOWN
, NULL
);
1664 info
.reason
= XmCR_HIDE_LIST
;
1666 XtCallCallbacks((Widget
) w
, XmNdropDownCallback
,
1669 } /* ShowHideDropDownList */
1671 /* --------------------------------------------------------------------
1672 * Hier laeuft die Nachricht auf, dass der Pfeil ausgeloest wurde...
1673 * (Daraufhin sollte die Liste aus- oder eingeklappt werden)
1674 * ...oder dass der Benutzer da draussen auf der anderen Seite der
1675 * Mattscheibe den Pfeil bereits anklickte ohne aber bereits losge-
1676 * gelassen zu haben. Bereits hier bekommt das Eingabefeld den Fokus
1677 * vor den Latz geknallt, denn sonst kann es passieren, dass zwar die
1678 * Liste ausgeklappt ist, aber das Eingabefeld noch keinen Tastatur-
1679 * fokus erhalten hat. Das sollte aber nicht so sein, denn es ist dann
1680 * keine konsequente Tastaturbedienung.
1682 static void ArrowCallback(Widget w
, XtPointer pClientData
,
1683 XmAnyCallbackStruct
*info
)
1685 XmComboBoxWidget cbw
= (XmComboBoxWidget
) XtParent(w
);
1687 switch ( info
->reason
) {
1689 LOG("ArrowCallback: XmCR_ARM\n");
1690 XmProcessTraversal(cbw
->combobox
.EditCtrl
, XmTRAVERSE_CURRENT
);
1691 if ( cbw
->combobox
.TwmHandlingOn
&& cbw
->combobox
.ListVisible
)
1692 cbw
->combobox
.IgnoreFocusOut
= True
;
1695 XmProcessTraversal(cbw
->combobox
.EditCtrl
, XmTRAVERSE_CURRENT
);
1696 ShowHideDropDownList(cbw
, info
->event
,
1697 (Boolean
)(!cbw
->combobox
.ListVisible
));
1700 } /* ArrowCallback */
1702 /* --------------------------------------------------------------------
1703 * Diese Benachrichtigung moechte uns nur mitteilen, dass wir soeben
1704 * den Fokus verloren haben (Ohhhh!) Sollte allerdings der Fokus nur
1705 * aus dem Grunde perdue sein, dass der Anwender den Mauszeiger ausser-
1706 * halb des Applikationsfensters plaziert hat, so koennen wir diese
1707 * Nachricht uebergehen. Erst wenn der Fokus an ein anderes Widget in
1708 * unserer Applikation verlorenging, muessen wir auf diese Information
1710 * Und jetzt zu noch einem total beknackten Problem - alles nur wegen
1711 * Motif und den diversen Window-Managern (bspw. olwm)... Leider kommt
1712 * beim FocusOut kein richtiger Hinweis auf den tatsaechlichen Event,
1713 * der dieses Callback ausloeste -- warum liefert denn dann Motif ueber-
1714 * haupt noch den Event???? Und ueberhauupt, die Geschichte mit dem
1715 * Fokus ist schon der reinste Horror. Aktueller Ausweg: wenn wir die
1716 * Benachrichtigung ueber den Focusabgang bekommen, registrieren wir
1717 * eine Work-Prozedur, die, sobald der Rechner wieder Luft hat, auf-
1718 * gerufen wird. Sie kann dann nachschauen, ob nicht inzwischen die
1719 * OverrideShell den Focus bekahm. Wenn ja, koennen wir den FocusOut
1720 * uebergehen, ansonsten muessen wir ihn beruecksichtigen.
1721 * -- Ist das eine ^@#$^*(#$^&! (Meine gute Erziehung hindert mich
1722 * daran, diesen Begriff hier zu nennen.)
1724 static Boolean
DelayedFocusOutWorkProc(XtPointer pClientData
)
1726 XmComboBoxWidget cbw
= (XmComboBoxWidget
) pClientData
;
1727 LOG2("DelayedFocusOutWorkProc: IgnoreFocusOut: %s\n",
1728 cbw
->combobox
.IgnoreFocusOut
? "True" : "False");
1729 if ( !cbw
->combobox
.IgnoreFocusOut
)
1730 ShowHideDropDownList(cbw
, &(cbw
->combobox
.xevent
), False
);
1731 cbw
->combobox
.IgnoreFocusOut
= False
;
1732 cbw
->combobox
.PendingFocusOut
= False
;
1733 return True
; /* diese Routine wird nicht mehr benoetigt. */
1734 } /* DelayedFocusOutWorkProc */
1736 static void EditFocusCallback(Widget w
, XtPointer pClientData
,
1737 XmAnyCallbackStruct
*info
)
1739 XmComboBoxWidget cbw
= (XmComboBoxWidget
) XtParent(w
);
1741 if ( cbw
->combobox
.StaticList
) return;
1743 if ( info
->reason
== XmCR_LOSING_FOCUS
) {
1744 LOG2("EditFocusCallback: PendingFocusOut: %s, ",
1745 cbw
->combobox
.PendingFocusOut
? "True" : "False");
1746 LOG3("mode: %i, detail: %i, ", (int)info
->event
->xcrossing
.mode
,
1747 (int)info
->event
->xcrossing
.detail
);
1748 LOG2("PendingOverrideInOut: %s\n",
1749 cbw
->combobox
.PendingOverrideInOut
? "True" : "False");
1750 if ( !cbw
->combobox
.PendingFocusOut
&&
1751 !cbw
->combobox
.PendingOverrideInOut
) {
1752 /* Normalerweise duerfen aber keine NULL-Events hier
1753 * vorbeikommen...aber man weiss ja nie so genau und
1754 * sicher ist sicher. Defensiv programmieren!
1757 cbw
->combobox
.xevent
= *info
->event
;
1758 cbw
->combobox
.WorkProcID
= XtAppAddWorkProc(
1759 XtWidgetToApplicationContext((Widget
) cbw
),
1760 (XtWorkProc
) DelayedFocusOutWorkProc
,
1762 cbw
->combobox
.PendingFocusOut
= True
;
1764 cbw
->combobox
.PendingOverrideInOut
= False
;
1766 } /* EditFocusCallback */
1768 /* --------------------------------------------------------------------
1769 * Hier wird der angegebene Eintrag in der Listbox der Combo-Box
1770 * markiert und zudem in den sichtbaren Bereich gerollt, sollte er
1771 * sich ausserhalb des dargestellten Bereichs der Liste befinden.
1773 * w Die Combo-Box (ueblicher Parameter)
1774 * Index Index des neu zu markierenden Eintrages.
1775 * Notify Schickt Mitteilung via Callback
1777 * Index des markierten Eintrages oder 0, falls die Listbox leer
1778 * war und deshalb auch kein Eintrag markiert werden konnte.
1780 static int SetSelectionPos(XmComboBoxWidget w
, int Index
, Boolean Notify
)
1782 Widget ListBox
= w
->combobox
.ListCtrl
;
1783 int ItemCount
; /* Anzahl Eintraege in Listbox */
1784 int TopItem
, VisibleItems
;
1786 XtVaGetValues(ListBox
, XmNitemCount
, &ItemCount
,
1787 XmNtopItemPosition
, &TopItem
,
1788 XmNvisibleItemCount
, &VisibleItems
,
1790 if ( Index
< 1 ) Index
= 1;
1791 if ( Index
> ItemCount
) Index
= ItemCount
;
1792 if ( Index
!= 0 && ItemCount
!= 0 ) {
1793 if ( Index
< TopItem
)
1794 XmListSetPos(ListBox
, Index
);
1795 if ( Index
>= TopItem
+ VisibleItems
)
1796 XmListSetBottomPos(ListBox
, Index
);
1797 XmListSelectPos(ListBox
, Index
, Notify
);
1801 } /* SetSelectionPos */
1803 /* --------------------------------------------------------------------
1804 * Diese Routine kuemmert sich darum, denjenigen Eintrag aus der List-
1805 * box mit der angegebenen Nummer herauszufischen und an die Eingabe-
1806 * zeile zu uebergeben. Dabei wird der Index auf den Eintrag auto-
1807 * matisch auf den zulaessigen Bereich begrenzt. Zugleich wird auch
1808 * noch der angegebene Eintrag in der Listbox markiert.
1810 static void TransferToEditCtrl(XmComboBoxWidget w
, int SelectionIndex
,
1813 Widget ListBox
= w
->combobox
.ListCtrl
;
1814 XmStringTable Items
;
1817 XtVaGetValues(ListBox
, XmNitems
, &Items
, NULL
);
1820 (SelectionIndex
== w
->combobox
.LastSelection
) &&
1821 (w
->combobox
.SelectionPolicy
== XmSINGLE_SELECT
) ) {
1825 if ( (SelectionIndex
== 0) &&
1826 (w
->combobox
.SelectionPolicy
== XmSINGLE_SELECT
) ) {
1827 XmListDeselectAllItems(w
->combobox
.ListCtrl
);
1828 w
->combobox
.PassVerification
= True
;
1829 XmTextFieldSetString(w
->combobox
.EditCtrl
, "");
1831 SelectionIndex
= SetSelectionPos(w
, SelectionIndex
, False
);
1832 if ( SelectionIndex
> 0 ) {
1833 XmStringGetLtoR(Items
[SelectionIndex
-1],
1834 XmSTRING_DEFAULT_CHARSET
, &pItemText
);
1835 w
->combobox
.PassVerification
= True
;
1836 XmTextFieldSetString(w
->combobox
.EditCtrl
, pItemText
);
1840 w
->combobox
.LastSelection
= SelectionIndex
;
1841 } /* TransferToEditCtrl */
1843 /* --------------------------------------------------------------------
1844 * Alle registrierten Callbacks bei Anwahl eines neuen Eintrages in
1845 * der Listbox aktivieren.
1847 static void CallSelectionCBL(XmComboBoxWidget w
, XEvent
*Event
)
1851 index
= XmComboBoxGetSelectedPos((Widget
) w
);
1853 * Wenn momentan KEIN Eintrag selektiert ist, dann rufe den neuen
1854 * XmNunselectionCallback auf!
1857 XmComboBoxUnselectionCallbackStruct info
;
1859 info
.reason
= XmCR_UNSELECT
;
1861 XtCallCallbacks((Widget
) w
, XmNunselectionCallback
, (XtPointer
) &info
);
1864 * Ansonsten den ueblichen SelectionCallback!
1866 XmComboBoxSelectionCallbackStruct info
;
1867 XmStringTable Items
;
1869 info
.reason
= w
->combobox
.SelectionPolicy
== XmSINGLE_SELECT
?
1870 XmCR_SINGLE_SELECT
: XmCR_BROWSE_SELECT
;
1873 XtVaGetValues(w
->combobox
.ListCtrl
, XmNitems
, &Items
, NULL
);
1874 info
.value
= Items
[info
.index
-1];
1875 XtCallCallbacks((Widget
) w
, XmNselectionCallback
, (XtPointer
) &info
);
1877 } /* CallSelectionCBL */
1879 /* --------------------------------------------------------------------
1880 * Hier laeuft das Tastatur-Management fuer die ComboBox zusammen.
1881 * ACHTUNG: Der 'w'-Parameter wird nur benoetigt, um das eigentliche
1882 * ComboBox-Widget zu ermitteln. Er muss daher die ID eines direkten
1883 * Kinds der ComboBox enthalten!
1885 static void CBoxManager(Widget w
, XEvent
*Event
, String
*params
,
1886 Cardinal
*num_params
)
1888 XmComboBoxWidget cbw
;
1892 int SelectionIndex
; /* Wer denn nun markiert wird... */
1893 int ItemCount
; /* Anzahl Eintraege in Listbox */
1894 int VisibleItems
; /* Hoehe der Liste in Eintraegen */
1898 * Nur wenn eine der Translationen page-up und page-down direkt im
1899 * Listenfeld ausgeloest wurden, wird auch als "w" die Liste ueber-
1900 * geben. Bei allen anderen Faellen ist dieses zumeist das TextField.
1902 if ( XtClass(w
) == xmListWidgetClass
)
1903 cbw
= (XmComboBoxWidget
) XtParent(XtParent(w
));
1905 cbw
= (XmComboBoxWidget
) XtParent(w
);
1906 ListBox
= cbw
->combobox
.ListCtrl
;
1908 switch ( *(params
[0]) ) {
1909 /* --------------------------------------------------------------------
1910 * Klappe die Liste auf Wunsch des Benutzers aus oder wieder ein.
1912 case 's': /* show-hide-list */
1913 ShowHideDropDownList(cbw
, Event
,
1914 (Boolean
)(!cbw
->combobox
.ListVisible
));
1916 case 'h': /* hide-list */
1917 ShowHideDropDownList(cbw
, Event
, False
);
1919 /* --------------------------------------------------------------------
1920 * Hier werden die Bewegungen in der Listbox behandelt.
1923 case 'd': /* down */
1925 case 'b': /* bottom */
1926 case 'p': /* page-up/page-down */
1928 XtVaGetValues(ListBox
, XmNitemCount
, &ItemCount
,
1929 XmNvisibleItemCount
, &VisibleItems
, NULL
);
1930 if ( XmListGetSelectedPos(ListBox
,
1931 &SelectionList
, &SelectionCount
) ) {
1932 SelectionIndex
= *SelectionList
;
1933 XtFree((char *)SelectionList
);
1935 case 'u': SelectionIndex
--; break;
1936 case 'd': SelectionIndex
++; break;
1937 case 't': SelectionIndex
= 1; break;
1938 case 'b': SelectionIndex
= ItemCount
; break;
1939 case 'p': if ( *(params
[0]+5) == 'u' )
1940 SelectionIndex
-= VisibleItems
;
1942 SelectionIndex
+= VisibleItems
;
1945 } else { /* momentan noch kein Eintrag in der Liste ausgewaehlt */
1946 if ( opt
== 'b' ) SelectionIndex
= ItemCount
;
1947 else SelectionIndex
= 1; /* nun ersten Eintrag nehmen */
1949 TransferToEditCtrl(cbw
, SelectionIndex
, False
);
1950 CallSelectionCBL(cbw
, Event
);
1952 /* --------------------------------------------------------------------
1953 * Der Benutzer hat die Eingabetaste gedrueckt oder einen Eintrag in
1954 * der Listbox angeklickt.
1956 case 'a': /* Return = activate */
1957 case 'S': /* Selection */
1958 if ( !cbw
->combobox
.StaticList
&& !cbw
->combobox
.ListVisible
) break;
1959 XtVaGetValues(ListBox
, XmNitemCount
, &ItemCount
, NULL
);
1960 if ( ItemCount
== 0 ) break;
1961 if ( XmListGetSelectedPos(ListBox
,
1962 &SelectionList
, &SelectionCount
) ) {
1963 SelectionIndex
= *SelectionList
;
1964 XtFree((char *)SelectionList
);
1966 if ( cbw
->combobox
.SelectionPolicy
!= XmSINGLE_SELECT
)
1972 TransferToEditCtrl(cbw
, SelectionIndex
,
1973 *(params
[0]) == 'S');
1974 CallSelectionCBL(cbw
, Event
);
1975 ShowHideDropDownList(cbw
, Event
, (Boolean
)
1976 (*(params
[0]) == 'S' ? True
: False
));
1978 /* --------------------------------------------------------------------
1979 * Der Benutzer hat die ESC-Taste gedrueckt. Ist die Liste zu diesem
1980 * Zeitpunkt noch ausgeklappt, so wird sie einfach nur eingeklappt und
1981 * weiter passiert nichts. Ist die Liste jedoch eingeklappt, so wird
1982 * das ESC an die normale Action-Routine des Eingabefeldes weiter-
1983 * gegeben, damit damit bspw. Dialog u.a. abgebrochen werden koennen.
1985 case 'c': /* Cancel */
1986 if ( cbw
->combobox
.ListVisible
)
1987 ShowHideDropDownList(cbw
, Event
, False
);
1989 XtCallActionProc(cbw
->combobox
.EditCtrl
,
1990 "process-cancel", Event
, NULL
, 0);
1992 /* --------------------------------------------------------------------
1993 * Wenn es erlaubt ist, dass auch einmal kein Eintrag in einer ComboBox
1994 * mit nicht editierbarem Eingabefeld ausgewaehlt ist, dann darf der
1995 * Anwender mittels osfDelete den aktuellen Eintrag deselektieren.
1997 case 'w': /* wipe */
1998 if ( cbw
->combobox
.SelectionPolicy
== XmSINGLE_SELECT
) {
1999 TransferToEditCtrl(cbw
, 0, True
);
2000 CallSelectionCBL(cbw
, Event
);
2003 /* --------------------------------------------------------------------
2006 case 'n': /* no-operation */
2011 /* --------------------------------------------------------------------
2012 * Der Benutzer hat einen Eintrag in der Listbox angeklickt. Der Ein-
2013 * fachkeit halber wird einfach nur ein Druecken der Eingabetaste
2016 static void ListSelectionCallback(Widget w
, XtPointer pClientData
,
2017 XmAnyCallbackStruct
*info
)
2019 String paramsMouse
[1] = { "a" }, paramsKeyboard
[1] = { "S" };
2020 Cardinal NumParams
= 1;
2021 XmComboBoxWidget cbw
= (XmComboBoxWidget
) pClientData
;
2023 * Wurde der Event durch die Tastatur oder einen Mausklick
2024 * ausgeloest? Wenn es ein Mausklick auf das Listenfeld war und es
2025 * sich um ein staendig angezeigtes Listenfeld einer nicht editierbaren
2026 * ComboBox handelt, dann gib' dem Eingabefeld den Tastaturfokus.
2028 if ( info
->event
== NULL
)
2029 CBoxManager(cbw
->combobox
.EditCtrl
, info
->event
,
2030 paramsKeyboard
, &NumParams
);
2032 CBoxManager(cbw
->combobox
.EditCtrl
, info
->event
,
2033 paramsMouse
, &NumParams
);
2034 if ( !cbw
->combobox
.StaticList
||
2035 (cbw
->combobox
.StaticList
&& !cbw
->combobox
.Editable
) )
2036 XmProcessTraversal(cbw
->combobox
.EditCtrl
,
2037 XmTRAVERSE_CURRENT
);
2039 } /* ListSelectionCallback */
2041 /* --------------------------------------------------------------------
2042 * Nach einem Doppelklick innerhalb des Listenfelds wird diese Routine
2043 * aufgerufen. Zunaechst einmal wird ganz normal wie bei einem ein-
2044 * fachen Anklicken vorgegangen, danach aber noch der ein spezieller
2045 * Callback aufgerufen.
2047 static void ListDefaultActionCallback(Widget w
, XtPointer pClientData
,
2048 XmAnyCallbackStruct
*OldInfo
)
2050 XmComboBoxWidget cbw
= (XmComboBoxWidget
) pClientData
;
2051 XmComboBoxDefaultActionCallbackStruct info
;
2052 XmStringTable Items
;
2054 ListSelectionCallback(w
, pClientData
, OldInfo
);
2055 info
.reason
= XmCR_DEFAULT_ACTION
;
2056 info
.event
= OldInfo
->event
;
2057 info
.index
= XmComboBoxGetSelectedPos((Widget
) cbw
);
2058 XtVaGetValues(cbw
->combobox
.ListCtrl
, XmNitems
, &Items
, NULL
);
2059 info
.value
= Items
[info
.index
-1];
2060 XtCallCallbacks((Widget
) cbw
, XmNdefaultActionCallback
, (XtPointer
) &info
);
2061 } /* ListDefaultActionCallback */
2064 /* --------------------------------------------------------------------
2065 * Ohweh!! Diese Routine wurde erforderlich, um XmNautomaticSelection
2066 * zu unterstuetzen. Denn wenn der Benutzer in der Liste herumsucht und
2067 * automaticSelection 'True' ist, kommt kein Callback-Aufruf mehr, wenn
2068 * die Maustaste losgelassen wird. Und damit wuessten wir sonst nicht,
2069 * wann die Liste einzuklappen ist! Irgendwie wird das alles mit der
2070 * Zeit immer konfuser und aufwendiger. Wenn das Chaos gequantelt
2071 * sein sollte, dann muss das Chaos-Quant (sog. 'Chaotonen') aber jede
2072 * Menge Chaos transportieren!!!
2074 static void Button1UpInList(Widget w
, XtPointer pClientData
,
2075 XEvent
*Event
, Boolean
*ContDispatch
)
2077 XmComboBoxWidget cbw
= (XmComboBoxWidget
) pClientData
;
2079 if ( Event
->xbutton
.button
== Button1
) {
2080 if ( cbw
->combobox
.AutomaticSelection
)
2081 ShowHideDropDownList(cbw
, Event
, False
);
2083 } /* Button1UpInList */
2085 /* --------------------------------------------------------------------
2086 * Sobald sich irgendetwas im Eingabefeld veraenderte, kommt das
2087 * TextField-Widget zuerst zu uns gelaufen, um sich unser Okay zu
2088 * holen. Bei einer nicht editierbaren Combo-Box wird hierueber die
2089 * Schnellsuche realisiert.
2091 static void EditVerifyCallback(Widget w
, XtPointer pClientData
,
2092 XmTextVerifyCallbackStruct
*info
)
2094 XmComboBoxWidget cbw
= (XmComboBoxWidget
) XtParent(w
);
2097 * Sollte gerade dem Eingabefeld Text aus der Listbox einverleibt
2098 * werden, so duerfen wir hier darueber natuerlich nicht meckern,
2099 * sondern unser <<ok>> dazu geben. (D.h. in diesem Fall haben wir
2100 * kein Recht, zu intervenieren.)
2102 if ( cbw
->combobox
.PassVerification
) {
2103 cbw
->combobox
.PassVerification
= False
;
2108 * Ist es eine Combo-Box, in die kein Text vom Benutzer eingegeben
2109 * werden kann, so wird bei der Eingabe von Zeichen die Schnellsuche
2112 if ( !cbw
->combobox
.Editable
) {
2113 Widget ListBox
= cbw
->combobox
.ListCtrl
;
2114 char WarpCharLow
, WarpCharHigh
;
2116 XmStringTable Items
;
2119 int i
, ItemCount
, Start
;
2124 if ( (info
->text
== NULL
) ||
2125 (info
->text
->length
== 0 ) ) return; /* Hoppala! */
2127 * Nun aus dem Zeichen einen String (Motif-like) basteln und
2128 * in der Listbox danach auf die Suche gehen.
2130 if ( info
->text
->length
> 1 ) {
2131 /* Das ist nun endweder ein normaler Paste, oder aber
2132 * das Ergebnis einer Drag'n'Drop-Operation.
2134 Item
= XmStringCreateSimple(info
->text
->ptr
);
2135 XmComboBoxSelectItem((Widget
) cbw
, Item
, True
);
2138 /* Ansonsten soll nur eine Schnellsuche ausgefuehrt
2139 * werden, der entsprechende Buchstabe ist das einzige
2140 * Zeichen im dem Callback uebergebenen Text.
2142 WarpCharLow
= tolower(*(info
->text
->ptr
));
2143 WarpCharHigh
= toupper(WarpCharLow
);
2145 XtVaGetValues(ListBox
, XmNitemCount
, &ItemCount
,
2148 if ( ItemCount
< 1 ) return;
2149 /* Ermittele, wo's los geht mit der Suche... */
2150 if ( XmListGetSelectedPos(ListBox
,
2151 &SelectionList
, &SelectionCount
) ) {
2152 Start
= *SelectionList
; i
= Start
+ 1;
2153 XtFree((char *)SelectionList
);
2154 } else i
= Start
= 1;
2156 if ( i
> ItemCount
) i
= 1;
2158 while ( i
!= Start
|| Ignore
) {
2160 XmStringGetLtoR(Items
[i
-1], XmSTRING_DEFAULT_CHARSET
,
2162 if ( (strchr(pItem
, WarpCharLow
) == pItem
) ||
2163 (strchr(pItem
, WarpCharHigh
) == pItem
) ) {
2165 TransferToEditCtrl(cbw
, i
, False
);
2166 CallSelectionCBL(cbw
, info
->event
);
2170 if ( ++i
> ItemCount
) i
= 1;
2175 * Wenn das Eingabefeld editierbar ist, dann fragen wir ueber die Callbacks
2176 * nach, ob es genehm ist, den neuen Text einzufuegen.
2178 XtCallCallbacks((Widget
) cbw
, XmNmodifyVerifyCallback
,
2181 } /* EditVerifyCallback */
2183 /* --------------------------------------------------------------------
2184 * Dieser Callback wird immer dann aufgerufen, wenn in einer ComboBox
2185 * mit einem veraenderlichem Eingabefeld der Eingabetext veraendert
2186 * wurde. In diesem Fall suchen wir hier nach einem passenden gleich-
2187 * lautenden Eintrag. Wenn wir einen finden, heben wir ihn in der Liste
2188 * sogleich hervor, ansonsten ist kein Eintrag hervorgehoben.
2190 static void EditChangedCallback(Widget w
, XtPointer pClientDate
,
2191 XmAnyCallbackStruct
*info
)
2193 XmComboBoxWidget cbw
= (XmComboBoxWidget
) XtParent(w
);
2194 XmStringTable Items
;
2200 * Zuerst nach einem passenden Eintrag zum Eingabefeld in der Liste
2203 XtVaGetValues(cbw
->combobox
.EditCtrl
, XmNvalue
, &EditLine
, NULL
);
2204 XtVaGetValues(cbw
->combobox
.ListCtrl
,
2205 XmNitemCount
, &ItemCount
,
2208 EditStr
= XmStringCreateSimple(EditLine
);
2209 XtVaSetValues(cbw
->combobox
.ListCtrl
, XmNselectedItemCount
, 0, NULL
);
2210 if ( ItemCount
< 1 ) return;
2211 for ( i
= 0; i
< ItemCount
; i
++ )
2212 if ( XmStringCompare(Items
[i
], EditStr
) ) {
2213 SetSelectionPos(cbw
, i
+1, False
);
2216 XmStringFree(EditStr
);
2218 * Zum Abschluss noch den Callback aufrufen...
2220 XtCallCallbacks((Widget
) cbw
, XmNvalueChangedCallback
, (XtPointer
) info
);
2221 } /* EditChangedCallback */
2223 /* --------------------------------------------------------------------
2224 * Dieser Callback wird immer dann aufgerufen, wenn in einer ComboBox
2225 * mit einem veraenderlichem Eingabefeld der Cursor bewegt wurde.
2226 * Dieser Callback ist nur fuer echte Fans von Callbacks da...
2228 static void MotionVerifyCallback(Widget w
, XtPointer pClientDate
,
2229 XmTextVerifyCallbackStruct
*info
)
2231 XmComboBoxWidget cbw
= (XmComboBoxWidget
) XtParent(w
);
2233 XtCallCallbacks((Widget
) cbw
, XmNmotionVerifyCallback
, (XtPointer
) info
);
2234 } /* MotionVerifyCallback */
2236 /* --------------------------------------------------------------------
2237 * Bastele einen vollstaendigen Namens- und Klassenbezeichner anhand
2238 * des angegebenen Widgets zusammen.
2240 static void MakeNameAndClass(Widget w
, char *NameBuff
, char *ClassBuff
)
2242 Widget Parent
= XtParent(w
);
2244 if ( Parent
) MakeNameAndClass(Parent
, NameBuff
, ClassBuff
);
2245 if ( XtIsSubclass(w
, applicationShellWidgetClass
) ) {
2246 /* Wenn wir ganz oben angekommen sind, holen wir uns den
2247 * Namen und die Klasse der Applikation selbst und nicht die
2250 String AppName
, AppClass
;
2251 XtGetApplicationNameAndClass(
2252 XtDisplayOfObject(w
), &AppName
, &AppClass
);
2253 strcpy(NameBuff
, AppName
);
2254 strcpy(ClassBuff
, AppClass
);
2256 /* Ansonsten sind wir noch mitten irgendwo in der Hierarchie
2257 * und besorgen uns den Namen und die Klasse dieses Widgets
2259 strcat(NameBuff
, ".");
2260 strcat(NameBuff
, XtName(w
));
2261 strcat(ClassBuff
, ".");
2262 strcat(ClassBuff
, ((CoreClassRec
*) XtClass(w
))->core_class
.class_name
);
2264 } /* MakeNameAndClass */
2266 /* --------------------------------------------------------------------
2267 * Eine einzelne Resource aus der Datenbank herausholen. Diese Resource
2268 * kommt im Allgemeinen immer als String zurueck und muss daher erst
2269 * noch in das gewuenschte Zielformat konvertiert werden.
2271 static Boolean
FetchResource(Widget w
,
2272 char *FullName
, char *FullClass
,
2273 char *RscName
, char *RscClass
,
2275 String
*RepresentationType
)
2278 char *EndOfName
= FullName
+ strlen(FullName
);
2279 char *EndOfClass
= FullClass
+ strlen(FullClass
);
2281 strcat(FullName
, "."); strcat(FullName
, RscName
);
2282 strcat(FullClass
, "."); strcat(FullClass
, RscClass
);
2283 ok
= XrmGetResource(
2284 XtDatabase(XtDisplayOfObject(w
)),
2285 FullName
, FullClass
, RepresentationType
, RscValue
);
2286 /* Wieder den alten Namens- und Klassenrumpf herstellen */
2287 *EndOfName
= 0; *EndOfClass
= 0;
2289 } /* FetchResource */
2291 /* --------------------------------------------------------------------
2292 * Nun folgen diejenigen Routinen, mit denen die Konvertierung in das
2293 * gewuenschte Zielformat einer Resource moeglich ist.
2297 * String XmPIXMAP / XmSTRING --> unsigned char
2298 * String --> Dimension
2299 * String --> XmString
2300 * String --> XmStringTable
2301 * String --> XmFontList
2302 * String --> Pixmap (genauer: Bitmap)
2306 static Boolean
FetchIntResource(Widget w
,
2307 char *FullName
, char *FullClass
,
2308 char *RscName
, char *RscClass
,
2311 XrmValue RscValue
, RscDest
;
2312 String RepresentationType
;
2314 if ( FetchResource(w
, FullName
, FullClass
,
2316 &RscValue
, &RepresentationType
) ) {
2317 RscDest
.size
= sizeof(int);
2318 RscDest
.addr
= (caddr_t
) pInt
;
2319 if ( XtConvertAndStore(w
, RepresentationType
, &RscValue
,
2324 } /* FetchIntResource */
2326 static Boolean
FetchShortResource(Widget w
,
2327 char *FullName
, char *FullClass
,
2328 char *RscName
, char *RscClass
,
2331 XrmValue RscValue
, RscDest
;
2332 String RepresentationType
;
2334 if ( FetchResource(w
, FullName
, FullClass
,
2336 &RscValue
, &RepresentationType
) ) {
2337 RscDest
.size
= sizeof(short);
2338 RscDest
.addr
= (caddr_t
) pShort
;
2339 if ( XtConvertAndStore(w
, RepresentationType
, &RscValue
,
2340 XtRShort
, &RscDest
) )
2344 } /* FetchShortResource */
2346 static Boolean
FetchLabelTypeResource(Widget w
,
2347 char *FullName
, char *FullClass
,
2348 char *RscName
, char *RscClass
,
2349 unsigned char *pUChar
)
2352 String RepresentationType
;
2354 if ( FetchResource(w
, FullName
, FullClass
,
2356 &RscValue
, &RepresentationType
) ) {
2357 if ( strcasecmp((char *) RscValue
.addr
, "XmPIXMAP") == 0 )
2364 } /* FetchLabelTypeResource */
2366 static Boolean
FetchDimensionResource(Widget w
,
2367 char *FullName
, char *FullClass
,
2368 char *RscName
, char *RscClass
,
2369 Dimension
*pDimension
)
2371 XrmValue RscValue
, RscDest
;
2372 String RepresentationType
;
2374 if ( FetchResource(w
, FullName
, FullClass
,
2376 &RscValue
, &RepresentationType
) ) {
2377 RscDest
.size
= sizeof(Dimension
);
2378 RscDest
.addr
= (caddr_t
) pDimension
;
2379 if ( XtConvertAndStore(w
, RepresentationType
, &RscValue
,
2380 XtRDimension
, &RscDest
) )
2384 } /* FetchDimensionResource */
2386 static Boolean
FetchStringResource(Widget w
,
2387 char *FullName
, char *FullClass
,
2388 char *RscName
, char *RscClass
,
2392 String RepresentationType
;
2394 if ( FetchResource(w
, FullName
, FullClass
,
2396 &RscValue
, &RepresentationType
) ) {
2397 *pString
= (char *) RscValue
.addr
;
2401 } /* FetchStringResource */
2403 static Boolean
FetchKeySymResource(Widget w
,
2404 char *FullName
, char *FullClass
,
2405 char *RscName
, char *RscClass
,
2408 XrmValue RscValue
, RscDest
;
2409 String RepresentationType
;
2411 if ( FetchResource(w
, FullName
, FullClass
,
2413 &RscValue
, &RepresentationType
) ) {
2414 RscDest
.size
= sizeof(KeySym
);
2415 RscDest
.addr
= (caddr_t
) pKeySym
;
2416 if ( XtConvertAndStore(w
, RepresentationType
, &RscValue
,
2417 XmRKeySym
, &RscDest
) )
2421 } /* FetchKeySymResource */
2423 static Boolean
FetchXmStringResource(Widget w
,
2424 char *FullName
, char *FullClass
,
2425 char *RscName
, char *RscClass
,
2429 String RepresentationType
;
2431 if ( FetchResource(w
, FullName
, FullClass
,
2433 &RscValue
, &RepresentationType
) ) {
2434 *pString
= XmCvtCTToXmString((char *) RscValue
.addr
);
2438 } /* FetchXmStringResource */
2440 static Boolean
FetchXmStringTableResource(Widget w
,
2441 char *FullName
, char *FullClass
,
2442 char *RscName
, char *RscClass
,
2443 XmStringTable
*pStringTable
,
2447 String RepresentationType
;
2448 String TmpList
, p
, pStart
;
2451 if ( FetchResource(w
, FullName
, FullClass
,
2453 &RscValue
, &RepresentationType
) ) {
2455 * Zuerst eine Kopie erzeugen und dann daraus die Liste
2458 TmpList
= XtNewString((String
)RscValue
.addr
);
2459 if ( TmpList
== NULL
) return False
;
2460 if ( *TmpList
== 0 ) { XtFree(TmpList
); return False
; }
2461 /* Ermittele, wieviele Eintrage in der Liste sind und
2462 * erstelle dann daraus die Liste.
2464 Entries
= 1; p
= TmpList
;
2466 if ( *p
++ == ',' ) ++Entries
;
2467 *pStringTable
= (XmStringTable
)
2468 XtMalloc(Entries
* sizeof(XmString
));
2471 for ( Entry
= 0; Entry
< Entries
; ++Entry
) {
2473 while ( (*p
!= 0) && (*p
!= ',') ) ++p
;
2475 (*pStringTable
)[Entry
] = (XmString
)
2476 XmStringCreateSimple(pStart
);
2478 /* Hier geht ausnahmsweise einmal Rueckgabe vor
2479 * Entschaedigung... hey, das war doch nur ein
2480 * (wenn auch ziemlich miserabler) Scherz
2483 *pTableSize
= Entries
;
2487 } /* FetchXmStringTableResource */
2489 static Boolean
FetchXmFontListResource(Widget w
,
2490 char *FullName
, char *FullClass
,
2491 char *RscName
, char *RscClass
,
2492 XmFontList
*pFontList
)
2494 XrmValue RscValue
, RscDest
;
2495 String RepresentationType
;
2497 if ( FetchResource(w
, FullName
, FullClass
,
2499 &RscValue
, &RepresentationType
) ) {
2500 RscDest
.size
= sizeof(XmFontList
);
2501 RscDest
.addr
= (caddr_t
) pFontList
;
2502 if ( XtConvertAndStore(w
, RepresentationType
, &RscValue
,
2503 XmRFontList
, &RscDest
) )
2507 } /* FetchXmFontListResource */
2509 static Boolean
FetchPixmapResource(Widget w
,
2510 char *FullName
, char *FullClass
,
2511 char *RscName
, char *RscClass
,
2514 XrmValue RscValue
, RscDest
;
2515 String RepresentationType
;
2517 if ( FetchResource(w
, FullName
, FullClass
,
2519 &RscValue
, &RepresentationType
) ) {
2520 RscDest
.size
= sizeof(Pixmap
);
2521 RscDest
.addr
= (caddr_t
) pPixmap
;
2522 if ( XtConvertAndStore(w
, RepresentationType
, &RscValue
,
2523 XtRBitmap
, &RscDest
) )
2527 } /* FetchPixmapResource */
2529 /* --------------------------------------------------------------------
2530 * Waehrend der Initialisierung alle gespiegelten Resourcen, fuer die
2531 * Eintraege in der Resourcen-Datenbank existieren an die passenden
2532 * Kinder-Widgets weiterleiten. Der Trick an der Sache: wir setzen
2533 * die betroffenen Resourcen vie XtSetValues mit uns selbst als Ziel.
2534 * Dadurch bekommt SetValues die Arbeit aufgehalst, die Resourcen den
2535 * richtigen Kindern zuzuordnen...
2541 #define RDimension 3
2544 #define RXmFontList 6
2547 #define RXmStringTable 9
2548 #define RXmItemCount 10
2559 static RESOURCEMIRROR ResourceMirror
[] = {
2560 { XmNblinkRate
, XmCBlinkRate
, RInt
, },
2561 { XmNcolumns
, XmCColumns
, RShort
, },
2562 { XmNmaxLength
, XmCMaxLength
, RInt
, },
2563 { XmNmarginHeight
, XmCMarginHeight
, RDimension
},
2564 { XmNmarginWidth
, XmCMarginWidth
, RDimension
},
2565 { XmNselectThreshold
, XmCSelectThreshold
, RInt
},
2567 { XmNlistMarginHeight
, XmCListMarginHeight
, RDimension
},
2568 { XmNlistMarginWidth
, XmCListMarginWidth
, RDimension
},
2569 { XmNlistSpacing
, XmCListSpacing
, RDimension
},
2570 { XmNitems
, XmCItems
, RXmStringTable
},
2571 { XmNitemCount
, XmCItemCount
, RXmItemCount
},
2573 { XmNmnemonic
, XmCMnemonic
, RKeySym
},
2574 { XmNmnemonicCharSet
, XmCMnemonicCharSet
, RString
},
2575 { XmNlabelString
, XmCLabelString
, RXmString
},
2576 { XmNlabelMarginBottom
, XmCLabelMarginBottom
, RDimension
},
2577 { XmNlabelMarginHeight
, XmCLabelMarginHeight
, RDimension
},
2578 { XmNlabelMarginLeft
, XmCLabelMarginLeft
, RDimension
},
2579 { XmNlabelMarginRight
, XmCLabelMarginRight
, RDimension
},
2580 { XmNlabelMarginTop
, XmCLabelMarginTop
, RDimension
},
2581 { XmNlabelMarginWidth
, XmCLabelMarginWidth
, RDimension
},
2582 { XmNlabelPixmap
, XmCLabelPixmap
, RPixmap
},
2583 { XmNlabelInsensitivePixmap
, XmCLabelInsensitivePixmap
, RPixmap
},
2584 { XmNlabelType
, XmCLabelType
, RLType
},
2585 { XmNlabelFontList
, XmCLabelFontList
, RXmFontList
},
2588 static void InitMirrorResources(XmComboBoxWidget w
)
2590 char FullName
[1024], FullClass
[1024];
2591 int AInt
, TableSize
;
2593 unsigned char AUChar
;
2594 Dimension ADimension
;
2596 XmStringTable AStringTable
;
2598 XmFontList AFontList
;
2601 int i
, size
= XtNumber(ResourceMirror
);
2603 FullName
[0] = 0; FullClass
[0] = 0;
2604 MakeNameAndClass((Widget
) w
, FullName
, FullClass
);
2606 for ( i
=0; i
< size
; i
++ ) {
2607 switch ( ResourceMirror
[i
].Converter
) {
2609 if ( FetchIntResource((Widget
) w
,
2610 FullName
, FullClass
,
2611 ResourceMirror
[i
].Name
, ResourceMirror
[i
].Class
,
2613 XtVaSetValues((Widget
) w
, ResourceMirror
[i
].Name
,
2617 if ( FetchIntResource((Widget
) w
,
2618 FullName
, FullClass
,
2619 ResourceMirror
[i
].Name
, ResourceMirror
[i
].Class
,
2620 &AInt
) && ( AInt
!= 0) )
2621 XtVaSetValues((Widget
) w
, ResourceMirror
[i
].Name
,
2625 if ( FetchShortResource((Widget
) w
,
2626 FullName
, FullClass
,
2627 ResourceMirror
[i
].Name
, ResourceMirror
[i
].Class
,
2629 XtVaSetValues((Widget
) w
, ResourceMirror
[i
].Name
,
2633 if ( FetchLabelTypeResource((Widget
) w
,
2634 FullName
, FullClass
,
2635 ResourceMirror
[i
].Name
, ResourceMirror
[i
].Class
,
2637 XtVaSetValues((Widget
) w
, ResourceMirror
[i
].Name
,
2641 if ( FetchDimensionResource((Widget
) w
,
2642 FullName
, FullClass
,
2643 ResourceMirror
[i
].Name
, ResourceMirror
[i
].Class
,
2645 XtVaSetValues((Widget
) w
, ResourceMirror
[i
].Name
,
2649 if ( FetchXmStringResource((Widget
) w
,
2650 FullName
, FullClass
,
2651 ResourceMirror
[i
].Name
, ResourceMirror
[i
].Class
,
2653 XtVaSetValues((Widget
) w
, ResourceMirror
[i
].Name
,
2656 case RXmStringTable
:
2657 if ( FetchXmStringTableResource((Widget
) w
,
2658 FullName
, FullClass
,
2659 ResourceMirror
[i
].Name
, ResourceMirror
[i
].Class
,
2660 &AStringTable
, &TableSize
) ) {
2661 XtVaSetValues((Widget
) w
,
2662 XmNitems
, (XtPointer
) AStringTable
,
2663 XmNitemCount
, TableSize
, NULL
);
2667 if ( FetchKeySymResource((Widget
) w
,
2668 FullName
, FullClass
,
2669 ResourceMirror
[i
].Name
, ResourceMirror
[i
].Class
,
2671 XtVaSetValues((Widget
) w
, ResourceMirror
[i
].Name
,
2675 if ( FetchStringResource((Widget
) w
,
2676 FullName
, FullClass
,
2677 ResourceMirror
[i
].Name
, ResourceMirror
[i
].Class
,
2679 XtVaSetValues((Widget
) w
, ResourceMirror
[i
].Name
,
2683 if ( FetchPixmapResource((Widget
) w
,
2684 FullName
, FullClass
,
2685 ResourceMirror
[i
].Name
, ResourceMirror
[i
].Class
,
2687 XtVaSetValues((Widget
) w
, ResourceMirror
[i
].Name
,
2689 if ( strcmp(ResourceMirror
[i
].Name
, XmNlabelPixmap
) == 0 )
2690 w
->combobox
.ConvertBitmapToPixmap
= True
;
2692 w
->combobox
.ConvertBitmapToPixmapInsensitive
= True
;
2696 if ( FetchXmFontListResource((Widget
) w
,
2697 FullName
, FullClass
,
2698 ResourceMirror
[i
].Name
, ResourceMirror
[i
].Class
,
2700 XtVaSetValues((Widget
) w
, ResourceMirror
[i
].Name
,
2705 } /* InitMirrorResources */
2707 /* --------------------------------------------------------------------
2708 * Wandelt ein 1-Bit tiefes Bitmap in ein n-Bit tiefes Pixmap um, dass
2709 * die gleiche Tiefe besitzt, wie der Bildschirm, auf dem das Pixmap
2710 * spaeter erscheinen soll.
2712 static Pixmap
BitmapToPixmap(XmComboBoxWidget w
,
2713 String Resource
, GC ColorGC
)
2715 Pixmap LabelPixmap
, LabelBitmap
;
2716 Display
*display
= XtDisplay(w
);
2719 unsigned int PixW
, PixH
, PixBW
, PixDepth
;
2721 XtVaGetValues(w
->combobox
.LabelCtrl
, Resource
, &LabelBitmap
, NULL
);
2722 XGetGeometry(display
, LabelBitmap
, &root
,
2723 &PixX
, &PixY
, &PixW
, &PixH
, &PixBW
, &PixDepth
);
2724 LabelPixmap
= XCreatePixmap(
2725 display
, RootWindowOfScreen(XtScreen(w
)),
2727 (w
->combobox
.LabelCtrl
)->core
.depth
);
2728 XCopyPlane(display
, LabelBitmap
, LabelPixmap
,
2729 ColorGC
, 0, 0, PixW
, PixH
, 0, 0, 1);
2730 XtVaSetValues(w
->combobox
.LabelCtrl
, Resource
, LabelPixmap
, NULL
);
2731 XFreePixmap(display
, LabelBitmap
);
2733 } /* BitmapToPixmap */
2735 /* --------------------------------------------------------------------
2736 * Alles initialisieren, sobald das Widget eingerichtet wird. Das sagt
2737 * sich hier so einfach, ist es aber *definitiv* nicht!!!!
2739 static void Initialize(Widget request
, XmComboBoxWidget newW
,
2740 ArgList wargs
, Cardinal
*ArgCount
)
2742 Dimension width
, height
, dummy
;
2748 * Da zu allem Ueberfluss die einzelnen Instanzen einer XmComboBox
2749 * auf verschiedenen Displays auftauchen koennen, wird hier:
2750 * 1. pro Widget ein eigener Cursor erzeugt (benoetigt fuer die Liste)
2751 * 2. pro Widget (hier = pro Applikation) die benoetigte Action-Routine
2752 * registiert. Doppelte Registrierung macht dem Toolkit nichts aus, da es
2753 * dann eine evtl. aeltere Definition loescht.
2755 XtAppAddActions(XtWidgetToApplicationContext((Widget
) newW
),
2756 actions
, XtNumber(actions
));
2758 /* Allgemeine Initialisierungen... */
2759 newW
->combobox
.ConvertBitmapToPixmap
= False
;
2760 newW
->combobox
.ConvertBitmapToPixmapInsensitive
= False
;
2762 newW
->combobox
.LastSelection
= 0;
2764 newW
->combobox
.InInit
= True
;
2767 * Das folgende Problem mit der Kontrolle, ob sich das Widget absolut auf
2768 * dem Bildschirm verschoben hat, trifft uns nur, wenn die Liste nicht
2769 * dauernd auf dem Bildschirm erscheint:
2770 * Lass' dich benachrichtigen, sobald dieses Widget in irgendeiner
2771 * Form bewegt wird -- und sei es nur, dass das gesamte Applikations-
2772 * fenster umhergeschoben wurde. Um die Benachrichtigung ueberhaupt
2773 * zu erreichen, ist es erforderlich, sich benachrichtigen zu lassen,
2774 * sobald die naechste Shell (oder ein Nachkomme) im Widget-Instanzen-
2775 * Baum verschoben wurde.
2777 if ( !newW
->combobox
.StaticList
) {
2779 while ( !XtIsSubclass(w
, shellWidgetClass
) )
2781 newW
->combobox
.MyNextShell
= w
;
2782 XtAddEventHandler(w
,
2783 StructureNotifyMask
| FocusChangeMask
,
2784 False
, (XtEventHandler
) ShellCallback
,
2788 /* Richte nun alle zu diesem Widget gehoerenden Kinder ein, als da
2790 * 1 x editierbares Eingabefeld
2791 * 1 x ein Pfeil nach unten
2792 * 1 x ein Schriftfeld
2794 newW
->combobox
.EditCtrl
= XtVaCreateManagedWidget(
2795 "edit", xmTextFieldWidgetClass
, (Widget
) newW
,
2796 XmNverifyBell
, False
,
2798 XtAddCallback(newW
->combobox
.EditCtrl
,
2799 XmNlosingFocusCallback
,
2800 (XtCallbackProc
) EditFocusCallback
, NULL
);
2801 XtAddCallback(newW
->combobox
.EditCtrl
,
2802 XmNmodifyVerifyCallback
,
2803 (XtCallbackProc
) EditVerifyCallback
, NULL
);
2804 XtAddCallback(newW
->combobox
.EditCtrl
,
2805 XmNvalueChangedCallback
,
2806 (XtCallbackProc
) EditChangedCallback
, NULL
);
2807 XtAddCallback(newW
->combobox
.EditCtrl
,
2809 (XtCallbackProc
) HelpCallback
,
2811 XtAddCallback(newW
->combobox
.EditCtrl
,
2812 XmNactivateCallback
,
2813 (XtCallbackProc
) ActivateCallback
,
2815 if ( newW
->combobox
.Editable
)
2816 XtAddCallback(newW
->combobox
.EditCtrl
,
2817 XmNmotionVerifyCallback
,
2818 (XtCallbackProc
) MotionVerifyCallback
,
2820 /* Neue Translations fuer das Eingabefeld aufnehmen */
2821 XtOverrideTranslations(newW
->combobox
.EditCtrl
,
2822 NewEditTranslations
);
2823 if ( !newW
->combobox
.Editable
) {
2824 XtOverrideTranslations(newW
->combobox
.EditCtrl
,
2825 NewEditTranslationsNE
);
2826 XtVaSetValues(newW
->combobox
.EditCtrl
,
2827 XmNcursorPositionVisible
, False
, NULL
);
2830 XtOverrideTranslations(newW
->combobox
.EditCtrl
,
2831 NewListTranslations
); /* Btn2Dwn aus! */
2835 newW
->combobox
.ArrowCtrl
= XtVaCreateManagedWidget(
2836 "arrow", xmArrowButtonWidgetClass
, (Widget
) newW
,
2837 XmNarrowDirection
, XmARROW_DOWN
,
2838 XmNtraversalOn
, False
,
2839 XmNnavigationType
, XmNONE
,
2841 XmNhighlightThickness
, 0,
2843 XmRemoveTabGroup(newW
->combobox
.ArrowCtrl
);
2844 if ( newW
->combobox
.StaticList
) {
2845 XtVaSetValues(newW
->combobox
.ArrowCtrl
,
2846 XmNmappedWhenManaged
, False
, NULL
);
2848 XtAddEventHandler(newW
->combobox
.ArrowCtrl
,
2849 EnterWindowMask
| LeaveWindowMask
,
2850 False
, (XtEventHandler
) ArrowCrossingCallback
,
2852 XtAddCallback(newW
->combobox
.ArrowCtrl
,
2853 XmNactivateCallback
,
2854 (XtCallbackProc
) ArrowCallback
, NULL
);
2855 XtAddCallback(newW
->combobox
.ArrowCtrl
,
2857 (XtCallbackProc
) ArrowCallback
, NULL
);
2858 XtAddCallback(newW
->combobox
.ArrowCtrl
,
2860 (XtCallbackProc
) HelpCallback
,
2865 newW
->combobox
.LabelCtrl
= XtVaCreateWidget(
2866 "label", xmLabelWidgetClass
, (Widget
) newW
,
2867 XmNstringDirection
, newW
->manager
.string_direction
,
2869 if ( newW
->combobox
.ShowLabel
) {
2870 XtManageChild((Widget
) newW
->combobox
.LabelCtrl
);
2871 XtAddCallback(newW
->combobox
.LabelCtrl
,
2873 (XtCallbackProc
) HelpCallback
,
2878 * Zuerst noch die Shell erzeugen, die so einfach mir nichts dir nichts
2879 * frei auf dem Bildschirm herumschweben kann und damit das Ausklappen
2880 * der Liste erst ermoeglicht -- und uns allerhand Scherereien bereitet!
2881 * War das ein bloeder Fehler in Motif 1.2! Diese Version vertraegt ab-
2882 * solut keine ShellWidgetClass noch overrideShellWidgetClass!!!! Naja,
2883 * mit einer vendorShellWidgetClass laesst sich aber exakt der gleiche
2884 * Effekt erreichen. NEU: vor allem funktioniert dann endlich auch
2886 * Noch neuer: Wenn die Liste dauerhaft angezeigt werden muss, entfaellt
2887 * diese Shell zwangslaeufig. Dann ist das Listenfeld ein direktes Kind
2890 if ( !newW
->combobox
.StaticList
) {
2891 newW
->combobox
.PopupShell
= XtVaCreateWidget(
2892 "combobox_shell", vendorShellWidgetClass
, (Widget
) newW
,
2893 XmNoverrideRedirect
, True
,
2894 XmNsaveUnder
, False
,
2895 XmNallowShellResize
, True
,
2897 XtAddEventHandler(newW
->combobox
.PopupShell
,
2898 EnterWindowMask
| LeaveWindowMask
,
2899 False
, (XtEventHandler
) OverrideShellCallback
,
2903 * Sieht ja pervers nach einer Rekursion aus...daher: OBACHT!
2905 newW
->combobox
.PopupShell
= (Widget
) newW
;
2909 * Nun kommt die Drop-Down-Liste an die Reihe. Die Liste muss dabei
2910 * mit einer Convenience-Funktion erstellt werden, damit ein Rollbalken
2911 * 'dran ist und das Ganze wird dann in eine Override-Shell gepackt.
2912 * Nicht zu vergessen ist der XtManageChild-Aufruf, damit die Liste
2913 * sofort nach dem Aufklappen der Shell sichtbar wird.
2915 XtSetArg(args
[n
], XmNselectionPolicy
, newW
->combobox
.SelectionPolicy
); n
++;
2917 if ( !newW
->combobox
.StaticList
) {
2919 * Es gibt halt so eine ganze Reihe von Einstellungen, die koennen nicht
2920 * veraendert werden, wenn das Listenfeld nur bei Bedarf ausgeklappt wird.
2922 XtSetArg(args
[n
], XmNhighlightThickness
, 0); n
++;
2924 XtSetArg(args
[n
], XmNlistSizePolicy
,
2925 newW
->combobox
.ListSizePolicy
); n
++;
2926 XtSetArg(args
[n
], XmNscrollBarDisplayPolicy
,
2927 newW
->combobox
.ScrollBarDisplayPolicy
); n
++;
2929 XtSetArg(args
[n
], XmNautomaticSelection
,
2930 newW
->combobox
.AutomaticSelection
); n
++;
2931 XtSetArg(args
[n
], XmNvisibleItemCount
,
2932 newW
->combobox
.VisibleItemCount
); n
++;
2933 newW
->combobox
.ListCtrl
= XmCreateScrolledList(
2934 newW
->combobox
.PopupShell
, "list",
2938 * Fuer den Fall, dass die Liste in einer eigenen Shell steckt und daher frei
2939 * auf dem Bildschirm herumschweben kann, sollten wir sicherheitshalber die
2940 * Tastaturbedienung (Fokus) abschalten, um Probleme zu vermeiden (jedenfalls
2943 if ( !newW
->combobox
.StaticList
) {
2944 XtVaSetValues(newW
->combobox
.ListCtrl
,
2945 XmNtraversalOn
, False
, NULL
);
2946 XtVaSetValues(XtParent(newW
->combobox
.ListCtrl
),
2947 XmNtraversalOn
, False
, NULL
);
2949 if ( !newW
->combobox
.Editable
) {
2950 XtVaSetValues(XtParent(newW
->combobox
.ListCtrl
),
2951 XmNtraversalOn
, False
, NULL
);
2952 XmRemoveTabGroup(newW
->combobox
.ListCtrl
);
2956 XtManageChild(newW
->combobox
.ListCtrl
);
2957 XtAddCallback(newW
->combobox
.ListCtrl
,
2958 XmNsingleSelectionCallback
,
2959 (XtCallbackProc
) ListSelectionCallback
,
2961 XtAddCallback(newW
->combobox
.ListCtrl
,
2962 XmNbrowseSelectionCallback
,
2963 (XtCallbackProc
) ListSelectionCallback
,
2965 XtAddCallback(newW
->combobox
.ListCtrl
,
2966 XmNdefaultActionCallback
,
2967 (XtCallbackProc
) ListDefaultActionCallback
,
2969 XtAddCallback(newW
->combobox
.ListCtrl
,
2971 (XtCallbackProc
) HelpCallback
,
2974 XtAddEventHandler(newW
->combobox
.ListCtrl
,
2976 False
, (XtEventHandler
) Button1UpInList
,
2980 XtOverrideTranslations(newW
->combobox
.ListCtrl
,
2981 NewListTranslations
);
2983 if ( newW
->combobox
.StaticList
&& newW
->combobox
.Editable
)
2984 XtOverrideTranslations(newW
->combobox
.ListCtrl
,
2985 NewListTranslationsE
);
2987 /* Jetzt wird es dann erst richtig spannend... Zuerst alle evtl.
2988 * in der Resource-Datenbank abgelegten Resourcen an die Kinder
2989 * weitergeben. Danach die uebergebenen Parameter ebenfalls an
2990 * die Kinder weiterreichen und schliesslich das Layout ermitteln.
2992 InitMirrorResources(newW
);
2993 UpdateColors(newW
, -1);
2994 SetValues(newW
, newW
, newW
, wargs
, ArgCount
);
2996 if ( newW
->combobox
.ConvertBitmapToPixmap
)
2997 newW
->combobox
.LabelPixmap
=
2998 BitmapToPixmap(newW
, XmNlabelPixmap
,
2999 ((XmLabelRec
*) newW
->combobox
.LabelCtrl
)->
3001 if ( newW
->combobox
.ConvertBitmapToPixmapInsensitive
)
3002 newW
->combobox
.LabelInsensitivePixmap
=
3003 BitmapToPixmap(newW
, XmNlabelInsensitivePixmap
,
3004 ((XmLabelRec
*) newW
->combobox
.LabelCtrl
)->
3005 label
.insensitive_GC
);
3007 DefaultGeometry(newW
, &width
, &height
, &dummy
, &dummy
);
3008 if ( newW
->core
.width
== 0 )
3009 newW
->core
.width
= width
;
3010 if ( newW
->core
.height
== 0 )
3011 newW
->core
.height
= height
;
3014 * Falls wir keine Fontliste besitzen, dann nehmen wir die von
3015 * dem Eingabefeld...
3017 if ( newW
->combobox
.Font
== NULL
) {
3018 XtVaGetValues(newW
->combobox
.EditCtrl
,
3019 XmNfontList
, &newW
->combobox
.Font
, NULL
);
3020 XtVaSetValues(newW
->combobox
.ListCtrl
,
3021 XmNfontList
, newW
->combobox
.Font
, NULL
);
3023 XtVaSetValues(newW
->combobox
.ListCtrl
,
3024 XmNfontList
, newW
->combobox
.Font
, NULL
);
3025 XtVaSetValues(newW
->combobox
.EditCtrl
,
3026 XmNfontList
, newW
->combobox
.Font
, NULL
);
3030 * Initialisiere alle Statusflaggen, die mit diesem unseligen Focus-
3031 * problem zu tun haben...
3033 newW
->combobox
.ListVisible
= False
;
3034 newW
->combobox
.IgnoreFocusOut
= False
;
3035 newW
->combobox
.PendingFocusOut
= False
;
3036 newW
->combobox
.PendingOverrideInOut
= False
;
3038 newW
->combobox
.PassVerification
= False
;
3041 * Jooa... bei der OSF pennen die wohl komplett?! Zusammen mit Form-
3042 * Widgets gibt das wohl immer Aerger...daher hier ein DoLayout()
3043 * aufrufen, damit Eingabefeld und Pfeil sowie das Listenfeld an der
3044 * richtigen Stelle sitzen!
3048 * Endlich fertig mit der Initialisierung. Das hier ist aber auch
3049 * wirklich viel Arbeit fuer so ein Widget!
3051 newW
->combobox
.InInit
= False
;
3054 /* --------------------------------------------------------------------
3055 * Diese Funktionen bitte nur im aeussersten Notfall benutzen, da sie
3056 * die Abstraktion dieser neuen Klasse umgehen und Informationen ueber
3057 * den internen Aufbau voraussetzen.
3059 Widget
XmComboBoxGetEditWidget(Widget w
)
3061 return ((XmComboBoxWidget
) w
)->combobox
.EditCtrl
;
3062 } /* XmComboBoxGetEditWidget */
3064 Widget
XmComboBoxGetListWidget(Widget w
)
3066 return ((XmComboBoxWidget
) w
)->combobox
.ListCtrl
;
3067 } /* XmComboBoxGetListWidget */
3069 Widget
XmComboBoxGetLabelWidget(Widget w
)
3071 return ((XmComboBoxWidget
) w
)->combobox
.LabelCtrl
;
3072 } /* XmComboBoxGetLabelWidget */
3075 /* --------------------------------------------------------------------
3076 * Sobald sich im Listenfeld Eintraege veraenderten, sei es, dass sie
3077 * geloescht wurden, sei es, dass sie veraendert wurden, so muss hier
3078 * gegebenenfalls auch der Text im Eingabefeld angepasst werden.
3079 * Letzteres betrifft aber nur Combo-Boxen mit nicht editierbarem
3080 * Eingabefeld. In jedem Fall wird aber bei jeder Combo-Box-Type in
3081 * dem Fall, dass ein Eintrag geloescht wird, der darauffolgende
3082 * Eintrag markiert. Eigentlich ist dieses nur eine nette Geste
3083 * gegenueber dem Benutzer...
3086 * w Combo-Box-Widget
3087 * Index Index auf denjenigen Eintrag der sich geaendert
3088 * hat, oder der geloescht wurde.
3089 * Deleted Zeigt an, ob der Eintrag geloescht wurde (True)
3090 * oder sich nur veraenderte (False)
3092 static int UpdateComboBox(XmComboBoxWidget w
, int Index
, Boolean Deleted
)
3094 int OldIndex
, ItemCount
;
3096 OldIndex
= XmComboBoxGetSelectedPos((Widget
) w
);
3097 if ( OldIndex
== Index
) {
3098 /* Es betrifft den Eintrag, der auch momentan ausgewaehlt ist.
3099 * Sollte er geloescht werden, so nimm' (soweit vorhanden) den
3100 * naechsten Eintrag, wurde er ausgetauscht, so lass ihn ausge-
3104 XtVaGetValues(w
->combobox
.ListCtrl
,
3105 XmNitemCount
, &ItemCount
, NULL
);
3106 if ( ItemCount
!= 0 ) {
3107 if ( Index
>= ItemCount
) Index
= ItemCount
;
3108 /* Markieren des Eintrags, ohne jedoch jetzt schon
3109 * den Eintrag in die Eingabezeile zu kopieren.
3111 SetSelectionPos(w
, Index
, False
);
3115 /* Das Problem betrifft uns nur bei nicht editierbaren Combo-Boxen
3116 * im vollen Umfang. Denn dann muss auch der Text im Eingabefeld
3117 * veraendert werden.
3119 if ( !w
->combobox
.Editable
) {
3120 TransferToEditCtrl(w
, Index
, False
);
3124 } /* UpdateComboBox */
3127 /* --------------------------------------------------------------------
3128 * Die Eintragsposition finden, an der der Eintrag sortiert stehen
3129 * muesste. Naja, es wurde ja 'mal langsam Zeit, diese Routine etwas
3130 * aufzupolieren, damit sie schneller wird.
3132 static int FindSortedItemPos(XmComboBoxWidget w
, XmString item
)
3134 Widget ListBox
= w
->combobox
.ListCtrl
;
3135 XmStringTable Items
;
3136 int ItemCount
, index
, Left
, Right
, Result
;
3137 char *pItemText
, *pCompareText
;
3139 XmComboBoxSortingCallbackStruct data
;
3141 XtVaGetValues(ListBox
, XmNitems
, &Items
,
3142 XmNitemCount
, &ItemCount
, NULL
);
3143 if ( ItemCount
== 0 ) return 1;
3146 * Moechte das Programm die Kontrolle ueber den Sortiervorgang
3147 * uebernehmen? Dann bereite alles vor...
3149 ExternSort
= XtHasCallbacks((Widget
) w
, XmNsortingCallback
) ==
3152 data
.reason
= XmCR_SORTING
;
3154 data
.operation
= XmOP_INIT
;
3156 XtCallCallbacks((Widget
) w
, XmNsortingCallback
, (XtPointer
) &data
);
3158 XmStringGetLtoR(item
, XmSTRING_DEFAULT_CHARSET
, &pCompareText
);
3160 Left
= 0; Right
= ItemCount
- 1;
3162 index
= (Left
+ Right
) / 2;
3164 data
.operation
= XmOP_COMPARE
;
3165 data
.item
= Items
[index
];
3167 XtCallCallbacks((Widget
) w
, XmNsortingCallback
, (XtPointer
) &data
);
3168 Result
= data
.result
;
3170 XmStringGetLtoR(Items
[index
], XmSTRING_DEFAULT_CHARSET
, &pItemText
);
3171 Result
= strcmp(pCompareText
, pItemText
);
3174 if ( Result
< 0 ) Right
= index
- 1;
3175 else if ( Result
> 0 ) Left
= index
+ 1;
3176 } while ( (Result
!= 0) && (Left
<= Right
) );
3179 * Nach Gebrauch wieder alles aufraeumen (bei einer externen Sortierung
3180 * muss das das Programm uebernehmen!)
3183 data
.operation
= XmOP_DONE
;
3184 XtCallCallbacks((Widget
) w
, XmNsortingCallback
, (XtPointer
) &data
);
3186 XtFree(pCompareText
);
3189 return index
+ 1; /* Beachte, dass Indizes mit 1 beginnen! */
3191 return index
+ 2; /* Beachte, dass Indizes mit 1 beginnen! */
3192 } /* FindSortedItemPos */
3194 /* --------------------------------------------------------------------
3195 * Kontrolliere, ob es sich ueberhaupt um eine Combo-Box (bzw. einen
3196 * hypothetischen Nachkommen) handelt -- ansonsten mecker kraeftig
3199 * True, falls wir hier ein falsches Widget untergejubelt bekommen!
3201 static Boolean
CheckComboBox(Widget w
, char *pFuncName
)
3206 #if (XmVersion >= 2000)
3207 return False
; /* temporary workaround */
3209 if ( XmIsComboBox(w
) ) return False
;
3210 pWName
= XrmQuarkToString(w
->core
.xrm_name
);
3212 "Warning: %s called on widget named %s beeing \
3213 not a descendant of class XmComboBox!",
3218 } /* CheckComboBox */
3220 /* --------------------------------------------------------------------
3221 * Saemtliche Interface-Routinen zur Combo-Box
3223 /* Zunaechst alles fuer die Listbox */
3224 #define ListBox (((XmComboBoxWidget) w)->combobox.ListCtrl)
3225 #define EditBox (((XmComboBoxWidget) w)->combobox.EditCtrl)
3226 #define ComboBox ((XmComboBoxWidget) w)
3229 * So angepasst, dass bei doppelt auftretenden Eintraegen, der
3230 * alte Eintrag weiterhin markiert bleibt. Diese Massnahme soll
3231 * eigentlich nur verhindern, dass zufaellig zwei Eintraege
3232 * markiert sind, falls nach der Anwahl eines Eintrages ein zweiter
3233 * gleichlautender Eintrag hinzugefuegt wurde.
3234 * Was hier die reine Lehre (oder war das die Leere?) anbetrifft:
3235 * in einer Combo-Box sollten sich sowieso nie gleichlautende
3236 * Eintraege befinden, da sie dort unsinnig sind und den Benutzer
3239 void XmComboBoxAddItem(Widget w
, XmString item
, int pos
)
3241 int OldIndex
= XmComboBoxGetSelectedPos(w
);
3243 if ( CheckComboBox(w
, "XmComboBoxAddItem") ) return;
3244 if ( ComboBox
->combobox
.Sorted
)
3245 pos
= FindSortedItemPos(ComboBox
, item
);
3246 XmListAddItem(ListBox
, item
, pos
);
3247 if ( OldIndex
!= XmComboBoxGetSelectedPos(w
) )
3248 /* Hier SetSelectionPos() statt XmComboBoxSelectPos(),
3249 * da der Text nicht in das Eingabefeld uebertragen werden
3252 SetSelectionPos(ComboBox
, OldIndex
, False
);
3253 } /* XmComboBoxAddItem */
3255 * Hier gilt das bereits oben gesagte (siehe XmComboBoxAddItem).
3256 * Bei sortierten Listboxen wird die Sortierung beim Gebrauch dieser
3257 * Funktion zerstoert!
3259 void XmComboBoxAddItems(Widget w
, XmString
*items
, int item_count
, int pos
)
3261 int OldIndex
= XmComboBoxGetSelectedPos(w
);
3263 if ( CheckComboBox(w
, "XmComboBoxAddItems") ) return;
3264 XmListAddItems(ListBox
, items
, item_count
, pos
);
3265 if ( OldIndex
!= XmComboBoxGetSelectedPos(w
) )
3266 /* Siehe Anmerkung in XmComboBoxAddItem */
3267 SetSelectionPos(ComboBox
, OldIndex
, False
);
3268 } /* XmComboBoxAddItems */
3270 void XmComboBoxAddItemUnselected(Widget w
, XmString item
, int pos
)
3271 { XmListAddItemUnselected(ListBox
, item
, pos
); }
3274 * Da bei den folgenden Routinen jeweils ein oder mehrere Eintraege
3275 * geloescht oder veraendert werden, muss gegebenefalls das Eingabe-
3276 * feld bei nicht editierbaren Combo-Boxen auf Vordermann gebracht
3279 void XmComboBoxDeleteItem(Widget w
, XmString item
)
3281 int Index
= XmListItemPos(ListBox
, item
);
3283 if ( CheckComboBox(w
, "XmComboBoxDeleteItem") ) return;
3284 if ( Index
) XmComboBoxDeletePos(w
, Index
);
3285 } /* XmComboBoxDeleteItem */
3287 void XmComboBoxDeleteItems(Widget w
, XmString
*items
, int item_count
)
3291 if ( CheckComboBox(w
, "XmComboBoxDeleteItems") ) return;
3292 for ( i
= 0; i
< item_count
; i
++ )
3293 XmListDeleteItem(w
, items
[i
]);
3294 } /* XmComboBoxDeleteItems */
3296 void XmComboBoxDeletePos(Widget w
, int pos
)
3298 int OldIndex
= XmComboBoxGetSelectedPos(w
);
3300 if ( CheckComboBox(w
, "XmComboBoxDeletePos") ) return;
3301 XmListDeletePos(ListBox
, pos
);
3302 if ( pos
== OldIndex
) UpdateComboBox(ComboBox
, pos
, True
);
3303 } /* XmComboBoxDeletePos */
3305 void XmComboBoxDeleteItemsPos(Widget w
, int item_count
, int pos
)
3309 if ( CheckComboBox(w
, "XmComboBoxDeleteItemsPos") ) return;
3310 for ( i
= 0; i
< item_count
; i
++ )
3311 XmComboBoxDeletePos(w
, pos
++);
3312 } /* XmComboBoxDeleteItemsPos */
3314 void XmComboBoxDeleteAllItems(Widget w
)
3316 if ( CheckComboBox(w
, "XmComboBoxAllDeleteItems") ) return;
3317 XmListDeleteAllItems(ListBox
);
3318 UpdateComboBox(ComboBox
, 0, True
);
3319 } /* XmComboBoxDeleteAllItems */
3322 * Werden Eintraege ausgetauscht, so heisst es fuer uns, auch hierbei
3323 * auf der Hut zu sein.
3325 void XmComboBoxReplaceItems(Widget w
, XmString
*old_items
, int item_count
, XmString
*new_items
)
3327 if ( CheckComboBox(w
, "XmComboBoxReplaceItems") ) return;
3328 XmListReplaceItems(ListBox
, old_items
, item_count
, new_items
);
3329 UpdateComboBox(ComboBox
, XmComboBoxGetSelectedPos(w
), False
);
3330 } /* XmComboBoxReplaceItems */
3332 void XmComboBoxReplaceItemsPos(Widget w
, XmString
*new_items
, int item_count
, int position
)
3334 int OldIndex
= XmComboBoxGetSelectedPos(w
);
3336 if ( CheckComboBox(w
, "XmComboBoxReplaceItemsPos") ) return;
3337 XmListReplaceItemsPos(ListBox
, new_items
, item_count
, position
);
3338 if ( (OldIndex
>= position
) && (OldIndex
< position
+ item_count
) )
3339 UpdateComboBox(ComboBox
, OldIndex
, False
);
3340 } /* XmComboBoxReplaceItemsPos */
3342 Boolean
XmComboBoxItemExists(Widget w
, XmString item
)
3344 if ( CheckComboBox(w
, "XmComboBoxItemExists") ) return False
;
3345 return XmListItemExists(ListBox
, item
);
3346 } /* XmComboBoxItemExists */
3348 int XmComboBoxItemPos(Widget w
, XmString item
)
3350 if ( CheckComboBox(w
, "XmComboBoxItemPos") ) return 0;
3351 return XmListItemPos(ListBox
, item
);
3352 } /* XmComboBoxItemPos */
3354 Boolean
XmComboBoxGetMatchPos(Widget w
, XmString item
, int **pos_list
, int *pos_count
)
3356 if ( CheckComboBox(w
, "XmComboBoxGetMatchPos") ) return False
;
3357 return XmListGetMatchPos(ListBox
, item
, pos_list
, pos_count
);
3358 } /* XmComboBoxGetMatchPos */
3361 * Sobald ein anderer Eintrag in der Listbox ausgewaehlt werden soll,
3362 * muessen wir hier helfend eingreifen.
3364 void XmComboBoxSelectPos(Widget w
, int pos
, Boolean notify
)
3368 if ( CheckComboBox(w
, "XmComboBoxSelectPos") ) return;
3369 index
= SetSelectionPos(ComboBox
, pos
, notify
);
3370 if ( index
) TransferToEditCtrl(ComboBox
, index
, False
);
3371 } /* XmComboBoxSelectPos */
3374 * dto. analog zu XmComboBoxSelectPos, nur statt des Index wird der
3375 * Eintragstext angegeben, um einen Eintrag in der Listbox zu
3378 void XmComboBoxSelectItem(Widget w
, XmString item
, Boolean notify
)
3382 if ( CheckComboBox(w
, "XmComboBoxSelectItem") ) return;
3383 XmListSelectItem(ListBox
, item
, notify
);
3384 index
= SetSelectionPos(ComboBox
, XmComboBoxGetSelectedPos(w
), False
);
3385 if ( index
) TransferToEditCtrl(ComboBox
, index
, False
);
3386 } /* XmComboBoxSelectItem */
3389 * Geaendert gegenueber dem ListBox-Pendant! Da in einer Combo-Box die
3390 * Liste nur maximal einen ausgewaehlten Eintrag besitzt, macht die
3391 * 'alte' Funktionalitaet von XmListGetSelectedPos ziemlich wenig Sinn.
3392 * Die neue Routine liefert statt dessen direkt den Index des aus-
3393 * gewaehlten Eintrages oder 0 zurueck.
3395 int XmComboBoxGetSelectedPos(Widget w
)
3397 int *SelectionList
, SelectionCount
, SelectionIndex
;
3399 if ( CheckComboBox(w
, "XmComboBoxGetSelectedPos") ) return 0;
3400 if ( XmListGetSelectedPos(ListBox
,
3401 &SelectionList
, &SelectionCount
) ) {
3402 SelectionIndex
= *SelectionList
;
3403 XtFree((char *)SelectionList
);
3404 } else SelectionIndex
= 0;
3405 return SelectionIndex
;
3406 } /* XmComboBoxGetSelectedPos */
3410 void XmComboBoxClearSelection(Widget w
, Time time
)
3412 XmTextFieldClearSelection(EditBox
, time
);
3413 } /* XmComboBoxClearSelection */
3415 Boolean
XmComboBoxCopy(Widget w
, Time time
)
3417 return XmTextFieldCopy(EditBox
, time
);
3418 } /* XmComboBoxCopy */
3420 Boolean
XmComboBoxCut(Widget w
, Time time
)
3422 return XmTextFieldCut(EditBox
, time
);
3423 } /* XmComboBoxCut */
3425 XmTextPosition
XmComboBoxGetInsertionPosition(Widget w
)
3427 return XmTextFieldGetInsertionPosition(EditBox
);
3428 } /* XmComboBoxGetInsertionPosition */
3430 XmTextPosition
XmComboBoxGetLastPosition(Widget w
)
3432 return XmTextFieldGetLastPosition(EditBox
);
3433 } /* XmComboBoxGetLastPosition */
3435 int XmComboBoxGetMaxLength(Widget w
)
3437 return XmTextFieldGetMaxLength(EditBox
);
3438 } /* XmComboBoxGetMaxLength */
3440 char * XmComboBoxGetSelection(Widget w
)
3442 return XmTextFieldGetSelection(EditBox
);
3443 } /* XmComboBoxGetSelection */
3445 Boolean
XmComboBoxGetSelectionPosition(Widget w
, XmTextPosition
*left
,
3446 XmTextPosition
*right
)
3448 return XmTextFieldGetSelectionPosition(EditBox
, left
, right
);
3449 } /* XmComboBoxGetSelectionPosition */
3451 char * XmComboBoxGetString(Widget w
)
3453 return XmTextFieldGetString(EditBox
);
3454 } /* XmComboBoxGetString */
3456 void XmComboBoxInsert(Widget w
, XmTextPosition position
, char *value
)
3458 XmTextFieldInsert(EditBox
, position
, value
);
3459 } /* XmComboBoxInsert */
3461 Boolean
XmComboBoxPaste(Widget w
)
3463 return XmTextFieldPaste(EditBox
);
3464 } /* XmComboBoxPaste */
3466 Boolean
XmComboBoxRemove(Widget w
)
3468 return XmTextFieldRemove(EditBox
);
3469 } /* XmComboBoxRemove */
3471 void XmComboBoxReplace(Widget w
, XmTextPosition from_pos
,
3472 XmTextPosition to_pos
, char *value
)
3474 XmTextFieldReplace(EditBox
, from_pos
, to_pos
, value
);
3475 } /* XmComboBoxReplace */
3477 void XmComboBoxSetAddMode(Widget w
, Boolean state
)
3479 XmTextFieldSetAddMode(EditBox
, state
);
3480 } /* XmComboBoxSetAddMode */
3482 void XmComboBoxSetHighlight(Widget w
, XmTextPosition left
,
3483 XmTextPosition right
, XmHighlightMode mode
)
3485 XmTextFieldSetHighlight(EditBox
, left
, right
, mode
);
3486 } /* XmComboBoxSetHighlight */
3488 void XmComboBoxSetInsertionPosition(Widget w
, XmTextPosition position
)
3490 XmTextFieldSetInsertionPosition(EditBox
, position
);
3491 } /* XmComboBoxSetInsertionPosition */
3493 void XmComboBoxSetMaxLength(Widget w
, int max_length
)
3495 XmTextFieldSetMaxLength(EditBox
, max_length
);
3496 } /* XmComboBoxSetMaxLength */
3498 void XmComboBoxSetSelection(Widget w
, XmTextPosition first
,
3499 XmTextPosition last
, Time time
)
3501 XmTextFieldSetSelection(EditBox
, first
, last
, time
);
3502 } /* XmComboBoxSetSelection */
3504 void XmComboBoxSetString(Widget w
, char *value
)
3506 /* Liebe OSF...ihr ^&*#%$*&)*(@$(*^(*&%# habt doch einen ziemlich gemeinen
3507 * Fehler in XmTextFieldSetString() drin... wenn man einen leeren String
3508 * (also "") angiebt, gibt's nur noch Aerger, wenn man spaeter wieder an
3509 * den Inhalt des Eingabefeldes heranwill.
3511 if ( (value
== NULL
) || (*value
== 0) )
3512 XtVaSetValues(w
, XmNvalue
, "", NULL
);
3514 XmTextFieldSetString(EditBox
, value
);
3515 } /* XmComboBoxSetString */
3517 void XmComboBoxShowPosition(Widget w
, XmTextPosition position
)
3519 XmTextFieldShowPosition(EditBox
, position
);
3520 } /* XmComboBoxShowPosition */
3523 * Loescht einen evtl. noch ausgewaehlten Eintrag in einer Combo Box,
3524 * wenn diese eine SelectionPolicy von XmSINGLE_SELECT hat.
3526 void XmComboBoxClearItemSelection(Widget w
)
3530 if ( CheckComboBox(w
, "XmComboBoxClearItemSelection") ) return;
3533 * Wenn bereits kein Eintrag markiert ist, dann loeschen wir nur noch
3534 * eben das Eingabefeld.
3536 index
= XmComboBoxGetSelectedPos(w
);
3538 XmComboBoxSetString(w
, "");
3541 * Ansonsten aktuellen Eintrag entsorgen (wie bei der Methode wipe-out)
3543 TransferToEditCtrl(ComboBox
, 0, True
);
3544 CallSelectionCBL(ComboBox
, NULL
);
3546 } /* XmComboBoxClearItemSelection */
3548 /* Die Drop-Down-Liste ein oder ausklappen */
3549 void XmComboBoxShowList(Widget w
)
3551 if ( CheckComboBox(w
, "XmComboBoxShowList") ) return;
3552 ShowHideDropDownList((XmComboBoxWidget
) w
, NULL
, False
);
3553 } /* XmComboBoxShowList */
3555 void XmComboBoxHideList(Widget w
)
3557 if ( CheckComboBox(w
, "XmComboBoxHideList") ) return;
3558 ShowHideDropDownList((XmComboBoxWidget
) w
, NULL
, True
);
3559 } /* XmComboBoxShowList */
3562 * Naja, ich komm' ja doch nicht um diese olle Funktion herum...
3564 Widget
XmCreateComboBox(Widget parent
, String name
, ArgList arglist
,
3567 return XtCreateWidget(name
, xmComboBoxWidgetClass
, parent
,
3569 } /* XmCreateComboBox */
3571 /* Ende von ComboBox.c */
3573 #endif /* XmVersion < 2000 */