ComboBox.c 111 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /*
  24. * DtWidget/ComboBox.c
  25. */
  26. /*
  27. * (c) Copyright 1996 Digital Equipment Corporation.
  28. * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company
  29. * (c) Copyright 1993, 1994, 1996 International Business Machines Corp.
  30. * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.
  31. * (c) Copyright 1993, 1994, 1996 Novell, Inc.
  32. * (c) Copyright 1996 FUJITSU LIMITED.
  33. * (c) Copyright 1996 Hitachi.
  34. */
  35. #ifdef REV_INFO
  36. #ifndef lint
  37. static char rcsid[] =
  38. "$XConsortium: ComboBox.c /main/15 1996/10/29 12:48:08 cde-hp $"
  39. #endif
  40. #endif
  41. /***********************************************************
  42. Copyright 1993 Interleaf, Inc.
  43. Permission to use, copy, modify, and distribute this software
  44. and its documentation for any purpose without fee is granted,
  45. provided that the above copyright notice appear in all copies
  46. and that both copyright notice and this permission notice appear
  47. in supporting documentation, and that the name of Interleaf not
  48. be used in advertising or publicly pertaining to distribution of
  49. the software without specific written prior permission.
  50. Interleaf makes no representation about the suitability of this
  51. software for any purpose. It is provided "AS IS" without any
  52. express or implied warranty.
  53. ******************************************************************/
  54. /*
  55. * (C) Copyright 1991,1992, 1993
  56. * Interleaf, Inc.
  57. * 9 Hillside Avenue,
  58. * Waltham, MA 02154
  59. *
  60. * ComboBox.c (DtComboBoxWidget):
  61. *
  62. * I wanted a margin around the widget (outside the shadow, like buttons),
  63. * so that the combo-box could be made the same size as a
  64. * push-button, etc. The bulletin-board widget always puts the shadow at
  65. * the outside edge of the widget, so combo-box is a sublcass of
  66. * manager, and we do everything ourselves.
  67. *
  68. * One must be carefull when using Dimension (for core width and height).
  69. * Dimension is an unsigned short. This causes problems when subtracting
  70. * and ending up with what should be a negative number (but it doesn't).
  71. * All child widget positioning is done by the combo_box. We don't
  72. * use any heavy-weight forms, etc. to help us out.
  73. *
  74. * There is no padding when editable. If using a label given it a
  75. * small margin, so it doesn't run up against the side of our
  76. * shadow or the arrow.
  77. *
  78. * Make some of the ComboBox functions common, so they can be shared
  79. * with SpinButton.
  80. *
  81. * The label-string resource got out of control. Its role kept getting
  82. * expanded; now the whole thing is a mess. Currently it shadows the
  83. * label's label-string. If the user sets it explicitly it will
  84. * take affect for as long as update-label is false. If update-label
  85. * is true, it will take affect until the end-user makes a selection
  86. * off the list.
  87. *
  88. * Known bugs:
  89. * Changing margin_width or margin_height resources when the
  90. * combo_box has focus will probably result in display glitches.
  91. *
  92. */
  93. /*
  94. * The DtComboBox widget is rigged with the Motif widget binary compatibilit
  95. * mechanism. All Motif-specific changes for this mechanism are preceded
  96. * by a comment including the string "MotifBc".
  97. *
  98. * For a description of the Motif widget binary compatibility mechanism
  99. * see the reference manual entry on XmResolveAllPartOffsets().
  100. *
  101. */
  102. /* _NO_PROTO support no longer required: */
  103. #include <Xm/XmP.h> /* for fast subclassing in XmIsComboBox */
  104. #include <Xm/XmosP.h> /* for INT_MAX */
  105. #include <Dt/DtMsgsP.h>
  106. #include "ComboBoxP.h"
  107. #include <Xm/DrawP.h>
  108. #include <Xm/DisplayP.h>
  109. #include <Xm/List.h>
  110. #include <Xm/ComboBox.h> /* for redirecting utility functions */
  111. #include "DtWidgetI.h" /* for _Dt thread-safety macros */
  112. /* some unpublished Motif interfaces */
  113. #include <Xm/XmPrivate.h>
  114. /* From MenuUtilP.h */
  115. extern int _XmGrabKeyboard(Widget widget, int owner_events, int pointer_mode,
  116. int keyboard_mode, Time time) ;
  117. /*
  118. * MotifBc
  119. */
  120. #define DtComboBoxIndex (XmManagerIndex + 1)
  121. static XmOffsetPtr ipot; /* Instance part offset table */
  122. static XmOffsetPtr cpot; /* Constraint part offset table */
  123. #define ScrollBarVisible( wid) (wid && XtIsManaged( wid))
  124. static void ClassInitialize (void);
  125. static void Initialize (DtComboBoxWidget request,
  126. DtComboBoxWidget new, ArgList given_args,
  127. Cardinal *num_args);
  128. static XmNavigability WidgetNavigable (DtComboBoxWidget combo);
  129. static void _ComboBoxFocusIn (DtComboBoxWidget combo, XEvent *event,
  130. char **params, Cardinal *num_params);
  131. static void _ComboBoxFocusOut (DtComboBoxWidget combo, XEvent *event,
  132. char **params, Cardinal *num_params);
  133. static void DrawHighlight (DtComboBoxWidget combo, Boolean clear);
  134. static void _ComboBoxActivate (Widget w, XEvent *event, char **params,
  135. Cardinal *num_params);
  136. static void _ComboBoxKbdCancel (Widget w, XEvent *event, char **params,
  137. Cardinal *num_params);
  138. static void _ComboBoxPrevTabGroup (Widget w, XEvent *event,
  139. char **params, Cardinal *num_params);
  140. static void _ComboBoxNextTabGroup (Widget w, XEvent *event,
  141. char **params, Cardinal *num_params);
  142. static void CheckResources (DtComboBoxWidget combo);
  143. static void Destroy (DtComboBoxWidget combo);
  144. static void Resize (DtComboBoxWidget combo);
  145. static void Redisplay (DtComboBoxWidget w, XEvent *event,
  146. Region region);
  147. static XtGeometryResult GeometryManager (Widget w,
  148. XtWidgetGeometry *request,
  149. XtWidgetGeometry *reply);
  150. static void SetComboBoxSize (DtComboBoxWidget combo);
  151. static void ForceChildSizes (DtComboBoxWidget combo);
  152. static void LayoutChildren (DtComboBoxWidget combo);
  153. static Boolean SetValues (DtComboBoxWidget current,
  154. DtComboBoxWidget request, DtComboBoxWidget new);
  155. static void ClearShadow (DtComboBoxWidget w, Boolean all);
  156. static void DrawShadow (DtComboBoxWidget w);
  157. static char* GetTextString (XmString xm_string);
  158. static void SetTextFieldData (DtComboBoxPart *combo_p, XmString item);
  159. static void SetMaximumLabelSize (DtComboBoxPart *combo_p);
  160. static void SetLabelData (DtComboBoxPart *combo_p, XmString item,
  161. Boolean force_label_string);
  162. static void select_cb (Widget w, XtPointer client_data,
  163. XtPointer call_data);
  164. static void shell_event_handler (Widget widget, XtPointer client_data,
  165. XEvent* event, Boolean *dispatch);
  166. static void list_event_handler (Widget widget, XtPointer client_data,
  167. XEvent* event, Boolean *dispatch);
  168. static void TextFieldActivate (DtComboBoxPart *combo_p, XtPointer call_data);
  169. static void activate_cb (Widget w, XtPointer client_data,
  170. XtPointer call_data);
  171. static void arrow_expose_cb (Widget w, XtPointer client_data,
  172. XtPointer call_data);
  173. static void text_losing_focus_cb (Widget w, XtPointer client_data,
  174. XtPointer call_data);
  175. static void text_activate_cb (Widget w, XtPointer client_data,
  176. XtPointer call_data);
  177. static void text_focus_cb (Widget w, XtPointer client_data,
  178. XtPointer call_data);
  179. static void SyncWithList (DtComboBoxPart *combo_p);
  180. static XmImportOperator _XmSetSyntheticResForChild (Widget widget,
  181. int offset,
  182. XtArgVal * value);
  183. /* Converter */
  184. static Boolean _CvtStringToType (Display *dpy, XrmValuePtr args,
  185. Cardinal *num_args, XrmValuePtr from, XrmValuePtr to, XtPointer *data);
  186. /* Grab and Ungrab processing */
  187. static void input_ungrab ( DtComboBoxWidget combo, int ungrab_mask);
  188. /* Resolution Independent Processing */
  189. void _DtComboBoxGetArrowSize( Widget w,
  190. int resource_offset,
  191. XtArgVal *value);
  192. void _DtComboBoxGetListMarginHeight( Widget w,
  193. int resource_offset,
  194. XtArgVal *value);
  195. void _DtComboBoxGetListMarginWidth( Widget w,
  196. int resource_offset,
  197. XtArgVal *value);
  198. void _DtComboBoxGetListSpacing( Widget w,
  199. int resource_offset,
  200. XtArgVal *value);
  201. static XmString InitLabel = NULL;
  202. /*
  203. * MotifBc
  204. */
  205. #define Arrow(w) XmField(w,ipot,DtComboBox,arrow,Widget)
  206. #define Shell(w) XmField(w,ipot,DtComboBox,shell,Widget)
  207. #define Frame(w) XmField(w,ipot,DtComboBox,frame,Widget)
  208. #define Label(w) XmField(w,ipot,DtComboBox,label,Widget)
  209. #define Sep(w) XmField(w,ipot,DtComboBox,sep,Widget)
  210. #define OldWidth(w) XmField(w,ipot,DtComboBox,old_width,Dimension)
  211. #define OldHeight(w) XmField(w,ipot,DtComboBox,old_height,Dimension)
  212. #define LabelMaxLength(w) XmField(w,ipot,DtComboBox,label_max_length,Dimension)
  213. #define LabelMaxHeight(w) XmField(w,ipot,DtComboBox,label_max_height,Dimension)
  214. #define MaxShellWidth(w) XmField(w,ipot,DtComboBox,max_shell_width,Dimension)
  215. #define MaxShellHeight(w) XmField(w,ipot,DtComboBox,max_shell_height,Dimension)
  216. #define MarginHeight(w) XmField(w,ipot,DtComboBox,margin_height,Dimension)
  217. #define MarginWidth(w) XmField(w,ipot,DtComboBox,margin_width,Dimension)
  218. #define SelectedItem(w) XmField(w,ipot,DtComboBox,selected_item,XmString)
  219. #define SelectedPosition(w) XmField(w,ipot,DtComboBox,selected_position,int)
  220. #define SelectionCallback(w) \
  221. XmField(w,ipot,DtComboBox,selection_callback,XtCallbackList)
  222. #define Type(w) XmField(w,ipot,DtComboBox,type,unsigned char)
  223. #define ArrowSpacing(w) XmField(w,ipot,DtComboBox,arrow_spacing,Dimension)
  224. #define ArrowSize(w) XmField(w,ipot,DtComboBox,arrow_size,Dimension)
  225. #define ActivateCallback(w) \
  226. XmField(w,ipot,DtComboBox,activate_callback,XtCallbackList)
  227. #define Alignment(w) XmField(w,ipot,DtComboBox,alignment,unsigned char)
  228. #define ArrowType(w) XmField(w,ipot,DtComboBox,arrow_type,unsigned char)
  229. #define TextColumns(w) XmField(w,ipot,DtComboBox,text_columns,short)
  230. #define FocusCallback(w) XmField(w,ipot,DtComboBox,focus_callback,XtCallbackList)
  231. #define HorizontalSpacing(w) XmField(w,ipot,DtComboBox,horizontal_spacing,Dimension)
  232. #define ItemCount(w) XmField(w,ipot,DtComboBox,item_count,int)
  233. #define Items(w) XmField(w,ipot,DtComboBox,items,XmStringTable)
  234. #define ListItems(w) XmField(w,ipot,DtComboBox,list_items,XmStringTable)
  235. #define LabelString(w) XmField(w,ipot,DtComboBox,label_string,XmString)
  236. #define List(w) XmField(w,ipot,DtComboBox,list,Widget)
  237. #define ListFontList(w) XmField(w,ipot,DtComboBox,list_font_list,XmFontList)
  238. #define ListMarginHeight(w) XmField(w,ipot,DtComboBox,list_margin_height,Dimension)
  239. #define ListMarginWidth(w) XmField(w,ipot,DtComboBox,list_margin_width,Dimension)
  240. #define ListSpacing(w) XmField(w,ipot,DtComboBox,list_spacing,Dimension)
  241. #define LosingFocusCallback(w) XmField(w,ipot,DtComboBox,losing_focus_callback,XtCallbackList)
  242. #define TextMaxLength(w) XmField(w,ipot,DtComboBox,text_max_length,unsigned int)
  243. #define MenuPostCallback(w) XmField(w,ipot,DtComboBox,menu_post_callback,XtCallbackList)
  244. #define Orientation(w) XmField(w,ipot,DtComboBox,orientation,unsigned char)
  245. #define PoppedUp(w) XmField(w,ipot,DtComboBox,popped_up,Boolean)
  246. #define RecomputeSize(w) XmField(w,ipot,DtComboBox,recompute_size,Boolean)
  247. #define Text(w) XmField(w,ipot,DtComboBox,text,Widget)
  248. #define TopItemPosition(w) XmField(w,ipot,DtComboBox,top_item_position,int)
  249. #define UpdateLabel(w) XmField(w,ipot,DtComboBox,update_label,Boolean)
  250. #define VerticalSpacing(w) XmField(w,ipot,DtComboBox,vertical_spacing,Dimension)
  251. #define VisibleItemCount(w) XmField(w,ipot,DtComboBox,visible_item_count,int)
  252. /*
  253. * DtComboBoxWidget specific defines.
  254. */
  255. #define PUnitType(w) w->primitive.unit_type
  256. #define ShellPoppedUp(w) w->shell.popped_up
  257. #define MUnitType(w) w->manager.unit_type
  258. #define COMBO_SHADOW(w) w->manager.shadow_thickness
  259. #define LayoutDirection(w) w->manager.string_direction
  260. #define NavigationType(w) w->manager.navigation_type
  261. #define TraversalOn(w) w->manager.traversal_on
  262. #define BackgroundGC(w) w->manager.background_GC
  263. #define HighlightGC(w) w->manager.highlight_GC
  264. #define TopShadowGC(w) w->manager.top_shadow_GC
  265. #define BottomShadowGC(w) w->manager.bottom_shadow_GC
  266. #define BackgroundPixel(w) w->core.background_pixel
  267. #define X(w) w->core.x
  268. #define Y(w) w->core.y
  269. #define Width(w) w->core.width
  270. #define Height(w) w->core.height
  271. #define BorderWidth(w) w->core.border_width
  272. #define Sensitive(w) w->core.sensitive
  273. #define AncestorSensitive(w) w->core.ancestor_sensitive
  274. #define Parent(w) w->core.parent
  275. #define COMBO_MARGIN_W(w) MarginWidth(w)
  276. #define COMBO_MARGIN_H(w) MarginHeight(w)
  277. #define COMBO_H_SPACING(w) HorizontalSpacing(w)
  278. #define COMBO_V_SPACING(w) VerticalSpacing(w)
  279. #define GRAB_POINTER 1 << 0
  280. #define GRAB_KEYBOARD 1 << 1
  281. #define DtNonePopup 0
  282. #define DtPopup 1 << 0
  283. #define DtButtonPressPopup 1 << 1
  284. #define DtKeyPressPopup 1 << 2
  285. #define LIST_EVENTS (ButtonReleaseMask | FocusChangeMask | EnterWindowMask)
  286. #define SHELL_EVENTS (ButtonPressMask | ButtonReleaseMask)
  287. #define INVALID_DIMENSION (0xFFFF)
  288. static char ComboBoxTranslationTable[] = "\
  289. <FocusIn>: ComboBoxFocusIn() \n\
  290. <FocusOut>: ComboBoxFocusOut() \n\
  291. <Key>osfDown: ComboBoxActivate() \n\
  292. <Btn1Down>: ComboBoxActivate() \n\
  293. <Key>osfSelect: ComboBoxActivate() \n\
  294. ~s ~m ~a <Key>space: ComboBoxActivate() \n\
  295. ";
  296. static char ComboBoxLabelTranslationTable[] = "\
  297. <Key>osfDown: ComboBoxActivate(label) \n\
  298. <Btn1Down>: ComboBoxActivate(label) \n\
  299. <Key>osfSelect: ComboBoxActivate(label) \n\
  300. ~s ~m ~a <Key>space: ComboBoxActivate(label) \n\
  301. ";
  302. /* Keyboard Only Traversing During Editable-Mode */
  303. static char ComboBoxTextTranslationTable[] = "\
  304. <Key>osfUp: ComboBoxActivate(label) \n\
  305. <Key>osfDown: ComboBoxActivate(label) \n\
  306. ";
  307. static char ComboBoxButtonTranslationTable[] = "\
  308. <Key>osfDown: ComboBoxActivate(label) \n\
  309. <Btn1Down>: ComboBoxActivate(label) \n\
  310. ~s ~m ~a <Key>space: ComboBoxActivate(label) \n\
  311. s ~m ~a <Key>Tab: ComboBoxPrevTabGroup()\n\
  312. ~m ~a <Key>Tab: ComboBoxNextTabGroup()\n\
  313. ";
  314. static char ComboBoxListTranslationTable[] = "\
  315. <Key>osfCancel: ListKbdCancel() ComboBoxKbdCancel() \n\
  316. ";
  317. static XtActionsRec ComboBoxActionTable[] = {
  318. {"ComboBoxFocusIn", (XtActionProc)_ComboBoxFocusIn},
  319. {"ComboBoxFocusOut", (XtActionProc)_ComboBoxFocusOut},
  320. {"ComboBoxActivate", (XtActionProc)_ComboBoxActivate},
  321. {"ComboBoxKbdCancel", (XtActionProc)_ComboBoxKbdCancel},
  322. {"ComboBoxPrevTabGroup", (XtActionProc)_ComboBoxPrevTabGroup},
  323. {"ComboBoxNextTabGroup", (XtActionProc)_ComboBoxNextTabGroup},
  324. };
  325. /*
  326. * DtComboBoxWidget resources
  327. */
  328. #define offset(field) XtOffset(DtComboBoxWidget, field)
  329. #define DtOffset(field) XmPartOffset(DtComboBox,field)
  330. static XmPartResource resources[] = {
  331. {XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension,
  332. sizeof(Dimension), offset(manager.shadow_thickness),
  333. XmRImmediate, (XtPointer)TEXT_FIELD_SHADOW},
  334. /*
  335. * ComboBox specific resources
  336. */
  337. {DtNactivateCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
  338. DtOffset(activate_callback), XmRCallback,
  339. (XtPointer)NULL},
  340. {DtNalignment, DtCAlignment, XmRAlignment, sizeof(unsigned char),
  341. DtOffset(alignment), XmRImmediate,
  342. (XtPointer)DtALIGNMENT_END},
  343. {DtNarrowSpacing, DtCArrowSpacing, XmRHorizontalDimension,
  344. sizeof(Dimension), DtOffset(arrow_spacing),
  345. XmRImmediate, (XtPointer)0},
  346. {DtNarrowType, DtCArrowType, DtRArrowType, sizeof(unsigned char),
  347. DtOffset(arrow_type), XmRImmediate, (XtPointer)DtMOTIF},
  348. {DtNcolumns, DtCColumns, XmRShort, sizeof(short),
  349. DtOffset(text_columns), XmRImmediate, (XtPointer)20},
  350. {DtNfocusCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
  351. DtOffset(focus_callback), XmRCallback,
  352. (XtPointer)NULL},
  353. {DtNhorizontalSpacing, DtCHorizontalSpacing, XmRHorizontalDimension,
  354. sizeof(Dimension), DtOffset(horizontal_spacing),
  355. XmRImmediate, (XtPointer)INVALID_DIMENSION},
  356. {DtNitemCount, DtCItemCount, XmRInt, sizeof(int),
  357. DtOffset(item_count), XmRImmediate, (XtPointer)0},
  358. /*
  359. * items is used only for seeing if the user changed the list. It
  360. * is only a pointer that reflects the current list's items.
  361. */
  362. {DtNitems, DtCItems, XmRXmStringTable, sizeof(XmStringTable),
  363. DtOffset(items), XmRImmediate, (XtPointer)NULL},
  364. {DtNlabelString, DtCXmString, XmRXmString, sizeof(XmString),
  365. DtOffset(label_string), XmRImmediate, (XtPointer)NULL},
  366. {DtNlist, DtCList, XmRWidget, sizeof(Widget),
  367. DtOffset(list), XmRImmediate, (XtPointer)NULL},
  368. {DtNlistFontList, DtCListFontList, XmRFontList, sizeof(XmFontList),
  369. DtOffset(list_font_list), XmRImmediate, (XtPointer)NULL},
  370. {DtNlistMarginHeight, DtCListMarginHeight, XmRVerticalDimension,
  371. sizeof(Dimension), DtOffset(list_margin_height),
  372. XmRImmediate, (XtPointer)MARGIN},
  373. {DtNlistMarginWidth, DtCListMarginWidth, XmRHorizontalDimension,
  374. sizeof(Dimension), DtOffset(list_margin_width),
  375. XmRImmediate, (XtPointer)MARGIN},
  376. {DtNlistSpacing, DtCListSpacing, XmRVerticalDimension,sizeof(Dimension),
  377. DtOffset(list_spacing), XmRImmediate, (XtPointer)0},
  378. {DtNlosingFocusCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
  379. DtOffset(losing_focus_callback), XmRCallback,
  380. (XtPointer)NULL},
  381. {DtNmarginHeight, DtCMarginHeight, XmRVerticalDimension,
  382. sizeof(Dimension), DtOffset(margin_height),
  383. XmRImmediate, (XtPointer)MARGIN},
  384. {DtNmarginWidth, DtCMarginWidth, XmRHorizontalDimension, sizeof(Dimension),
  385. DtOffset(margin_width), XmRImmediate, (XtPointer)MARGIN},
  386. {DtNmaxLength, DtCMaxLength, XmRInt, sizeof(unsigned int),
  387. DtOffset(text_max_length), XmRImmediate, (XtPointer)INT_MAX},
  388. {DtNmenuPostCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
  389. DtOffset(menu_post_callback), XmRCallback, (XtPointer)NULL},
  390. {DtNorientation, DtCOrientation, XmROrientation, sizeof(unsigned char),
  391. DtOffset(orientation), XmRImmediate, (XtPointer)DtRIGHT},
  392. {DtNpoppedUp, DtCPoppedUp, XmRBoolean, sizeof(Boolean),
  393. DtOffset(popped_up), XmRImmediate, (XtPointer)FALSE},
  394. {DtNrecomputeSize, DtCRecomputeSize, XmRBoolean, sizeof(Boolean),
  395. DtOffset(recompute_size), XmRImmediate, (XtPointer)TRUE},
  396. {DtNselectedItem, DtCXmString, XmRXmString, sizeof(XmString),
  397. DtOffset(selected_item), XmRImmediate, (XtPointer)NULL},
  398. {DtNselectedPosition, DtCSelectedPosition, XmRInt, sizeof(int),
  399. DtOffset(selected_position), XmRImmediate, (XtPointer)0},
  400. {DtNselectionCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
  401. DtOffset(selection_callback), XmRCallback, (XtPointer)NULL},
  402. {DtNtextField, DtCTextField, XmRWidget, sizeof(Widget),
  403. DtOffset(text), XmRImmediate, (XtPointer)NULL},
  404. {DtNtopItemPosition, DtCTopItemPosition, XmRInt, sizeof(int),
  405. DtOffset(top_item_position), XmRImmediate, (XtPointer)1},
  406. {DtNcomboBoxType, DtCComboBoxType, DtRComboBoxType, sizeof(unsigned char),
  407. DtOffset(type), XmRImmediate,(XtPointer)DtDROP_DOWN_LIST},
  408. {DtNupdateLabel, DtCUpdateLabel, XmRBoolean, sizeof(Boolean),
  409. DtOffset(update_label), XmRImmediate, (XtPointer)TRUE},
  410. {DtNvisibleItemCount, DtCVisibleItemCount, XmRInt, sizeof(int),
  411. DtOffset(visible_item_count), XmRImmediate, (XtPointer)10},
  412. {DtNverticalSpacing, DtCVerticalSpacing, XmRVerticalDimension,
  413. sizeof(Dimension), DtOffset(vertical_spacing),
  414. XmRImmediate, (XtPointer)INVALID_DIMENSION},
  415. };
  416. /*
  417. * List resources (used for GetValues).
  418. */
  419. static XmSyntheticResource syn_resources[] = {
  420. {DtNarrowSpacing, sizeof(Dimension), DtOffset(arrow_spacing),
  421. XmeFromHorizontalPixels, XmeToHorizontalPixels},
  422. {DtNhorizontalSpacing, sizeof(Dimension), DtOffset(horizontal_spacing),
  423. XmeFromHorizontalPixels, XmeToHorizontalPixels},
  424. {DtNverticalSpacing, sizeof(Dimension), DtOffset(vertical_spacing),
  425. XmeFromVerticalPixels, XmeToVerticalPixels},
  426. {DtNmarginWidth, sizeof(Dimension), DtOffset(margin_width),
  427. XmeFromHorizontalPixels, XmeToHorizontalPixels},
  428. {DtNmarginHeight, sizeof(Dimension), DtOffset(margin_height),
  429. XmeFromVerticalPixels, XmeToVerticalPixels},
  430. {DtNarrowSize, sizeof(Dimension), DtOffset(arrow_size),
  431. _DtComboBoxGetArrowSize, XmeToHorizontalPixels},
  432. {DtNlabelString, sizeof(XmString), DtOffset(label_string),
  433. _DtComboBoxGetLabelString, _XmSetSyntheticResForChild},
  434. {DtNitemCount, sizeof(int), DtOffset(item_count),
  435. _DtComboBoxGetListItemCount, _XmSetSyntheticResForChild},
  436. {DtNitems, sizeof(XmStringTable), DtOffset(items),
  437. _DtComboBoxGetListItems, _XmSetSyntheticResForChild},
  438. {DtNlistFontList, sizeof(XmFontList), DtOffset(list_font_list),
  439. _DtComboBoxGetListFontList, _XmSetSyntheticResForChild},
  440. {DtNlistMarginHeight, sizeof(Dimension),
  441. DtOffset(list_margin_height),
  442. _DtComboBoxGetListMarginHeight, XmeToVerticalPixels},
  443. {DtNlistMarginWidth, sizeof(Dimension),DtOffset(list_margin_width),
  444. _DtComboBoxGetListMarginWidth, XmeToHorizontalPixels},
  445. {DtNlistSpacing, sizeof(Dimension), DtOffset(list_spacing),
  446. _DtComboBoxGetListSpacing, XmeToVerticalPixels},
  447. {DtNtopItemPosition, sizeof(int), DtOffset(top_item_position),
  448. _DtComboBoxGetListTopItemPosition, _XmSetSyntheticResForChild},
  449. {DtNvisibleItemCount, sizeof(int), DtOffset(visible_item_count),
  450. _DtComboBoxGetListVisibleItemCount, _XmSetSyntheticResForChild},
  451. };
  452. #undef DtOffset
  453. #undef offset
  454. /* Need Class Extension for widget navigation */
  455. static XmBaseClassExtRec baseClassExtRec = {
  456. NULL,
  457. NULLQUARK,
  458. XmBaseClassExtVersion,
  459. sizeof(XmBaseClassExtRec),
  460. (XtInitProc)NULL, /* InitializePrehook */
  461. (XtSetValuesFunc)NULL, /* SetValuesPrehook */
  462. (XtInitProc)NULL, /* InitializePosthook */
  463. (XtSetValuesFunc)NULL, /* SetValuesPosthook */
  464. NULL, /* secondaryObjectClass */
  465. (XtInitProc)NULL, /* secondaryCreate */
  466. (XmGetSecResDataFunc)NULL, /* getSecRes data */
  467. { 0 }, /* fastSubclass flags */
  468. (XtArgsProc)NULL, /* getValuesPrehook */
  469. (XtArgsProc)NULL, /* getValuesPosthook */
  470. (XtWidgetClassProc)NULL, /* classPartInitPrehook */
  471. (XtWidgetClassProc)NULL, /* classPartInitPosthook*/
  472. NULL, /* ext_resources */
  473. NULL, /* compiled_ext_resources*/
  474. 0, /* num_ext_resources */
  475. FALSE, /* use_sub_resources */
  476. (XmWidgetNavigableProc)WidgetNavigable,
  477. /* widgetNavigable */
  478. (XmFocusChangeProc)NULL, /* focusChange */
  479. (XmWrapperData)NULL /* wrapperData */
  480. };
  481. /*
  482. * Define Class Record.
  483. */
  484. externaldef(dtcomboBoxclassrec) DtComboBoxClassRec dtComboBoxClassRec =
  485. {
  486. { /* core_class fields */
  487. (WidgetClass)&(xmManagerClassRec), /* superclass */
  488. (String)"DtComboBox", /* class_name */
  489. (Cardinal)sizeof(DtComboBoxPart), /* widget_size */
  490. (XtProc)ClassInitialize, /* class_initialize */
  491. (XtWidgetClassProc)NULL, /* class_part_init */
  492. (XtEnum)FALSE, /* class_inited */
  493. (XtInitProc)Initialize, /* initialize */
  494. (XtArgsProc)NULL, /* initialize_hook */
  495. (XtRealizeProc)XtInheritRealize, /* realize */
  496. (XtActionList)ComboBoxActionTable, /* actions */
  497. (Cardinal)XtNumber(ComboBoxActionTable), /* num_actions */
  498. (XtResourceList)resources, /* resources */
  499. (Cardinal)XtNumber(resources), /* num_resources */
  500. (XrmClass)NULLQUARK, /* xrm_class */
  501. (Boolean)TRUE, /* compress_motion */
  502. (XtEnum)XtExposeCompressMaximal, /* compress_exposure */
  503. (Boolean)TRUE, /* compress_enterleave*/
  504. (Boolean)FALSE, /* visible_interest */
  505. (XtWidgetProc)Destroy, /* destroy */
  506. (XtWidgetProc)Resize, /* resize */
  507. (XtExposeProc)Redisplay, /* expose */
  508. (XtSetValuesFunc)SetValues, /* set_values */
  509. (XtArgsFunc)NULL, /* set values hook */
  510. (XtAlmostProc)XtInheritSetValuesAlmost, /* set values almost */
  511. (XtArgsProc)NULL, /* get values hook */
  512. (XtAcceptFocusProc)NULL, /* accept_focus */
  513. (XtVersionType)XtVersionDontCheck, /* Version */
  514. (XtPointer)NULL, /* PRIVATE cb list */
  515. (String)XtInheritTranslations, /* tm_table */
  516. (XtGeometryHandler)XtInheritQueryGeometry, /* query_geom */
  517. (XtStringProc)XtInheritDisplayAccelerator, /* display_accelerator*/
  518. (XtPointer)&baseClassExtRec /* extension */
  519. },
  520. { /* composite_class fields */
  521. (XtGeometryHandler)GeometryManager, /* geometry_manager */
  522. (XtWidgetProc)XtInheritChangeManaged, /* change_managed */
  523. (XtWidgetProc)XtInheritInsertChild, /* insert_child */
  524. (XtWidgetProc)XtInheritDeleteChild, /* delete_child */
  525. (XtPointer)NULL /* extension */
  526. },
  527. { /* constraint_class fields */
  528. (XtResourceList)NULL, /* resources */
  529. (Cardinal)0, /* num_resources */
  530. (Cardinal)0, /* constraint_size */
  531. (XtInitProc)NULL, /* initialize */
  532. (XtWidgetProc)NULL, /* destroy */
  533. (XtSetValuesFunc)NULL, /* set_values */
  534. (XtPointer)NULL /* extension */
  535. },
  536. { /* manager class */
  537. (String)XtInheritTranslations, /* translations */
  538. (XmSyntheticResource*)syn_resources, /* syn resources */
  539. (int)XtNumber(syn_resources), /* num syn_resources */
  540. (XmSyntheticResource*)NULL, /* get_cont_resources */
  541. (int)0, /* num_get_cont_resources */
  542. (XmParentProcessProc)XmInheritParentProcess,/* parent_process */
  543. (XtPointer)NULL /* extension */
  544. },
  545. { /* combo_box_class fields */
  546. (Boolean)0,
  547. }
  548. };
  549. externaldef(dtcomboBoxwidgetclass) WidgetClass dtComboBoxWidgetClass =
  550. (WidgetClass)&dtComboBoxClassRec;
  551. /* Parse the translation tables only once for the whole class
  552. */
  553. static XtTranslations trans;
  554. static XtTranslations list_trans;
  555. static XtTranslations label_trans;
  556. static XtTranslations text_trans;
  557. static XtTranslations button_trans;
  558. /*
  559. * Must set up the record type for the class extensions to work.
  560. */
  561. static void
  562. ClassInitialize(void)
  563. {
  564. baseClassExtRec.record_type = XmQmotif;
  565. /*
  566. * MotifBc
  567. */
  568. XmResolveAllPartOffsets(dtComboBoxWidgetClass, &ipot, &cpot);
  569. /* Parse the translation tables here
  570. */
  571. trans = XtParseTranslationTable(ComboBoxTranslationTable);
  572. list_trans = XtParseTranslationTable(ComboBoxListTranslationTable);
  573. label_trans = XtParseTranslationTable(ComboBoxLabelTranslationTable);
  574. text_trans = XtParseTranslationTable(ComboBoxTextTranslationTable);
  575. button_trans =XtParseTranslationTable(ComboBoxButtonTranslationTable);
  576. /* Add a type converter for String to DtRComboBoxType
  577. */
  578. XtSetTypeConverter("String","ComboBoxType", _CvtStringToType, NULL, 0,
  579. XtCacheAll, NULL);
  580. InitLabel = XmStringCreateLocalized(CB_LABEL);
  581. }
  582. /*
  583. * ComboBox initialization function. This builds the widgets inside
  584. * our widget, to get the correct layout. If the type resource
  585. * is DtDROP_DOWN_COMBO_BOX, we create a textField; if FALSE, we create a
  586. * label. If the user changes this resource later, we will create the
  587. * other widget (textField or Label). We don't want to carry backage from
  588. * both widgets if the user never changes the type resource.
  589. */
  590. static void
  591. Initialize( DtComboBoxWidget request,
  592. DtComboBoxWidget new,
  593. ArgList given_args,
  594. Cardinal *num_args)
  595. {
  596. /* use the address of the first element of DtComboBoxPart structure
  597. * as of DtComboBoxPart
  598. */
  599. DtComboBoxPart *combo_p = (DtComboBoxPart*)
  600. &(XmField(new,ipot,DtComboBox,arrow,Widget));
  601. Boolean force_label_string = FALSE;
  602. Arg args[15];
  603. int n;
  604. /* Resolution Independent */
  605. unsigned char unit_type = MUnitType(new);
  606. /* Overwrite the manager's focusIn and focusOut translations */
  607. XtOverrideTranslations((Widget)new, trans);
  608. /*
  609. * force_label_string usage if it is specified and items is not.
  610. * This will be the perminant label string only if update-label
  611. * is false, else it is only used until the user picks something
  612. * new off the list.
  613. */
  614. if (LabelString(new) == NULL)
  615. LabelString(new) = InitLabel;
  616. else if (!Items(new))
  617. force_label_string = TRUE;
  618. /* Copy given label-string. */
  619. if (LabelString(new))
  620. LabelString(new) = XmStringCopy(LabelString(new));
  621. Text(new) = (Widget)NULL;
  622. Label(new) = (Widget)NULL;
  623. Sep(new) = (Widget)NULL;
  624. OldWidth(new) = 0;
  625. OldHeight(new) = 0;
  626. CheckResources(new);
  627. /*
  628. * Create the text or label depending on the type resource.
  629. * When part of X-Designer, we create both at initialization to
  630. * avoid later crashes.
  631. */
  632. if (Type(new) == DtDROP_DOWN_COMBO_BOX)
  633. {
  634. n = 0;
  635. XtSetArg(args[n], XmNcolumns, TextColumns(new)); n++;
  636. XtSetArg(args[n], XmNmaxLength, TextMaxLength(new)); n++;
  637. XtSetArg(args[n], XmNmarginWidth, TEXT_CONTEXT_MARGIN); n++;
  638. XtSetArg(args[n], XmNmarginHeight, 2); n++;
  639. /* Resolution Independent */
  640. if (unit_type != XmPIXELS) {
  641. XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
  642. }
  643. Text(new) = XtCreateManagedWidget("Text",
  644. xmTextFieldWidgetClass,
  645. (Widget)new, args, n);
  646. XtAddCallback(Text(new), XmNlosingFocusCallback,
  647. text_losing_focus_cb, (XtPointer)new);
  648. XtAddCallback(Text(new), XmNactivateCallback,
  649. text_activate_cb, (XtPointer)new);
  650. XtAddCallback(Text(new), XmNfocusCallback,
  651. text_focus_cb, (XtPointer)new);
  652. XtOverrideTranslations(Text(new), text_trans);
  653. if (HorizontalSpacing(new) == INVALID_DIMENSION)
  654. HorizontalSpacing(new) = 0;
  655. if (VerticalSpacing(new) == INVALID_DIMENSION)
  656. VerticalSpacing(new) = 0;
  657. if (unit_type != XmPIXELS) {
  658. XtSetArg(args[0], XmNunitType, unit_type);
  659. XtSetValues(Text(new), args, 1);
  660. }
  661. }
  662. else
  663. {
  664. XmStringDirection new_direction =
  665. XmDirectionToStringDirection(LayoutDirection(new));
  666. COMBO_SHADOW(new) = LABEL_SHADOW;
  667. n = 0;
  668. XtSetArg(args[n], XmNalignment, Alignment(new)); n++;
  669. XtSetArg(args[n], XmNrecomputeSize, FALSE); n++;
  670. XtSetArg(args[n], XmNlabelString, InitLabel); n++;
  671. XtSetArg(args[n], XmNmarginLeft, LABEL_PADDING); n++;
  672. XtSetArg(args[n], XmNmarginRight, LABEL_PADDING); n++;
  673. XtSetArg(args[n], XmNmarginWidth, TEXT_CONTEXT_MARGIN); n++;
  674. XtSetArg(args[n], XmNmarginHeight, 0); n++;
  675. XtSetArg(args[n], XmNstringDirection, new_direction); n++;
  676. /* Resolution Independent */
  677. if (unit_type != XmPIXELS) {
  678. XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
  679. }
  680. Label(new) = XtCreateManagedWidget("Label",
  681. xmLabelWidgetClass,
  682. (Widget)new, args, n);
  683. XtOverrideTranslations(Label(new), label_trans);
  684. if (HorizontalSpacing(new) == INVALID_DIMENSION)
  685. HorizontalSpacing(new) = 1;
  686. if (VerticalSpacing(new) == INVALID_DIMENSION)
  687. VerticalSpacing(new) = 2;
  688. if (unit_type != XmPIXELS) {
  689. XtSetArg(args[0], XmNunitType, unit_type);
  690. XtSetValues(Label(new), args, 1);
  691. }
  692. }
  693. /*
  694. * Create the separator used if non-editable combo-box.
  695. */
  696. if (Type(new) == DtDROP_DOWN_LIST)
  697. {
  698. n = 0;
  699. XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
  700. /* Resolution Independent */
  701. if (unit_type != XmPIXELS) {
  702. XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
  703. }
  704. Sep(new) = XtCreateManagedWidget("ComboBoxSeparator",
  705. xmSeparatorWidgetClass,
  706. (Widget)new, args, n);
  707. XtOverrideTranslations((Widget)Sep(new), button_trans);
  708. if (unit_type != XmPIXELS) {
  709. XtSetArg(args[0], XmNunitType, unit_type);
  710. XtSetValues(Sep(new), args, 1);
  711. }
  712. }
  713. /*
  714. * Create the ArrowWidget.
  715. */
  716. n = 0;
  717. XtSetArg(args[n], XmNtraversalOn, FALSE); n++;
  718. XtSetArg(args[n], XmNhighlightThickness, 0); n++;
  719. XtSetArg(args[n], XmNshadowThickness, 0); n++;
  720. if (ArrowType(new) == DtMOTIF) {
  721. XtSetArg(args[n], XmNarrowDirection, XmARROW_DOWN); n++;
  722. XtSetArg(args[n], XmNforeground, BackgroundPixel(new)); n++;
  723. Arrow(new) = XtCreateManagedWidget("ComboBoxArrow",
  724. xmArrowButtonWidgetClass,
  725. (Widget)new, args, n);
  726. }
  727. else {
  728. Arrow(new) = XtCreateManagedWidget("ComboBoxArrow",
  729. xmDrawnButtonWidgetClass,
  730. (Widget)new, args, n);
  731. XtAddCallback(Arrow(new), XmNexposeCallback, arrow_expose_cb,
  732. (XtPointer)new);
  733. }
  734. XtAddCallback(Arrow(new), XmNactivateCallback, activate_cb,
  735. (XtPointer)new);
  736. XtOverrideTranslations((Widget)Arrow(new), button_trans);
  737. /*
  738. * Create the shell and associated list widgets.
  739. */
  740. n = 0;
  741. XtSetArg(args[n], XtNoverrideRedirect, TRUE); n++;
  742. XtSetArg(args[n], XtNallowShellResize, TRUE); n++;
  743. XtSetArg(args[n], XtNsaveUnder, TRUE); n++;
  744. Shell(new) = XtCreatePopupShell("ComboBoxMenuShell",
  745. topLevelShellWidgetClass,
  746. (Widget)new, args, n);
  747. n = 0;
  748. Frame(new) = XtCreateManagedWidget("ComboBoxRowColumn",
  749. xmFrameWidgetClass,
  750. Shell(new), args, n);
  751. n = 0;
  752. /* Store combo widget in list for later use */
  753. XtSetArg(args[n], XmNuserData, (XtPointer)new); n++;
  754. if (ListFontList(new)) {
  755. XtSetArg(args[n], XmNfontList, ListFontList(new)); n++;
  756. }
  757. /* to disable double click */
  758. XtSetArg(args[n], XmNdoubleClickInterval, 0); n++;
  759. XtSetArg(args[n], XmNitemCount, ItemCount(new)); n++;
  760. XtSetArg(args[n], XmNitems, Items(new)); n++;
  761. XtSetArg(args[n], XmNlistMarginHeight, ListMarginHeight(new)); n++;
  762. XtSetArg(args[n], XmNlistMarginWidth, ListMarginWidth(new)); n++;
  763. XtSetArg(args[n], XmNlistSpacing, ListSpacing(new)); n++;
  764. {
  765. XmStringDirection new_direction =
  766. XmDirectionToStringDirection(LayoutDirection(new));
  767. XtSetArg(args[n], XmNstringDirection, new_direction); n++;
  768. }
  769. XtSetArg(args[n], XmNtopItemPosition, TopItemPosition(new)); n++;
  770. XtSetArg(args[n], XmNvisibleItemCount, VisibleItemCount(new)); n++;
  771. XtSetArg(args[n], XmNlistSizePolicy, XmRESIZE_IF_POSSIBLE); n++;
  772. XtSetArg(args[n], XmNselectionPolicy, XmBROWSE_SELECT); n++;
  773. /* Resolution Independent */
  774. if (unit_type != XmPIXELS) {
  775. XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
  776. }
  777. List(new) = XmCreateScrolledList(Frame(new), "List", args, n);
  778. XtOverrideTranslations((Widget)List(new), list_trans);
  779. n = 0;
  780. XtSetArg(args[n], XmNshadowThickness, (XtArgVal) 0); n++;
  781. XtSetValues(XtParent(List(new)), args, n);
  782. /* selected_item resource used before selected_position */
  783. if (SelectedItem(new) && XmeStringIsValid(SelectedItem(new)) ) {
  784. SelectedItem(new) =XmStringCopy(SelectedItem(new));
  785. DtComboBoxSelectItem((Widget)new, SelectedItem(new));
  786. }
  787. else {
  788. SelectedItem(new) = (XmString) NULL;
  789. if (SelectedPosition(new)<0 || SelectedPosition(new)>=ItemCount(new))
  790. SelectedPosition(new) = 0;
  791. if ( ItemCount(new))
  792. XmListSelectPos(List(new), SelectedPosition(new) + 1, FALSE);
  793. }
  794. if (unit_type != XmPIXELS) {
  795. XtSetArg(args[0], XmNunitType, unit_type);
  796. XtSetValues(List(new), args, 1);
  797. }
  798. SyncWithList(combo_p);
  799. XtManageChild(List(new));
  800. XtRealizeWidget(Shell(new));
  801. MaxShellWidth(new) = Width(((Widget) Shell(new)));
  802. MaxShellHeight(new) = Height(((Widget) Shell(new)));
  803. XtAddCallback(List(new), XmNdefaultActionCallback, select_cb, new);
  804. XtAddCallback(List(new), XmNbrowseSelectionCallback, select_cb, new);
  805. /*
  806. * Set up event handlers needed for handling grab states.
  807. */
  808. XtInsertEventHandler(List(new), LIST_EVENTS, TRUE,
  809. (XtEventHandler)list_event_handler,
  810. (XtPointer)new, XtListHead);
  811. XtInsertEventHandler(Shell(new), SHELL_EVENTS, TRUE,
  812. (XtEventHandler)shell_event_handler,
  813. (XtPointer)new, XtListHead);
  814. /*
  815. * Set initial value in text or label if items was specified
  816. */
  817. if (Type(new) == DtDROP_DOWN_LIST) {
  818. SetMaximumLabelSize(combo_p);
  819. SetLabelData(combo_p, NULL, force_label_string);
  820. }
  821. else
  822. SetTextFieldData(combo_p, NULL);
  823. SetComboBoxSize(new);
  824. LayoutChildren(new);
  825. }
  826. /*
  827. * Allow the manager to gain focus if not editable. If editable (using
  828. * text-field), then let the toolkit give focus to the text-field.
  829. */
  830. static XmNavigability
  831. WidgetNavigable(DtComboBoxWidget combo)
  832. {
  833. XmNavigationType nav_type = NavigationType(((XmManagerWidget)combo));
  834. if (Sensitive(combo) && AncestorSensitive(combo) &&
  835. TraversalOn(((XmManagerWidget)combo))) {
  836. if ((nav_type == XmSTICKY_TAB_GROUP) ||
  837. (nav_type == XmEXCLUSIVE_TAB_GROUP) ||
  838. ((nav_type == XmTAB_GROUP) &&
  839. !_XmShellIsExclusive((Widget)combo))) {
  840. if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
  841. return(XmDESCENDANTS_TAB_NAVIGABLE);
  842. else
  843. return(XmTAB_NAVIGABLE);
  844. }
  845. return(XmDESCENDANTS_NAVIGABLE);
  846. }
  847. return(XmNOT_NAVIGABLE);
  848. }
  849. /*
  850. * The combo_box gets focus.
  851. */
  852. static void
  853. _ComboBoxFocusIn( DtComboBoxWidget combo,
  854. XEvent *event,
  855. char **params,
  856. Cardinal *num_params)
  857. {
  858. DrawHighlight(combo, FALSE);
  859. }
  860. /*
  861. * The combo_box loses focus. Only happens if not editable.
  862. */
  863. static void
  864. _ComboBoxFocusOut( DtComboBoxWidget combo,
  865. XEvent *event,
  866. char **params,
  867. Cardinal *num_params)
  868. {
  869. DrawHighlight(combo, TRUE);
  870. }
  871. /*
  872. * This function gets called whenever we draw or clear the shadow (to
  873. * redraw highlight during resize, etc), as well as during focus_in
  874. * and focus_out events.
  875. */
  876. static void
  877. DrawHighlight( DtComboBoxWidget combo,
  878. Boolean clear)
  879. {
  880. XRectangle rect[4] ;
  881. if (XtIsRealized((Widget)combo)) {
  882. if (clear) {
  883. rect[0].x = rect[1].x = rect[2].x = 0;
  884. rect[3].x = OldWidth(combo) - COMBO_MARGIN_W(combo);
  885. rect[0].y = rect[2].y = rect[3].y = 0 ;
  886. rect[1].y = OldHeight(combo) - COMBO_MARGIN_H(combo);
  887. rect[0].width = rect[1].width = OldWidth(combo);
  888. rect[2].width = rect[3].width = COMBO_MARGIN_W(combo);
  889. rect[0].height = rect[1].height = COMBO_MARGIN_H(combo);
  890. rect[2].height = rect[3].height = OldHeight(combo);
  891. XFillRectangles(XtDisplayOfObject((Widget)combo),
  892. XtWindowOfObject((Widget)combo),
  893. BackgroundGC(combo), rect, 4);
  894. }
  895. else if (XmGetFocusWidget((Widget)combo) == (Widget)combo) {
  896. rect[0].x = rect[1].x = rect[2].x = 0;
  897. rect[3].x = XtWidth(combo) - COMBO_MARGIN_W(combo);
  898. rect[0].y = rect[2].y = rect[3].y = 0 ;
  899. rect[1].y = XtHeight(combo) - COMBO_MARGIN_H(combo);
  900. rect[0].width = rect[1].width = XtWidth(combo);
  901. rect[2].width = rect[3].width = COMBO_MARGIN_W(combo);
  902. rect[0].height = rect[1].height = COMBO_MARGIN_H(combo);
  903. rect[2].height = rect[3].height = XtHeight(combo);
  904. XFillRectangles(XtDisplayOfObject((Widget)combo),
  905. XtWindowOfObject((Widget)combo),
  906. HighlightGC(combo), rect, 4);
  907. }
  908. }
  909. }
  910. /* Add a global variable to avoid the handler to process the
  911. * the ButtonPress which popup the shell
  912. */
  913. static int popup_shell_init=DtNonePopup;
  914. /*
  915. * osfSelect virtual key hit. Simulate hitting the arrow.
  916. */
  917. static void
  918. _ComboBoxActivate( Widget w,
  919. XEvent *event,
  920. char **params,
  921. Cardinal *num_params)
  922. {
  923. DtComboBoxWidget combo;
  924. XmAnyCallbackStruct cb;
  925. if (*num_params == 0) /* no params means combo */
  926. combo = (DtComboBoxWidget)w;
  927. else /* params means label */
  928. {
  929. combo = (DtComboBoxWidget)XtParent(w);
  930. }
  931. _DtProcessLock();
  932. if (event->type == KeyPress)
  933. popup_shell_init = DtKeyPressPopup;
  934. else if (event->type == ButtonPress)
  935. popup_shell_init = DtButtonPressPopup;
  936. else
  937. popup_shell_init = DtPopup;
  938. _DtProcessUnlock();
  939. cb.reason = XmCR_ACTIVATE;
  940. cb.event = event;
  941. activate_cb((Widget)Arrow(combo), (XtPointer)combo, (XtPointer)&cb);
  942. }
  943. /*
  944. * osfCancel virtual key hit.
  945. */
  946. static void
  947. _ComboBoxKbdCancel( Widget w,
  948. XEvent *event,
  949. char **params,
  950. Cardinal *num_params)
  951. {
  952. DtComboBoxWidget combo;
  953. XtPointer data;
  954. Arg args[1];
  955. /* Get combo-box off list data */
  956. XtSetArg(args[0], XmNuserData, &data);
  957. XtGetValues(w, args, 1);
  958. combo = (DtComboBoxWidget)data;
  959. input_ungrab( combo, GRAB_POINTER | GRAB_KEYBOARD );
  960. }
  961. /* #7
  962. * Tab Group Action for Buttons
  963. */
  964. static void
  965. _ComboBoxPrevTabGroup( Widget w,
  966. XEvent *event,
  967. char **params,
  968. Cardinal *num_params)
  969. {
  970. XmProcessTraversal ((Widget)XtParent(w), XmTRAVERSE_PREV_TAB_GROUP);
  971. }
  972. static void
  973. _ComboBoxNextTabGroup( Widget w,
  974. XEvent *event,
  975. char **params,
  976. Cardinal *num_params)
  977. {
  978. XmProcessTraversal ((Widget)XtParent(w), XmTRAVERSE_NEXT_TAB_GROUP);
  979. }
  980. /*
  981. * This function goes through most of the resources and makes sure
  982. * they have legal values.
  983. */
  984. static void
  985. CheckResources( DtComboBoxWidget combo)
  986. {
  987. if ((Alignment(combo) != DtALIGNMENT_CENTER) &&
  988. (Alignment(combo) != DtALIGNMENT_BEGINNING) &&
  989. (Alignment(combo) != DtALIGNMENT_END)) {
  990. XtWarning(CB_ALIGNMENT);
  991. Alignment(combo) = DtALIGNMENT_CENTER;
  992. }
  993. if ((Orientation(combo) != DtLEFT) &&
  994. (Orientation(combo) != DtRIGHT)) {
  995. XtWarning(CB_ORIENTATION);
  996. Orientation(combo) = DtRIGHT;
  997. }
  998. if (ItemCount(combo) < 0) {
  999. XtWarning(CB_ITEM_COUNT);
  1000. ItemCount(combo) = 0;
  1001. }
  1002. if ((SelectedPosition(combo) < 0) ||
  1003. ((SelectedPosition(combo) >= ItemCount(combo)) &&
  1004. (ItemCount(combo) > 0))) {
  1005. XtWarning(CB_VISIBLE_ITEM);
  1006. SelectedPosition(combo) = 0;
  1007. }
  1008. /* NEW: to adjust the size of the list to its content *
  1009. if (ItemCount(combo) < VisibleItemCount(combo))
  1010. VisibleItemCount(combo) = ItemCount(combo); */
  1011. }
  1012. /*
  1013. * Destroy procedure called by the toolkit. Free local resources
  1014. */
  1015. static void
  1016. Destroy(DtComboBoxWidget combo)
  1017. {
  1018. if (LabelString(combo))
  1019. XmStringFree(LabelString(combo));
  1020. if (SelectedItem(combo))
  1021. XmStringFree( SelectedItem(combo) );
  1022. }
  1023. /*
  1024. * Resize function called by toolkit. The size of our combo-box
  1025. * has already been changed. That is why we must store
  1026. * old_width and old_height.
  1027. */
  1028. static void
  1029. Resize(DtComboBoxWidget combo)
  1030. {
  1031. ClearShadow(combo, TRUE);
  1032. LayoutChildren(combo);
  1033. DrawShadow(combo);
  1034. OldWidth(combo) = Width(combo);
  1035. OldHeight(combo) = Height(combo);
  1036. }
  1037. /*
  1038. * Redisplay function called by toolkit. The widget didn't change size,
  1039. * so just redisplay the shadow.
  1040. */
  1041. static void
  1042. Redisplay( DtComboBoxWidget w,
  1043. XEvent *event,
  1044. Region region)
  1045. {
  1046. DrawShadow(w);
  1047. }
  1048. /*
  1049. * GeometryManager function called by toolkit when a child resizes/moves.
  1050. * We are not allowing any changes but width/height of the text-field.
  1051. * this is because the user can retrieve the text-field and make changes
  1052. * that we want to honor. If they mess around with the label or arrow,
  1053. * then we won't honor the request.
  1054. * If the text-field requests a change, then make the change, and allow
  1055. * our SetComboBoxSize() and LayoutChildren() figure out what size will
  1056. * be allowed.
  1057. * Returning GeometryDone was suppose to tell the toolkit
  1058. * that we resized the child ourselves, but the text-field had trouble
  1059. * with this (its' geometry_manager wasn't called or working right?), so
  1060. * we return GeometryYes.
  1061. */
  1062. static XtGeometryResult
  1063. GeometryManager(Widget w,
  1064. XtWidgetGeometry *request,
  1065. XtWidgetGeometry *reply)
  1066. {
  1067. DtComboBoxWidget combo = (DtComboBoxWidget) Parent(w);
  1068. /* Ignore everything but text-field */
  1069. if (w != Text(combo))
  1070. return(XtGeometryNo);
  1071. /* Only allow width/height changes */
  1072. if (!(request->request_mode & (CWWidth | CWHeight)))
  1073. return(XtGeometryNo);
  1074. /* Set the text-field to the requested size */
  1075. if (request->request_mode & CWWidth)
  1076. Width(w) = request->width;
  1077. if (request->request_mode & CWHeight)
  1078. Height(w) = request->height;
  1079. XtResizeWidget(w, Width(w), Height(w), BorderWidth(w));
  1080. ClearShadow(combo, TRUE);
  1081. if (RecomputeSize(combo))
  1082. SetComboBoxSize(combo);
  1083. LayoutChildren(combo);
  1084. DrawShadow(combo);
  1085. return(XtGeometryYes);
  1086. }
  1087. /*
  1088. * This function sets the size of the combo_box widget based on the
  1089. * current size of the children. Don't worry if it doesn't work, the
  1090. * children will be squeezed in later.
  1091. */
  1092. static void
  1093. SetComboBoxSize(DtComboBoxWidget combo)
  1094. {
  1095. Widget text_holder = ((Type(combo) == DtDROP_DOWN_COMBO_BOX) ?
  1096. Text(combo) : Label(combo));
  1097. Dimension shadow = COMBO_SHADOW(combo) * 2;
  1098. Dimension h_spacing = COMBO_H_SPACING(combo) * 2;
  1099. Dimension v_spacing = COMBO_V_SPACING(combo) * 2;
  1100. Dimension arrow_width, text_width, text_height;
  1101. Dimension sep_width = 0;
  1102. XtGeometryResult ResizeResult;
  1103. Arg args[3];
  1104. unsigned char unit_type = XmPIXELS;
  1105. /* Resolution Independent */
  1106. if (MUnitType(combo) != XmPIXELS) {
  1107. unit_type = MUnitType(combo);
  1108. XtSetArg(args[0], XmNunitType, XmPIXELS);
  1109. XtSetValues(text_holder, args, 1);
  1110. if (Type(combo) == DtDROP_DOWN_LIST)
  1111. XtSetValues((Widget)Sep(combo), args, 1);
  1112. }
  1113. /*
  1114. * Find out how big the arrow can be (needed to get
  1115. * available_width for text_holder).
  1116. */
  1117. /* MotifBc */
  1118. XtSetArg(args[0], XmNwidth, &text_width);
  1119. XtSetArg(args[1], XmNheight, &text_height);
  1120. XtGetValues(text_holder, args, 2);
  1121. arrow_width = (Dimension)((float)text_height * ARROW_MULT);
  1122. arrow_width = (arrow_width < ARROW_MIN) ? ARROW_MIN : arrow_width;
  1123. if (Type(combo) == DtDROP_DOWN_LIST) {
  1124. XtSetArg(args[0], XmNwidth, &sep_width);
  1125. XtGetValues((Widget)Sep(combo), args, 1);
  1126. }
  1127. ResizeResult=XtMakeResizeRequest((Widget)combo, arrow_width + sep_width +
  1128. ArrowSpacing(combo) +
  1129. text_width + shadow + h_spacing +
  1130. (COMBO_MARGIN_W(combo) * 2),
  1131. text_height + shadow + v_spacing +
  1132. (COMBO_MARGIN_H(combo) * 2),
  1133. NULL, NULL);
  1134. if (ResizeResult==XtGeometryNo || ResizeResult==XtGeometryAlmost) {
  1135. XtWarning(CB_RESIZE);
  1136. }
  1137. OldWidth(combo) = Width(combo);
  1138. OldHeight(combo) = Height(combo);
  1139. /* Resolution Independent */
  1140. if (unit_type != XmPIXELS) {
  1141. XtSetArg(args[0], XmNunitType, unit_type);
  1142. XtSetValues(text_holder, args, 1);
  1143. if (Type(combo) == DtDROP_DOWN_LIST)
  1144. XtSetValues((Widget)Sep(combo), args, 1);
  1145. }
  1146. }
  1147. /*
  1148. * This function makes the text_holder (label or text-field) smaller
  1149. * if the combo_box couldn't grow to the needed full size. It will
  1150. * also make the text_holder grow if there is space. The textfield will
  1151. * grow with the combo_box, but the label will only grow to its'
  1152. * maximum size. The label will also shrink down to nothing, but the
  1153. * text-field will always keep its' core height.
  1154. */
  1155. static void
  1156. ForceChildSizes(DtComboBoxWidget combo)
  1157. {
  1158. Dimension full_available_height, available_height, available_width;
  1159. Dimension arrow_width;
  1160. Dimension sep_width = 0;
  1161. Dimension tmp_width, tmp_height, tmp_borderwidth;
  1162. Arg args[3];
  1163. unsigned char unit_type = XmPIXELS;
  1164. /* Resolution Independent */
  1165. if (MUnitType(combo) != XmPIXELS) {
  1166. unit_type = MUnitType(combo);
  1167. XtSetArg(args[0], XmNunitType, XmPIXELS);
  1168. if (Type(combo) == DtDROP_DOWN_LIST) {
  1169. XtSetValues(Sep(combo), args, 1);
  1170. XtSetValues(Label(combo), args, 1);
  1171. }
  1172. else
  1173. XtSetValues(Text(combo), args, 1);
  1174. XtSetValues(Arrow(combo), args, 1);
  1175. }
  1176. /* Calculate available height for children */
  1177. if ((available_height = Height(combo) - (COMBO_SHADOW(combo) * 2) -
  1178. (COMBO_MARGIN_H(combo) * 2) - (COMBO_V_SPACING(combo) * 2)) <= 0) {
  1179. full_available_height = available_height = 1;
  1180. }
  1181. else {
  1182. /* Separator need available_height plus the vertical_spacing */
  1183. full_available_height = (available_height +
  1184. (COMBO_V_SPACING(combo) * 2));
  1185. }
  1186. /* Get initial available width for children */
  1187. available_width = (Width(combo) - (COMBO_SHADOW(combo) * 2) -
  1188. (COMBO_MARGIN_W(combo) * 2) -
  1189. (COMBO_H_SPACING(combo) * 2));
  1190. /* label only grows to maximum width needed */
  1191. if ((Type(combo) == DtDROP_DOWN_LIST) &&
  1192. ((int)available_height > (int)LabelMaxHeight(combo)))
  1193. available_height = LabelMaxHeight(combo);
  1194. else if (Type(combo) == DtDROP_DOWN_COMBO_BOX) {
  1195. XtSetArg(args[0], XmNheight, &available_height);
  1196. XtGetValues((Widget)Text(combo), args, 1);
  1197. }
  1198. /*
  1199. * Find out how big the arrow can be (needed to get
  1200. * available_width for text_holder).
  1201. */
  1202. arrow_width = (Dimension)((float)available_height * ARROW_MULT);
  1203. arrow_width = (arrow_width < ARROW_MIN) ? ARROW_MIN : arrow_width;
  1204. if (Type(combo) == DtDROP_DOWN_LIST) {
  1205. XtSetArg(args[0], XmNwidth, &sep_width);
  1206. XtGetValues((Widget)Sep(combo), args, 1);
  1207. }
  1208. /* Make sure width isn't too small or too big */
  1209. if ((available_width -=
  1210. (arrow_width + sep_width + ArrowSpacing(combo) )) <= (Dimension)0)
  1211. available_width = 1;
  1212. /* Motif BC */
  1213. XtSetArg(args[0], XmNwidth, &tmp_width);
  1214. XtSetArg(args[1], XmNheight, &tmp_height);
  1215. XtSetArg(args[2], XmNborderWidth, &tmp_borderwidth);
  1216. if (Type(combo) == DtDROP_DOWN_LIST) { /** label **/
  1217. if ((int)available_width > (int)LabelMaxLength(combo))
  1218. available_width = LabelMaxLength(combo);
  1219. /* Motif BC */
  1220. XtGetValues((Widget)Label(combo), args, 3);
  1221. if ((available_width != tmp_width) ||
  1222. (available_height != tmp_height))
  1223. XtResizeWidget(Label(combo), available_width, available_height,
  1224. tmp_borderwidth);
  1225. /* Motif BC */
  1226. XtGetValues((Widget)Sep(combo), args, 3);
  1227. if (full_available_height != tmp_height)
  1228. XtResizeWidget(Sep(combo), tmp_width, full_available_height,
  1229. tmp_borderwidth);
  1230. }
  1231. else {
  1232. /* Motif BC */
  1233. XtGetValues((Widget)Text(combo), args, 3);
  1234. if ( Width(((Widget)Text(combo))) != available_width) /** TextField **/
  1235. XtResizeWidget(Text(combo), available_width,
  1236. tmp_height, tmp_borderwidth);
  1237. }
  1238. /* Motif BC */
  1239. XtGetValues((Widget)Arrow(combo), args, 3);
  1240. if ((arrow_width != tmp_width) || (tmp_height != available_height)) {
  1241. available_height = (available_height < ARROW_MIN) ? ARROW_MIN :
  1242. available_height;
  1243. XtResizeWidget(Arrow(combo), arrow_width, available_height,
  1244. tmp_borderwidth);
  1245. }
  1246. /* Resolution Independent */
  1247. if (unit_type != XmPIXELS) {
  1248. XtSetArg(args[0], XmNunitType, unit_type);
  1249. if (Type(combo) == DtDROP_DOWN_LIST) {
  1250. XtSetValues(Sep(combo), args, 1);
  1251. XtSetValues(Label(combo), args, 1);
  1252. }
  1253. else
  1254. XtSetValues(Text(combo), args, 1);
  1255. XtSetValues(Arrow(combo), args, 1);
  1256. }
  1257. }
  1258. /*
  1259. * This function positions the children within the combo_box widget.
  1260. * It calls ForceChildSizes() to make sure the children fit within the
  1261. * combo_box widget, but it will not try to resize the combo_box widget.
  1262. */
  1263. static void
  1264. LayoutChildren(DtComboBoxWidget combo)
  1265. {
  1266. Widget text_holder = ((Type(combo) == DtDROP_DOWN_COMBO_BOX)
  1267. ? Text(combo) : Label(combo));
  1268. Position start_x = (COMBO_SHADOW(combo) + COMBO_MARGIN_W(combo) +
  1269. COMBO_H_SPACING(combo));
  1270. Position start_y = (COMBO_SHADOW(combo) + COMBO_MARGIN_H(combo) +
  1271. COMBO_V_SPACING(combo));
  1272. short available_height = Height(combo) - (start_y * 2);
  1273. Position y, arrow_y;
  1274. unsigned char unit_type = XmPIXELS;
  1275. Dimension tmp_width, tmp_height, sep_width;
  1276. Arg args[3];
  1277. ForceChildSizes(combo);
  1278. /* Resolution Independent */
  1279. if (MUnitType(combo) != XmPIXELS) {
  1280. unit_type = MUnitType(combo);
  1281. XtSetArg(args[0], XmNunitType, XmPIXELS);
  1282. XtSetValues(text_holder, args, 1);
  1283. XtSetValues(Arrow(combo), args, 1);
  1284. if (Type(combo) == DtDROP_DOWN_LIST)
  1285. XtSetValues(Sep(combo), args, 1);
  1286. }
  1287. /* Center text_holder within combo_box */
  1288. /* MotifBc */
  1289. XtSetArg(args[0], XmNheight, &tmp_height);
  1290. XtGetValues(text_holder, args, 1);
  1291. y = available_height - tmp_height;
  1292. y = ((y < 0) ? 0 : y)/2 + start_y;
  1293. /* Center arrow within combo_box */
  1294. /* MotifBc */
  1295. XtSetArg(args[1], XmNwidth, &tmp_width);
  1296. XtGetValues(Arrow(combo), args, 2);
  1297. arrow_y = available_height - tmp_height;
  1298. arrow_y = ((arrow_y < 0) ? 0 : arrow_y)/2 + start_y;
  1299. /* MotifBc */
  1300. if (Type(combo) == DtDROP_DOWN_LIST) {
  1301. XtSetArg(args[0], XmNwidth, &sep_width);
  1302. XtGetValues(Sep(combo), args, 1);
  1303. }
  1304. if (Orientation(combo) == DtLEFT) {
  1305. XtMoveWidget(Arrow(combo), start_x, arrow_y);
  1306. start_x += tmp_width;
  1307. if (Type(combo) == DtDROP_DOWN_LIST) {
  1308. XtMoveWidget(Sep(combo), start_x, start_y -
  1309. COMBO_V_SPACING(combo));
  1310. start_x += sep_width;
  1311. }
  1312. start_x += ArrowSpacing(combo);
  1313. XtMoveWidget(text_holder, start_x, y);
  1314. }
  1315. else {
  1316. XtMoveWidget(text_holder, start_x, y);
  1317. /*
  1318. * We want the arrow at the end of the combo_box, so
  1319. * the user can use recompute_size more effectively.
  1320. */
  1321. start_x = Width(combo) - start_x - tmp_width;
  1322. if (Type(combo) == DtDROP_DOWN_LIST) {
  1323. start_x -= sep_width;
  1324. XtMoveWidget(Sep(combo), start_x, start_y -
  1325. COMBO_V_SPACING(combo));
  1326. start_x += sep_width;
  1327. }
  1328. XtMoveWidget(Arrow(combo), start_x, arrow_y);
  1329. }
  1330. /* Resolution Independent */
  1331. if (unit_type != XmPIXELS) {
  1332. XtSetArg(args[0], XmNunitType, unit_type);
  1333. XtSetValues(text_holder, args, 1);
  1334. XtSetValues(Arrow(combo), args, 1);
  1335. if (Type(combo) == DtDROP_DOWN_LIST)
  1336. XtSetValues(Sep(combo), args, 1);
  1337. }
  1338. }
  1339. /*
  1340. * SetValues() routine for ComboBox widget.
  1341. */
  1342. static Boolean
  1343. SetValues( DtComboBoxWidget current,
  1344. DtComboBoxWidget request,
  1345. DtComboBoxWidget new)
  1346. {
  1347. DtComboBoxPart *new_p = (DtComboBoxPart*)
  1348. &(XmField(new,ipot,DtComboBox,arrow,Widget));
  1349. Boolean label_size_changed = FALSE;
  1350. Boolean force_label_string = FALSE;
  1351. Arg args[10];
  1352. int n;
  1353. unsigned char new_unit_type = XmPIXELS, curr_unit_type = XmPIXELS;
  1354. CheckResources(new);
  1355. /* Resolution Independent */
  1356. if (MUnitType(new) != XmPIXELS) {
  1357. new_unit_type = MUnitType(new);
  1358. XtSetArg(args[0], XmNunitType, XmPIXELS);
  1359. if (Arrow(new)) XtSetValues(Arrow(new), args, 1);
  1360. if (List(new)) XtSetValues(List(new), args, 1);
  1361. if (Shell(new)) XtSetValues(Shell(new), args, 1);
  1362. if (Label(new)) XtSetValues(Label(new), args, 1);
  1363. if (Text(new)) XtSetValues(Text(new), args, 1);
  1364. if (Sep(new)) XtSetValues(Sep(new), args, 1);
  1365. }
  1366. if (MUnitType(current) != XmPIXELS) {
  1367. curr_unit_type = MUnitType(current);
  1368. XtSetArg(args[0], XmNunitType, XmPIXELS);
  1369. if (Arrow(current)) XtSetValues(Arrow(current), args, 1);
  1370. if (List(current)) XtSetValues(List(current), args, 1);
  1371. if (Shell(current)) XtSetValues(Shell(current), args, 1);
  1372. if (Label(current)) XtSetValues(Label(current), args, 1);
  1373. if (Text(current)) XtSetValues(Text(current), args, 1);
  1374. if (Sep(current)) XtSetValues(Sep(current), args, 1);
  1375. }
  1376. if (Text(new) != Text(current)) {
  1377. XtWarning(CB_TEXT);
  1378. Text(new) = Text(current);
  1379. }
  1380. /*
  1381. * Pass any list specific resources on to our List Widget.
  1382. * Check each one, since it's too costly to always set them.
  1383. */
  1384. n = 0;
  1385. if (ItemCount(new) != ItemCount(current)){
  1386. if (Items(new) && (ItemCount(new) < 0)) {
  1387. XtWarning(CB_ITEM_COUNT);
  1388. ItemCount(new) = 0;
  1389. }
  1390. XtSetArg(args[n], XmNitemCount, ItemCount(new)); n++;
  1391. }
  1392. if (Items(new) != ListItems(current)) {
  1393. XtSetArg(args[n], XmNitems, Items(new)); n++;
  1394. /* Make sure itemCount will get sent to list */
  1395. if (ItemCount(new) == ItemCount(current)) {
  1396. XtSetArg(args[n], XmNitemCount, ItemCount(new)); n++;
  1397. }
  1398. }
  1399. if (ListFontList(new) != ListFontList(current)) {
  1400. XtSetArg(args[n], XmNfontList, ListFontList(new)); n++;
  1401. }
  1402. if (ListMarginHeight(new) != ListMarginHeight(current)) {
  1403. XtSetArg(args[n], XmNlistMarginHeight, ListMarginHeight(new)); n++;
  1404. }
  1405. if (ListMarginWidth(new) != ListMarginWidth(current)) {
  1406. XtSetArg(args[n], XmNlistMarginWidth, ListMarginWidth(new)); n++;
  1407. }
  1408. if (ListSpacing(new) != ListSpacing(current)) {
  1409. XtSetArg(args[n], XmNlistSpacing, ListSpacing(new)); n++;
  1410. }
  1411. if (LayoutDirection(new) != LayoutDirection(current)) {
  1412. XmStringDirection new_direction =
  1413. XmDirectionToStringDirection(LayoutDirection(new));
  1414. XtSetArg(args[n], XmNstringDirection, new_direction); n++;
  1415. }
  1416. if (TopItemPosition(new) != TopItemPosition(current)) {
  1417. XtSetArg(args[n], XmNtopItemPosition, TopItemPosition(new)); n++;
  1418. }
  1419. if (VisibleItemCount(new) != VisibleItemCount(current)) {
  1420. XtSetArg(args[n], XmNvisibleItemCount, VisibleItemCount(new)); n++;
  1421. }
  1422. if (n > 0) {
  1423. /* MotifBc */
  1424. Arg tmp_arg[2];
  1425. Dimension tmp_width, tmp_height;
  1426. XtSetValues(List(new), args, n);
  1427. /* MotifBc */
  1428. XtSetArg(tmp_arg[0], XmNwidth, &tmp_width);
  1429. XtSetArg(tmp_arg[1], XmNheight, &tmp_height);
  1430. XtGetValues(((Widget) Shell(new)), tmp_arg, 2);
  1431. MaxShellWidth(new) = tmp_width;
  1432. MaxShellHeight(new) = tmp_height;
  1433. }
  1434. /* If arrow type changes delete the old one and create the new one */
  1435. if (ArrowType(new) != ArrowType(current)) {
  1436. XtRemoveCallback(Arrow(new), XmNactivateCallback, activate_cb,
  1437. (XtPointer)new);
  1438. if (ArrowType(current) == DtWINDOWS)
  1439. XtRemoveCallback(Arrow(new), XmNexposeCallback,
  1440. arrow_expose_cb, (XtPointer)new);
  1441. XtDestroyWidget(Arrow(new));
  1442. n = 0;
  1443. XtSetArg(args[n], XmNtraversalOn, FALSE); n++;
  1444. XtSetArg(args[n], XmNhighlightThickness, 0); n++;
  1445. XtSetArg(args[n], XmNshadowThickness, 0); n++;
  1446. if (ArrowType(new) == DtMOTIF) {
  1447. XtSetArg(args[n], XmNarrowDirection, XmARROW_DOWN); n++;
  1448. XtSetArg(args[n], XmNforeground, BackgroundPixel(new)); n++;
  1449. Arrow(new) = XtCreateManagedWidget("ComboBoxArrow",
  1450. xmArrowButtonWidgetClass,
  1451. (Widget)new, args, n);
  1452. }
  1453. else {
  1454. Arrow(new) = XtCreateManagedWidget("ComboBoxArrow",
  1455. xmDrawnButtonWidgetClass,
  1456. (Widget)new, args, n);
  1457. XtAddCallback(Arrow(new), XmNexposeCallback, arrow_expose_cb,
  1458. (XtPointer)new);
  1459. }
  1460. XtAddCallback(Arrow(new), XmNactivateCallback, activate_cb,
  1461. (XtPointer)new);
  1462. }
  1463. /*
  1464. * Type resource changed. If the widget (textField or Label)
  1465. * doesn't exist, then create it. Always reset orientation
  1466. * constraint resources when type changes; otherwise, the
  1467. * text_holder widget positioning could be screwed up. We don't
  1468. * reset both widgets if the orientation changes (because we might
  1469. * not have created both widgets).
  1470. * If label must be created, also create the separator widget.
  1471. */
  1472. if (Type(new) != Type(current)) {
  1473. if (Type(new) == DtDROP_DOWN_COMBO_BOX) {
  1474. if (Text(new) == NULL) {
  1475. n = 0;
  1476. XtSetArg(args[n], XmNcolumns, TextColumns(new)); n++;
  1477. XtSetArg(args[n], XmNmaxLength, TextMaxLength(new)); n++;
  1478. XtSetArg(args[n], XmNmarginWidth, 2); n++;
  1479. XtSetArg(args[n], XmNmarginHeight, 2); n++;
  1480. Text(new) = XtCreateWidget("ComboBoxTextField",
  1481. xmTextFieldWidgetClass,
  1482. (Widget)new, args, n);
  1483. XtAddCallback(Text(new), XmNlosingFocusCallback,
  1484. text_losing_focus_cb, (XtPointer)new);
  1485. XtAddCallback(Text(new), XmNactivateCallback,
  1486. text_activate_cb, (XtPointer)new);
  1487. XtAddCallback(Text(new), XmNfocusCallback,
  1488. text_focus_cb, (XtPointer)new);
  1489. if (HorizontalSpacing(new) == HorizontalSpacing(current))
  1490. HorizontalSpacing(new) = 0;
  1491. if (VerticalSpacing(new) == VerticalSpacing(current))
  1492. VerticalSpacing(new) = 0;
  1493. }
  1494. XtUnmanageChild(Sep(new));
  1495. XtUnmanageChild(Label(new));
  1496. XtManageChild(Text(new));
  1497. }
  1498. else {
  1499. if (Label(new) == NULL) {
  1500. XmStringDirection new_direction =
  1501. XmDirectionToStringDirection(LayoutDirection(new));
  1502. XtTranslations label_trans =
  1503. XtParseTranslationTable(ComboBoxLabelTranslationTable);
  1504. n = 0;
  1505. XtSetArg(args[n], XmNalignment, Alignment(new)); n++;
  1506. XtSetArg(args[n], XmNrecomputeSize, FALSE); n++;
  1507. XtSetArg(args[n], XmNmarginLeft, LABEL_PADDING); n++;
  1508. XtSetArg(args[n], XmNmarginRight, LABEL_PADDING); n++;
  1509. XtSetArg(args[n], XmNmarginWidth, TEXT_CONTEXT_MARGIN); n++;
  1510. XtSetArg(args[n], XmNmarginHeight, 0); n++;
  1511. XtSetArg(args[n], XmNstringDirection, new_direction); n++;
  1512. Label(new) = XtCreateWidget("ComboBoxLabel",
  1513. xmLabelWidgetClass,
  1514. (Widget)new, args, n);
  1515. XtOverrideTranslations((Widget)Label(new), label_trans);
  1516. if (HorizontalSpacing(new) == HorizontalSpacing(current))
  1517. HorizontalSpacing(new) = 1;
  1518. if (VerticalSpacing(new) == VerticalSpacing(current))
  1519. VerticalSpacing(new) = 2;
  1520. n = 0;
  1521. XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
  1522. Sep(new) = XtCreateWidget("ComboBoxSeparator",
  1523. xmSeparatorWidgetClass,
  1524. (Widget)new, args, n);
  1525. }
  1526. else if (LayoutDirection(new) != LayoutDirection(current)) {
  1527. XmStringDirection new_direction =
  1528. XmDirectionToStringDirection(LayoutDirection(new));
  1529. XtSetArg(args[0], XmNstringDirection, new_direction);
  1530. XtSetValues(Label(new), args, 1);
  1531. }
  1532. XtUnmanageChild(Text(new));
  1533. XtManageChild(Label(new));
  1534. XtManageChild(Sep(new));
  1535. }
  1536. /*
  1537. * Text-fields and labels have different shadows. Only
  1538. * change if user didn't change the shadow resource.
  1539. */
  1540. if (COMBO_SHADOW(new) == COMBO_SHADOW(current))
  1541. COMBO_SHADOW(new) = ((Type(new) == DtDROP_DOWN_COMBO_BOX) ?
  1542. TEXT_FIELD_SHADOW : LABEL_SHADOW);
  1543. }
  1544. if (Text(new) && (Text(new) == Text(current))) {
  1545. n = 0;
  1546. if (TextColumns(new) != TextColumns(current)) {
  1547. XtSetArg(args[n], XmNcolumns, TextColumns(new)); n++;
  1548. }
  1549. if (TextMaxLength(new) != TextMaxLength(current) ) {
  1550. XtSetArg(args[n], XmNmaxLength, TextMaxLength(new)); n++;
  1551. }
  1552. if (n > 0)
  1553. XtSetValues(Text(new), args, n);
  1554. }
  1555. /*
  1556. * LabelWidget alignment has changed.
  1557. */
  1558. if (Label(new) && (Alignment(new) != Alignment(current))) {
  1559. XtSetArg(args[0], XmNalignment, Alignment(new));
  1560. XtSetValues(Label(new), args, 1);
  1561. }
  1562. if (Label(new) && ((Items(new) != ListItems(current)) ||
  1563. (ItemCount(new) != ItemCount(current)) ||
  1564. (Label(new) != Label(current)))) {
  1565. SetMaximumLabelSize(new_p);
  1566. label_size_changed = TRUE;
  1567. }
  1568. /* Copy and free label-string */
  1569. if (LabelString(new) != LabelString(current)) {
  1570. if (LabelString(new))
  1571. LabelString(new) = XmStringCopy(LabelString(new));
  1572. if (LabelString(current))
  1573. XmStringFree(LabelString(current));
  1574. /*
  1575. * force_label_string usage if it is specified and items is not.
  1576. * This will be the perminant label string only if update-label
  1577. * is false, else it is only used until the user picks something
  1578. * new off the list.
  1579. */
  1580. if (Items(new) == ListItems(current))
  1581. force_label_string = TRUE;
  1582. }
  1583. if ((Items(new) != ListItems(current)) ||
  1584. (Alignment(new) != Alignment(current)) ||
  1585. (Type(new) != Type(current)) ||
  1586. (ItemCount(new) != ItemCount(current)) ||
  1587. (SelectedPosition(new) != SelectedPosition(current)) ||
  1588. (XmStringByteCompare(SelectedItem(new), SelectedItem(current))!=True) ||
  1589. (Label(new) != Label(current)) ||
  1590. (UpdateLabel(new) != UpdateLabel(current)) ||
  1591. (LabelString(new) != LabelString(current))) {
  1592. /* selected_item resource used before selected_position */
  1593. if (SelectedItem(new) && XmeStringIsValid(SelectedItem(new)) &&
  1594. (XmStringByteCompare(SelectedItem(new),
  1595. SelectedItem(current))!=True) ){
  1596. if (SelectedItem(current)) {
  1597. XmStringFree(SelectedItem(current));
  1598. SelectedItem(current) = NULL;
  1599. }
  1600. SelectedItem(new) = XmStringCopy(SelectedItem(new));
  1601. DtComboBoxSelectItem((Widget)new, SelectedItem(new));
  1602. }
  1603. else {
  1604. if (SelectedPosition(new)<0||SelectedPosition(new)>=ItemCount(new))
  1605. SelectedPosition(new) = 0;
  1606. if ((ItemCount(new)) &&
  1607. (SelectedPosition(new) != SelectedPosition(current))) {
  1608. XmListSelectPos(List(new), SelectedPosition(new) + 1, FALSE);
  1609. if (SelectedItem(current)) {
  1610. XmStringFree(SelectedItem(current));
  1611. SelectedItem(current) = NULL;
  1612. }
  1613. SyncWithList(new_p);
  1614. SelectedItem(new) =
  1615. XmStringCopy((ListItems(new))[SelectedPosition(new)]);
  1616. }
  1617. /* Else, same item selected as last time */
  1618. else {
  1619. SelectedItem(new) = XmStringCopy(SelectedItem(new));
  1620. if ((SelectedItem(new) != NULL) && (ListItems(new) != NULL))
  1621. DtComboBoxSelectItem((Widget)new, SelectedItem(new));
  1622. if (SelectedItem(current)) {
  1623. XmStringFree(SelectedItem(current));
  1624. SelectedItem(current) = NULL;
  1625. }
  1626. }
  1627. }
  1628. if (Type(new) == DtDROP_DOWN_COMBO_BOX)
  1629. SetTextFieldData(new_p, NULL);
  1630. else
  1631. SetLabelData(new_p, NULL, force_label_string);
  1632. }
  1633. /* Else, same item selected as last time */
  1634. else {
  1635. SelectedItem(new) = XmStringCopy(SelectedItem(new));
  1636. if ((SelectedItem(new) != NULL) && (ListItems(new) != NULL))
  1637. DtComboBoxSelectItem((Widget)new, SelectedItem(new));
  1638. if (SelectedItem(current)) {
  1639. XmStringFree(SelectedItem(current));
  1640. SelectedItem(current) = NULL;
  1641. }
  1642. }
  1643. /*
  1644. * Must recalculate the combo_box and re-layout the children.
  1645. * If this is not editable, then set the label to its' maximum
  1646. * size; it will get chopped if it is too big. This is needed
  1647. * because we shrink the label down, and SetComboBoxSize() uses
  1648. * the label's core sizes to figure what size to become.
  1649. */
  1650. if ((Type(new) != Type(current)) ||
  1651. (ArrowType(new) != ArrowType(current)) ||
  1652. (COMBO_MARGIN_W(new) != COMBO_MARGIN_W(current)) ||
  1653. (COMBO_MARGIN_H(new) != COMBO_MARGIN_H(current)) ||
  1654. (COMBO_H_SPACING(new) != COMBO_H_SPACING(current)) ||
  1655. (COMBO_V_SPACING(new) != COMBO_V_SPACING(current)) ||
  1656. (COMBO_SHADOW(new) != COMBO_SHADOW(current)) ||
  1657. (Orientation(new) != Orientation(current)) ||
  1658. (ArrowSpacing(new) != ArrowSpacing(current)) ||
  1659. ((Type(new) == DtDROP_DOWN_LIST) && label_size_changed)) {
  1660. ClearShadow(current, TRUE);
  1661. if (RecomputeSize(new))
  1662. SetComboBoxSize(new);
  1663. LayoutChildren(new);
  1664. DrawShadow(new);
  1665. }
  1666. SyncWithList(new_p);
  1667. /* Resolution Independent */
  1668. if (new_unit_type != XmPIXELS) {
  1669. XtSetArg(args[0], XmNunitType, new_unit_type);
  1670. if (Arrow(new)) XtSetValues(Arrow(new), args, 1);
  1671. if (List(new)) XtSetValues(List(new), args, 1);
  1672. if (Shell(new)) XtSetValues(Shell(new), args, 1);
  1673. if (Label(new)) XtSetValues(Label(new), args, 1);
  1674. if (Text(new)) XtSetValues(Text(new), args, 1);
  1675. if (Sep(new)) XtSetValues(Sep(new), args, 1);
  1676. }
  1677. if (curr_unit_type != XmPIXELS) {
  1678. XtSetArg(args[0], XmNunitType, curr_unit_type);
  1679. if (Arrow(current)) XtSetValues(Arrow(current), args, 1);
  1680. if (List(current)) XtSetValues(List(current), args, 1);
  1681. if (Shell(current)) XtSetValues(Shell(current), args, 1);
  1682. if (Label(current)) XtSetValues(Label(current), args, 1);
  1683. if (Text(current)) XtSetValues(Text(current), args, 1);
  1684. if (Sep(current)) XtSetValues(Sep(current), args, 1);
  1685. }
  1686. return(FALSE);
  1687. }
  1688. /*
  1689. * This function clears the shadow around our widget. If all is TRUE,
  1690. * then clear all 4 sides; otherwise, only clear the right and bottom
  1691. * sides (during resize).
  1692. */
  1693. static void
  1694. ClearShadow( DtComboBoxWidget w,
  1695. Boolean all)
  1696. {
  1697. Dimension shadow = COMBO_SHADOW(w);
  1698. Dimension margin_w = COMBO_MARGIN_W(w);
  1699. Dimension margin_h = COMBO_MARGIN_H(w);
  1700. if ((shadow > 0) && XtIsRealized((Widget)w)) {
  1701. if (all) {
  1702. XClearArea(XtDisplayOfObject((Widget)w),
  1703. XtWindowOfObject((Widget)w),
  1704. margin_w, margin_h,
  1705. OldWidth(w) - (margin_w * 2),
  1706. shadow, FALSE);
  1707. XClearArea(XtDisplayOfObject((Widget)w),
  1708. XtWindowOfObject((Widget)w),
  1709. margin_w, margin_h, shadow,
  1710. OldHeight(w) - (margin_h * 2), FALSE);
  1711. }
  1712. XClearArea(XtDisplayOfObject((Widget)w),
  1713. XtWindowOfObject((Widget)w), margin_w,
  1714. OldHeight(w) - margin_h - shadow,
  1715. OldWidth(w) - (margin_w * 2), shadow, FALSE);
  1716. XClearArea(XtDisplayOfObject((Widget)w), XtWindowOfObject((Widget)w),
  1717. OldWidth(w) - margin_w - shadow,
  1718. margin_h, shadow,
  1719. OldHeight(w) - (margin_h * 2), FALSE);
  1720. }
  1721. DrawHighlight(w, TRUE);
  1722. }
  1723. /*
  1724. * This functions draws the shadow around our combo-box.
  1725. */
  1726. static void
  1727. DrawShadow(DtComboBoxWidget w)
  1728. {
  1729. Dimension shadow = COMBO_SHADOW(w);
  1730. Dimension margin_w = COMBO_MARGIN_W(w);
  1731. Dimension margin_h = COMBO_MARGIN_H(w);
  1732. if ((shadow > 0) && XtIsRealized((Widget)w)) {
  1733. XmeDrawShadows(XtDisplayOfObject((Widget)w),
  1734. XtWindowOfObject((Widget)w),
  1735. TopShadowGC(w),
  1736. BottomShadowGC(w),
  1737. margin_w, margin_h,
  1738. Width(w) - (margin_w * 2),
  1739. Height(w) - (margin_h * 2),
  1740. shadow, XmSHADOW_OUT);
  1741. }
  1742. DrawHighlight(w, FALSE);
  1743. }
  1744. /*
  1745. * Take the string out of the list and put it into the text-field.
  1746. * text-fields don't handle xm-strings, so we must get the char*
  1747. * out of it (only getting the first segment). This is slower than
  1748. * storing the text-strings (char*) ourselves, but that would take
  1749. * up a lot of memory. Since this setting happens during a user
  1750. * action, speed isn't a problem.
  1751. */
  1752. static void
  1753. SetTextFieldData(DtComboBoxPart *combo_p, XmString item)
  1754. {
  1755. XmListWidget list = (XmListWidget)combo_p->list;
  1756. XmStringContext context;
  1757. Boolean done = FALSE;
  1758. Arg args[2];
  1759. XmStringComponentType type;
  1760. char *text;
  1761. XmStringCharSet charset;
  1762. XmStringDirection direction;
  1763. XmStringComponentType unknown_tag;
  1764. unsigned short ul;
  1765. unsigned char *uv;
  1766. XmStringTable list_items;
  1767. int item_count;
  1768. Boolean isItemCopied = FALSE;
  1769. /* MotifBc
  1770. */
  1771. XtSetArg(args[0], XmNitemCount, &item_count);
  1772. XtSetArg(args[1], XmNitems, &list_items);
  1773. XtGetValues((Widget)list, args, 2);
  1774. if (item_count && item_count>combo_p->selected_position &&
  1775. !item && list_items) {
  1776. item = XmStringCopy(list_items[combo_p->selected_position]);
  1777. isItemCopied = TRUE;
  1778. }
  1779. if (!item) {
  1780. combo_p->selected_item = NULL;
  1781. XtSetArg(args[0], XmNvalue, "");
  1782. XtSetValues(combo_p->text, args, 1);
  1783. }
  1784. else {
  1785. if (combo_p->selected_item != item)
  1786. {
  1787. if (combo_p->selected_item)
  1788. XmStringFree (combo_p->selected_item);
  1789. combo_p->selected_item = XmStringCopy(item);
  1790. }
  1791. XmStringInitContext(&context, item);
  1792. /* Loop until 1st char* found */
  1793. while (!done) {
  1794. type = XmStringGetNextComponent(context, &text, &charset,
  1795. &direction, &unknown_tag,
  1796. &ul, &uv);
  1797. switch (type) {
  1798. case XmSTRING_COMPONENT_END:
  1799. done = TRUE;
  1800. break;
  1801. case XmSTRING_COMPONENT_TEXT:
  1802. case XmSTRING_COMPONENT_LOCALE_TEXT:
  1803. XtSetArg(args[0], XmNvalue, text);
  1804. XtSetValues(combo_p->text, args, 1);
  1805. XtFree(text);
  1806. done = TRUE;
  1807. break;
  1808. default:
  1809. break;
  1810. }
  1811. }
  1812. XmStringFreeContext(context);
  1813. if (isItemCopied)
  1814. XmStringFree(item);
  1815. }
  1816. }
  1817. /*
  1818. * Set the maximum size of the label, depending on the
  1819. * characteristics of the list of items.
  1820. */
  1821. static void
  1822. SetMaximumLabelSize(DtComboBoxPart *combo_p)
  1823. {
  1824. XmListWidget list = (XmListWidget)combo_p->list;
  1825. XmFontList font_list;
  1826. Dimension width, height, border_width;
  1827. Dimension longest = 0;
  1828. Dimension highest = 0;
  1829. Arg args[5];
  1830. int i, item_count;
  1831. XmStringTable list_items;
  1832. unsigned char unit_type = XmPIXELS;
  1833. /* Resolution Independent */
  1834. XtSetArg(args[0], XmNunitType, &unit_type);
  1835. XtGetValues(combo_p->list, args, 1); /* Assume list/Combo has same uniType*/
  1836. if (unit_type != XmPIXELS) {
  1837. XtSetArg(args[0], XmNunitType, XmPIXELS);
  1838. XtSetValues(combo_p->label, args, 1);
  1839. XtSetValues(combo_p->list, args, 1);
  1840. }
  1841. /* Get font info from the widget */
  1842. XtSetArg(args[0], XmNfontList, &font_list);
  1843. XtGetValues(combo_p->label, args, 1);
  1844. /* MotifBc
  1845. */
  1846. XtSetArg(args[0], XmNitems, &list_items);
  1847. XtSetArg(args[1], XmNitemCount, &item_count);
  1848. XtGetValues((Widget)list, args, 2);
  1849. if ( item_count && item_count >= combo_p->item_count &&
  1850. list_items && combo_p->update_label) {
  1851. /*
  1852. * Loop through all the items to find the biggest dimensions
  1853. */
  1854. for (i = 0; i < combo_p->item_count; i++) {
  1855. XmStringExtent(font_list, list_items[i], &width, &height);
  1856. longest = (width > longest) ? width : longest;
  1857. highest = (height > highest) ? height : highest;
  1858. }
  1859. }
  1860. else {
  1861. XmStringExtent(font_list, combo_p->label_string, &longest, &highest);
  1862. }
  1863. combo_p->label_max_length = longest + ((LABEL_PADDING+TEXT_CONTEXT_MARGIN) * 2);
  1864. combo_p->label_max_height = highest;
  1865. /* MotifBc */
  1866. XtSetArg(args[0], XmNborderWidth, &border_width);
  1867. XtGetValues(combo_p->label, args, 1);
  1868. XtResizeWidget(combo_p->label, combo_p->label_max_length, highest,
  1869. border_width);
  1870. /* Resolution Independent */
  1871. if (unit_type != XmPIXELS) {
  1872. XtSetArg(args[0], XmNunitType, unit_type);
  1873. XtSetValues(combo_p->label, args, 1);
  1874. XtSetValues(combo_p->list, args, 1);
  1875. }
  1876. }
  1877. /*
  1878. * Put the current list item into the label.
  1879. * This could probably be faster if we see if the label is the
  1880. * same as the new item?
  1881. */
  1882. static void
  1883. SetLabelData( DtComboBoxPart *combo_p,
  1884. XmString item,
  1885. Boolean force_label_string)
  1886. {
  1887. XmListWidget list = (XmListWidget)combo_p->list;
  1888. int index = combo_p->selected_position;
  1889. Arg args[2];
  1890. XmStringTable list_items;
  1891. int item_count;
  1892. /*
  1893. * If the item is empty, get the current item from the list, or
  1894. * use label_string if update_label is FALSE. If that is empty,
  1895. * use InitLabel.
  1896. */
  1897. if (force_label_string || (combo_p->update_label == FALSE))
  1898. item = combo_p->label_string ? combo_p->label_string : InitLabel;
  1899. else {
  1900. if (!item) {
  1901. /* MotifBc
  1902. */
  1903. XtSetArg(args[0], XmNitemCount, &item_count);
  1904. XtSetArg(args[1], XmNitems, &list_items);
  1905. XtGetValues((Widget)list, args, 2);
  1906. if (item_count && item_count>index && list_items)
  1907. item = list_items[index];
  1908. else
  1909. item = InitLabel;
  1910. }
  1911. /* Keep label_string in sync with item picked */
  1912. if (combo_p->label_string)
  1913. XmStringFree(combo_p->label_string);
  1914. combo_p->label_string = XmStringCopy(item);
  1915. }
  1916. combo_p->selected_item = XmStringCopy(item);
  1917. XtSetArg(args[0], XmNlabelString, item);
  1918. XtSetValues(combo_p->label, args, 1);
  1919. }
  1920. /*
  1921. * This is the browseSelect and defaultAction callback handler for the
  1922. * ListWidget. If using the textWidget, we only take the first
  1923. * segment of the XmString (TextWidgets don't handle XmStrings). If we
  1924. * are using a label, then just set the labelString resource.
  1925. */
  1926. static void
  1927. select_cb( Widget w,
  1928. XtPointer client_data,
  1929. XtPointer call_data)
  1930. {
  1931. DtComboBoxWidget combo_w = (DtComboBoxWidget)client_data;
  1932. DtComboBoxPart *combo_p = (DtComboBoxPart*)
  1933. &(XmField(combo_w,ipot,DtComboBox,arrow,Widget));
  1934. XmListCallbackStruct *info = (XmListCallbackStruct*)call_data;
  1935. DtComboBoxCallbackStruct cb;
  1936. SelectedPosition(combo_w) = info->item_position - 1;
  1937. if (SelectedItem(combo_w))
  1938. XmStringFree(SelectedItem(combo_w));
  1939. SelectedItem(combo_w) = XmStringCopy(info->item);
  1940. if (Type(combo_w) == DtDROP_DOWN_COMBO_BOX) {
  1941. SetTextFieldData(combo_p, SelectedItem(combo_w));
  1942. }
  1943. else { /* Set the labelWidget string */
  1944. SetLabelData(combo_p, SelectedItem(combo_w), FALSE);
  1945. }
  1946. /*
  1947. * Only popdown if this is the defaultAction callback. We don't
  1948. * want to popdown with browseSelect callback; that would cause the
  1949. * menu to popdown when the user moved selection with the keyboard.
  1950. * Doing it this way, allows the menu to stay up during
  1951. * keyboard navigation. When menu goes away, make sure input
  1952. * focus goes back into the textField (if editable).
  1953. */
  1954. /* This is one of three places to popdown the menu and here is
  1955. * to pop it down by Keyboard input: KSelect
  1956. * Another place using keyboard input to popdown the menu is
  1957. * in _ComboBoxKbdCancel() by <Key>osfEsc
  1958. * the last place is in shell_event_handler and that is for
  1959. * poping down through Button operation: BSelect
  1960. */
  1961. if (info->reason == XmCR_DEFAULT_ACTION)
  1962. input_ungrab( combo_w, GRAB_POINTER | GRAB_KEYBOARD );
  1963. if ( ShellPoppedUp(((ShellWidget)Shell(combo_w))) == FALSE) {
  1964. /* The list will free info->item */
  1965. /* The semantic of a DtNselectionCallback is:
  1966. * a callback to here + ShellPoppedUp==False
  1967. * In reality, there are two scenario for this:
  1968. * 1. XmList's XmNdefaultActionCallback which is activated by
  1969. * KSelect, will first pop down the shell (see above) and
  1970. * and then get here.
  1971. * 2. BSelect on XmList, which first call the list_event_handler()
  1972. * (for the handler is registered as LIST_HEAD) to pop down
  1973. * the shell, and then call XmList's XmNbrowseSelectionCallback
  1974. * which in turn get here
  1975. */
  1976. cb.reason = DtCR_SELECT;
  1977. cb.event = info->event;
  1978. cb.item_or_text = XmStringCopy(info->item);
  1979. cb.item_position = SelectedPosition(combo_w);
  1980. XtCallCallbackList((Widget)combo_w, SelectionCallback(combo_w),
  1981. (XtPointer)&cb);
  1982. if (cb.item_or_text != NULL) {
  1983. XmStringFree(cb.item_or_text);
  1984. cb.item_or_text = NULL;
  1985. }
  1986. }
  1987. }
  1988. /*
  1989. * This is the event_handler for our shell widget. The grab happens
  1990. * on the shell while the user is not doing anything inside the list.
  1991. * This allows us to know if the user pressed a button outside our
  1992. * application. If the user pressed a button anywhere but inside
  1993. * the shell, then popdown the menu and ungrab everything.
  1994. */
  1995. static void
  1996. shell_event_handler( Widget widget,
  1997. XtPointer client_data,
  1998. XEvent* event,
  1999. Boolean *dispatch)
  2000. {
  2001. DtComboBoxWidget combo_w = (DtComboBoxWidget)client_data;
  2002. XmScrolledWindowWidget sw = (XmScrolledWindowWidget)XtParent(List(combo_w));
  2003. XmScrollBarWidget v_scrollbar;
  2004. XmScrollBarWidget h_scrollbar;
  2005. Window window = event->xbutton.window;
  2006. Arg args[2];
  2007. _DtProcessLock();
  2008. if (popup_shell_init) {
  2009. if (popup_shell_init != DtKeyPressPopup) {
  2010. /* Menu popped up by ButtonPress */
  2011. popup_shell_init = DtNonePopup;
  2012. _DtProcessUnlock();
  2013. return;
  2014. }
  2015. else
  2016. /* Menu popped up by KActivate */
  2017. popup_shell_init = DtNonePopup;
  2018. }
  2019. _DtProcessUnlock();
  2020. /* MotifBc */
  2021. XtSetArg(args[0], XmNverticalScrollBar, &v_scrollbar);
  2022. XtSetArg(args[1], XmNhorizontalScrollBar, &h_scrollbar);
  2023. XtGetValues((Widget)sw, args, 2);
  2024. /* condition : Shell is popped up;
  2025. * ButtonPress event;
  2026. * the cursor is Not inside the XmList area,
  2027. * the horizontal scrollbar or the vertical one;
  2028. * action: remove all the grabs by DtComboBox
  2029. */
  2030. if ( ShellPoppedUp(((ShellWidget)Shell(combo_w))) &&
  2031. (event->type == ButtonPress &&
  2032. (window != XtWindowOfObject(List(combo_w))) &&
  2033. !(ScrollBarVisible((Widget)h_scrollbar) &&
  2034. (window == XtWindowOfObject((Widget)h_scrollbar))) &&
  2035. !(ScrollBarVisible((Widget)v_scrollbar) &&
  2036. (window == XtWindowOfObject((Widget)v_scrollbar))))
  2037. )
  2038. input_ungrab( combo_w, GRAB_POINTER | GRAB_KEYBOARD );
  2039. /* condition : ButtonRelease event
  2040. * the cursor is outside the scrollbar(horizontal or vertical)
  2041. * action: call action routine "Release" of ScrollBar to release
  2042. * possible pressed slider arrow (up/down)
  2043. */
  2044. if (event->type == ButtonRelease) {
  2045. if ( ScrollBarVisible((Widget)h_scrollbar) &&
  2046. window != XtWindowOfObject((Widget)h_scrollbar) )
  2047. XtCallActionProc((Widget)h_scrollbar, "Release", event,NULL,0);
  2048. if ( ScrollBarVisible((Widget)v_scrollbar) &&
  2049. window != XtWindowOfObject((Widget)v_scrollbar) )
  2050. XtCallActionProc((Widget)v_scrollbar, "Release", event,NULL,0);
  2051. }
  2052. }
  2053. /*
  2054. * This is the event_handler for our list widget. Getting the pointer
  2055. * grabbing to work correctly was not very easy. In order for everything
  2056. * to work correctly, we only do grab-pointer, for the shell, while not
  2057. * doing anything inside the list. If doing something inside the list
  2058. * we remove the grab on the shell. This is the only way that the
  2059. * list will get the ButtonRelease if doing browse while outside the
  2060. * list. The toolkit automatically does a grab in between ButtonPress
  2061. * and ButtonRelease; therefore, the shell ungrab can't be done inside
  2062. * the ButtonPress event.
  2063. */
  2064. static void
  2065. list_event_handler( Widget widget,
  2066. XtPointer client_data,
  2067. XEvent* event,
  2068. Boolean *dispatch) /* call remaining event handlers */
  2069. {
  2070. DtComboBoxWidget combo_w = (DtComboBoxWidget)client_data;
  2071. Arg args[5];
  2072. int num_args;
  2073. int top_item_position;
  2074. int visible_item_count;
  2075. int item_count;
  2076. XmScrolledWindowWidget sw = (XmScrolledWindowWidget)XtParent(widget);
  2077. XmScrollBarWidget v_scrollbar;
  2078. XmScrollBarWidget h_scrollbar;
  2079. switch (event->type) {
  2080. case ButtonRelease:
  2081. /*
  2082. * Pop down the menu when Button is released inside the menu.
  2083. */
  2084. /* Doing the popdown here upon receiving ButtonRelease event,
  2085. * rather than in shell_even_hanlder(), is
  2086. * essential to allow select_cb() to recognize that this
  2087. * XmNbrowseSelectionCallback is the last one in this popup session
  2088. * and must treat it as a DtNselectionCallback
  2089. */
  2090. input_ungrab( combo_w, GRAB_KEYBOARD );
  2091. /* condition : ButtonRelease event
  2092. * cursor is outside the scrollbar(horizontal or vertical)
  2093. * action: call action routine "Release" of ScrollBar to release
  2094. * possible pressed slider arrow (up/down)
  2095. */
  2096. /* MotifBc */
  2097. XtSetArg(args[0], XmNverticalScrollBar, &v_scrollbar);
  2098. XtSetArg(args[1], XmNhorizontalScrollBar, &h_scrollbar);
  2099. XtGetValues((Widget)sw, args, 2);
  2100. if ( ScrollBarVisible((Widget)h_scrollbar) )
  2101. XtCallActionProc((Widget)h_scrollbar, "Release", event,NULL,0);
  2102. if ( ScrollBarVisible((Widget)v_scrollbar) )
  2103. XtCallActionProc((Widget)v_scrollbar, "Release", event,NULL,0);
  2104. break;
  2105. case FocusOut:
  2106. /*
  2107. * There is interaction conflict between the list and the
  2108. * scrollbars in terms of Focus. We always want our list
  2109. * to have focus, so grab it back if we lose it.
  2110. */
  2111. if ( ShellPoppedUp(((ShellWidget)(Shell(combo_w)))) ) {
  2112. _XmGrabKeyboard(widget, False, GrabModeAsync, GrabModeAsync,
  2113. CurrentTime);
  2114. XtSetKeyboardFocus(List(combo_w), None);
  2115. }
  2116. break;
  2117. case EnterNotify:
  2118. /* call ListBeginSelect() action directly to simulate Btn1Down*/
  2119. {Display *disp = XtDisplay(List(combo_w));
  2120. Window win = XtWindow(List(combo_w));
  2121. Window root;
  2122. Window child;
  2123. XmListWidget list;
  2124. int root_x, root_y, win_x, win_y, item_pos;
  2125. unsigned int keys_buttons;
  2126. unsigned char unit_type = XmPIXELS;
  2127. /* Resolution Independent */
  2128. if ( MUnitType(combo_w) != XmPIXELS) {
  2129. unit_type = MUnitType(combo_w);
  2130. XtSetArg(args[0], XmNunitType, XmPIXELS);
  2131. XtSetValues(List(combo_w), args, 1);
  2132. }
  2133. root = XDefaultRootWindow( disp );
  2134. XQueryPointer ( disp, win, &root,
  2135. &child, &root_x, &root_y,
  2136. &win_x, &win_y, &keys_buttons );
  2137. if ( keys_buttons & Button1Mask ) {
  2138. item_pos = XmListYToPos(List(combo_w), event->xbutton.y);
  2139. list = (XmListWidget)List(combo_w);
  2140. /* MotifBc
  2141. */
  2142. num_args = 0;
  2143. XtSetArg(args[num_args],XmNtopItemPosition,&top_item_position);
  2144. num_args ++;
  2145. XtSetArg(args[num_args], XmNvisibleItemCount,
  2146. &visible_item_count);
  2147. num_args ++;
  2148. XtSetArg(args[num_args], XmNitemCount, &item_count);
  2149. num_args ++;
  2150. XtGetValues((Widget)list, args, num_args);
  2151. /* Adjust top_item_position value to its' internal form */
  2152. if (top_item_position)
  2153. top_item_position--;
  2154. else
  2155. top_item_position = item_count - 1;
  2156. if((item_pos<1 ) ||
  2157. (item_pos>=(top_item_position + visible_item_count))||
  2158. (item_pos < top_item_position) ||
  2159. (item_pos >= item_count) )
  2160. {
  2161. Position item_x, item_y;
  2162. Dimension item_height, item_width;
  2163. XmListPosToBounds((Widget)list,
  2164. ((top_item_position + visible_item_count )>
  2165. item_count)? item_count:
  2166. (top_item_position + visible_item_count ),
  2167. &item_x, &item_y, &item_width, &item_height);
  2168. if ( item_pos ==0 && event->xbutton.y<(int)(item_height/2) )
  2169. event->xbutton.y = item_height/2;
  2170. else
  2171. event->xbutton.y = item_y + item_height/2;
  2172. event->xbutton.x = item_x;
  2173. }
  2174. XtCallActionProc(List(combo_w), "ListBeginSelect",
  2175. /* XEvent */ event,
  2176. /* params */NULL,
  2177. /* num_params */0);
  2178. }
  2179. /* Resolution Independent */
  2180. if ( unit_type != XmPIXELS) {
  2181. XtSetArg(args[0], XmNunitType, unit_type);
  2182. XtSetValues(List(combo_w), args, 1);
  2183. }
  2184. }
  2185. break;
  2186. }
  2187. }
  2188. /* Caller must free string */
  2189. static char*
  2190. GetTextString(XmString xm_string)
  2191. {
  2192. XmStringContext context;
  2193. XmStringComponentType type;
  2194. XmStringCharSet charset;
  2195. XmStringDirection direction;
  2196. XmStringComponentType unknown_tag;
  2197. unsigned short ul;
  2198. unsigned char *uv;
  2199. char *text = NULL;
  2200. Boolean done = FALSE;
  2201. XmStringInitContext(&context, xm_string);
  2202. /* Loop until 1st char* found */
  2203. while (!done) {
  2204. type = XmStringGetNextComponent(context, &text, &charset,
  2205. &direction, &unknown_tag,
  2206. &ul, &uv);
  2207. switch (type) {
  2208. case XmSTRING_COMPONENT_END:
  2209. done = TRUE;
  2210. break;
  2211. case XmSTRING_COMPONENT_TEXT:
  2212. case XmSTRING_COMPONENT_LOCALE_TEXT:
  2213. done = TRUE;
  2214. break;
  2215. default:
  2216. break;
  2217. }
  2218. }
  2219. XmStringFreeContext(context);
  2220. return(text);
  2221. }
  2222. static void
  2223. TextFieldActivate(DtComboBoxPart *combo_p, XtPointer call_data)
  2224. {
  2225. XmTextFieldWidget w = (XmTextFieldWidget)(combo_p->text);
  2226. XmListWidget list = (XmListWidget)combo_p->list;
  2227. XmAnyCallbackStruct cb;
  2228. char *data = NULL;
  2229. char *text = NULL;
  2230. Arg arg;
  2231. XmStringTable list_items;
  2232. XtSetArg(arg, XmNvalue, &data);
  2233. XtGetValues((Widget)w, &arg, 1);
  2234. /* MotifBc
  2235. */
  2236. XtSetArg(arg, XmNitems, &list_items);
  2237. XtGetValues((Widget)list, &arg, 1);
  2238. if ( list_items)
  2239. text = GetTextString(list_items[combo_p->selected_position]);
  2240. if (text && data && (strcmp(text, data) == 0)) {
  2241. XtFree(text);
  2242. }
  2243. /* Only send callback if both are not NULL */
  2244. else if (!((text == NULL) && (data == NULL))) {
  2245. XmAnyCallbackStruct *local_cb = (XmAnyCallbackStruct *)call_data;
  2246. cb.reason = XmCR_ACTIVATE;
  2247. cb.event = local_cb ? local_cb->event : NULL;
  2248. /* MotifBc
  2249. */
  2250. if (XtHasCallbacks((Widget)w, XmNactivateCallback)==XtCallbackHasSome)
  2251. XtCallCallbacks((Widget)w, XmNactivateCallback,
  2252. (XtPointer) &cb);
  2253. if (text)
  2254. XtFree(text);
  2255. }
  2256. if ( data )
  2257. XtFree (data);
  2258. }
  2259. /*
  2260. * This is the activate callback for the arrow button. This
  2261. * sets the shell position and width, does the correct grabs, and
  2262. * puts the shell on the screen.
  2263. */
  2264. static void
  2265. activate_cb( Widget w,
  2266. XtPointer client_data,
  2267. XtPointer call_data)
  2268. {
  2269. DtComboBoxWidget combo_w = (DtComboBoxWidget)client_data;
  2270. DtComboBoxPart *combo_p = (DtComboBoxPart*)
  2271. &(XmField(combo_w,ipot,DtComboBox,arrow,Widget));
  2272. Display *disp = XtDisplayOfObject((Widget)combo_w);
  2273. XmDisplay xmdisp = (XmDisplay) XmGetXmDisplay(disp);
  2274. int screen;
  2275. Dimension width, height;
  2276. Dimension disp_width, disp_height;
  2277. Position root_x, root_y, root_y0;
  2278. Arg args[5];
  2279. int n;
  2280. unsigned char unit_type = XmPIXELS;
  2281. /* Resolution Independent Handling */
  2282. XtSetArg(args[0], XmNunitType, &unit_type);
  2283. XtGetValues((Widget)combo_w, args, 1);
  2284. /* Getting Focus */
  2285. if ( !_XmFocusIsHere( (Widget)combo_w) )
  2286. XmProcessTraversal((Widget)combo_w,
  2287. (XmTraversalDirection) XmTRAVERSE_CURRENT);
  2288. if (Type(combo_w) == DtDROP_DOWN_COMBO_BOX)
  2289. TextFieldActivate(combo_p, call_data);
  2290. /*
  2291. * Don't popup if no items in the list.
  2292. */
  2293. /* MotifBc
  2294. */
  2295. XtSetArg(args[0], XmNitemCount, &n);
  2296. XtGetValues(((Widget)List(combo_w)), args, 1);
  2297. if ( n != ItemCount(combo_w) )
  2298. SyncWithList(combo_p);
  2299. if ( !n )
  2300. return;
  2301. screen = DefaultScreen(disp);
  2302. disp_width = DisplayWidth(disp, screen);
  2303. disp_height = DisplayHeight(disp, screen);
  2304. /*
  2305. * Call the menu-post callback if requested. This allows the
  2306. * user to change the items, instead of using the losing-focus callback.
  2307. * If the user used the losing-focus callback to change the items, the
  2308. * size of the list/shell will change while it is popped up. We
  2309. * could disallow SetValues while the menu is posted, but let's see
  2310. * how things go first.
  2311. */
  2312. if (MenuPostCallback(combo_w)) {
  2313. XmAnyCallbackStruct info;
  2314. info.reason = DtCR_MENU_POST;
  2315. info.event = (XEvent*)NULL;
  2316. XtCallCallbackList((Widget)combo_w, MenuPostCallback(combo_w),
  2317. (XtPointer)&info);
  2318. }
  2319. width = MaxShellWidth(combo_w);
  2320. height = MaxShellHeight(combo_w);
  2321. /* Get root coords of ComboBox */
  2322. XtTranslateCoords((Widget)combo_w, X(combo_w), Y(combo_w),
  2323. &root_x, &root_y);
  2324. root_y0 = root_y;
  2325. /*
  2326. * Make necessary adjustments for offset of our widget
  2327. * inside its' parent. Calculate the width of the shell.
  2328. * This must be done every time the shell gets popped up, because
  2329. * the x/y can change as well as the width (from list's visibleItemCount
  2330. * or geometry management changes).
  2331. */
  2332. root_x -= X(combo_w);
  2333. root_y -= Y(combo_w);
  2334. root_y += (Height(combo_w) - COMBO_MARGIN_H(combo_w));
  2335. /*
  2336. * Make sure the shell is at least as big as our combo-box, and
  2337. * make sure it stays on the screen.
  2338. */
  2339. /* to enforce a scrollbar with Shell */
  2340. if (width < Width(combo_w))
  2341. {
  2342. Dimension sb_width, spacing, list_width;
  2343. Widget sb;
  2344. n = 0;
  2345. XtSetArg(args[n], XmNverticalScrollBar, &sb); n++;
  2346. XtSetArg(args[n], XmNspacing, &spacing); n++;
  2347. XtGetValues(XtParent(List(combo_w)), args, n);
  2348. /* Resolution Independent Resource */
  2349. if ( unit_type != XmPIXELS) {
  2350. n = XmConvertUnits(List(combo_w), XmHORIZONTAL,
  2351. (int)unit_type, spacing, XmPIXELS);
  2352. spacing = n;
  2353. }
  2354. if (sb && XtIsWidget(sb) ) {
  2355. n = 0;
  2356. XtSetArg(args[n], XmNwidth, &sb_width); n++;
  2357. XtGetValues(sb, args, n);
  2358. /* Resolution Independent Resource */
  2359. if (unit_type != XmPIXELS) {
  2360. n = XmConvertUnits(sb, XmHORIZONTAL,
  2361. (int)unit_type, sb_width, XmPIXELS);
  2362. sb_width = n;
  2363. }
  2364. }
  2365. else
  2366. sb_width = 0;
  2367. n = 0;
  2368. width = Width(combo_w);
  2369. list_width = ( ScrollBarVisible(sb) ?
  2370. (width - sb_width - spacing)
  2371. :(width - spacing) );
  2372. if (unit_type != XmPIXELS) {
  2373. n = XmConvertUnits(sb, XmHORIZONTAL,
  2374. XmPIXELS, list_width, (int)unit_type);
  2375. list_width = n; n=0;
  2376. }
  2377. XtSetArg(args[n], XmNwidth, list_width); n++;
  2378. XtSetValues(List(combo_w), args, n);
  2379. }
  2380. if ((int)(root_x + width) > (int)disp_width)
  2381. root_x = (disp_width - width);
  2382. else if (root_x <=0)
  2383. root_x = 0;
  2384. else
  2385. ;
  2386. if ((int)(root_y + height) > (int)disp_height)
  2387. root_y = root_y0 - Y(combo_w) - height;
  2388. if (unit_type != XmPIXELS) {
  2389. XtSetArg(args[0], XmNunitType, XmPIXELS);
  2390. XtSetValues(Shell(combo_w), args, 1);
  2391. }
  2392. n = 0;
  2393. XtSetArg(args[n], XmNx, root_x); n++;
  2394. XtSetArg(args[n], XmNy, root_y); n++;
  2395. XtSetValues(Shell(combo_w), args, n);
  2396. if (unit_type != XmPIXELS) {
  2397. XtSetArg(args[0], XmNunitType, unit_type);
  2398. XtSetValues(Shell(combo_w), args, 1);
  2399. }
  2400. PoppedUp(combo_w) = TRUE;
  2401. XtPopup(Shell(combo_w), XtGrabNone);
  2402. /*
  2403. * Set up the grab for the shell and list. The shell gets the
  2404. * pointer grab so that events will go into the list and scrollbars
  2405. * correctly, but events outside the shell will go to the shell.
  2406. * See shell and list event handlers for details about grabs.
  2407. */
  2408. _XmAddGrab(Shell(combo_w), True, True);
  2409. _XmGrabPointer(Shell(combo_w), True, ButtonPressMask |ButtonReleaseMask,
  2410. GrabModeAsync, GrabModeAsync, None,
  2411. XmGetMenuCursor(disp), CurrentTime);
  2412. _XmGrabKeyboard(List(combo_w), False, GrabModeAsync, GrabModeAsync,
  2413. CurrentTime);
  2414. xmdisp->display.userGrabbed = True;
  2415. /*
  2416. * Where to define the cursor for the list widget. It would be
  2417. * nice to do it in the list's realize function, but that's not
  2418. * possible. We can't use the ComboBox realize function, because
  2419. * the list isn't realized at that point. This is the simpliest
  2420. * way to get this done. This is needed to make sure the list has the
  2421. * correct menu during browse scrolling, etc.
  2422. */
  2423. XDefineCursor(disp, XtWindowOfObject(Shell(combo_w)),
  2424. XmGetMenuCursor(disp));
  2425. }
  2426. /*
  2427. * Make sure arrow is symetrical. 45 degree angle. I'm not sure how
  2428. * inefficient get/releasing the GC every time is (they are cached by
  2429. * the toolkit)?
  2430. */
  2431. static void
  2432. arrow_expose_cb(Widget w,
  2433. XtPointer client_data,
  2434. XtPointer call_data)
  2435. {
  2436. DtComboBoxWidget combo_w = (DtComboBoxWidget)client_data;
  2437. Display *disp = XtDisplayOfObject(w);
  2438. Window win = XtWindowOfObject(w);
  2439. XGCValues values;
  2440. short center_w;
  2441. short center_h;
  2442. XPoint points[10];
  2443. Arg args[3];
  2444. GC gc;
  2445. Dimension arrow_width, arrow_height;
  2446. unsigned char unit_type = XmPIXELS;
  2447. /* Resolution Independent */
  2448. if ( MUnitType(combo_w) != XmPIXELS ) {
  2449. unit_type = MUnitType(combo_w);
  2450. XtSetArg(args[0], XmNunitType, XmPIXELS);
  2451. XtSetValues(w, args, 1);
  2452. }
  2453. /* MotifBc */
  2454. XtSetArg(args[0], XmNwidth, &arrow_width);
  2455. XtSetArg(args[1], XmNheight, &arrow_height);
  2456. XtSetArg(args[2], XmNforeground, &(values.foreground));
  2457. XtGetValues(w, args, 3);
  2458. center_w = arrow_width/2;
  2459. center_h = (int) (arrow_height -3.)/2;
  2460. values.line_width = 0;
  2461. values.line_style = LineSolid;
  2462. values.fill_style = FillSolid;
  2463. gc = XtGetGC(w, GCForeground | GCFillStyle | GCLineStyle | GCLineWidth,
  2464. &values);
  2465. XDrawLine(disp, win, gc, 1, center_h + center_w + 1, Width(w) - 2,
  2466. center_h + center_w + 1);
  2467. /* A - bottom point */
  2468. points[0].x = center_w;
  2469. points[0].y = center_h + (int)(center_w * .8);
  2470. /* B - far left point */
  2471. points[1].x = center_w - (int)(center_w * .8);
  2472. points[1].y = center_h;
  2473. /* C - inner left point */
  2474. points[2].x = center_w - (int)(center_w * .3);
  2475. points[2].y = points[1].y;
  2476. /* D - top left point */
  2477. points[3].x = points[2].x;
  2478. points[3].y = center_h - (int)(center_w * .8);
  2479. /* E - top right point */
  2480. points[4].x = center_w + (int)(center_w * .3);
  2481. points[4].y = points[3].y;
  2482. /* F - inner right point */
  2483. points[5].x = points[4].x;
  2484. points[5].y = points[1].y;
  2485. /* G - far right point */
  2486. points[6].x = center_w + (int)(center_w * .8);
  2487. points[6].y = points[1].y;
  2488. /* A - bottom point */
  2489. points[7].x = points[0].x;
  2490. points[7].y = points[0].y;
  2491. XDrawLines(disp, win, gc, points, 8, CoordModeOrigin);
  2492. XFillPolygon(disp, win, gc, points, 8, Convex, CoordModeOrigin);
  2493. XtReleaseGC(w, gc);
  2494. /* Resolution Independent */
  2495. if ( unit_type != XmPIXELS ) {
  2496. XtSetArg(args[0], XmNunitType, unit_type);
  2497. XtSetValues(w, args, 1);
  2498. }
  2499. }
  2500. /*
  2501. * We get the text-field losing-focus callback, so pass it on to
  2502. * the user if they requested it. Our losing-focus callback
  2503. * is just a convenience callback, so that the user doesn't
  2504. * have to get the text-field first. This make our integration
  2505. * with XDesigner a little easier.d
  2506. */
  2507. static void
  2508. text_losing_focus_cb( Widget w,
  2509. XtPointer client_data,
  2510. XtPointer call_data)
  2511. {
  2512. DtComboBoxWidget combo = (DtComboBoxWidget)client_data;
  2513. DtComboBoxPart *combo_p = (DtComboBoxPart*)
  2514. &(XmField(combo,ipot,DtComboBox,arrow,Widget));
  2515. XmTextFieldWidget wt=(XmTextFieldWidget) Text(combo);
  2516. XmString xmStr;
  2517. Arg arg;
  2518. String text_string;
  2519. int i, need_sync_flag=1;
  2520. /* MotifBc
  2521. */
  2522. XtSetArg(arg, XmNvalue, &text_string);
  2523. XtGetValues((Widget)wt, &arg, 1);
  2524. xmStr = (XmString) XmStringCreateLocalized(text_string?text_string:"");
  2525. if ( text_string )
  2526. XtFree (text_string);
  2527. if (LosingFocusCallback(combo))
  2528. XtCallCallbackList((Widget)combo, LosingFocusCallback(combo),
  2529. (XtPointer)call_data);
  2530. /* To synchronize the ComboBox record with XmList */
  2531. XtVaGetValues(List(combo), XmNitemCount, &i, NULL);
  2532. if (i != ItemCount(combo) ) {
  2533. SyncWithList(combo_p);
  2534. need_sync_flag = 0;
  2535. }
  2536. for (i = 0; i < ItemCount(combo); i++) {
  2537. if ( need_sync_flag &&
  2538. !( (ListItems(combo))[i] && XmeStringIsValid((ListItems(combo))[i]) )) {
  2539. SyncWithList(combo_p);
  2540. need_sync_flag = 0;
  2541. }
  2542. if (XmStringCompare(xmStr, (ListItems(combo))[i]))
  2543. break;
  2544. }
  2545. if (i < ItemCount(combo) && i != SelectedPosition(combo) ) {
  2546. SelectedPosition(combo) = i;
  2547. if (SelectedItem(combo))
  2548. XmStringFree(SelectedItem(combo));
  2549. SelectedItem(combo) = xmStr;
  2550. if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
  2551. SetTextFieldData(combo_p, NULL);
  2552. else
  2553. SetLabelData(combo_p, NULL, FALSE);
  2554. XmListSetPos(List(combo), SelectedPosition(combo) + 1);
  2555. XmListSelectPos(List(combo), SelectedPosition(combo) + 1, True);
  2556. XtVaGetValues(List(combo), XmNtopItemPosition,
  2557. &(combo_p->top_item_position), NULL);
  2558. }
  2559. else
  2560. XmStringFree( xmStr );
  2561. }
  2562. /*
  2563. * We get the text-field activate callback, so pass it on to
  2564. * the user if they requested it. Our activate callback
  2565. * is just a convenience callback, so that the user doesn't
  2566. * have to get the text-field first. This make our integration
  2567. * with XDesigner a little easier.
  2568. */
  2569. static void
  2570. text_activate_cb( Widget w,
  2571. XtPointer client_data,
  2572. XtPointer call_data)
  2573. {
  2574. DtComboBoxWidget combo = (DtComboBoxWidget)client_data;
  2575. DtComboBoxPart *combo_p = (DtComboBoxPart*)
  2576. &(XmField(combo,ipot,DtComboBox,arrow,Widget));
  2577. XmTextFieldWidget wt=(XmTextFieldWidget) Text(combo);
  2578. XmString xmStr;
  2579. Arg arg;
  2580. String text_string;
  2581. int i, need_sync_flag=1;
  2582. /* MotifBc
  2583. */
  2584. XtSetArg(arg, XmNvalue, &text_string);
  2585. XtGetValues((Widget)wt, &arg, 1);
  2586. xmStr = (XmString) XmStringCreateLocalized(text_string?text_string:"");
  2587. if ( text_string )
  2588. XtFree (text_string);
  2589. if (ActivateCallback(combo))
  2590. XtCallCallbackList((Widget)combo,
  2591. ActivateCallback(combo),
  2592. (XtPointer)call_data);
  2593. /* To synchronize the ComboBox record with XmList */
  2594. XtVaGetValues(List(combo), XmNitemCount, &i, NULL);
  2595. if (i != ItemCount(combo) ) {
  2596. SyncWithList(combo_p);
  2597. need_sync_flag = 0;
  2598. }
  2599. for (i = 0; i < ItemCount(combo); i++) {
  2600. if ( need_sync_flag &&
  2601. !( (ListItems(combo))[i] &&
  2602. XmeStringIsValid((ListItems(combo))[i]) )) {
  2603. SyncWithList(combo_p);
  2604. need_sync_flag = 0;
  2605. }
  2606. if (XmStringCompare(xmStr, (ListItems(combo))[i]))
  2607. break;
  2608. }
  2609. if (i < ItemCount(combo) && i != SelectedPosition(combo) ) {
  2610. SelectedPosition(combo) = i;
  2611. if (SelectedItem(combo))
  2612. XmStringFree(SelectedItem(combo));
  2613. SelectedItem(combo) = xmStr;
  2614. if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
  2615. SetTextFieldData(combo_p, NULL);
  2616. else
  2617. SetLabelData(combo_p, NULL, FALSE);
  2618. XmListSetPos(List(combo), SelectedPosition(combo) + 1);
  2619. XmListSelectPos(List(combo), SelectedPosition(combo) + 1, True);
  2620. XtVaGetValues(List(combo), XmNtopItemPosition,
  2621. &(combo_p->top_item_position), NULL);
  2622. }
  2623. else
  2624. XmStringFree( xmStr );
  2625. }
  2626. /*
  2627. * We get the text-field focus callback, so pass it on to
  2628. * the user if they requested it. Our focus callback
  2629. * is just a convenience callback, so that the user doesn't
  2630. * have to get the text-field first. This make our integration
  2631. * with XDesigner a little easier.
  2632. */
  2633. static void
  2634. text_focus_cb( Widget w,
  2635. XtPointer client_data,
  2636. XtPointer call_data)
  2637. {
  2638. DtComboBoxWidget combo = (DtComboBoxWidget)client_data;
  2639. if (FocusCallback(combo))
  2640. XtCallCallbackList((Widget)combo, FocusCallback(combo),
  2641. (XtPointer)call_data);
  2642. }
  2643. /*
  2644. * Try and keep our list related rsources in sync with the list widget.
  2645. * This is not always possible, depending on if the programmer makes
  2646. * list widget calls directly. If we get out of sync with the
  2647. * list widget, our SetValues() may not work correctly (when the
  2648. * comparisons are done). Should do get values in case list widget
  2649. * names are changed?
  2650. */
  2651. static void
  2652. SyncWithList(DtComboBoxPart *combo_p)
  2653. {
  2654. XmListWidget list = (XmListWidget)combo_p->list;
  2655. Arg args[10];
  2656. int num_args;
  2657. unsigned char unit_type = XmPIXELS;
  2658. /* Resolution Independent */
  2659. XtSetArg(args[0],XmNunitType,&unit_type);
  2660. XtGetValues((Widget)list, args, 1);
  2661. if (unit_type != XmPIXELS) {
  2662. XtSetArg(args[0],XmNunitType,XmPIXELS);
  2663. XtSetValues((Widget)list, args, 1);
  2664. }
  2665. /* MotifBc
  2666. */
  2667. num_args = 0;
  2668. XtSetArg(args[num_args],XmNitems,&(combo_p->list_items)); num_args ++;
  2669. XtSetArg(args[num_args],XmNitems,&(combo_p->items)); num_args ++;
  2670. XtSetArg(args[num_args],XmNitemCount,&(combo_p->item_count)); num_args ++;
  2671. XtSetArg(args[num_args],XmNfontList,&(combo_p->list_font_list));
  2672. num_args ++;
  2673. XtSetArg(args[num_args],XmNlistMarginHeight,&(combo_p->list_margin_height));
  2674. num_args ++;
  2675. XtSetArg(args[num_args],XmNlistMarginWidth,&(combo_p->list_margin_width));
  2676. num_args ++;
  2677. XtSetArg(args[num_args],XmNlistSpacing,&(combo_p->list_spacing));
  2678. num_args ++;
  2679. XtSetArg(args[num_args],XmNtopItemPosition,&(combo_p->top_item_position));
  2680. num_args ++;
  2681. XtSetArg(args[num_args],XmNvisibleItemCount,&(combo_p->visible_item_count));
  2682. num_args ++;
  2683. XtGetValues((Widget)list, args, num_args);
  2684. /* Adjustment with empty list */
  2685. if (! combo_p->item_count) {
  2686. combo_p->items = NULL;
  2687. combo_p->list_items = NULL;
  2688. }
  2689. /* Resolution Independent */
  2690. if (unit_type != XmPIXELS) {
  2691. XtSetArg(args[0],XmNunitType,unit_type);
  2692. XtSetValues((Widget)list, args, 1);
  2693. }
  2694. }
  2695. /*
  2696. * Routines which manipulate the ComboBox list. These are external
  2697. * for use by users of our widget.
  2698. */
  2699. Widget
  2700. DtCreateComboBox(Widget parent,
  2701. char *name,
  2702. ArgList arglist,
  2703. Cardinal num_args)
  2704. {
  2705. return(XtCreateWidget(name, dtComboBoxWidgetClass, parent,
  2706. arglist, num_args));
  2707. }
  2708. void
  2709. DtComboBoxAddItem( Widget combow,
  2710. XmString item,
  2711. int pos,
  2712. Boolean unique)
  2713. {
  2714. DtComboBoxWidget combo = (DtComboBoxWidget)combow;
  2715. DtComboBoxPart *combo_p = (DtComboBoxPart*)
  2716. &(XmField(combo,ipot,DtComboBox,arrow,Widget));
  2717. XmStringTable list_items;
  2718. int i;
  2719. Arg arg;
  2720. _DtWidgetToAppContext(combow);
  2721. _DtAppLock(app);
  2722. /* Try to help confused applications. */
  2723. if (XmIsComboBox(combow))
  2724. {
  2725. XmComboBoxAddItem(combow, item, pos, unique);
  2726. _DtAppUnlock(app);
  2727. return;
  2728. }
  2729. /* MotifBc
  2730. */
  2731. XtSetArg(arg, XmNitems, &list_items);
  2732. XtGetValues(((Widget)List(combo)), &arg, 1);
  2733. if (item && list_items) {
  2734. for (i = 0; i < ItemCount(combo); i++)
  2735. if (XmStringCompare(item, list_items[i]))
  2736. break;
  2737. if ((i < ItemCount(combo)) && unique)
  2738. {
  2739. _DtAppUnlock(app);
  2740. return;
  2741. }
  2742. }
  2743. XmListAddItemUnselected(List(combo), item, pos);
  2744. SyncWithList(combo_p);
  2745. if (Label(combo)) {
  2746. SetMaximumLabelSize(combo_p);
  2747. if (Type(combo) == DtDROP_DOWN_LIST) {
  2748. ClearShadow(combo, TRUE);
  2749. if (RecomputeSize(combo))
  2750. SetComboBoxSize(combo);
  2751. LayoutChildren(combo);
  2752. DrawShadow(combo);
  2753. }
  2754. }
  2755. if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
  2756. SetTextFieldData(combo_p, NULL);
  2757. else
  2758. SetLabelData(combo_p, NULL, FALSE);
  2759. _DtAppUnlock(app);
  2760. }
  2761. void
  2762. DtComboBoxDeletePos( Widget combow,
  2763. int pos)
  2764. {
  2765. DtComboBoxWidget combo = (DtComboBoxWidget)combow;
  2766. DtComboBoxPart *combo_p = (DtComboBoxPart*)
  2767. &(XmField(combo,ipot,DtComboBox,arrow,Widget));
  2768. int selection_changed = 0;
  2769. _DtWidgetToAppContext(combow);
  2770. _DtAppLock(app);
  2771. /* Try to help confused applications. */
  2772. if (XmIsComboBox(combow))
  2773. {
  2774. XmComboBoxDeletePos(combow, pos);
  2775. _DtAppUnlock(app);
  2776. return;
  2777. }
  2778. if ( pos <= 0 || pos >combo_p->item_count ) {
  2779. XtWarning(CB_DEL_POS);
  2780. _DtAppUnlock(app);
  2781. return;
  2782. }
  2783. XmListDeletePos(List(combo), pos);
  2784. if ( pos == (combo_p->selected_position+1) ) {
  2785. /* Since we delete the current item, we have to set one */
  2786. if ( pos == combo_p->item_count && combo_p->selected_position>0) {
  2787. combo_p->selected_position--;
  2788. selection_changed ++;
  2789. }
  2790. XmListSelectPos(List(combo), combo_p->selected_position+1, True);
  2791. }
  2792. else if ( pos <= combo_p->selected_position) {
  2793. combo_p->selected_position--;
  2794. selection_changed ++;
  2795. }
  2796. SyncWithList(combo_p);
  2797. if ( selection_changed ) {
  2798. if ( combo_p->selected_item )
  2799. XmStringFree(combo_p->selected_item );
  2800. combo_p->selected_item =
  2801. ItemCount(combo)?
  2802. XmStringCopy(combo_p->list_items[combo_p->selected_position]):
  2803. (XmString) NULL;
  2804. }
  2805. if (Label(combo)) {
  2806. SetMaximumLabelSize(combo_p);
  2807. if (Type(combo) == DtDROP_DOWN_LIST) {
  2808. ClearShadow(combo, TRUE);
  2809. if (RecomputeSize(combo))
  2810. SetComboBoxSize(combo);
  2811. LayoutChildren(combo);
  2812. DrawShadow(combo);
  2813. }
  2814. }
  2815. if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
  2816. SetTextFieldData(combo_p, NULL);
  2817. else
  2818. SetLabelData(combo_p, NULL, FALSE);
  2819. _DtAppUnlock(app);
  2820. }
  2821. void
  2822. DtComboBoxSetItem( Widget combow,
  2823. XmString item)
  2824. {
  2825. DtComboBoxWidget combo = (DtComboBoxWidget)combow;
  2826. DtComboBoxPart *combo_p = (DtComboBoxPart*)
  2827. &(XmField(combo,ipot,DtComboBox,arrow,Widget));
  2828. XmStringTable list_items;
  2829. int i;
  2830. Arg arg;
  2831. _DtWidgetToAppContext(combow);
  2832. _DtAppLock(app);
  2833. /* Try to help confused applications. */
  2834. if (XmIsComboBox(combow))
  2835. {
  2836. XmComboBoxSetItem(combow, item);
  2837. _DtAppUnlock(app);
  2838. return;
  2839. }
  2840. /* MotifBc
  2841. */
  2842. XtSetArg(arg, XmNitems, &list_items);
  2843. XtGetValues(((Widget)List(combow)), &arg, 1);
  2844. if (item && list_items) {
  2845. for (i = 0; i < ItemCount(combo); i++)
  2846. if (XmStringCompare(item, list_items[i]))
  2847. break;
  2848. if (i < ItemCount(combo)) {
  2849. SelectedPosition(combo) = i;
  2850. if (SelectedItem(combo))
  2851. XmStringFree(SelectedItem(combo));
  2852. SelectedItem(combo) = XmStringCopy(item);
  2853. if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
  2854. SetTextFieldData(combo_p, NULL);
  2855. else
  2856. SetLabelData(combo_p, NULL, FALSE);
  2857. XmListSetItem(List(combo), item);
  2858. XmListSelectItem(List(combo), item, FALSE);
  2859. SyncWithList(combo_p);
  2860. }
  2861. else
  2862. XtWarning(CB_SET_ITEM);
  2863. }
  2864. else
  2865. XtWarning(CB_SET_ITEM);
  2866. _DtAppUnlock(app);
  2867. }
  2868. void
  2869. DtComboBoxSelectItem( Widget combow,
  2870. XmString item)
  2871. {
  2872. DtComboBoxWidget combo = (DtComboBoxWidget)combow;
  2873. DtComboBoxPart *combo_p = (DtComboBoxPart*)
  2874. &(XmField(combo,ipot,DtComboBox,arrow,Widget));
  2875. XmStringTable list_items;
  2876. XmString tmpStr;
  2877. int i;
  2878. Arg arg;
  2879. _DtWidgetToAppContext(combow);
  2880. _DtAppLock(app);
  2881. /* Try to help confused applications. */
  2882. if (XmIsComboBox(combow))
  2883. {
  2884. XmComboBoxSelectItem(combow, item);
  2885. _DtAppUnlock(app);
  2886. return;
  2887. }
  2888. /* MotifBc
  2889. */
  2890. XtSetArg(arg, XmNitems, &list_items);
  2891. XtGetValues(((Widget)List(combo)), &arg, 1);
  2892. if (item && list_items) {
  2893. for (i = 0; i < ItemCount(combo); i++)
  2894. if (XmStringCompare(item, list_items[i]))
  2895. break;
  2896. if (i < ItemCount(combo)) {
  2897. SelectedPosition(combo) = i;
  2898. tmpStr=SelectedItem(combo);
  2899. SelectedItem(combo) = XmStringCopy(item);
  2900. if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
  2901. SetTextFieldData(combo_p, NULL);
  2902. else
  2903. SetLabelData(combo_p, NULL, FALSE);
  2904. XmListDeselectAllItems(List(combo));
  2905. XmListSelectItem(List(combo), item, FALSE);
  2906. if(tmpStr)
  2907. XmStringFree(tmpStr);
  2908. SyncWithList(combo_p);
  2909. }
  2910. else
  2911. XtWarning(CB_SELECT_ITEM);
  2912. }
  2913. else
  2914. XtWarning(CB_SELECT_ITEM);
  2915. _DtAppUnlock(app);
  2916. }
  2917. /*
  2918. * Synthetic GetValues for List resources.
  2919. */
  2920. static XmImportOperator
  2921. _XmSetSyntheticResForChild( Widget widget,
  2922. int offset,
  2923. XtArgVal * value)
  2924. {
  2925. return(XmSYNTHETIC_LOAD);
  2926. }
  2927. void
  2928. _DtComboBoxGetArrowSize(Widget w,
  2929. int resource_offset,
  2930. XtArgVal *value)
  2931. {
  2932. DtComboBoxWidget combo = (DtComboBoxWidget)w;
  2933. Dimension data;
  2934. Arg arg;
  2935. XtSetArg(arg, XmNheight, &data);
  2936. XtGetValues(Arrow(combo), &arg, 1);
  2937. *value = (XtArgVal)data;
  2938. }
  2939. void
  2940. _DtComboBoxGetLabelString( Widget w,
  2941. int resource_offset,
  2942. XtArgVal *value)
  2943. {
  2944. DtComboBoxWidget combo = (DtComboBoxWidget)w;
  2945. if (LabelString(combo))
  2946. *value = (XtArgVal)XmStringCopy(LabelString(combo));
  2947. else
  2948. *value = (XtArgVal)NULL;
  2949. }
  2950. void
  2951. _DtComboBoxGetListItemCount( Widget w,
  2952. int resource_offset,
  2953. XtArgVal *value)
  2954. {
  2955. DtComboBoxWidget combo = (DtComboBoxWidget)w;
  2956. int data;
  2957. Arg arg;
  2958. XtSetArg(arg, XmNitemCount, &data);
  2959. XtGetValues(List(combo), &arg, 1);
  2960. *value = (XtArgVal)data;
  2961. }
  2962. void
  2963. _DtComboBoxGetListItems(Widget w,
  2964. int resource_offset,
  2965. XtArgVal *value)
  2966. {
  2967. DtComboBoxWidget combo = (DtComboBoxWidget)w;
  2968. XmStringTable data;
  2969. Arg arg;
  2970. XtSetArg(arg, XmNitems, &data);
  2971. XtGetValues(List(combo), &arg, 1);
  2972. *value = (XtArgVal)data;
  2973. }
  2974. void
  2975. _DtComboBoxGetListFontList( Widget w,
  2976. int resource_offset,
  2977. XtArgVal *value)
  2978. {
  2979. DtComboBoxWidget combo = (DtComboBoxWidget)w;
  2980. XmFontList data;
  2981. Arg arg;
  2982. XtSetArg(arg, XmNfontList, &data);
  2983. XtGetValues(List(combo), &arg, 1);
  2984. *value = (XtArgVal)data;
  2985. }
  2986. void
  2987. _DtComboBoxGetListMarginHeight( Widget w,
  2988. int resource_offset,
  2989. XtArgVal *value)
  2990. {
  2991. DtComboBoxWidget combo = (DtComboBoxWidget)w;
  2992. Dimension data;
  2993. Arg arg;
  2994. XtSetArg(arg, XmNmarginHeight, &data);
  2995. XtGetValues(List(combo), &arg, 1);
  2996. *value = (XtArgVal)data;
  2997. }
  2998. void
  2999. _DtComboBoxGetListMarginWidth( Widget w,
  3000. int resource_offset,
  3001. XtArgVal *value)
  3002. {
  3003. DtComboBoxWidget combo = (DtComboBoxWidget)w;
  3004. Dimension data;
  3005. Arg arg;
  3006. XtSetArg(arg, XmNmarginWidth, &data);
  3007. XtGetValues(List(combo), &arg, 1);
  3008. *value = (XtArgVal)data;
  3009. }
  3010. void
  3011. _DtComboBoxGetListSpacing( Widget w,
  3012. int resource_offset,
  3013. XtArgVal *value)
  3014. {
  3015. DtComboBoxWidget combo = (DtComboBoxWidget)w;
  3016. Dimension data;
  3017. Arg arg;
  3018. XtSetArg(arg, XmNspacing, &data);
  3019. XtGetValues(List(combo), &arg, 1);
  3020. *value = (XtArgVal)data;
  3021. }
  3022. void
  3023. _DtComboBoxGetListTopItemPosition( Widget w,
  3024. int resource_offset,
  3025. XtArgVal *value)
  3026. {
  3027. DtComboBoxWidget combo = (DtComboBoxWidget)w;
  3028. int data;
  3029. Arg arg;
  3030. XtSetArg(arg, XmNtopItemPosition, &data);
  3031. XtGetValues(List(combo), &arg, 1);
  3032. *value = (XtArgVal)data;
  3033. }
  3034. void
  3035. _DtComboBoxGetListVisibleItemCount( Widget w,
  3036. int resource_offset,
  3037. XtArgVal *value)
  3038. {
  3039. DtComboBoxWidget combo = (DtComboBoxWidget)w;
  3040. int data;
  3041. Arg arg;
  3042. XtSetArg(arg, XmNvisibleItemCount, &data);
  3043. XtGetValues(List(combo), &arg, 1);
  3044. *value = (XtArgVal)data;
  3045. }
  3046. static Boolean
  3047. _CvtStringToType(
  3048. Display *dpy,
  3049. XrmValuePtr args,
  3050. Cardinal *num_args,
  3051. XrmValuePtr from,
  3052. XrmValuePtr to,
  3053. XtPointer *data)
  3054. {
  3055. char *from_str;
  3056. static unsigned char to_value;
  3057. if(*num_args !=0 ) {
  3058. XtError(CB_CVTSTRING);
  3059. }
  3060. from_str = (char *)from->addr;
  3061. if(strcmp(from_str, "DROP_DOWN_LIST")==0 ||
  3062. strcmp(from_str, "drop_down_list")==0 ||
  3063. strcmp(from_str, "DtDROP_DOWN_LIST")==0)
  3064. to_value = DtDROP_DOWN_LIST;
  3065. else if (strcmp(from_str, "DROP_DOWN_COMBO_BOX")==0 ||
  3066. strcmp(from_str, "drop_down_combo_box")==0 ||
  3067. strcmp(from_str, "DtDROP_DOWN_COMBO_BOX")==0)
  3068. to_value = DtDROP_DOWN_COMBO_BOX;
  3069. else {
  3070. XtDisplayStringConversionWarning(dpy, from->addr, "ComboBoxType");
  3071. return False;
  3072. }
  3073. if (to->addr == NULL) to->addr = (caddr_t) &to_value;
  3074. else if (to->size <sizeof(unsigned char)) {
  3075. XtDisplayStringConversionWarning(dpy, from->addr, "ComboBoxType");
  3076. return False;
  3077. }
  3078. else
  3079. *(unsigned char *) to->addr = to_value;
  3080. to->size = sizeof(unsigned char);
  3081. return True;
  3082. }
  3083. static void
  3084. input_ungrab ( DtComboBoxWidget combo, int ungrab_mask)
  3085. {
  3086. XmDisplay disp = (XmDisplay) XmGetXmDisplay(XtDisplay(combo));
  3087. if ( ungrab_mask & GRAB_POINTER )
  3088. XtUngrabPointer(Shell(combo), CurrentTime);
  3089. if ( ungrab_mask & GRAB_KEYBOARD )
  3090. XtUngrabKeyboard(List(combo), CurrentTime);
  3091. _XmRemoveGrab(Shell(combo));
  3092. /* We move XtPopdown() here and do _XmRemoveGrab first.
  3093. * This is a fix to solve an MR in Desktop which over a time period
  3094. * develope a possible core-dump due to duplicated removeGrab() calls
  3095. */
  3096. PoppedUp(combo) = FALSE;
  3097. XtPopdown(Shell(combo));
  3098. if (Type(combo) == DtDROP_DOWN_COMBO_BOX)
  3099. XmProcessTraversal(Text(combo), XmTRAVERSE_CURRENT);
  3100. /* This is to enable the Drag-and-Drop operation */
  3101. disp->display.userGrabbed = False;
  3102. }