SpinBox.c 85 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670
  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 librararies 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. /* $XConsortium: SpinBox.c /main/9 1996/10/29 12:49:58 cde-hp $
  24. *
  25. * (c) Copyright 1996 Digital Equipment Corporation.
  26. * (c) Copyright 1993,1994,1996 Hewlett-Packard Company.
  27. * (c) Copyright 1993,1994,1996 International Business Machines Corp.
  28. * (c) Copyright 1993,1994,1996 Sun Microsystems, Inc.
  29. * (c) Copyright 1993,1994,1996 Novell, Inc.
  30. * (c) Copyright 1996 FUJITSU LIMITED.
  31. * (c) Copyright 1996 Hitachi.
  32. */
  33. /***********************************************************
  34. Copyright 1993 Interleaf, Inc.
  35. Permission to use, copy, modify, and distribute this software
  36. and its documentation for any purpose without fee is granted,
  37. provided that the above copyright notice appear in all copies
  38. and that both copyright notice and this permission notice appear
  39. in supporting documentation, and that the name of Interleaf not
  40. be used in advertising or publicly pertaining to distribution of
  41. the software without specific written prior permission.
  42. Interleaf makes no representation about the suitability of this
  43. software for any purpose. It is provided "AS IS" without any
  44. express or implied warranty.
  45. ******************************************************************/
  46. /*
  47. * (C) Copyright 1991,1992, 1993
  48. * Interleaf, Inc.
  49. * 9 Hillside Avenue,
  50. * Waltham, MA 02154
  51. *
  52. * SpinBox.c (DtSpinBoxWidget):
  53. *
  54. * I wanted a margin around the widget (outside the shadow, like buttons),
  55. * so that the spin_box could be made the smae size as a
  56. * push-button, etc. The bulletin-board widget always puts the shadow at
  57. * the outside edge of the widget, so spin_box is a sublcass of
  58. * manager, and we do everything ourselves.
  59. *
  60. * One must be carefull when using Dimension (for core width and height).
  61. * Dimension is an unsigned short. This causes problems when subtracting
  62. * and ending up with what should be a negative number (but it doesn't).
  63. * All child widget positioning is done by the spin_box. We don't
  64. * use any heavy-weight forms, etc. to help us out.
  65. *
  66. * There is no padding when editable. If using a label, give it a
  67. * small margin, so it doesn't run up against the side of our
  68. * shadow or the arrow.
  69. *
  70. * Make some of the SpinBox functions common, so they can be shared
  71. * with ComboBox.
  72. *
  73. * Known bugs:
  74. * Changing margin_width or margin_height resources when the
  75. * spin_box has focus will probably result in display glitches.
  76. */
  77. /*
  78. * The DtSpinBox widget is rigged with the Motif widget binary compatibilit
  79. * mechanism. All Motif-specific changes for this mechanism are preceded
  80. * by a comment including the string "MotifBc".
  81. *
  82. * For a description of the Motif widget binary compatibility mechanism
  83. * see the reference manual entry on XmResolveAllPartOffsets().
  84. *
  85. */
  86. #include <Dt/DtMsgsP.h>
  87. #include <Xm/DrawP.h>
  88. #include <Xm/XmP.h>
  89. #include <Xm/RepType.h>
  90. #include "SpinBoxP.h"
  91. #include "DtWidgetI.h"
  92. #include <Xm/XmPrivate.h> /* _XmShellIsExclusive */
  93. #ifdef I18N_MSG
  94. #include <langinfo.h>
  95. #endif
  96. /*
  97. * MotifBc
  98. */
  99. #define DtSpinBoxIndex (XmManagerIndex + 1)
  100. static XmOffsetPtr ipot; /* Instance part offset table */
  101. static XmOffsetPtr cpot; /* Constraint part offset table */
  102. static void ClassInitialize ();
  103. static void Initialize (DtSpinBoxWidget request,
  104. DtSpinBoxWidget new, ArgList given_args,
  105. Cardinal *num_args);
  106. static XmNavigability WidgetNavigable (DtSpinBoxWidget spin);
  107. static void _SpinBoxFocusIn (DtSpinBoxWidget spin, XEvent *event,
  108. char **params, Cardinal *num_params);
  109. static void _SpinBoxFocusOut (DtSpinBoxWidget spin, XEvent *event,
  110. char **params, Cardinal *num_params);
  111. static void DrawHighlight (DtSpinBoxWidget spin, Boolean clear);
  112. static void _SpinBoxUp (DtSpinBoxWidget spin,
  113. XEvent *event, char **params,
  114. Cardinal *num_params);
  115. static void _SpinBoxDown (DtSpinBoxWidget spin,
  116. XEvent *event, char **params,
  117. Cardinal *num_params);
  118. static void _SpinBoxLeft (DtSpinBoxWidget spin,
  119. XEvent *event, char **params,
  120. Cardinal *num_params);
  121. static void _SpinBoxRight (DtSpinBoxWidget spin,
  122. XEvent *event, char **params,
  123. Cardinal *num_params);
  124. static void _SpinBoxBeginLine (DtSpinBoxWidget spin,
  125. XEvent *event, char **params,
  126. Cardinal *num_params);
  127. static void _SpinBoxEndLine (DtSpinBoxWidget spin,
  128. XEvent *event, char **params,
  129. Cardinal *num_params);
  130. static void _SpinBoxGetFocus (DtSpinBoxWidget spin,
  131. XEvent *event, char **params,
  132. Cardinal *num_params);
  133. static void _SpinBoxPrevTabGroup (DtSpinBoxWidget spin,
  134. XEvent *event, char **params,
  135. Cardinal *num_params);
  136. static void _SpinBoxNextTabGroup (DtSpinBoxWidget spin,
  137. XEvent *event, char **params,
  138. Cardinal *num_params);
  139. static void CheckResources (DtSpinBoxWidget spin);
  140. static void Destroy (DtSpinBoxWidget spin);
  141. static void Resize (DtSpinBoxWidget spin);
  142. static void Redisplay (DtSpinBoxWidget w, XEvent *event,
  143. Region region);
  144. static XtGeometryResult GeometryManager (Widget w,
  145. XtWidgetGeometry *request,
  146. XtWidgetGeometry *reply);
  147. static void SetSpinBoxSize (DtSpinBoxWidget spin);
  148. static void ForceChildSizes (DtSpinBoxWidget spin);
  149. static void CalculateSizes (DtSpinBoxWidget spin,
  150. Dimension *pwidth,
  151. Dimension *pheight,
  152. Dimension *parrow_width);
  153. static void LayoutChildren (DtSpinBoxWidget spin);
  154. static Boolean SetValues (DtSpinBoxWidget current,
  155. DtSpinBoxWidget request,
  156. DtSpinBoxWidget new);
  157. static void ClearShadow (DtSpinBoxWidget w, Boolean all);
  158. static void DrawShadow (DtSpinBoxWidget w);
  159. static void StoreResourceInfo (DtSpinBoxPart *spin_p,
  160. DtSpinBoxPart *old_p,
  161. Boolean do_items);
  162. static char* GetTextString (XmString xm_string);
  163. static void SetTextFieldData (DtSpinBoxWidget spin);
  164. static void SetMaximumLabelSize (DtSpinBoxPart *spin_p);
  165. static void SetLabelData (DtSpinBoxWidget spin);
  166. static void timer_dispatch (XtPointer client_data, XtIntervalId *id);
  167. static void TextFieldActivate (DtSpinBoxPart *spin_p);
  168. static Boolean SendCallback (DtSpinBoxWidget spin, XEvent *event,
  169. Boolean value_changed, int position,
  170. float current, Boolean crossed);
  171. static void FinishUpDown (DtSpinBoxWidget spin,
  172. XtPointer arrow_call_data, int new_position,
  173. float new_current, Boolean crossed);
  174. static void up_cb (Widget w, XtPointer client_data,
  175. XtPointer call_data);
  176. static void down_cb (Widget w, XtPointer client_data,
  177. XtPointer call_data);
  178. static void disarm_cb (Widget w, XtPointer client_data,
  179. XtPointer call_data);
  180. static void grab_leave_cb (Widget w, XtPointer client_data,
  181. XEvent *event, Boolean *dispatch);
  182. static void text_losing_focus_cb (Widget w, XtPointer client_data,
  183. XtPointer call_data);
  184. static void text_activate_cb (Widget w, XtPointer client_data,
  185. XtPointer call_data);
  186. static void text_focus_cb (Widget w, XtPointer client_data,
  187. XtPointer call_data);
  188. static XmImportOperator _XmSetSyntheticResForChild (Widget widget,
  189. int offset,
  190. XtArgVal * value);
  191. static XmString InitLabel = NULL;
  192. /*
  193. * MotifBc
  194. */
  195. #define Label(w) XmField(w,ipot,DtSpinBox,label,Widget)
  196. #define UpArrow(w) XmField(w,ipot,DtSpinBox,up_arrow,Widget)
  197. #define DownArrow(w) XmField(w,ipot,DtSpinBox,down_arrow,Widget)
  198. #define WhichArrow(w) XmField(w,ipot,DtSpinBox,which_arrow,unsigned char)
  199. #define InitCb(w) XmField(w,ipot,DtSpinBox,init_cb,Boolean)
  200. #define Grabbed(w) XmField(w,ipot,DtSpinBox,grabbed,Boolean)
  201. #define Base(w) XmField(w,ipot,DtSpinBox,base,int)
  202. #define Min(w) XmField(w,ipot,DtSpinBox,min,float)
  203. #define Max(w) XmField(w,ipot,DtSpinBox,max,float)
  204. #define Increment(w) XmField(w,ipot,DtSpinBox,increment,float)
  205. #define Current(w) XmField(w,ipot,DtSpinBox,current,float)
  206. #define FloatFormat(w) (String) &(XmField(w,ipot,DtSpinBox,float_format,char *))
  207. #define OldWidth(w) XmField(w,ipot,DtSpinBox,old_width,Dimension)
  208. #define OldHeight(w) XmField(w,ipot,DtSpinBox,old_height,Dimension)
  209. #define LabelMaxLength(w) XmField(w,ipot,DtSpinBox,label_max_length,Dimension)
  210. #define LabelMaxHeight(w) XmField(w,ipot,DtSpinBox,label_max_height,Dimension)
  211. #define ArrowSensitivity(w) XmField(w,ipot,DtSpinBox,arrow_sensitivity,unsigned char)
  212. #define DecimalPoints(w) XmField(w,ipot,DtSpinBox,decimal_points,short)
  213. #define NumericIncrement(w) XmField(w,ipot,DtSpinBox,numeric_increment,int)
  214. #define Maximum(w) XmField(w,ipot,DtSpinBox,maximum,int)
  215. #define Minimum(w) XmField(w,ipot,DtSpinBox,minimum,int)
  216. #define ItemCount(w) XmField(w,ipot,DtSpinBox,item_count,int)
  217. #define Position(w) XmField(w,ipot,DtSpinBox,position,int)
  218. #define ChildType(w) XmField(w,ipot,DtSpinBox,child_type,unsigned char)
  219. #define Items(w) XmField(w,ipot,DtSpinBox,items,XmStringTable)
  220. #define ActivateCallback(w) XmField(w,ipot,DtSpinBox,activate_callback,XtCallbackList)
  221. #define Alignment(w) XmField(w,ipot,DtSpinBox,alignment,unsigned char)
  222. #define ArrowLayout(w) XmField(w,ipot,DtSpinBox,arrow_layout,unsigned char)
  223. #define ArrowSize(w) XmField(w,ipot,DtSpinBox,arrow_size,Dimension)
  224. #define TextColumns(w) XmField(w,ipot,DtSpinBox,text_columns,short)
  225. #define Editable(w) XmField(w,ipot,DtSpinBox,editable,Boolean)
  226. #define FocusCallback(w) XmField(w,ipot,DtSpinBox,focus_callback,XtCallbackList)
  227. #define InitialDelay(w) XmField(w,ipot,DtSpinBox,initial_delay,unsigned int)
  228. #define LosingFocusCallback(w) XmField(w,ipot,DtSpinBox,losing_focus_callback,XtCallbackList)
  229. #define MarginHeight(w) XmField(w,ipot,DtSpinBox,margin_height,Dimension)
  230. #define MarginWidth(w) XmField(w,ipot,DtSpinBox,margin_width,Dimension)
  231. #define TextMaxLength(w) XmField(w,ipot,DtSpinBox,text_max_length,int)
  232. #define ModifyVerifyCallback(w) XmField(w,ipot,DtSpinBox,modify_verify_callback,XtCallbackList)
  233. #define RecomputeSize(w) XmField(w,ipot,DtSpinBox,recompute_size,Boolean)
  234. #define RepeatDelay(w) XmField(w,ipot,DtSpinBox,repeat_delay,unsigned int)
  235. #define Text(w) XmField(w,ipot,DtSpinBox,text,Widget)
  236. #define ValueChangedCallback(w) XmField(w,ipot,DtSpinBox,value_changed_callback,XtCallbackList)
  237. #define Wrap(w) XmField(w,ipot,DtSpinBox,wrap,Boolean)
  238. #define Timer(w) XmField(w,ipot,DtSpinBox,timer,XtIntervalId)
  239. /* SpinBox and Superclass resource macros*/
  240. #define PUnitType(w) w->primitive.unit_type
  241. #define MUnitType(w) w->manager.unit_type
  242. #define MFgPixel(w) w->manager.foreground
  243. #define SPIN_SHADOW(w) w->manager.shadow_thickness
  244. #define CBgPixel(w) w->core.background_pixel
  245. #define CBgPixmap(w) w->core.background_pixmap
  246. #define Width(w) w->core.width
  247. #define Height(w) w->core.height
  248. #define SPIN_MARGIN_W(w) MarginWidth(w)
  249. #define SPIN_MARGIN_H(w) MarginHeight(w)
  250. #define MAXINT 2147483647 /* Taken from TextF.c */
  251. #define DEFAULT_COL 20
  252. /* USL: Label get Focus */
  253. static XtTranslations child_trans_label;
  254. /* USL: Keyboard only for Text */
  255. static XtTranslations child_trans_text;
  256. static XtTranslations child_trans_arrow;
  257. static XtTranslations child_trans;
  258. static XtTranslations spin_trans;
  259. static char const SpinBoxTranslationTable[] = "\
  260. <FocusIn>: SpinBoxFocusIn() \n\
  261. <FocusOut>: SpinBoxFocusOut() \n\
  262. <Key>osfUp: SpinBoxUp() \n\
  263. <Key>osfDown: SpinBoxDown() \n\
  264. <Key>osfRight: SpinBoxRight() \n\
  265. <Key>osfLeft: SpinBoxLeft() \n\
  266. <Key>osfBeginLine: SpinBoxBeginLine() \n\
  267. <Key>osfEndLine: SpinBoxEndLine() \n\
  268. ";
  269. static char const SpinBoxChildTranslationTable[] = "\
  270. <Key>osfUp: SpinBoxUp(child) \n\
  271. <Key>osfDown: SpinBoxDown(child) \n\
  272. <Key>osfRight: SpinBoxRight(child) \n\
  273. <Key>osfLeft: SpinBoxLeft(child) \n\
  274. <Key>osfBeginLine: SpinBoxBeginLine(child) \n\
  275. <Key>osfEndLine: SpinBoxEndLine(child) \n\
  276. ";
  277. /* #5: Label get focus */
  278. static char const SpinBoxLabelTranslationTable[] = "\
  279. <Key>osfUp: SpinBoxUp(child) \n\
  280. <Key>osfDown: SpinBoxDown(child) \n\
  281. <Key>osfRight: SpinBoxRight(child) \n\
  282. <Key>osfLeft: SpinBoxLeft(child) \n\
  283. <Key>osfBeginLine: SpinBoxBeginLine(child) \n\
  284. <Key>osfEndLine: SpinBoxEndLine(child) \n\
  285. <Key>osfDown: SpinBoxGetFocus() \n\
  286. <Btn1Down>,<Btn1Up>: SpinBoxGetFocus() \n\
  287. <Key>osfSelect: SpinBoxGetFocus() \n\
  288. ~s ~m ~a <Key>space: SpinBoxGetFocus() \n\
  289. ";
  290. /* USL: Keyboard Only Traversing During Editable-Mode */
  291. static char const SpinBoxTextTranslationTable[] = "\
  292. <Key>osfUp: SpinBoxUp(child) SpinBoxRight(child)\n\
  293. <Key>osfDown: SpinBoxDown(child) SpinBoxLeft(child)\n\
  294. ";
  295. static char const SpinBoxArrowTranslationTable[] = "\
  296. <Key>osfUp: SpinBoxUp(child) \n\
  297. <Key>osfDown: SpinBoxDown(child) \n\
  298. <Key>osfRight: SpinBoxRight(child) \n\
  299. <Key>osfLeft: SpinBoxLeft(child) \n\
  300. <Key>osfBeginLine: SpinBoxBeginLine(child) \n\
  301. <Key>osfEndLine: SpinBoxEndLine(child) \n\
  302. s ~m ~a <Key>Tab: SpinBoxPrevTabGroup()\n\
  303. ~m ~a <Key>Tab: SpinBoxNextTabGroup()\n\
  304. ";
  305. static XtActionsRec SpinBoxActionTable[] = {
  306. {"SpinBoxFocusIn", (XtActionProc)_SpinBoxFocusIn},
  307. {"SpinBoxFocusOut", (XtActionProc)_SpinBoxFocusOut},
  308. {"SpinBoxUp", (XtActionProc)_SpinBoxUp},
  309. {"SpinBoxDown", (XtActionProc)_SpinBoxDown},
  310. {"SpinBoxRight", (XtActionProc)_SpinBoxRight},
  311. {"SpinBoxLeft", (XtActionProc)_SpinBoxLeft},
  312. {"SpinBoxBeginLine", (XtActionProc)_SpinBoxBeginLine},
  313. {"SpinBoxEndLine", (XtActionProc)_SpinBoxEndLine},
  314. {"SpinBoxGetFocus", (XtActionProc)_SpinBoxGetFocus},
  315. {"SpinBoxPrevTabGroup", (XtActionProc)_SpinBoxPrevTabGroup},
  316. {"SpinBoxNextTabGroup", (XtActionProc)_SpinBoxNextTabGroup},
  317. };
  318. /* DtSpinBoxWidget resources */
  319. /* MotifBc */
  320. #define offset(field) XtOffset(DtSpinBoxWidget, field)
  321. #define DtOffset(field) XmPartOffset(DtSpinBox,field)
  322. static XmPartResource resources[] = {
  323. {XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension,
  324. sizeof(Dimension), offset(manager.shadow_thickness),
  325. XmRImmediate, (XtPointer)TEXT_FIELD_SHADOW},
  326. /* Common resources */
  327. {DtNactivateCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
  328. DtOffset(activate_callback), XmRCallback,
  329. (XtPointer)NULL},
  330. {DtNalignment, DtCAlignment, XmRAlignment, sizeof(unsigned char),
  331. DtOffset(alignment), XmRImmediate,
  332. (XtPointer)DtALIGNMENT_BEGINNING},
  333. {DtNarrowLayout, DtCArrowLayout, DtRArrowLayout, sizeof(unsigned char),
  334. DtOffset(arrow_layout), XmRImmediate,
  335. (XtPointer)DtARROWS_END},
  336. {DtNarrowSensitivity, DtCArrowSensitivity, DtRArrowSensitivity,
  337. sizeof(unsigned char), DtOffset(arrow_sensitivity),
  338. XmRImmediate, (XtPointer)DtARROWS_SENSITIVE},
  339. {DtNspinBoxChildType, DtCSpinBoxChildType, DtRSpinBoxChildType,
  340. sizeof(unsigned char),
  341. DtOffset(child_type), XmRImmediate, (XtPointer)DtSTRING},
  342. {DtNcolumns, DtCColumns, XmRShort, sizeof(short),
  343. DtOffset(text_columns), XmRImmediate, (XtPointer)DEFAULT_COL},
  344. {DtNdecimalPoints, DtCDecimalPoints, XmRShort, sizeof( short ),
  345. DtOffset(decimal_points), XmRImmediate, (XtPointer)0},
  346. {DtNeditable, DtCEditable, XmRBoolean, sizeof(Boolean),
  347. DtOffset(editable), XmRImmediate, (XtPointer)TRUE},
  348. {DtNfocusCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
  349. DtOffset(focus_callback), XmRCallback,
  350. (XtPointer)NULL},
  351. {DtNincrementValue, DtCIncrementValue, XmRInt, sizeof(int),
  352. DtOffset(numeric_increment), XmRImmediate, (XtPointer)1},
  353. {DtNinitialDelay, DtCInitialDelay, XmRInt, sizeof(unsigned int),
  354. DtOffset(initial_delay), XmRImmediate, (XtPointer)250},
  355. {DtNnumValues, DtCNumValues, DtRNumValues, sizeof(int),
  356. DtOffset(item_count), XmRImmediate, (XtPointer)0},
  357. {DtNvalues, DtCItems, XmRXmStringTable, sizeof(XmStringTable),
  358. DtOffset(items), XmRImmediate, (XtPointer)NULL},
  359. {DtNlosingFocusCallback, DtCCallback, XmRCallback, sizeof(XtCallbackList),
  360. DtOffset(losing_focus_callback), XmRCallback,
  361. (XtPointer)NULL},
  362. {DtNmarginHeight, DtCMarginHeight, XmRVerticalDimension, sizeof(Dimension),
  363. DtOffset(margin_height), XmRImmediate, (XtPointer)MARGIN},
  364. {DtNmarginWidth, DtCMarginWidth, XmRHorizontalDimension, sizeof(Dimension),
  365. DtOffset(margin_width), XmRImmediate, (XtPointer)MARGIN},
  366. {DtNmaximumValue, DtCMaximumValue, XmRInt, sizeof(int),
  367. DtOffset(maximum), XmRImmediate, (XtPointer)10},
  368. {DtNmaxLength, DtCMaxLength, XmRInt, sizeof(int),
  369. DtOffset(text_max_length), XmRImmediate, (XtPointer)MAXINT},
  370. {DtNminimumValue, DtCMinimumValue, XmRInt, sizeof(int),
  371. DtOffset(minimum), XmRImmediate, (XtPointer)0},
  372. {DtNmodifyVerifyCallback, DtCCallback, XmRCallback,
  373. sizeof(XtCallbackList), DtOffset(modify_verify_callback),
  374. XmRCallback, (XtPointer)NULL},
  375. {DtNposition, DtCPosition, XmRInt, sizeof(int),
  376. DtOffset(position), XmRImmediate, (XtPointer)0},
  377. {DtNrecomputeSize, DtCRecomputeSize, XmRBoolean, sizeof(Boolean),
  378. DtOffset(recompute_size), XmRImmediate, (XtPointer)TRUE},
  379. {DtNrepeatDelay, DtCRepeatDelay, XmRInt, sizeof(unsigned int),
  380. DtOffset(repeat_delay), XmRImmediate, (XtPointer)200},
  381. {DtNtextField, DtCTextField, XmRWidget, sizeof(Widget),
  382. DtOffset(text), XmRImmediate, (XtPointer)NULL},
  383. {DtNvalueChangedCallback, DtCCallback, XmRCallback,
  384. sizeof(XtCallbackList), DtOffset(value_changed_callback),
  385. XmRCallback, (XtPointer)NULL},
  386. {DtNwrap, DtCWrap, XmRBoolean, sizeof(Boolean),
  387. DtOffset(wrap), XmRImmediate, (XtPointer)TRUE},
  388. };
  389. /* Synthetic resources. Only used for Motif API arrowSize right now */
  390. static XmSyntheticResource syn_resources[] = {
  391. {DtNarrowSize, sizeof(Dimension), DtOffset(arrow_size),
  392. _DtSpinBoxGetArrowSize, _XmSetSyntheticResForChild},
  393. {DtNmarginHeight, sizeof(Dimension), DtOffset(margin_height),
  394. XmeFromVerticalPixels, XmeToVerticalPixels},
  395. {DtNmarginWidth, sizeof(Dimension), DtOffset(margin_width),
  396. XmeFromHorizontalPixels, XmeToHorizontalPixels},
  397. };
  398. #undef DtOffset
  399. #undef offset
  400. /* Need Class Extension for widget navigation */
  401. static XmBaseClassExtRec baseClassExtRec = {
  402. NULL,
  403. NULLQUARK,
  404. XmBaseClassExtVersion,
  405. sizeof(XmBaseClassExtRec),
  406. (XtInitProc)NULL, /* InitializePrehook */
  407. (XtSetValuesFunc)NULL, /* SetValuesPrehook */
  408. (XtInitProc)NULL, /* InitializePosthook */
  409. (XtSetValuesFunc)NULL, /* SetValuesPosthook */
  410. NULL, /* secondaryObjectClass */
  411. (XtInitProc)NULL, /* secondaryCreate */
  412. (XmGetSecResDataFunc)NULL, /* getSecRes data */
  413. { 0 }, /* fastSubclass flags */
  414. (XtArgsProc)NULL, /* getValuesPrehook */
  415. (XtArgsProc)NULL, /* getValuesPosthook */
  416. (XtWidgetClassProc)NULL, /* classPartInitPrehook */
  417. (XtWidgetClassProc)NULL, /* classPartInitPosthook*/
  418. NULL, /* ext_resources */
  419. NULL, /* compiled_ext_resources*/
  420. 0, /* num_ext_resources */
  421. FALSE, /* use_sub_resources */
  422. (XmWidgetNavigableProc)WidgetNavigable,
  423. /* widgetNavigable */
  424. (XmFocusChangeProc)NULL, /* focusChange */
  425. (XmWrapperData)NULL /* wrapperData */
  426. };
  427. /*
  428. * Define Class Record.
  429. */
  430. externaldef(dtspinboxclassrec) DtSpinBoxClassRec dtSpinBoxClassRec =
  431. {
  432. { /* core_class fields */
  433. (WidgetClass)&(xmManagerClassRec), /* superclass */
  434. (String)"DtSpinBox", /* class_name */
  435. (Cardinal)sizeof(DtSpinBoxPart), /* widget_size */
  436. (XtProc)ClassInitialize, /* class_initialize */
  437. (XtWidgetClassProc)NULL, /* class_part_init */
  438. (XtEnum)FALSE, /* class_inited */
  439. (XtInitProc)Initialize, /* initialize */
  440. (XtArgsProc)NULL, /* initialize_hook */
  441. (XtRealizeProc)XtInheritRealize, /* realize */
  442. (XtActionList)SpinBoxActionTable, /* actions */
  443. (Cardinal)XtNumber(SpinBoxActionTable), /* num_actions */
  444. (XtResourceList)resources, /* resources */
  445. (Cardinal)XtNumber(resources), /* num_resources */
  446. (XrmClass)NULLQUARK, /* xrm_class */
  447. (Boolean)TRUE, /* compress_motion */
  448. (XtEnum)XtExposeCompressMaximal, /* compress_exposure */
  449. (Boolean)TRUE, /* compress_enterleave*/
  450. (Boolean)FALSE, /* visible_interest */
  451. (XtWidgetProc)Destroy, /* destroy */
  452. (XtWidgetProc)Resize, /* resize */
  453. (XtExposeProc)Redisplay, /* expose */
  454. (XtSetValuesFunc)SetValues, /* set_values */
  455. (XtArgsFunc)NULL, /* set values hook */
  456. (XtAlmostProc)XtInheritSetValuesAlmost, /* set values almost */
  457. (XtArgsProc)NULL, /* get values hook */
  458. (XtAcceptFocusProc)NULL, /* accept_focus */
  459. (XtVersionType)XtVersionDontCheck, /* Version */
  460. (XtPointer)NULL, /* PRIVATE cb list */
  461. (String)XtInheritTranslations, /* tm_table */
  462. (XtGeometryHandler)XtInheritQueryGeometry, /* query_geom */
  463. (XtStringProc)XtInheritDisplayAccelerator, /* display_accelerator*/
  464. (XtPointer)&baseClassExtRec /* extension */
  465. },
  466. { /* composite_class fields */
  467. (XtGeometryHandler)GeometryManager, /* geometry_manager */
  468. (XtWidgetProc)XtInheritChangeManaged, /* change_managed */
  469. (XtWidgetProc)XtInheritInsertChild, /* insert_child */
  470. (XtWidgetProc)XtInheritDeleteChild, /* delete_child */
  471. (XtPointer)NULL /* extension */
  472. },
  473. { /* constraint_class fields */
  474. (XtResourceList)NULL, /* resources */
  475. (Cardinal)0, /* num_resources */
  476. (Cardinal)0, /* constraint_size */
  477. (XtInitProc)NULL, /* initialize */
  478. (XtWidgetProc)NULL, /* destroy */
  479. (XtSetValuesFunc)NULL, /* set_values */
  480. (XtPointer)NULL /* extension */
  481. },
  482. { /* manager class */
  483. (String)XtInheritTranslations, /* translations */
  484. (XmSyntheticResource*)syn_resources, /* syn resources */
  485. (int)XtNumber(syn_resources), /* num syn_resources */
  486. (XmSyntheticResource*)NULL, /* get_cont_resources */
  487. (int)0, /* num_get_cont_resources */
  488. (XmParentProcessProc)XmInheritParentProcess,/* parent_process */
  489. (XtPointer)NULL /* extension */
  490. },
  491. { /* spin_box_class fields */
  492. (Boolean)0,
  493. }
  494. };
  495. externaldef(dtspinboxwidgetclass) WidgetClass dtSpinBoxWidgetClass =
  496. (WidgetClass)&dtSpinBoxClassRec;
  497. static XmRepTypeId _DtRID_SB_ARROW_SENSITIVITY_TYPE;
  498. static String _DtArrowSensitivityNames[] = {
  499. "arrows_insensitive",
  500. "arrows_increment_sensitive",
  501. "arrows_decrement_sensitive",
  502. "arrows_sensitive"
  503. };
  504. /*
  505. * Must set up the record type for the class extensions to work.
  506. */
  507. static void
  508. ClassInitialize(void)
  509. {
  510. baseClassExtRec.record_type = XmQmotif;
  511. /*
  512. * MotifBc
  513. */
  514. XmResolveAllPartOffsets(dtSpinBoxWidgetClass, &ipot, &cpot);
  515. child_trans = XtParseTranslationTable(SpinBoxChildTranslationTable);
  516. spin_trans = XtParseTranslationTable(SpinBoxTranslationTable);
  517. child_trans_label=XtParseTranslationTable(SpinBoxLabelTranslationTable);
  518. child_trans_text=XtParseTranslationTable(SpinBoxTextTranslationTable);
  519. child_trans_arrow=XtParseTranslationTable(SpinBoxArrowTranslationTable);
  520. _DtRID_SB_ARROW_SENSITIVITY_TYPE =
  521. XmRepTypeRegister(DtRArrowSensitivity, _DtArrowSensitivityNames,
  522. NULL, XtNumber(_DtArrowSensitivityNames));
  523. InitLabel = XmStringCreateLocalized(SB_LABEL);
  524. }
  525. /*
  526. * SpinBox initialization function. This builds the widgets inside
  527. * our widget, to get the correct layout. If the editable resource
  528. * is TRUE, we create a textField; if FALSE, we create a label. If the
  529. * user changes this resource later, we will create the other widget
  530. * (textField or Label). We don't want to carry backage from both
  531. * widgets if the user never changes the editable resource.
  532. */
  533. static void
  534. Initialize( DtSpinBoxWidget request,
  535. DtSpinBoxWidget new,
  536. ArgList given_args,
  537. Cardinal *num_args)
  538. { /* MotifBc */
  539. DtSpinBoxPart *spin_p = (DtSpinBoxPart*)
  540. &(XmField(new,ipot,DtSpinBox,label,Widget));
  541. char *widget_name;
  542. Arg args[20];
  543. int n;
  544. /* Resolution Independent */
  545. unsigned char unit_type = MUnitType(new);
  546. /* Overwrite the manager's focusIn and focusOut translations */
  547. XtOverrideTranslations((Widget)new, spin_trans);
  548. widget_name = XtMalloc(strlen(XtName((Widget)new)) + 10);
  549. Text(new) = (Widget)NULL;
  550. Label(new) = (Widget)NULL;
  551. OldWidth(new) = 0;
  552. OldHeight(new) = 0;
  553. InitCb(new) = TRUE;
  554. Grabbed(new) = FALSE;
  555. CheckResources(new);
  556. /*
  557. * Create the text or label depending on editable resource.
  558. */
  559. if (Editable(new)) {
  560. sprintf(widget_name, "%s_TF", XtName((Widget)new));
  561. n = 0;
  562. XtSetArg(args[n], XmNmaxLength, TextMaxLength(new)); n++;
  563. XtSetArg(args[n], XmNmarginWidth, TEXT_CONTEXT_MARGIN); n++;
  564. XtSetArg(args[n], XmNmarginHeight, 2); n++;
  565. /* Resolution Independent */
  566. if (unit_type != XmPIXELS) {
  567. XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
  568. }
  569. Text(new) = XtCreateManagedWidget(widget_name,
  570. xmTextFieldWidgetClass,
  571. (Widget)new, args, n);
  572. XtAddCallback(Text(new), XmNlosingFocusCallback,
  573. text_losing_focus_cb, (XtPointer)new);
  574. XtAddCallback(Text(new), XmNactivateCallback,
  575. text_activate_cb, (XtPointer)new);
  576. XtAddCallback(Text(new), XmNfocusCallback,
  577. text_focus_cb, (XtPointer)new);
  578. /* USL */
  579. XtOverrideTranslations((Widget)Text(new), child_trans_text);
  580. n = 0;
  581. if (TextColumns(request) == DEFAULT_COL && Width(request)) {
  582. Dimension width;
  583. CalculateSizes(new, &width, NULL, NULL);
  584. XtSetArg(args[n], XmNwidth, width); n++;
  585. }
  586. else {
  587. XtSetArg(args[n], XmNcolumns, TextColumns(new)); n++;
  588. }
  589. if (unit_type != XmPIXELS) {
  590. XtSetArg(args[n], XmNunitType, unit_type); n++;
  591. }
  592. XtSetValues(Text(new), args, n);
  593. }
  594. else {
  595. sprintf(widget_name, "%s_Label", XtName((Widget)new));
  596. SPIN_SHADOW(new) = LABEL_SHADOW;
  597. n = 0;
  598. XtSetArg(args[n], XmNalignment, Alignment(new)); n++;
  599. XtSetArg(args[n], XmNrecomputeSize, FALSE); n++;
  600. XtSetArg(args[n], XmNlabelString, InitLabel); n++;
  601. XtSetArg(args[n], XmNmarginLeft, LABEL_PADDING); n++;
  602. XtSetArg(args[n], XmNmarginRight, LABEL_PADDING); n++;
  603. XtSetArg(args[n], XmNmarginWidth, TEXT_CONTEXT_MARGIN); n++;
  604. XtSetArg(args[n], XmNmarginHeight, 2); n++;
  605. if (unit_type != XmPIXELS) {
  606. XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
  607. }
  608. Label(new) = XtCreateManagedWidget(widget_name, xmLabelWidgetClass,
  609. (Widget)new, args, n);
  610. /* USL */
  611. XtOverrideTranslations((Widget)Label(new), child_trans_label);
  612. n = 0;
  613. if (unit_type != XmPIXELS) {
  614. XtSetArg(args[n], XmNunitType, unit_type); n++;
  615. }
  616. if (Width(new)) {
  617. Dimension width;
  618. CalculateSizes(new, &width, NULL, NULL);
  619. XtSetArg(args[n], XmNwidth, width); n++;
  620. }
  621. if (n>0)
  622. XtSetValues(Label(new), args, n);
  623. }
  624. /*
  625. * Create the 2 ArrowWidgets.
  626. */
  627. sprintf(widget_name, "%s_Up", XtName((Widget)new));
  628. n = 0;
  629. if (ArrowLayout(new) == DtARROWS_SPLIT) {
  630. XtSetArg(args[n], XmNarrowDirection, XmARROW_RIGHT); n++;
  631. }
  632. XtSetArg(args[n], XmNhighlightThickness, 0); n++;
  633. XtSetArg(args[n], XmNshadowThickness, 0); n++;
  634. XtSetArg(args[n], XmNtraversalOn, FALSE); n++;
  635. XtSetArg(args[n], XmNforeground, CBgPixel(new)); n++;
  636. UpArrow(new) = XtCreateManagedWidget(widget_name,
  637. xmArrowButtonWidgetClass,
  638. (Widget)new, args, n);
  639. XtOverrideTranslations((Widget)UpArrow(new), child_trans_arrow);
  640. sprintf(widget_name, "%s_Down", XtName((Widget)new));
  641. if (ArrowLayout(new) == DtARROWS_SPLIT) {
  642. XtSetArg(args[n], XmNarrowDirection, XmARROW_LEFT); n++;
  643. }
  644. else {
  645. XtSetArg(args[n], XmNarrowDirection, XmARROW_DOWN); n++;
  646. }
  647. DownArrow(new) = XtCreateManagedWidget(widget_name,
  648. xmArrowButtonWidgetClass,
  649. (Widget)new, args, n);
  650. XtOverrideTranslations((Widget)DownArrow(new), child_trans_arrow);
  651. /* Set sensitivity of arrows (up arrow is right arrow) */
  652. if ((ArrowSensitivity(new) == DtARROWS_INSENSITIVE) ||
  653. (ArrowSensitivity(new) == DtARROWS_DECREMENT_SENSITIVE))
  654. XtSetSensitive(UpArrow(new), FALSE);
  655. if ((ArrowSensitivity(new) == DtARROWS_INSENSITIVE) ||
  656. (ArrowSensitivity(new) == DtARROWS_INCREMENT_SENSITIVE))
  657. XtSetSensitive(DownArrow(new), FALSE);
  658. /*
  659. * Arm causes the value to change and the timer to start.
  660. * Disarm (leaveNotify from grab) causes the timer to stop.
  661. */
  662. XtAddCallback(UpArrow(new), XmNarmCallback, up_cb, (XtPointer)new);
  663. XtAddCallback(UpArrow(new), XmNdisarmCallback, disarm_cb,
  664. (XtPointer)new);
  665. XtAddEventHandler(UpArrow(new), LeaveWindowMask, FALSE, grab_leave_cb,
  666. (XtPointer)new);
  667. XtAddCallback(DownArrow(new), XmNarmCallback, down_cb, (XtPointer)new);
  668. XtAddCallback(DownArrow(new), XmNdisarmCallback, disarm_cb,
  669. (XtPointer)new);
  670. XtAddEventHandler(DownArrow(new), LeaveWindowMask, FALSE,
  671. grab_leave_cb, (XtPointer)new);
  672. /* Initialize everything based on what the resource values are */
  673. StoreResourceInfo(spin_p, NULL, TRUE);
  674. /*
  675. * Set initial value in text or label if items was specified
  676. */
  677. if (Editable(new) == FALSE) {
  678. SetLabelData(new);
  679. SetMaximumLabelSize(spin_p);
  680. }
  681. else
  682. {
  683. SetTextFieldData(new);
  684. }
  685. SetSpinBoxSize(new);
  686. LayoutChildren(new);
  687. XtFree(widget_name);
  688. /* Store Converter for DtNmaximumValue, DtNminimumValue, DtNincrementValue,
  689. */
  690. XtSetTypeConverter(XmRString, DtRMaximumValue, XtCvtStringToInt, NULL, 0,
  691. XtCacheAll, NULL);
  692. XtSetTypeConverter(XmRString, DtRMinimumValue, XtCvtStringToInt, NULL, 0,
  693. XtCacheAll, NULL);
  694. XtSetTypeConverter(XmRString, DtRIncrementValue, XtCvtStringToInt, NULL, 0,
  695. XtCacheAll, NULL);
  696. XtSetTypeConverter(XmRString, DtRNumValues, XtCvtStringToInt, NULL, 0,
  697. XtCacheAll, NULL);
  698. /*
  699. * this is so these resources can be set uniformly through XtCreateWidget
  700. * or through defaults file as *spin.backgound
  701. */
  702. n=0;
  703. XtSetArg(args[n],XmNbackground,CBgPixel(new));n++;
  704. XtSetArg(args[n],XmNbackgroundPixmap,CBgPixmap(new));n++;
  705. XtSetArg(args[n],XmNforeground,MFgPixel(new));n++;
  706. if(Text(new))
  707. XtSetValues (Text(new),args,n);
  708. if(Label(new))
  709. XtSetValues (Label(new),args,n);
  710. if(UpArrow(new))
  711. XtSetValues (UpArrow(new),args,n);
  712. if(DownArrow(new))
  713. XtSetValues (DownArrow(new),args,n);
  714. }
  715. /*
  716. * Allow the manager to gain focus if not editable. If editable (using
  717. * text-field), then let the toolkit give focus to the text-field.
  718. */
  719. static XmNavigability
  720. WidgetNavigable(DtSpinBoxWidget spin)
  721. {
  722. XmNavigationType nav_type = ((XmManagerWidget)spin)->manager.navigation_type;
  723. if (spin->core.sensitive && spin->core.ancestor_sensitive &&
  724. ((XmManagerWidget)spin)->manager.traversal_on) {
  725. if ((nav_type == XmSTICKY_TAB_GROUP) ||
  726. (nav_type == XmEXCLUSIVE_TAB_GROUP) ||
  727. ((nav_type == XmTAB_GROUP) &&
  728. !_XmShellIsExclusive((Widget)spin))) {
  729. if (Editable(spin))
  730. return(XmDESCENDANTS_TAB_NAVIGABLE);
  731. else
  732. return(XmTAB_NAVIGABLE);
  733. }
  734. return(XmDESCENDANTS_NAVIGABLE);
  735. }
  736. return(XmNOT_NAVIGABLE);
  737. }
  738. /*
  739. * The spin_box gets focus.
  740. */
  741. static void
  742. _SpinBoxFocusIn( DtSpinBoxWidget spin,
  743. XEvent *event,
  744. char **params,
  745. Cardinal *num_params)
  746. {
  747. DrawHighlight(spin, FALSE);
  748. }
  749. /*
  750. * The spin_box loses focus.
  751. */
  752. static void
  753. _SpinBoxFocusOut( DtSpinBoxWidget spin,
  754. XEvent *event,
  755. char **params,
  756. Cardinal *num_params)
  757. {
  758. DrawHighlight(spin, TRUE);
  759. }
  760. /*
  761. * This function gets called whenever we draw or clear the shadow (to
  762. * redraw highlight during resize, etc), as well as during focus_in
  763. * and focus_out events.
  764. */
  765. static void
  766. DrawHighlight( DtSpinBoxWidget spin,
  767. Boolean clear)
  768. {
  769. XRectangle rect[4] ;
  770. if (XtIsRealized((Widget)spin)) {
  771. if (clear) {
  772. rect[0].x = rect[1].x = rect[2].x = 0;
  773. rect[3].x = OldWidth(spin) - SPIN_MARGIN_W(spin);
  774. rect[0].y = rect[2].y = rect[3].y = 0 ;
  775. rect[1].y = OldHeight(spin) - SPIN_MARGIN_H(spin);
  776. rect[0].width = rect[1].width = OldWidth(spin);
  777. rect[2].width = rect[3].width = SPIN_MARGIN_W(spin);
  778. rect[0].height = rect[1].height = SPIN_MARGIN_H(spin);
  779. rect[2].height = rect[3].height = OldHeight(spin);
  780. XFillRectangles(XtDisplayOfObject((Widget)spin),
  781. XtWindowOfObject((Widget)spin),
  782. spin->manager.background_GC, rect, 4);
  783. }
  784. else if (XmGetFocusWidget((Widget)spin) == (Widget)spin) {
  785. rect[0].x = rect[1].x = rect[2].x = 0;
  786. rect[3].x = XtWidth(spin) - SPIN_MARGIN_W(spin);
  787. rect[0].y = rect[2].y = rect[3].y = 0 ;
  788. rect[1].y = XtHeight(spin) - SPIN_MARGIN_H(spin);
  789. rect[0].width = rect[1].width = XtWidth(spin);
  790. rect[2].width = rect[3].width = SPIN_MARGIN_W(spin);
  791. rect[0].height = rect[1].height = SPIN_MARGIN_H(spin);
  792. rect[2].height = rect[3].height = XtHeight(spin);
  793. XFillRectangles(XtDisplayOfObject((Widget)spin),
  794. XtWindowOfObject((Widget)spin),
  795. spin->manager.highlight_GC, rect, 4);
  796. }
  797. }
  798. }
  799. /*
  800. * osfUp virtual key hit. Simulate hitting the up arrow.
  801. */
  802. static void
  803. _SpinBoxUp( DtSpinBoxWidget spin,
  804. XEvent *event,
  805. char **params,
  806. Cardinal *num_params)
  807. {
  808. if (*num_params != 0) /* params means label or arrows */
  809. spin = (DtSpinBoxWidget)XtParent(spin);
  810. if (ArrowLayout(spin) != DtARROWS_SPLIT) {
  811. up_cb((Widget)UpArrow(spin), (XtPointer)spin, NULL);
  812. disarm_cb((Widget)UpArrow(spin), (XtPointer)spin, NULL);
  813. }
  814. }
  815. /*
  816. * osfDown virtual key hit. Simulate hitting the down arrow.
  817. */
  818. static void
  819. _SpinBoxDown(DtSpinBoxWidget spin,
  820. XEvent *event,
  821. char **params,
  822. Cardinal *num_params)
  823. {
  824. if (*num_params != 0) /* params means label or arrows */
  825. spin = (DtSpinBoxWidget)XtParent(spin);
  826. if (ArrowLayout(spin) != DtARROWS_SPLIT) {
  827. down_cb((Widget)DownArrow(spin), (XtPointer)spin, NULL);
  828. disarm_cb((Widget)DownArrow(spin), (XtPointer)spin, NULL);
  829. }
  830. }
  831. /*
  832. * osfRight virtual key hit. Simulate hitting the up arrow.
  833. */
  834. static void
  835. _SpinBoxRight(DtSpinBoxWidget spin,
  836. XEvent *event,
  837. char **params,
  838. Cardinal *num_params)
  839. {
  840. if (*num_params != 0) /* params means label or arrows */
  841. spin = (DtSpinBoxWidget)XtParent(spin);
  842. if (ArrowLayout(spin) == DtARROWS_SPLIT) {
  843. up_cb((Widget)UpArrow(spin), (XtPointer)spin, NULL);
  844. disarm_cb((Widget)UpArrow(spin), (XtPointer)spin, NULL);
  845. }
  846. }
  847. /*
  848. * osfLeft virtual key hit. Simulate hitting the down arrow.
  849. */
  850. static void
  851. _SpinBoxLeft(DtSpinBoxWidget spin,
  852. XEvent *event,
  853. char **params,
  854. Cardinal *num_params)
  855. {
  856. if (*num_params != 0) /* params means label or arrows */
  857. spin = (DtSpinBoxWidget)XtParent(spin);
  858. if (ArrowLayout(spin) == DtARROWS_SPLIT) {
  859. down_cb((Widget)DownArrow(spin), (XtPointer)spin, NULL);
  860. disarm_cb((Widget)DownArrow(spin), (XtPointer)spin, NULL);
  861. }
  862. }
  863. /*
  864. * osfBeginLine virtual key hit. Go to first item.
  865. */
  866. static void
  867. _SpinBoxBeginLine( DtSpinBoxWidget spin,
  868. XEvent *event,
  869. char **params,
  870. Cardinal *num_params)
  871. {
  872. int new_position;
  873. float new_current;
  874. if (*num_params != 0) /* params means label or arrows */
  875. spin = (DtSpinBoxWidget)XtParent(spin);
  876. if (ChildType(spin) == DtNUMERIC) {
  877. new_position = Minimum(spin);
  878. new_current = Min(spin);
  879. }
  880. else {
  881. new_position = 0;
  882. }
  883. if (SendCallback(spin, event, FALSE, new_position,
  884. new_current, FALSE) == TRUE) {
  885. /* User said yes, so set widget values */
  886. Position(spin) = new_position;
  887. Current(spin) = new_current;
  888. if (Editable(spin))
  889. SetTextFieldData(spin);
  890. else
  891. SetLabelData(spin);
  892. /* send value_changed callback */
  893. (void)SendCallback(spin, event, TRUE, Position(spin),
  894. Current(spin), FALSE);
  895. }
  896. }
  897. /*
  898. * osfEndLine virtual key hit. Go to last item.
  899. */
  900. static void
  901. _SpinBoxEndLine( DtSpinBoxWidget spin,
  902. XEvent *event,
  903. char **params,
  904. Cardinal *num_params)
  905. {
  906. int new_position;
  907. float new_current;
  908. if (*num_params != 0) /* params means label or arrows */
  909. spin = (DtSpinBoxWidget)XtParent(spin);
  910. if (ChildType(spin) == DtNUMERIC) {
  911. new_position = Maximum(spin);
  912. new_current = Max(spin);
  913. }
  914. else {
  915. new_position = ItemCount(spin) - 1;
  916. }
  917. if (SendCallback(spin, event, FALSE, new_position,
  918. new_current, FALSE) == TRUE) {
  919. /* User said yes, so set widget values */
  920. Position(spin) = new_position;
  921. Current(spin) = new_current;
  922. if (Editable(spin))
  923. SetTextFieldData(spin);
  924. else
  925. SetLabelData(spin);
  926. /* send value_changed callback */
  927. (void)SendCallback(spin, event, TRUE, Position(spin),
  928. Current(spin), FALSE);
  929. }
  930. }
  931. /*
  932. * USL: Get Focus for SpinBox when hit its label part
  933. */
  934. static void
  935. _SpinBoxGetFocus( DtSpinBoxWidget spin,
  936. XEvent *event,
  937. char **params,
  938. Cardinal *num_params)
  939. {
  940. XmProcessTraversal((Widget)XtParent(spin),
  941. (XmTraversalDirection) XmTRAVERSE_CURRENT);
  942. }
  943. /*
  944. * USL: Process Focus Traversal for SpinBox when cursor is in its arrow part
  945. */
  946. static void
  947. _SpinBoxPrevTabGroup(DtSpinBoxWidget spin,
  948. XEvent *event,
  949. char **params,
  950. Cardinal *num_params)
  951. {
  952. XmProcessTraversal((Widget)XtParent(spin),
  953. (XmTraversalDirection) XmTRAVERSE_PREV_TAB_GROUP);
  954. }
  955. static void
  956. _SpinBoxNextTabGroup(DtSpinBoxWidget spin,
  957. XEvent *event,
  958. char **params,
  959. Cardinal *num_params)
  960. {
  961. XmProcessTraversal((Widget)XtParent(spin),
  962. (XmTraversalDirection) XmTRAVERSE_NEXT_TAB_GROUP);
  963. }
  964. /*
  965. * This function goes through most of the resources and makes sure
  966. * they have legal values.
  967. */
  968. static void
  969. CheckResources(DtSpinBoxWidget spin)
  970. {
  971. if (!XmRepTypeValidValue(_DtRID_SB_ARROW_SENSITIVITY_TYPE,
  972. ArrowSensitivity(spin), (Widget)spin)) {
  973. XtWarning(SB_ARROW_SENSITIVE);
  974. ArrowSensitivity(spin) = DtARROWS_SENSITIVE;
  975. }
  976. if ((Alignment(spin) != DtALIGNMENT_CENTER) &&
  977. (Alignment(spin) != DtALIGNMENT_BEGINNING) &&
  978. (Alignment(spin) != DtALIGNMENT_END)) {
  979. XtWarning(SB_ALIGNMENT);
  980. Alignment(spin) = DtALIGNMENT_CENTER;
  981. }
  982. if (InitialDelay(spin) == 0) {
  983. XtWarning(SB_INIT_DELAY);
  984. InitialDelay(spin) = 250;
  985. }
  986. if ((ArrowLayout(spin) != DtARROWS_FLAT_BEGINNING) &&
  987. (ArrowLayout(spin) != DtARROWS_FLAT_END) &&
  988. (ArrowLayout(spin) != DtARROWS_SPLIT) &&
  989. (ArrowLayout(spin) != DtARROWS_BEGINNING) &&
  990. (ArrowLayout(spin) != DtARROWS_END)) {
  991. XtWarning(SB_ARROW_LAYOUT);
  992. ArrowLayout(spin) = DtARROWS_BEGINNING;
  993. }
  994. if (RepeatDelay(spin) == 0) {
  995. XtWarning(SB_REPEAT_DELAY);
  996. RepeatDelay(spin) = 200;
  997. }
  998. if (ItemCount(spin) < 0) {
  999. XtWarning(SB_ITEM_COUNT);
  1000. ItemCount(spin) = 0;
  1001. }
  1002. if ((ChildType(spin) == DtSTRING) &&
  1003. ((Position(spin) < 0) ||
  1004. ((Position(spin) >= ItemCount(spin)) &&
  1005. (ItemCount(spin) > 0)))) {
  1006. XtWarning(SB_POSITION_STRING);
  1007. Position(spin) = 0;
  1008. }
  1009. if ((DecimalPoints(spin) < 0) ||
  1010. (DecimalPoints(spin) > MAX_FLOAT_DECIMALS)) {
  1011. XtWarning(SB_DECIMAL_POINTS);
  1012. DecimalPoints(spin) = 0;
  1013. }
  1014. if (Minimum(spin) > Maximum(spin)) {
  1015. XtWarning(SB_MIN_MAX);
  1016. Minimum(spin) = Maximum(spin);
  1017. }
  1018. if ((ChildType(spin) == DtNUMERIC) &&
  1019. ((Position(spin) < Minimum(spin)) ||
  1020. (Position(spin) > Maximum(spin)) ||
  1021. ((Position(spin) % NumericIncrement(spin)) != 0))) {
  1022. XtWarning(SB_POSITION_NUMERIC);
  1023. Position(spin) = Minimum(spin);
  1024. }
  1025. }
  1026. /*
  1027. * Destroy procedure called by the toolkit.
  1028. */
  1029. static void
  1030. Destroy(DtSpinBoxWidget spin)
  1031. {
  1032. int i;
  1033. if ((int)Timer(spin))
  1034. {
  1035. XtRemoveTimeOut(Timer(spin));
  1036. Timer(spin) = (XtIntervalId)NULL;
  1037. }
  1038. if (ItemCount(spin)>0) {
  1039. for (i = 0; i < ItemCount(spin); i++) {
  1040. XmStringFree((Items(spin))[i]);
  1041. }
  1042. XtFree((char*)(Items(spin)));
  1043. }
  1044. /*
  1045. * Don't remove callbacks and event handlers set on the children,
  1046. * this has already been done by Xt (children are cleaned up before
  1047. * the parent).
  1048. */
  1049. }
  1050. /*
  1051. * Resize function called by toolkit. The size of our spin-box
  1052. * has already been changed. That is why we must store
  1053. * old_width and old_height.
  1054. */
  1055. static void
  1056. Resize(DtSpinBoxWidget spin)
  1057. {
  1058. ClearShadow(spin, TRUE);
  1059. LayoutChildren(spin);
  1060. DrawShadow(spin);
  1061. OldWidth(spin) = spin->core.width;
  1062. OldHeight(spin) = spin->core.height;
  1063. }
  1064. /*
  1065. * Redisplay function called by toolkit. The widget didn't change size,
  1066. * so just redisplay the shadow.
  1067. */
  1068. static void
  1069. Redisplay( DtSpinBoxWidget w,
  1070. XEvent *event,
  1071. Region region)
  1072. {
  1073. DrawShadow(w);
  1074. }
  1075. /*
  1076. * GeometryManager function called by toolkit when a child resizes/moves.
  1077. * We are not allowing any changes but width/height of the text-field.
  1078. * this is because the user can retrieve the text-field and make changes
  1079. * that we want to honor. If they mess around with the label or arrow,
  1080. * then we won't honor the request.
  1081. * If the text-field requests a change, then make the change, and allow
  1082. * our SetSpinBoxSize() and LayoutChildren() figure out what size will
  1083. * be allowed.
  1084. * Returning GeometryDone was suppose to tell the toolkit
  1085. * that we resized the child ourselves, but the text-field had trouble
  1086. * with this (its' geometry_manager wasn't called or working right?), so
  1087. * we return GeometryYes.
  1088. */
  1089. static XtGeometryResult
  1090. GeometryManager(Widget w, /* child */
  1091. XtWidgetGeometry *request,
  1092. XtWidgetGeometry *reply)
  1093. {
  1094. /* MotifBc */
  1095. DtSpinBoxWidget spin = (DtSpinBoxWidget)XtParent(w);
  1096. /* Resolution Independent */
  1097. Arg args[4];
  1098. Dimension width, height, border_width;
  1099. int n;
  1100. unsigned char unit_type;
  1101. /* Ignore everything but text-field */
  1102. if (w != Text(spin) ) {
  1103. return(XtGeometryNo);
  1104. }
  1105. /* Only allow width/height changes */
  1106. if (!(request->request_mode & (CWWidth | CWHeight)))
  1107. return(XtGeometryNo);
  1108. /* Resolution Independent */
  1109. XtSetArg(args[0], XmNunitType, &unit_type);
  1110. XtGetValues(w, args, 1);
  1111. if ( unit_type != XmPIXELS) {
  1112. XtSetArg(args[0], XmNunitType, XmPIXELS);
  1113. XtSetValues(w, args, 1);
  1114. }
  1115. n = 0;
  1116. /* Set the text-field to the requested size */
  1117. if (request->request_mode & CWWidth) {
  1118. /* MotifBc */
  1119. XtSetArg(args[n], XmNwidth, &width); n++;
  1120. }
  1121. if (request->request_mode & CWHeight) {
  1122. /* MotifBc */
  1123. XtSetArg(args[n], XmNheight, &height); n++;
  1124. }
  1125. /* MotifBc */
  1126. XtSetArg(args[n], XmNborderWidth, &border_width); n++;
  1127. XtGetValues(w, args, n);
  1128. XtResizeWidget(w, width, height, border_width);
  1129. if ( unit_type != XmPIXELS) {
  1130. XtSetArg(args[0], XmNunitType, unit_type);
  1131. XtSetValues(w, args, 1);
  1132. }
  1133. ClearShadow(spin, TRUE);
  1134. if (RecomputeSize(spin))
  1135. SetSpinBoxSize(spin);
  1136. LayoutChildren(spin);
  1137. DrawShadow(spin);
  1138. return(XtGeometryDone);
  1139. }
  1140. /*
  1141. * This function sets the size of the spin_box widget based on the
  1142. * current size of the children. Don't worry if it doesn't work, the
  1143. * children will be squeezed in later.
  1144. */
  1145. static void
  1146. SetSpinBoxSize(DtSpinBoxWidget spin)
  1147. {
  1148. Widget text_holder = Editable(spin) ? Text(spin) : Label(spin);
  1149. Dimension shadow = SPIN_SHADOW(spin) * 2;
  1150. Dimension arrow_width, arrow_height;
  1151. /* MotifBc & Resolution Independent */
  1152. Dimension height, width;
  1153. Arg args[2];
  1154. unsigned char unit_type = MUnitType(spin);
  1155. /* Resolution Independent */
  1156. if (unit_type != XmPIXELS) {
  1157. XtSetArg(args[0], XmNunitType, XmPIXELS);
  1158. XtSetValues((Widget)spin, args, 1);
  1159. XtSetValues(text_holder, args, 1);
  1160. }
  1161. /* MotifBc */
  1162. XtSetArg(args[0], XmNheight, &height);
  1163. XtSetArg(args[1], XmNwidth, &width);
  1164. XtGetValues(text_holder, args, 2);
  1165. /*
  1166. * Find out how big the arrow can be (needed to get
  1167. * width for text_holder).
  1168. */
  1169. arrow_width = (Dimension)((float)height * ARROW_MULT);
  1170. arrow_width = (arrow_width < ARROW_MIN) ? ARROW_MIN : arrow_width;
  1171. /* Get height based on arrow width */
  1172. arrow_height = arrow_width;
  1173. if ((ArrowLayout(spin) == DtARROWS_BEGINNING) ||
  1174. (ArrowLayout(spin) == DtARROWS_END))
  1175. arrow_height += arrow_height;
  1176. /* Make height bigger of 2 - arrows vs text_holder */
  1177. if (arrow_height > (Dimension)height)
  1178. height = arrow_height;
  1179. /* If not stacked add extra width for arrows */
  1180. if ((ArrowLayout(spin) != DtARROWS_BEGINNING) &&
  1181. (ArrowLayout(spin) != DtARROWS_END)) {
  1182. arrow_width += arrow_width;
  1183. }
  1184. (void)XtMakeResizeRequest((Widget)spin, arrow_width +
  1185. width + shadow +
  1186. (SPIN_MARGIN_W(spin) * 2),
  1187. height + shadow + (SPIN_MARGIN_H(spin) * 2),
  1188. NULL, NULL);
  1189. OldWidth(spin) = Width(spin);
  1190. OldHeight(spin) = Height(spin);
  1191. /* Resolution Independent */
  1192. if (unit_type != XmPIXELS) {
  1193. XtSetArg(args[0], XmNunitType, unit_type);
  1194. XtSetValues((Widget)spin, args, 1);
  1195. XtSetValues(text_holder, args, 1);
  1196. }
  1197. }
  1198. /*
  1199. * This function makes the text_holder (label or text-field) smaller
  1200. * if the spin_box couldn't grow to the needed full size. It will
  1201. * also make the text_holder grow if there is space. The textfield will
  1202. * grow with the spin_box, but the label will only grow to its'
  1203. * maximum size. The label will also shrink down to nothing, but the
  1204. * text-field will always keep its' core height.
  1205. */
  1206. static void
  1207. ForceChildSizes(DtSpinBoxWidget spin)
  1208. {
  1209. Dimension available_height, available_width, arrow_width;
  1210. /* MotifBc & Resolution Independent */
  1211. Arg args[3];
  1212. unsigned char unit_type = XmPIXELS;
  1213. /* Resolution Independent */
  1214. if (MUnitType(spin) != XmPIXELS) {
  1215. unit_type = MUnitType(spin);
  1216. XtSetArg(args[0], XmNunitType, XmPIXELS);
  1217. XtSetValues(UpArrow(spin), args, 1);
  1218. XtSetValues(DownArrow(spin), args, 1);
  1219. if (Editable(spin) == False)
  1220. XtSetValues(Label(spin), args, 1);
  1221. else
  1222. XtSetValues(Text(spin), args, 1);
  1223. }
  1224. CalculateSizes(spin, &available_width, &available_height, &arrow_width);
  1225. if (Editable(spin) == FALSE) { /** label **/
  1226. if (available_width > LabelMaxLength(spin))
  1227. available_width = LabelMaxLength(spin);
  1228. if ((available_width != (Label(spin))->core.width) ||
  1229. (available_height != (Label(spin))->core.height))
  1230. XtResizeWidget(Label(spin), available_width, available_height,
  1231. (Label(spin))->core.border_width);
  1232. }
  1233. else if ((Text(spin))->core.width != available_width) /** TextField **/
  1234. XtResizeWidget(Text(spin), available_width,
  1235. (Text(spin))->core.height,
  1236. (Text(spin))->core.border_width);
  1237. if ((arrow_width != UpArrow(spin)->core.width) ||
  1238. ((UpArrow(spin))->core.height != arrow_width)) {
  1239. available_height = (available_height < ARROW_MIN) ? ARROW_MIN :
  1240. available_height;
  1241. XtResizeWidget(UpArrow(spin), arrow_width, arrow_width,
  1242. (UpArrow(spin))->core.border_width);
  1243. }
  1244. if ((arrow_width != (DownArrow(spin))->core.width) ||
  1245. ((DownArrow(spin))->core.height != arrow_width)) {
  1246. available_height = (available_height < ARROW_MIN) ? ARROW_MIN :
  1247. available_height;
  1248. XtResizeWidget(DownArrow(spin), arrow_width, arrow_width,
  1249. DownArrow(spin)->core.border_width);
  1250. }
  1251. /* Resolution Independent */
  1252. if (MUnitType(spin) != XmPIXELS) {
  1253. XtSetArg(args[0], XmNunitType, unit_type);
  1254. XtSetValues(UpArrow(spin), args, 1);
  1255. XtSetValues(DownArrow(spin), args, 1);
  1256. if (Editable(spin) == False)
  1257. XtSetValues(Label(spin), args, 1);
  1258. else
  1259. XtSetValues(Text(spin), args, 1);
  1260. }
  1261. }
  1262. static void
  1263. CalculateSizes (DtSpinBoxWidget spin,
  1264. Dimension *pwidth,
  1265. Dimension *pheight,
  1266. Dimension *parrow_width)
  1267. {
  1268. Dimension width, height, arrow_width;
  1269. /* Calculate available height for children */
  1270. if ((height = spin->core.height - (SPIN_SHADOW(spin) * 2) -
  1271. (SPIN_MARGIN_H(spin) * 2)) <= 0)
  1272. height = 1;
  1273. /* Get initial available width for children */
  1274. width = (spin->core.width - (SPIN_SHADOW(spin) * 2) -
  1275. (SPIN_MARGIN_W(spin) * 2));
  1276. /* label only grows to maximum width needed */
  1277. if ((Editable(spin) == FALSE) &&
  1278. (height > LabelMaxHeight(spin)))
  1279. height = LabelMaxHeight(spin);
  1280. else if (Editable(spin))
  1281. height = (Text(spin))->core.height;
  1282. /*
  1283. * Find out how big the arrow can be (needed to get
  1284. * width for text_holder).
  1285. */
  1286. arrow_width = (Dimension)(height * ARROW_MULT);
  1287. arrow_width = (arrow_width < ARROW_MIN) ? ARROW_MIN : arrow_width;
  1288. /* Make sure width isn't too small or too big */
  1289. if ((width -= arrow_width) <= 0)
  1290. width = 1;
  1291. /* If not stacked subtract extra arrow */
  1292. if ((ArrowLayout(spin) != DtARROWS_BEGINNING) &&
  1293. (ArrowLayout(spin) != DtARROWS_END)) {
  1294. width -= arrow_width;
  1295. }
  1296. if (pwidth) *pwidth = width;
  1297. if (pheight) *pheight = height;
  1298. if (parrow_width) *parrow_width = arrow_width;
  1299. }
  1300. /*
  1301. * This function positions the children within the spin_box widget.
  1302. * It calls ForceChildSizes() to make sure the children fit within the
  1303. * spin_box widget, but it will not try to resize the spin_box widget.
  1304. */
  1305. static void
  1306. LayoutChildren(DtSpinBoxWidget spin)
  1307. {
  1308. Widget text_holder = Editable(spin) ? Text(spin) : Label(spin);
  1309. Position start_x = SPIN_SHADOW(spin) + SPIN_MARGIN_W(spin);
  1310. Position start_y = SPIN_SHADOW(spin) + SPIN_MARGIN_H(spin);
  1311. Dimension available_height = spin->core.height - (start_y * 2);
  1312. Position y, arrow_y;
  1313. Dimension arrow_height;
  1314. /* Resolution Independent */
  1315. Arg args[4];
  1316. unsigned char unit_type = XmPIXELS;
  1317. ForceChildSizes(spin);
  1318. /* Resolution Independent */
  1319. if (MUnitType(spin) != XmPIXELS) {
  1320. unit_type = MUnitType(spin);
  1321. XtSetArg(args[0], XmNunitType, XmPIXELS);
  1322. XtSetValues(UpArrow(spin), args, 1);
  1323. XtSetValues(DownArrow(spin), args, 1);
  1324. XtSetValues(text_holder, args, 1);
  1325. }
  1326. /* Center text_holder within spin_box */
  1327. y = available_height - text_holder->core.height;
  1328. y = ((y < 0) ? 0 : y)/2 + start_y;
  1329. arrow_height = (UpArrow(spin))->core.height;
  1330. if ((ArrowLayout(spin) == DtARROWS_BEGINNING) ||
  1331. (ArrowLayout(spin) == DtARROWS_END))
  1332. arrow_height += arrow_height;
  1333. arrow_y = available_height - arrow_height;
  1334. arrow_y = ((arrow_y < 0) ? 0 : arrow_y)/2 + start_y;
  1335. switch (ArrowLayout(spin)) {
  1336. case DtARROWS_FLAT_BEGINNING:
  1337. XtMoveWidget(UpArrow(spin), start_x, arrow_y);
  1338. start_x += (UpArrow(spin))->core.width;
  1339. XtMoveWidget(DownArrow(spin), start_x, arrow_y);
  1340. start_x += (DownArrow(spin))->core.width;
  1341. XtMoveWidget(text_holder, start_x, y);
  1342. break;
  1343. case DtARROWS_FLAT_END:
  1344. XtMoveWidget(text_holder, start_x, y);
  1345. /*
  1346. * This start_x places arrow right after text_holder. With
  1347. * labels we want the arrow at the end of the spin_box, so
  1348. * the user can use recompute_size more effectively.
  1349. * start_x += text_holder->core.width;
  1350. */
  1351. start_x = (spin->core.width - start_x -
  1352. (UpArrow(spin))->core.width -
  1353. (DownArrow(spin))->core.width);
  1354. XtMoveWidget(UpArrow(spin), start_x, arrow_y);
  1355. start_x += (UpArrow(spin))->core.width;
  1356. XtMoveWidget(DownArrow(spin), start_x, arrow_y);
  1357. break;
  1358. case DtARROWS_SPLIT:
  1359. XtMoveWidget(DownArrow(spin), start_x, arrow_y);
  1360. start_x += (DownArrow(spin))->core.width;
  1361. XtMoveWidget(text_holder, start_x, y);
  1362. start_x += text_holder->core.width;
  1363. XtMoveWidget(UpArrow(spin), start_x, arrow_y);
  1364. break;
  1365. case DtARROWS_BEGINNING:
  1366. XtMoveWidget(UpArrow(spin), start_x, arrow_y);
  1367. arrow_y += (UpArrow(spin))->core.height;
  1368. XtMoveWidget(DownArrow(spin), start_x, arrow_y);
  1369. start_x += (DownArrow(spin))->core.width;
  1370. XtMoveWidget(text_holder, start_x, y);
  1371. break;
  1372. case DtARROWS_END:
  1373. XtMoveWidget(text_holder, start_x, y);
  1374. /*
  1375. * This start_x places arrow right after text_holder. With
  1376. * labels we want the arrow at the end of the spin_box, so
  1377. * the user can use recompute_size more effectively.
  1378. * start_x += text_holder->core.width;
  1379. */
  1380. start_x = spin->core.width - start_x - (UpArrow(spin))->core.width;
  1381. XtMoveWidget(UpArrow(spin), start_x, arrow_y);
  1382. arrow_y += (UpArrow(spin))->core.width;
  1383. XtMoveWidget(DownArrow(spin), start_x, arrow_y);
  1384. break;
  1385. }
  1386. /* Resolution Independent */
  1387. if (MUnitType(spin) != XmPIXELS) {
  1388. XtSetArg(args[0], XmNunitType, unit_type);
  1389. XtSetValues(UpArrow(spin), args, 1);
  1390. XtSetValues(DownArrow(spin), args, 1);
  1391. XtSetValues(text_holder, args, 1);
  1392. }
  1393. }
  1394. /*
  1395. * SetValues() routine for SpinBox widget. Most of the real work
  1396. * is done in SetItems() and SetNumeric(). If items is set we store
  1397. * our own XmStrings.
  1398. * This function was built with static spin_boxs in mind, meaning that
  1399. * is-numeric or editable resources won't be changed constantly. These
  1400. * resources can be changed, but this function doesn't handle them in
  1401. * a super-efficient manor. for example, changing child-type will cause
  1402. * the label to be resize even if it isn't managed.
  1403. */
  1404. static Boolean
  1405. SetValues( DtSpinBoxWidget current,
  1406. DtSpinBoxWidget request,
  1407. DtSpinBoxWidget new)
  1408. {
  1409. DtSpinBoxPart *new_p = (DtSpinBoxPart*)
  1410. &(XmField(new,ipot,DtSpinBox,label,Widget));
  1411. DtSpinBoxPart *cur_p = (DtSpinBoxPart*)
  1412. &(XmField(current,ipot,DtSpinBox,label,Widget));
  1413. Boolean store_info;
  1414. char *widget_name;
  1415. Boolean label_size_changed = FALSE;
  1416. Arg args[20];
  1417. int n;
  1418. /* Resolution Independent */
  1419. unsigned char unit_type = MUnitType(new);
  1420. CheckResources(new);
  1421. if (Text(new) != Text(current)) {
  1422. XtWarning(SB_TEXT);
  1423. Text(new) = Text(current);
  1424. }
  1425. /*
  1426. * Editable resource changed. If the widget (textField or Label)
  1427. * doesn't exist, then create it.
  1428. */
  1429. if (Editable(new) != Editable(current)) {
  1430. if (Editable(new)) {
  1431. XtUnmanageChild(Label(new));
  1432. if (Text(new) == NULL) {
  1433. widget_name = XtMalloc(strlen(XtName((Widget)new)) + 10);
  1434. sprintf(widget_name, "%s_TF", XtName((Widget)new));
  1435. n = 0;
  1436. XtSetArg(args[n], XmNcolumns, TextColumns(new)); n++;
  1437. XtSetArg(args[n], XmNmaxLength, TextMaxLength(new)); n++;
  1438. XtSetArg(args[n], XmNmarginWidth, 2); n++;
  1439. XtSetArg(args[n], XmNmarginHeight, 2); n++;
  1440. if (unit_type != XmPIXELS) {
  1441. XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
  1442. }
  1443. Text(new) = XtCreateManagedWidget(widget_name,
  1444. xmTextFieldWidgetClass,
  1445. (Widget)new, args, n);
  1446. XtAddCallback(Text(new), XmNlosingFocusCallback,
  1447. text_losing_focus_cb, (XtPointer)new);
  1448. XtAddCallback(Text(new), XmNactivateCallback,
  1449. text_activate_cb, (XtPointer)new);
  1450. XtAddCallback(Text(new), XmNfocusCallback,
  1451. text_focus_cb, (XtPointer)new);
  1452. XtFree(widget_name);
  1453. if (unit_type != XmPIXELS) {
  1454. XtSetArg(args[n], XmNunitType, unit_type); n++;
  1455. XtSetValues(Text(new), args, 1);
  1456. }
  1457. }
  1458. else
  1459. XtManageChild(Text(new));
  1460. }
  1461. else {
  1462. XtUnmanageChild(Text(new));
  1463. if (Label(new) == NULL) {
  1464. widget_name = XtMalloc(strlen(XtName((Widget)new)) + 10);
  1465. sprintf(widget_name, "%s_Label", XtName((Widget)new));
  1466. n = 0;
  1467. XtSetArg(args[n], XmNalignment, Alignment(new)); n++;
  1468. XtSetArg(args[n], XmNrecomputeSize, FALSE); n++;
  1469. XtSetArg(args[n], XmNlabelString, InitLabel); n++;
  1470. XtSetArg(args[n], XmNmarginLeft, LABEL_PADDING); n++;
  1471. XtSetArg(args[n], XmNmarginRight, LABEL_PADDING); n++;
  1472. XtSetArg(args[n], XmNmarginWidth, TEXT_CONTEXT_MARGIN); n++;
  1473. XtSetArg(args[n], XmNmarginHeight, 0); n++;
  1474. if (unit_type != XmPIXELS) {
  1475. XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
  1476. }
  1477. Label(new) = XtCreateManagedWidget(widget_name,
  1478. xmLabelWidgetClass,
  1479. (Widget)new, args, n);
  1480. XtOverrideTranslations((Widget)Label(new), child_trans);
  1481. XtFree(widget_name);
  1482. if (unit_type != XmPIXELS) {
  1483. XtSetArg(args[n], XmNunitType, unit_type); n++;
  1484. XtSetValues(Label(new), args, 1);
  1485. }
  1486. }
  1487. else
  1488. XtManageChild(Label(new));
  1489. }
  1490. /*
  1491. * Text-fields and labels have different shadows. Only
  1492. * change if user didn't change the shadow resource.
  1493. */
  1494. if (SPIN_SHADOW(new) == SPIN_SHADOW(current))
  1495. SPIN_SHADOW(new) = (Editable(new)) ? TEXT_FIELD_SHADOW :
  1496. LABEL_SHADOW;
  1497. }
  1498. /* Check arrow sensitivity (up arrow is right arrow)*/
  1499. if (ArrowSensitivity(new) != ArrowSensitivity(current)) {
  1500. XtSetSensitive(UpArrow(new),
  1501. ((ArrowSensitivity(new) == DtARROWS_SENSITIVE) ||
  1502. (ArrowSensitivity(new) == DtARROWS_INCREMENT_SENSITIVE)));
  1503. XtSetSensitive(DownArrow(new),
  1504. ((ArrowSensitivity(new) == DtARROWS_SENSITIVE) ||
  1505. (ArrowSensitivity(new) == DtARROWS_DECREMENT_SENSITIVE)));
  1506. }
  1507. /*
  1508. * Check arrow layout. Only need to change arrows if going to or
  1509. * from DtARROWS_SPLIT. The LayoutChildren() routine actually
  1510. * positions the arrows in the correct place.
  1511. */
  1512. if (ArrowLayout(new) != ArrowLayout(current)) {
  1513. if (ArrowLayout(new) == DtARROWS_SPLIT) {
  1514. XtSetArg(args[0], XmNarrowDirection, XmARROW_RIGHT);
  1515. XtSetValues(UpArrow(new), args, 1);
  1516. XtSetArg(args[0], XmNarrowDirection, XmARROW_LEFT);
  1517. XtSetValues(DownArrow(new), args, 1);
  1518. }
  1519. else {
  1520. XtSetArg(args[0], XmNarrowDirection, XmARROW_UP);
  1521. XtSetValues(UpArrow(new), args, 1);
  1522. XtSetArg(args[0], XmNarrowDirection, XmARROW_DOWN);
  1523. XtSetValues(DownArrow(new), args, 1);
  1524. }
  1525. }
  1526. if (Text(new) && (Text(new) == Text(current))) {
  1527. n = 0;
  1528. if (TextColumns(new) != TextColumns(current)) {
  1529. XtSetArg(args[n], XmNcolumns, TextColumns(new)); n++;
  1530. }
  1531. if (TextMaxLength(new) != TextMaxLength(current)) {
  1532. XtSetArg(args[n], XmNmaxLength, TextMaxLength(new)); n++;
  1533. }
  1534. if (n > 0)
  1535. XtSetValues(Text(new), args, n);
  1536. }
  1537. /*
  1538. * LabelWidget alignment has changed.
  1539. */
  1540. if (Label(new) && (Alignment(new) != Alignment(current))) {
  1541. XtSetArg(args[0], XmNalignment, Alignment(new));
  1542. XtSetValues(Label(new), args, 1);
  1543. }
  1544. store_info = ((Items(new) != Items(current)) ||
  1545. (ItemCount(new) != ItemCount(current)) ||
  1546. (DecimalPoints(new) != DecimalPoints(current)) ||
  1547. (Maximum(new) != Maximum(current)) ||
  1548. (Minimum(new) != Minimum(current)) ||
  1549. (NumericIncrement(new) != NumericIncrement(current)) ||
  1550. ((ChildType(new) == DtNUMERIC) &&
  1551. (Position(new) != Position(current))));
  1552. if (store_info)
  1553. StoreResourceInfo(new_p, cur_p, (Items(new) != Items(current)));
  1554. if (Label(new) && (store_info ||
  1555. (Label(new) != Label(current)) ||
  1556. (ChildType(new) != ChildType(current)))) {
  1557. SetMaximumLabelSize(new_p);
  1558. label_size_changed = TRUE;
  1559. }
  1560. if (store_info ||
  1561. (Alignment(new) != Alignment(current)) ||
  1562. (Editable(new) != Editable(current)) ||
  1563. (Position(new) != Position(current)) ||
  1564. (Label(new) != Label(current)) ||
  1565. (ChildType(new) != ChildType(current))) {
  1566. if (Editable(new))
  1567. SetTextFieldData(new);
  1568. else
  1569. SetLabelData(new);
  1570. }
  1571. /*
  1572. * Must recalculate the spin_box and re-layout the children.
  1573. * If this is not editable, then set the label to its' maximum
  1574. * size; it will get chopped if it is too big. This is needed
  1575. * because we shrink the label down, and SetSpinBoxSize() uses
  1576. * the label's core sizes to figure what size to become.
  1577. */
  1578. if ((Editable(new) != Editable(current)) ||
  1579. (SPIN_MARGIN_W(new) != SPIN_MARGIN_W(current)) ||
  1580. (SPIN_MARGIN_H(new) != SPIN_MARGIN_H(current)) ||
  1581. (SPIN_SHADOW(new) != SPIN_SHADOW(current)) ||
  1582. (ArrowLayout(new) != ArrowLayout(current)) ||
  1583. (!(Editable(new)) && label_size_changed)) {
  1584. ClearShadow(current, TRUE);
  1585. if (RecomputeSize(new))
  1586. SetSpinBoxSize(new);
  1587. LayoutChildren(new);
  1588. DrawShadow(new);
  1589. }
  1590. n=0;
  1591. if(CBgPixel(new) != CBgPixel(current))
  1592. {
  1593. XtSetArg(args[n],XmNbackground,CBgPixel(new));n++;
  1594. }
  1595. if(CBgPixmap(new) != CBgPixmap(current))
  1596. {
  1597. XtSetArg(args[n],XmNbackgroundPixmap,CBgPixmap(new));n++;
  1598. }
  1599. if(MFgPixel(new) != MFgPixel(current))
  1600. {
  1601. XtSetArg(args[n],XmNforeground,MFgPixel(new));n++;
  1602. }
  1603. if(Text(new))
  1604. XtSetValues (Text(new),args,n);
  1605. if(Label(new))
  1606. XtSetValues (Label(new),args,n);
  1607. if(UpArrow(new))
  1608. XtSetValues (UpArrow(new),args,n);
  1609. if(DownArrow(new))
  1610. XtSetValues (DownArrow(new),args,n);
  1611. return(FALSE);
  1612. }
  1613. /*
  1614. * This function clears the shadow around our widget. If all is TRUE,
  1615. * then clear all 4 sides; otherwise, only clear the right and bottom
  1616. * sides (during resize).
  1617. */
  1618. static void
  1619. ClearShadow( DtSpinBoxWidget w,
  1620. Boolean all)
  1621. {
  1622. Dimension shadow = SPIN_SHADOW(w);
  1623. Dimension margin_w = SPIN_MARGIN_W(w);
  1624. Dimension margin_h = SPIN_MARGIN_H(w);
  1625. if ((shadow > 0) && XtIsRealized((Widget)w)) {
  1626. if (all) {
  1627. XClearArea(XtDisplayOfObject((Widget)w),
  1628. XtWindowOfObject((Widget)w),
  1629. margin_w, margin_h,
  1630. OldWidth(w) - (margin_w * 2),
  1631. shadow, FALSE);
  1632. XClearArea(XtDisplayOfObject((Widget)w),
  1633. XtWindowOfObject((Widget)w),
  1634. margin_w, margin_h, shadow,
  1635. OldHeight(w) - (margin_h * 2), FALSE);
  1636. }
  1637. XClearArea(XtDisplayOfObject((Widget)w), XtWindowOfObject((Widget)w),
  1638. margin_w, OldHeight(w) - margin_h - shadow,
  1639. OldWidth(w) - (margin_w * 2), shadow, FALSE);
  1640. XClearArea(XtDisplayOfObject((Widget)w), XtWindowOfObject((Widget)w),
  1641. OldWidth(w) - margin_w - shadow,
  1642. margin_h, shadow,
  1643. OldHeight(w) - (margin_h * 2), FALSE);
  1644. }
  1645. DrawHighlight(w, TRUE);
  1646. }
  1647. /*
  1648. * This functions draws the shadow around our spin_box.
  1649. */
  1650. static void
  1651. DrawShadow(DtSpinBoxWidget w)
  1652. {
  1653. Dimension shadow = SPIN_SHADOW(w);
  1654. Dimension margin_w = SPIN_MARGIN_W(w);
  1655. Dimension margin_h = SPIN_MARGIN_H(w);
  1656. if ((shadow > 0) && XtIsRealized((Widget)w)) {
  1657. XmeDrawShadows(XtDisplayOfObject((Widget)w),
  1658. XtWindowOfObject((Widget)w),
  1659. w->manager.top_shadow_GC,
  1660. w->manager.bottom_shadow_GC,
  1661. margin_w, margin_h,
  1662. w->core.width - (margin_w * 2),
  1663. w->core.height - (margin_h * 2),
  1664. shadow, XmSHADOW_OUT);
  1665. }
  1666. DrawHighlight(w, FALSE);
  1667. }
  1668. /*
  1669. * This function sets up the items information for the SpinBox, as
  1670. * well as variables needed for child_type.
  1671. */
  1672. static void
  1673. StoreResourceInfo( DtSpinBoxPart *spin_p,
  1674. DtSpinBoxPart *old_p,
  1675. Boolean do_items)
  1676. {
  1677. XmStringTable table;
  1678. int i, base = 1;
  1679. if (do_items && spin_p->items) {
  1680. /* Free up current items if needed */
  1681. if (old_p && old_p->items) {
  1682. for (i = 0; i < old_p->item_count; i++) {
  1683. XmStringFree(old_p->items[i]);
  1684. }
  1685. XtFree((char*)old_p->items);
  1686. }
  1687. /*
  1688. * Loop through all the items, copy them into our space.
  1689. */
  1690. table = (XmStringTable)XtMalloc(sizeof(XmString) * spin_p->item_count);
  1691. for (i = 0; i < spin_p->item_count; i++) {
  1692. table[i] = XmStringCopy(spin_p->items[i]);
  1693. }
  1694. spin_p->items = table;
  1695. for (i = 0; i < spin_p->item_count; i++)
  1696. spin_p->items[i] = table[i];
  1697. }
  1698. /*
  1699. * Store the numeric information
  1700. */
  1701. /* get base number for convert ints to floats */
  1702. for (i = 0; i < spin_p->decimal_points; i++)
  1703. base *= 10;
  1704. /* Set new initial values */
  1705. spin_p->min = (float)spin_p->minimum/base;
  1706. spin_p->max = (float)spin_p->maximum/base;
  1707. spin_p->increment = (float)spin_p->numeric_increment/base;
  1708. spin_p->current = (float)spin_p->position/base;
  1709. /* Create format string used to build correct XmString value */
  1710. spin_p->float_format[0] = '%';
  1711. sprintf((char*)(spin_p->float_format+1), ".%df", spin_p->decimal_points);
  1712. }
  1713. /* Caller must free string */
  1714. static char*
  1715. GetTextString(XmString xm_string)
  1716. {
  1717. XmStringContext context;
  1718. XmStringComponentType type;
  1719. XmStringCharSet charset;
  1720. XmStringDirection direction;
  1721. XmStringComponentType unknown_tag;
  1722. unsigned short ul;
  1723. unsigned char *uv;
  1724. char *text = NULL;
  1725. Boolean done = FALSE;
  1726. XmStringInitContext(&context, xm_string);
  1727. /* Loop until 1st char* found */
  1728. while (!done) {
  1729. type = XmStringGetNextComponent(context, &text, &charset,
  1730. &direction, &unknown_tag,
  1731. &ul, &uv);
  1732. switch (type) {
  1733. case XmSTRING_COMPONENT_END:
  1734. done = TRUE;
  1735. break;
  1736. case XmSTRING_COMPONENT_TEXT:
  1737. case XmSTRING_COMPONENT_LOCALE_TEXT:
  1738. done = TRUE;
  1739. break;
  1740. default:
  1741. break;
  1742. }
  1743. }
  1744. XmStringFreeContext(context);
  1745. return(text);
  1746. }
  1747. /*
  1748. * Take the string out of the list and put it into the text-field.
  1749. * text-fields don't handle xm-strings, so we must get the char*
  1750. * out of it (only getting the first segment). This is slower than
  1751. * storing the text-strings (char*) ourselves, but that would take
  1752. * up a lot of memory. Since this setting happens during a user
  1753. * action, speed isn't a problem.
  1754. */
  1755. static void
  1756. SetTextFieldData(DtSpinBoxWidget spin)
  1757. {
  1758. char string[NUMERIC_LENGTH];
  1759. XmString xm_string;
  1760. char *text;
  1761. Arg arg;
  1762. if (ChildType(spin) == DtNUMERIC) {
  1763. sprintf(string, FloatFormat(spin), (float)(Current(spin)));
  1764. XtSetArg(arg, XmNvalue, string);
  1765. XtSetValues(Text(spin), &arg, 1);
  1766. }
  1767. else {
  1768. if (ItemCount(spin) == 0){
  1769. XtSetArg(arg, XmNvalue, "");
  1770. XtSetValues(Text(spin), &arg, 1);
  1771. return;
  1772. }
  1773. else {
  1774. xm_string = (Items(spin))[Position(spin)];
  1775. if ((text = GetTextString(xm_string))) {
  1776. XtSetArg(arg, XmNvalue, text);
  1777. XtSetValues(Text(spin), &arg, 1);
  1778. XtFree(text);
  1779. }
  1780. }
  1781. }
  1782. }
  1783. /*
  1784. * Set the maximum size of the label, depending on the
  1785. * characteristics of the list of items. Not very efficient
  1786. * if switching from numeric to non-numeric.
  1787. */
  1788. static void
  1789. SetMaximumLabelSize(DtSpinBoxPart *spin_p)
  1790. {
  1791. XmString xm_string;
  1792. XmFontList font_list;
  1793. char string[NUMERIC_LENGTH];
  1794. Dimension width, height;
  1795. Dimension longest = 0;
  1796. Dimension highest = 0;
  1797. Arg args[5];
  1798. int i;
  1799. /* Resolution Independent */
  1800. unsigned char unit_type;
  1801. /* Get font info from the widget */
  1802. XtSetArg(args[0], XmNfontList, &font_list);
  1803. XtSetArg(args[1], XmNunitType, &unit_type); /* resolution Independent */
  1804. XtGetValues(spin_p->label, args, 2);
  1805. if ( unit_type != XmPIXELS) {
  1806. XtSetArg(args[0], XmNunitType, XmPIXELS);
  1807. XtSetValues(spin_p->label, args, 1);
  1808. }
  1809. if (spin_p->child_type == DtNUMERIC) {
  1810. /* Find out maximum size of the widget from min/max */
  1811. sprintf(string, spin_p->float_format, spin_p->min);
  1812. xm_string = XmStringCreateLocalized(string);
  1813. XmStringExtent(font_list, xm_string, &longest, &highest);
  1814. XmStringFree(xm_string);
  1815. sprintf(string, spin_p->float_format, spin_p->max);
  1816. xm_string = XmStringCreateLocalized(string);
  1817. XmStringExtent(font_list, xm_string, &width, &height);
  1818. XmStringFree(xm_string);
  1819. longest = (width > longest) ? width : longest;
  1820. highest = (height > highest) ? height : highest;
  1821. }
  1822. else if (spin_p->items) {
  1823. /*
  1824. * Loop through all the items to find the biggest dimensions
  1825. */
  1826. for (i = 0; i < spin_p->item_count; i++) {
  1827. XmStringExtent(font_list, spin_p->items[i], &width, &height);
  1828. longest = (width > longest) ? width : longest;
  1829. highest = (height > highest) ? height : highest;
  1830. }
  1831. }
  1832. else {
  1833. XmStringExtent(font_list, InitLabel, &longest, &highest);
  1834. }
  1835. spin_p->label_max_length =
  1836. ( (Dimension)(longest + ( (LABEL_PADDING + TEXT_CONTEXT_MARGIN) *2) ) >
  1837. (Dimension)Width(spin_p->label) ) ?
  1838. (longest + ((LABEL_PADDING+TEXT_CONTEXT_MARGIN) * 2)) :
  1839. Width(spin_p->label);
  1840. spin_p->label_max_height = highest > Height(spin_p->label) ?
  1841. highest : Height(spin_p->label);
  1842. XtResizeWidget(spin_p->label, spin_p->label_max_length,
  1843. spin_p->label_max_height,
  1844. spin_p->label->core.border_width);
  1845. /* Resolution Independent */
  1846. if ( unit_type != XmPIXELS) {
  1847. XtSetArg(args[0], XmNunitType, unit_type);
  1848. XtSetValues(spin_p->label, args, 1);
  1849. }
  1850. }
  1851. /*
  1852. * Put the current list item into the label.
  1853. */
  1854. static void
  1855. SetLabelData(DtSpinBoxWidget spin)
  1856. {
  1857. XmString xm_string;
  1858. char string[NUMERIC_LENGTH];
  1859. int index = Position(spin);
  1860. Arg arg;
  1861. if (ChildType(spin) == DtNUMERIC) {
  1862. sprintf(string, FloatFormat(spin), (float)Current(spin));
  1863. xm_string = XmStringCreateLocalized(string);
  1864. XtSetArg(arg, XmNlabelString, xm_string);
  1865. XtSetValues(Label(spin), &arg, 1);
  1866. }
  1867. else {
  1868. /*
  1869. * If the item is not empty, get the current item from the list, else
  1870. * use InitLabel.
  1871. */
  1872. xm_string = (ItemCount(spin)>0) ? (Items(spin))[index] : InitLabel;
  1873. XtSetArg(arg, XmNlabelString, xm_string);
  1874. XtSetValues(Label(spin), &arg, 1);
  1875. }
  1876. }
  1877. /*
  1878. * Timout dispatch routine. This calls the appropriate callback function
  1879. * to simulate up or down arrow activation.
  1880. */
  1881. static void
  1882. timer_dispatch( XtPointer client_data,
  1883. XtIntervalId *id)
  1884. {
  1885. DtSpinBoxWidget spin_w = (DtSpinBoxWidget)client_data;
  1886. Timer(spin_w) = (XtIntervalId)NULL;
  1887. InitCb(spin_w) = FALSE;
  1888. if (WhichArrow(spin_w) == XmARROW_UP) {
  1889. if (Grabbed(spin_w)) {
  1890. XtRemoveGrab(UpArrow(spin_w));
  1891. Grabbed(spin_w) = FALSE;
  1892. }
  1893. up_cb(NULL, client_data, NULL);
  1894. }
  1895. else {
  1896. if (Grabbed(spin_w)) {
  1897. XtRemoveGrab(DownArrow(spin_w));
  1898. Grabbed(spin_w) = FALSE;
  1899. }
  1900. down_cb(NULL, client_data, NULL);
  1901. }
  1902. }
  1903. static void
  1904. TextFieldActivate(DtSpinBoxPart *spin_p)
  1905. {
  1906. XmTextFieldWidget w = (XmTextFieldWidget)(spin_p->text);
  1907. XmAnyCallbackStruct cb;
  1908. char string[NUMERIC_LENGTH];
  1909. char *data = NULL;
  1910. char *text = NULL;
  1911. Arg arg;
  1912. Boolean free_me = TRUE;
  1913. XtSetArg(arg, XmNvalue, &data);
  1914. XtGetValues((Widget)w, &arg, 1);
  1915. if (spin_p->child_type == DtNUMERIC) {
  1916. sprintf(string, spin_p->float_format, (float)spin_p->current);
  1917. text = string;
  1918. free_me = FALSE;
  1919. }
  1920. else if (spin_p->items)
  1921. text = GetTextString(spin_p->items[spin_p->position]);
  1922. if (text && data && (strcmp(text, data) == 0)) {
  1923. if (free_me)
  1924. XtFree(text);
  1925. return;
  1926. }
  1927. /* Only send callback if both are not NULL */
  1928. else if (!((text == NULL) && (data == NULL))) {
  1929. cb.reason = XmCR_ACTIVATE;
  1930. cb.event = NULL;
  1931. /* MotifBc */
  1932. if (XtHasCallbacks((Widget)w, XmNactivateCallback)==XtCallbackHasSome)
  1933. XtCallCallbacks((Widget)w, XmNactivateCallback,
  1934. (XtPointer) &cb);
  1935. if (text && free_me)
  1936. XtFree(text);
  1937. }
  1938. }
  1939. /*
  1940. * This function calls the appropriate callback for the spin_box.
  1941. * It gathers the correct arguments and fills in the callback structure.
  1942. */
  1943. static Boolean
  1944. SendCallback( DtSpinBoxWidget spin,
  1945. XEvent *event,
  1946. Boolean value_changed,
  1947. int position,
  1948. float current, /* Used for numeric */
  1949. Boolean crossed)
  1950. {
  1951. DtSpinBoxCallbackStruct cb;
  1952. XmString xm_string = NULL;
  1953. char string[NUMERIC_LENGTH];
  1954. if (ChildType(spin) == DtNUMERIC) {
  1955. sprintf(string, FloatFormat(spin), (float)current);
  1956. xm_string = XmStringCreateLocalized(string);
  1957. }
  1958. else {
  1959. xm_string = (ItemCount(spin)>0) ? (Items(spin))[position] : InitLabel;
  1960. xm_string = XmStringCopy(xm_string);
  1961. }
  1962. if (event)
  1963. cb.reason = DtCR_OK;
  1964. else if (WhichArrow(spin) == XmARROW_UP)
  1965. cb.reason = DtCR_SPIN_NEXT;
  1966. else
  1967. cb.reason = DtCR_SPIN_PRIOR;
  1968. cb.doit = TRUE;
  1969. cb.event = event;
  1970. cb.widget = (Widget)spin;
  1971. cb.position = position;
  1972. cb.value = xm_string;
  1973. cb.crossed_boundary = crossed;
  1974. if (value_changed) {
  1975. XtCallCallbackList((Widget)spin, ValueChangedCallback(spin),
  1976. (XtPointer)&cb);
  1977. cb.doit = TRUE;
  1978. }
  1979. else {
  1980. XtCallCallbackList((Widget)spin, ModifyVerifyCallback(spin),
  1981. (XtPointer)&cb);
  1982. }
  1983. XmStringFree(xm_string);
  1984. return(cb.doit);
  1985. }
  1986. /*
  1987. * This function gets called by the up/down arm callback functions.
  1988. * We set up the timer and send the modify-verify and value-changed
  1989. * callbacks.
  1990. * There are potential problems if the user does some weird stuff
  1991. * in the callbacks. I have added protection against the case where
  1992. * a user does a grab (with XtAddGrab/XtPopup/etc.) in the callbacks.
  1993. * Grabbing in the callback would cause us to lose the button-release
  1994. * (disarm), which would make the timer go on forever. A grab is
  1995. * done after the callbacks just to make sure we will receive the
  1996. * button-release. The button-release will call disarm_cb() which will
  1997. * un-grab and disable the timer. I have also added a leave callback
  1998. * which helps to protect against these kinds of problems.
  1999. * If the callback goes into another event-loop (which I hope would
  2000. * never happen), we would spin continuously (since our XtAddGrab never
  2001. * get called), until the user left the window (which would call
  2002. * grab_leave_cb). The grabbed flag gets set if we do the grab, so that
  2003. * we know if we can remove the grab. Our XtAddGrab() might not get called
  2004. * if the callback enters another event-loop.
  2005. *
  2006. * The event sent in the callback will be NULL during continuous spinning.
  2007. */
  2008. static void
  2009. FinishUpDown( DtSpinBoxWidget spin,
  2010. XtPointer arrow_call_data,
  2011. int new_position,
  2012. float new_current,
  2013. Boolean crossed)
  2014. {
  2015. XmArrowButtonCallbackStruct *arrow_data;
  2016. XEvent *last_event = NULL;
  2017. int repeat_delay = RepeatDelay(spin);
  2018. if (InitCb(spin))
  2019. repeat_delay = InitialDelay(spin);
  2020. Timer(spin) = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)spin),
  2021. repeat_delay, timer_dispatch, (XtPointer)spin);
  2022. /* Try to get Xevent */
  2023. if ((arrow_data = (XmArrowButtonCallbackStruct*)arrow_call_data))
  2024. last_event = arrow_data->event;
  2025. /*
  2026. * Send modify_verify callback. If user says no, then
  2027. * clear the timer and reset the state before returning.
  2028. */
  2029. if (SendCallback(spin, last_event, FALSE, new_position,
  2030. new_current, crossed) == FALSE) {
  2031. XtRemoveTimeOut(Timer(spin));
  2032. Timer(spin) = (XtIntervalId)NULL;
  2033. InitCb(spin) = TRUE;
  2034. return;
  2035. }
  2036. /* User said yes, so set widget values */
  2037. Position(spin) = new_position;
  2038. Current(spin) = new_current;
  2039. if (Editable(spin))
  2040. SetTextFieldData(spin);
  2041. else
  2042. SetLabelData(spin);
  2043. /* send value_changed callback */
  2044. (void)SendCallback(spin, last_event, TRUE, Position(spin),
  2045. Current(spin), crossed);
  2046. /* See notes at top of function on XtAddGrab usage */
  2047. Grabbed(spin) = TRUE;
  2048. if (WhichArrow(spin) == XmARROW_UP)
  2049. XtAddGrab(UpArrow(spin), FALSE, FALSE);
  2050. else
  2051. XtAddGrab(DownArrow(spin), FALSE, FALSE);
  2052. }
  2053. /*
  2054. * Show the next value in the SpinBox. If numeric, just add the
  2055. * increment value. If using string-table, get the next one in the
  2056. * table. This function takes care of wrap around. Set the arrow
  2057. * type. This is needed for the timer_dispatch function. up_cb
  2058. * gets called the first time the button is pressed, and each time the
  2059. * timer goes off.
  2060. * All widget internals are expected to be correct here; they
  2061. * get verified when set by the user.
  2062. */
  2063. static void
  2064. up_cb( Widget w,
  2065. XtPointer client_data,
  2066. XtPointer call_data)
  2067. {
  2068. DtSpinBoxWidget spin = (DtSpinBoxWidget)client_data;
  2069. DtSpinBoxPart *spin_p = (DtSpinBoxPart*)
  2070. &(XmField(spin,ipot,DtSpinBox,label,Widget));
  2071. Boolean crossed_boundary = FALSE;
  2072. int new_position = Position(spin);
  2073. float new_current = Current(spin);
  2074. /* Getting Focus */
  2075. if ( !_XmFocusIsHere( (Widget)spin) )
  2076. XmProcessTraversal((Widget)spin,
  2077. (XmTraversalDirection) XmTRAVERSE_CURRENT);
  2078. if (Editable(spin))
  2079. TextFieldActivate(spin_p);
  2080. /*
  2081. * If non-numeric and no items then ignore the user activate event.
  2082. */
  2083. if ((ChildType(spin) == DtSTRING) && (ItemCount(spin) == 0))
  2084. return;
  2085. if (ChildType(spin) == DtNUMERIC) {
  2086. if ((new_current + Increment(spin)) > Max(spin)) {
  2087. if (Wrap(spin)) {
  2088. new_position = Minimum(spin);
  2089. new_current = Min(spin);
  2090. crossed_boundary = TRUE;
  2091. }
  2092. else
  2093. XBell(XtDisplayOfObject((Widget)spin), 0);
  2094. }
  2095. else {
  2096. new_position += NumericIncrement(spin);
  2097. new_current += Increment(spin);
  2098. }
  2099. }
  2100. else if (ItemCount(spin) >0) {
  2101. if (new_position == (ItemCount(spin) - 1)) {
  2102. if (Wrap(spin)) {
  2103. new_position = 0;
  2104. crossed_boundary = TRUE;
  2105. }
  2106. else
  2107. XBell(XtDisplayOfObject((Widget)spin), 0);
  2108. }
  2109. else
  2110. new_position++;
  2111. }
  2112. WhichArrow(spin) = XmARROW_UP;
  2113. FinishUpDown(spin, call_data, new_position, new_current, crossed_boundary);
  2114. }
  2115. /*
  2116. * Show the previous value in the SpinBox. If numeric, just decrement
  2117. * the increment value. If using string-table, get the previous one in the
  2118. * table. This function takes care of wrap around. Set the arrow
  2119. * type. This is needed for the timer_dispatch function. down_cb
  2120. * gets called the first time the button is pressed, and each time the
  2121. * timer goes off.
  2122. * All widget internals are expected to be correct here; they
  2123. * get verified when set by the user.
  2124. */
  2125. static void
  2126. down_cb(Widget w,
  2127. XtPointer client_data,
  2128. XtPointer call_data)
  2129. {
  2130. DtSpinBoxWidget spin = (DtSpinBoxWidget)client_data;
  2131. DtSpinBoxPart *spin_p = (DtSpinBoxPart*)
  2132. &(XmField(spin,ipot,DtSpinBox,label,Widget));
  2133. Boolean crossed_boundary = FALSE;
  2134. int new_position = Position(spin);
  2135. float new_current = Current(spin);
  2136. /* #5: Getting Focus */
  2137. if ( !_XmFocusIsHere( (Widget)spin) )
  2138. XmProcessTraversal((Widget)spin,
  2139. (XmTraversalDirection) XmTRAVERSE_CURRENT);
  2140. if (Editable(spin))
  2141. TextFieldActivate(spin_p);
  2142. /*
  2143. * If non-numeric and no items then ignore the user activate event.
  2144. */
  2145. if ((ChildType(spin) == DtSTRING) && (ItemCount(spin) == 0))
  2146. return;
  2147. if (ChildType(spin) == DtNUMERIC) {
  2148. if ((new_current - Increment(spin)) < Min(spin)) {
  2149. if (Wrap(spin)) {
  2150. new_current = Max(spin);
  2151. new_position = Maximum(spin);
  2152. crossed_boundary = TRUE;
  2153. }
  2154. else
  2155. XBell(XtDisplayOfObject((Widget)spin), 0);
  2156. }
  2157. else {
  2158. new_current -= Increment(spin);
  2159. new_position -= NumericIncrement(spin);
  2160. }
  2161. }
  2162. else if (ItemCount(spin)>0) {
  2163. if (new_position == 0) {
  2164. if (Wrap(spin)) {
  2165. new_position = ItemCount(spin) - 1;
  2166. crossed_boundary = TRUE;
  2167. }
  2168. else
  2169. XBell(XtDisplayOfObject((Widget)spin), 0);
  2170. }
  2171. else
  2172. new_position--;
  2173. }
  2174. WhichArrow(spin) = XmARROW_DOWN;
  2175. FinishUpDown(spin, call_data, new_position, new_current, crossed_boundary);
  2176. }
  2177. static void
  2178. disarm_cb( Widget w,
  2179. XtPointer client_data,
  2180. XtPointer call_data)
  2181. {
  2182. DtSpinBoxWidget spin = (DtSpinBoxWidget)client_data;
  2183. if ((int)Timer(spin)) {
  2184. InitCb(spin) = TRUE;
  2185. XtRemoveTimeOut(Timer(spin));
  2186. Timer(spin) = (XtIntervalId)NULL;
  2187. if (Grabbed(spin)) {
  2188. XtRemoveGrab(w);
  2189. Grabbed(spin) = FALSE;
  2190. }
  2191. }
  2192. }
  2193. static void
  2194. grab_leave_cb( Widget w,
  2195. XtPointer client_data,
  2196. XEvent *event,
  2197. Boolean *dispatch)
  2198. {
  2199. DtSpinBoxWidget spin = (DtSpinBoxWidget)client_data;
  2200. if ((int)Timer(spin) &&
  2201. ((event->xcrossing.mode == NotifyGrab) ||
  2202. (event->xcrossing.mode == NotifyUngrab) ||
  2203. (!(event->xcrossing.state & Button1Mask)))) {
  2204. InitCb(spin) = TRUE;
  2205. XtRemoveTimeOut(Timer(spin));
  2206. Timer(spin) = (XtIntervalId)NULL;
  2207. if (Grabbed(spin)) {
  2208. XtRemoveGrab(w);
  2209. Grabbed(spin) = FALSE;
  2210. }
  2211. }
  2212. }
  2213. /*
  2214. * We get the text-field losing-focus callback, so pass it on to
  2215. * the user if they requested it. Our losing-focus callback
  2216. * is just a convenience callback, so that the user doesn't
  2217. * have to get the text-field first. This make our integration
  2218. * with XDesigner a little easier.
  2219. */
  2220. static void
  2221. text_losing_focus_cb( Widget w,
  2222. XtPointer client_data,
  2223. XtPointer call_data)
  2224. {
  2225. DtSpinBoxWidget spin = (DtSpinBoxWidget)client_data;
  2226. if (LosingFocusCallback(spin))
  2227. XtCallCallbackList((Widget)spin,
  2228. LosingFocusCallback(spin),
  2229. (XtPointer)call_data);
  2230. }
  2231. /*
  2232. * We get the text-field activate callback, so pass it on to
  2233. * the user if they requested it. Our activate callback
  2234. * is just a convenience callback, so that the user doesn't
  2235. * have to get the text-field first. This make our integration
  2236. * with XDesigner a little easier.
  2237. */
  2238. static void
  2239. text_activate_cb(Widget w,
  2240. XtPointer client_data,
  2241. XtPointer call_data)
  2242. {
  2243. DtSpinBoxWidget spin = (DtSpinBoxWidget)client_data;
  2244. if (ActivateCallback(spin))
  2245. XtCallCallbackList((Widget)spin,
  2246. ActivateCallback(spin),
  2247. (XtPointer)call_data);
  2248. }
  2249. /*
  2250. * We get the text-field focus callback, so pass it on to
  2251. * the user if they requested it. Our focus callback
  2252. * is just a convenience callback, so that the user doesn't
  2253. * have to get the text-field first. This make our integration
  2254. * with XDesigner a little easier.
  2255. */
  2256. static void
  2257. text_focus_cb( Widget w,
  2258. XtPointer client_data,
  2259. XtPointer call_data)
  2260. {
  2261. DtSpinBoxWidget spin = (DtSpinBoxWidget)client_data;
  2262. if (FocusCallback(spin))
  2263. XtCallCallbackList((Widget)spin,
  2264. FocusCallback(spin),
  2265. (XtPointer)call_data);
  2266. }
  2267. /*
  2268. * Synthetic resource get functions.
  2269. */
  2270. static XmImportOperator
  2271. _XmSetSyntheticResForChild( Widget widget,
  2272. int offset,
  2273. XtArgVal * value)
  2274. {
  2275. return(XmSYNTHETIC_LOAD);
  2276. }
  2277. void
  2278. _DtSpinBoxGetArrowSize( Widget w,
  2279. int resource_offset,
  2280. XtArgVal *value)
  2281. {
  2282. DtSpinBoxWidget spin = (DtSpinBoxWidget)w;
  2283. Dimension data;
  2284. Arg arg;
  2285. /* MotifBc */
  2286. XtSetArg(arg, XmNheight, &data);
  2287. XtGetValues(UpArrow(spin), &arg, 1);
  2288. *value = (XtArgVal)data;
  2289. }
  2290. /*
  2291. * Routines which manipulate the SpinBox list. These are external
  2292. * for use by users of our widget.
  2293. */
  2294. Widget
  2295. DtCreateSpinBox( Widget parent,
  2296. char *name,
  2297. Arg *arglist,
  2298. Cardinal num_args)
  2299. {
  2300. return(XtCreateWidget(name, dtSpinBoxWidgetClass, parent,
  2301. arglist, num_args));
  2302. }
  2303. void
  2304. DtSpinBoxAddItem( Widget spinw,
  2305. XmString item,
  2306. int pos)
  2307. {
  2308. DtSpinBoxWidget spin = (DtSpinBoxWidget)spinw;
  2309. DtSpinBoxPart *spin_p;
  2310. XmString old, new_str, tmp;
  2311. int total_items;
  2312. _DtWidgetToAppContext(spinw);
  2313. _DtAppLock(app);
  2314. spin_p = (DtSpinBoxPart*) &(XmField(spin,ipot,DtSpinBox,label,Widget));
  2315. total_items = ItemCount(spin) + 1;
  2316. Items(spin) = (XmString *)XtRealloc((char*)Items(spin),
  2317. (sizeof(XmString) * total_items));
  2318. new_str = XmStringCopy(item);
  2319. pos--; /* User gives pos starting at 1 (0 means end of list) */
  2320. if ((pos < 0) || (pos > ItemCount(spin)))
  2321. pos = ItemCount(spin);
  2322. if (pos >= ItemCount(spin))
  2323. (Items(spin))[pos] = new_str;
  2324. else {
  2325. old = (Items(spin))[pos];
  2326. (Items(spin))[pos] = new_str;
  2327. for (pos++; pos < total_items; pos++) {
  2328. tmp = (Items(spin))[pos];
  2329. (Items(spin))[pos] = old;
  2330. old = tmp;
  2331. }
  2332. }
  2333. ItemCount(spin) = total_items;
  2334. if (Label(spin)) {
  2335. SetMaximumLabelSize(spin_p);
  2336. if (Editable(spin) == FALSE) {
  2337. ClearShadow(spin, TRUE);
  2338. if (RecomputeSize(spin))
  2339. SetSpinBoxSize(spin);
  2340. LayoutChildren(spin);
  2341. DrawShadow(spin);
  2342. }
  2343. }
  2344. /* Update the text-field or label */
  2345. if (Editable(spin))
  2346. SetTextFieldData(spin);
  2347. else
  2348. SetLabelData(spin);
  2349. _DtAppUnlock(app);
  2350. }
  2351. void
  2352. DtSpinBoxDeletePos( Widget spinw,
  2353. int pos)
  2354. {
  2355. DtSpinBoxWidget spin = (DtSpinBoxWidget)spinw;
  2356. DtSpinBoxPart *spin_p;
  2357. int total_items;
  2358. _DtWidgetToAppContext(spinw);
  2359. _DtAppLock(app);
  2360. if (ItemCount(spin) < 1)
  2361. {
  2362. _DtAppUnlock(app);
  2363. return;
  2364. }
  2365. spin_p = (DtSpinBoxPart*) &(XmField(spin,ipot,DtSpinBox,label,Widget));
  2366. pos--;
  2367. if ((pos < 0) || (pos > ItemCount(spin)))
  2368. pos = ItemCount(spin) - 1;
  2369. total_items = ItemCount(spin) - 1;
  2370. XmStringFree((Items(spin))[pos]);
  2371. /* To keep Position of SpinBox up to date */
  2372. if (Position(spin) > 0 &&
  2373. ((Position(spin) >= total_items) || pos < Position(spin)) )
  2374. Position(spin) = Position(spin) - 1;
  2375. if (pos < ItemCount(spin)) {
  2376. for (; pos < total_items; pos++)
  2377. (Items(spin))[pos] = (Items(spin))[pos+1];
  2378. }
  2379. if (total_items > 0)
  2380. Items(spin) = (XmString *)XtRealloc((char*)Items(spin),
  2381. (sizeof(XmString) * total_items));
  2382. else {
  2383. XtFree((char *)Items(spin));
  2384. Items(spin) = (XmString *)NULL;
  2385. }
  2386. ItemCount(spin) = total_items;
  2387. if (Label(spin)) {
  2388. SetMaximumLabelSize(spin_p);
  2389. if (Editable(spin) == FALSE) {
  2390. ClearShadow(spin, TRUE);
  2391. if (RecomputeSize(spin))
  2392. SetSpinBoxSize(spin);
  2393. LayoutChildren(spin);
  2394. DrawShadow(spin);
  2395. }
  2396. }
  2397. /* Update the text-field or label */
  2398. if (Editable(spin))
  2399. SetTextFieldData(spin);
  2400. else
  2401. SetLabelData(spin);
  2402. _DtAppUnlock(app);
  2403. }
  2404. /*
  2405. * Make the given item the currently visible item in the
  2406. * text-field or label.
  2407. */
  2408. void
  2409. DtSpinBoxSetItem( Widget spinw,
  2410. XmString item)
  2411. {
  2412. DtSpinBoxWidget spin = (DtSpinBoxWidget)spinw;
  2413. int i;
  2414. _DtWidgetToAppContext(spinw);
  2415. _DtAppLock(app);
  2416. if (item && ItemCount(spin)>0) {
  2417. for (i = 0; i < ItemCount(spin); i++)
  2418. if (XmStringCompare(item, (Items(spin))[i]))
  2419. break;
  2420. if (i < ItemCount(spin)) {
  2421. Position(spin) = i;
  2422. if (Editable(spin))
  2423. SetTextFieldData(spin);
  2424. else
  2425. SetLabelData(spin);
  2426. }
  2427. else
  2428. XtWarning(SB_SET_ITEM);
  2429. }
  2430. else
  2431. XtWarning(SB_SET_ITEM);
  2432. _DtAppUnlock(app);
  2433. }