DataBaseLoad.c 104 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /*****************************************************************************
  24. *
  25. * File: DataBaseLoad.c
  26. *
  27. * Project: CDE
  28. *
  29. * Description: This file contains the functions which load and parse
  30. * the front panel databases.
  31. *
  32. * (c) Copyright 1993, 1994 Hewlett-Packard Company
  33. * (c) Copyright 1993, 1994 International Business Machines Corp.
  34. * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  35. * (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
  36. *
  37. *
  38. ****************************************************************************/
  39. #include <X11/Xlib.h>
  40. #include <X11/Xresource.h> /* XrmQuark */
  41. #include <Dt/DtP.h> /* required for DtDirPaths type */
  42. #include <Dt/DbReader.h> /* required for DtDbPathId type */
  43. #include <Dt/Connect.h> /* required for DtDbPathId type */
  44. #include <Dt/Dts.h>
  45. #include <Dt/Utility.h>
  46. #include <Dt/IconFile.h>
  47. #include <Dt/Icon.h>
  48. #include <Dt/UserMsg.h>
  49. #include "WmParse.h"
  50. #include "WmPanelP.h"
  51. #include "DataBaseLoad.h"
  52. #include "Parse.h"
  53. #include "UI.h"
  54. #include <pwd.h>
  55. #include <fcntl.h>
  56. #include <stdint.h>
  57. #include <sys/stat.h>
  58. /************************************************************************
  59. *
  60. * panel is the global top of the panel tree structure.
  61. *
  62. * switch is a local that is held until the hierary is built.
  63. *
  64. ************************************************************************/
  65. PanelData panel;
  66. static SwitchData * switch1;
  67. static ElementValue * control_element_values = NULL;
  68. static Boolean control_element_value_found = False;
  69. #define ANY_CONTAINER_TYPE 99
  70. static char * TYPES_DIR = "/.dt/types/fp_dynamic/";
  71. static char * TYPES_DIR_NO_SLASH = "/.dt/types/fp_dynamic";
  72. static char * HOME_DIR = NULL;
  73. static char * RM = "/bin/rm";
  74. typedef Boolean (*FieldParse)(char *, void **);
  75. typedef void (*FieldFree)(void **);
  76. typedef struct
  77. {
  78. FieldParse parse_function;
  79. void * default_value;
  80. FieldFree free_function;
  81. } ParseFunction;
  82. /************************************************************************
  83. *
  84. * Definitions and structure initializations for PANEL record type.
  85. *
  86. ************************************************************************/
  87. static char * panel_keywords[] =
  88. {
  89. "PANEL",
  90. "PANEL_GEOMETRY",
  91. "DISPLAY_HANDLES",
  92. "DISPLAY_MENU",
  93. "DISPLAY_MINIMIZE",
  94. "RESOLUTION",
  95. "CONTROL_BEHAVIOR",
  96. "DISPLAY_CONTROL_LABELS",
  97. "SUBPANEL_UNPOST",
  98. "LOCKED",
  99. "HELP_STRING",
  100. "HELP_VOLUME",
  101. "HELP_TOPIC",
  102. };
  103. static ParseFunction panel_parse_functions[] =
  104. {
  105. { StringToString, NULL, FreeString}, /* Name */
  106. { StringToString, NULL, FreeString}, /* Panel Geometry */
  107. { StringToBoolean, (void *) True, NULL}, /* Display Handles */
  108. { StringToBoolean, (void *) True, NULL}, /* Display Menu */
  109. { StringToBoolean, (void *) True, NULL}, /* Display Minimize */
  110. { StringToResolution, (void *) 3, NULL}, /* Resolution */
  111. { StringToControlBehavior, (void *) 0, NULL}, /* Control Behavior */
  112. { StringToBoolean, (void *) False, NULL}, /* Display Control Labels */
  113. { StringToBoolean, (void *) True, NULL}, /* Subpanel Unpost */
  114. { StringToBoolean, (void *) False, NULL}, /* Locked */
  115. { StringToString, NULL, FreeString}, /* Help String */
  116. { StringToString, NULL, FreeString}, /* Help Volume */
  117. { StringToString, NULL, FreeString}, /* Help Topic */
  118. };
  119. /************************************************************************
  120. *
  121. * Definitions and structure initializations for BOX record type.
  122. *
  123. ************************************************************************/
  124. static char * box_keywords[] =
  125. {
  126. "BOX",
  127. "CONTAINER_NAME",
  128. "POSITION_HINTS",
  129. "LOCKED",
  130. "DELETE",
  131. "HELP_STRING",
  132. "HELP_VOLUME",
  133. "HELP_TOPIC",
  134. };
  135. static ParseFunction box_parse_functions[] =
  136. {
  137. {StringToString, NULL, FreeString}, /* Name */
  138. {StringToString, NULL, FreeString}, /* Container Name */
  139. {StringToPositionHints, (void *) 0, NULL}, /* Position Hints */
  140. {StringToBoolean, (void *) False, NULL}, /* Locked */
  141. {StringToBoolean, (void *) False, NULL}, /* Delete */
  142. {StringToString, NULL, FreeString}, /* Help String */
  143. {StringToString, NULL, FreeString}, /* Help Volume */
  144. {StringToString, NULL, FreeString}, /* Help Topic */
  145. };
  146. /************************************************************************
  147. *
  148. * Definitions and structure initializations for SUBPANEL record type.
  149. *
  150. ************************************************************************/
  151. static char * subpanel_keywords[] =
  152. {
  153. "SUBPANEL",
  154. "CONTAINER_NAME",
  155. "CONTROL_INSTALL",
  156. "TITLE",
  157. "LOCKED",
  158. "DELETE",
  159. "HELP_STRING",
  160. "HELP_VOLUME",
  161. "HELP_TOPIC",
  162. };
  163. static ParseFunction subpanel_parse_functions[] =
  164. {
  165. { StringToString, NULL, FreeString}, /* Name */
  166. { StringToString, NULL, FreeString}, /* Container Name */
  167. { StringToBoolean, (void *) True, NULL}, /* Control Install */
  168. { StringToString, NULL, FreeString}, /* Title */
  169. { StringToBoolean, (void *) False, NULL}, /* Locked */
  170. { StringToBoolean, (void *) False, NULL}, /* Delete */
  171. { StringToString, NULL, FreeString}, /* Help String */
  172. { StringToString, NULL, FreeString}, /* Help Volume */
  173. { StringToString, NULL, FreeString}, /* Help Topic */
  174. };
  175. /************************************************************************
  176. *
  177. * Definitions and structure initializations for SWITCH record type.
  178. *
  179. ************************************************************************/
  180. static char * switch_keywords[] =
  181. {
  182. "SWITCH",
  183. "CONTAINER_NAME",
  184. "POSITION_HINTS",
  185. "NUMBER_OF_ROWS",
  186. "LOCKED",
  187. "DELETE",
  188. "HELP_STRING",
  189. "HELP_VOLUME",
  190. "HELP_TOPIC",
  191. };
  192. static ParseFunction switch_parse_functions[] =
  193. {
  194. { StringToString, NULL, FreeString}, /* Name */
  195. { StringToString, NULL, FreeString}, /* Container Name */
  196. { StringToPositionHints, (void *) 0, NULL}, /* Position Hints */
  197. { StringToInt, (void *) 2, NULL}, /* Number of Rows */
  198. { StringToBoolean, (void *) False, NULL}, /* Locked */
  199. { StringToBoolean, (void *) False, NULL}, /* Delete */
  200. { StringToString, NULL, FreeString}, /* Help String */
  201. { StringToString, NULL, FreeString}, /* Help Volume */
  202. { StringToString, NULL, FreeString}, /* Help Topic */
  203. };
  204. /************************************************************************
  205. *
  206. * Definitions and structure initializations for CONTROL record type.
  207. *
  208. ************************************************************************/
  209. static char * control_keywords[] =
  210. {
  211. "CONTROL",
  212. "TYPE",
  213. "CONTAINER_TYPE",
  214. "CONTAINER_NAME",
  215. "POSITION_HINTS",
  216. "ICON",
  217. "ALTERNATE_ICON",
  218. "LABEL",
  219. "PUSH_ACTION",
  220. "PUSH_ANIMATION",
  221. "DROP_ACTION",
  222. "DROP_ANIMATION",
  223. "PUSH_RECALL",
  224. "MONITOR_TYPE",
  225. "CLIENT_NAME",
  226. "CLIENT_GEOMETRY",
  227. "FILE_NAME",
  228. "DATE_FORMAT",
  229. "LOCKED",
  230. "DELETE",
  231. "HELP_STRING",
  232. "HELP_VOLUME",
  233. "HELP_TOPIC",
  234. };
  235. static ParseFunction control_parse_functions[] =
  236. {
  237. {StringToString, NULL, FreeString}, /* Name */
  238. {StringToControlType, (void *)CONTROL_ICON, NULL}, /* Type */
  239. {StringToControlContainerType, NULL, NULL}, /* Container Type */
  240. {StringToString, NULL, FreeString}, /* Container Name */
  241. {StringToPositionHints,(void *) 0, NULL}, /* Position Hints */
  242. {StringToString, NULL, FreeString}, /* Image */
  243. {StringToString, NULL, FreeString}, /* Altername Image */
  244. {StringToString, NULL, FreeString}, /* Label */
  245. {StringToAction, NULL, FreeAction}, /* Push Action */
  246. {StringToString, NULL, FreeString}, /* Push Animation */
  247. {StringToAction, NULL, FreeAction}, /* Drop Action */
  248. {StringToString, NULL, FreeString}, /* Drop Animation */
  249. {StringToBoolean, (void *) False, NULL}, /* Push Recall */
  250. {StringToMonitorType, (void *) MONITOR_NONE,NULL}, /* Monitor Type */
  251. {StringToString, NULL, FreeString}, /* Client Name */
  252. {StringToGeometry, NULL, FreeGeometry}, /* Client Geometry */
  253. {StringToFileName, NULL, FreeString}, /* File Name */
  254. {StringToString, NULL, FreeString}, /* Date Format */
  255. {StringToBoolean, (void *) False, NULL}, /* Locked */
  256. {StringToBoolean, (void *) False, NULL}, /* Delete */
  257. {StringToString, NULL, FreeString}, /* Help String */
  258. {StringToString, NULL, FreeString}, /* Help Volume */
  259. {StringToString, NULL, FreeString}, /* Help Topic */
  260. };
  261. /************************************************************************
  262. *
  263. * Structure definition and initialization for the front panel
  264. * keyword lists.
  265. *
  266. ************************************************************************/
  267. char * entry_types[] =
  268. {
  269. "PANEL",
  270. "BOX",
  271. "SUBPANEL",
  272. "SWITCH",
  273. "CONTROL"
  274. };
  275. char * control_types[] =
  276. {
  277. "blank",
  278. "busy",
  279. "icon",
  280. "client",
  281. "clock",
  282. "date",
  283. "file",
  284. };
  285. char * resolution_types[] =
  286. {
  287. "high",
  288. "medium",
  289. "low",
  290. "match_display"
  291. };
  292. char * monitor_types[] =
  293. {
  294. "none",
  295. "mail",
  296. "file",
  297. };
  298. #define ANIMATION "ANIMATION"
  299. typedef struct
  300. {
  301. char * record_keyword;
  302. int keyword_count;
  303. char ** field_keywords;
  304. ParseFunction * parse_functions;
  305. } RecordKeywords;
  306. static RecordKeywords record_keywords[] =
  307. {
  308. { "PANEL", PANEL_KEYWORD_COUNT,
  309. panel_keywords, panel_parse_functions },
  310. { "BOX", BOX_KEYWORD_COUNT,
  311. box_keywords, box_parse_functions },
  312. { "SUBPANEL", SUBPANEL_KEYWORD_COUNT,
  313. subpanel_keywords, subpanel_parse_functions },
  314. { "SWITCH", SWITCH_KEYWORD_COUNT,
  315. switch_keywords, switch_parse_functions },
  316. { "CONTROL", CONTROL_KEYWORD_COUNT,
  317. control_keywords, control_parse_functions },
  318. };
  319. /************************************************************************
  320. *
  321. * Static and external function definitions
  322. *
  323. ************************************************************************/
  324. extern void WmFrontPanelSetBusy (Boolean);
  325. extern char * _DtDbGetDataBaseEnv (void);
  326. static Boolean PanelParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
  327. static Boolean BoxParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
  328. static Boolean SubpanelParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
  329. static Boolean SwitchParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
  330. static Boolean ControlParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
  331. static Boolean AnimationParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
  332. static Boolean ControlSingleParseCB(DtDtsDbField *, DtDbPathId, char *, Boolean);
  333. static void ProcessRecord (DtDtsDbField *, ElementValue *);
  334. static void AllocateRecordData (RecordData **, int, int *, int *);
  335. static void ReorderByContainerType(RecordData *, int , int);
  336. static void ReorderByContainerName(RecordData *, int , int, int);
  337. static void ReorderByName(RecordData *, int , int, int);
  338. static void ReorderByPosition(RecordData *, int , int, int, int);
  339. static void OrderRecord (RecordData *, int, int);
  340. static char ** GetNameList (RecordData *, int, int, int, int);
  341. static void EliminateUnused (RecordData *, int *, char **, int, int, int, int);
  342. static void EliminateDeleted (RecordData *, int *, int, int, int, int, int);
  343. static void ResolveDuplicates (RecordData *, int *, int, int, int, int, int);
  344. static void InitializeField (ElementValue *, int, ParseFunction *);
  345. static void ProcessBox (BoxData *);
  346. static int ProcessBoxControl (ControlData *);
  347. static void ProcessSubpanel (SubpanelData *);
  348. static void ProcessSwitch (SwitchData *);
  349. static void ProcessControl (XtPointer, char, ControlData ***, int *, ElementValue *);
  350. static void InitializePrimaryControlFields (ElementValue *);
  351. static void InitializeSecondaryControlFields (ElementValue *);
  352. static void InitializeFileControlFields (ElementValue *, char *);
  353. /************************************************************************
  354. *
  355. * Variable and record declarations and initializations to keep track
  356. * of the data base info as it is read and to be used as storage for
  357. * subsequent parsing and reprocessing.
  358. *
  359. ************************************************************************/
  360. static int panel_count = 0;
  361. static int panel_data_count = 0;
  362. static RecordData * panel_data = NULL;
  363. static int box_count = 0;
  364. static int box_data_count = 0;
  365. static RecordData * box_data = NULL;
  366. static int subpanel_count = 0;
  367. static int subpanel_data_count = 0;
  368. static RecordData * subpanel_data = NULL;
  369. static int switch_count = 0;
  370. static int switch_data_count = 0;
  371. static RecordData * switch_data = NULL;
  372. static int control_count = 0;
  373. static int control_data_count = 0;
  374. static RecordData * control_data = NULL;
  375. static DtDbConverter panel_converter[] = { (DtDbConverter) PanelParseCB,
  376. NULL };
  377. static DtDbConverter box_converter[] = { (DtDbConverter) BoxParseCB,
  378. NULL };
  379. static DtDbConverter subpanel_converter[] = { (DtDbConverter) SubpanelParseCB,
  380. NULL };
  381. static DtDbConverter switch_converter[] = { (DtDbConverter) SwitchParseCB,
  382. NULL };
  383. static DtDbConverter control_converter[] = { (DtDbConverter) ControlParseCB,
  384. NULL };
  385. static DtDbConverter animation_converter[] ={ (DtDbConverter) AnimationParseCB,
  386. NULL };
  387. static DtDbRecordDesc record_descriptor[] =
  388. {
  389. { "PANEL", PANEL_KEYWORD_COUNT, panel_converter },
  390. { "BOX", BOX_KEYWORD_COUNT, box_converter },
  391. { "SUBPANEL", SUBPANEL_KEYWORD_COUNT, subpanel_converter },
  392. { "SWITCH", SWITCH_KEYWORD_COUNT, switch_converter },
  393. { "CONTROL", CONTROL_KEYWORD_COUNT, control_converter },
  394. { "ANIMATION", DTUNLIMITEDFIELDS, animation_converter }
  395. };
  396. static DtDbConverter control_single_converter[] =
  397. { (DtDbConverter) ControlSingleParseCB, NULL};
  398. static DtDbRecordDesc control_record_descriptor[] =
  399. {
  400. { "CONTROL", CONTROL_KEYWORD_COUNT, control_single_converter },
  401. { "ANIMATION", DTUNLIMITEDFIELDS, animation_converter }
  402. };
  403. /************************************************************************
  404. *
  405. * FrontPanelReadDatabases
  406. * Read in the front panel database, parse out each line, build
  407. * the internal data structures that are then used to create the
  408. * visual representation.
  409. *
  410. * Processing occurs in a series of steps:
  411. *
  412. * 1. Read in all of the database records and copy the unparsed
  413. * string information into a structure.
  414. * a. Group the records according to type.
  415. * b. Group the records according to container.
  416. * c. Ensure the original read order is maintained to process
  417. * overrides.
  418. *
  419. * This step occurs out of the callback for each of the component
  420. * types.
  421. *
  422. * 2. Eliminate the unused component definitions by working top-down
  423. * throught the lists. Select the PANEL and SWITCH definition
  424. * to be used at this time.
  425. *
  426. * 3. Eliminate overridden components by either selecting the first
  427. * locked definition or if none are locked, selecting the last
  428. * definition.
  429. *
  430. * 4. Reorder the component groups according to the position hints
  431. *
  432. * 5. Build hierarchical data structure from record sets, top-down.
  433. * Fully parse each record as the structure is built.
  434. *
  435. *
  436. * 6. Return.
  437. *
  438. ************************************************************************/
  439. Boolean
  440. FrontPanelReadDatabases (void)
  441. {
  442. char * search_paths;
  443. char * new_search_paths;
  444. struct passwd * pw_info;
  445. char * dynamic_dir;
  446. struct stat stat_info;
  447. int fd;
  448. int i;
  449. char * fp_database;
  450. int num_entries;
  451. char ** name_list;
  452. DtDirPaths * dir_paths;
  453. panel.animation_data = NULL;
  454. panel.animation_count = 0;
  455. /* Before reading the databases, add the front panel dynamic */
  456. /* directory to the search path. */
  457. search_paths = _DtDbGetDataBaseEnv();
  458. if ((HOME_DIR = (char *) getenv ("HOME")) == NULL)
  459. {
  460. pw_info = getpwuid (getuid());
  461. HOME_DIR = pw_info->pw_dir;
  462. }
  463. HOME_DIR = XtNewString (HOME_DIR);
  464. new_search_paths =
  465. XtMalloc (strlen ("DTDATABASESEARCHPATH") + strlen (HOME_DIR) +
  466. strlen (TYPES_DIR_NO_SLASH) + strlen (search_paths) + 3);
  467. sprintf (new_search_paths, "%s=%s%s,%s",
  468. "DTDATABASESEARCHPATH", HOME_DIR, TYPES_DIR_NO_SLASH, search_paths);
  469. putenv (new_search_paths);
  470. XtFree (search_paths);
  471. /* See if the fp_dynamic directory exists. If not, create it */
  472. dynamic_dir = XtMalloc (strlen (HOME_DIR) + strlen (TYPES_DIR) + 3);
  473. sprintf (dynamic_dir, "%s%s", HOME_DIR, TYPES_DIR);
  474. if (lstat (dynamic_dir, &stat_info) != 0)
  475. if ((fd=mkdir (dynamic_dir, S_IRWXU | S_IRGRP | S_IROTH |
  476. S_IXGRP | S_IXOTH)) != 0)
  477. {
  478. }
  479. XtFree ((char *) dynamic_dir);
  480. /* Read the database and do the initial set of processing on */
  481. /* the file based information. This work occurs within the */
  482. /* callback function referenced in the data read call. */
  483. dir_paths = _DtGetDatabaseDirPaths();
  484. #ifdef DT_PERFORMANCE
  485. _DtPerfChkpntMsgSend("Begin Front panel database read");
  486. #endif
  487. _DtDbRead (dir_paths, FILE_TYPE_SUFFIX, record_descriptor, 6);
  488. #ifdef DT_PERFORMANCE
  489. _DtPerfChkpntMsgSend("End Front panel database read");
  490. #endif
  491. if (panel_count == 0)
  492. {
  493. _DtFreeDatabaseDirPaths (dir_paths);
  494. return False;
  495. }
  496. /* Once all of the PANEL records have been read in, select the panel */
  497. /* record that is to be used to build the front panel. */
  498. /* */
  499. /* This selection is done by first scanning the list to find a LOCKED */
  500. /* panel. The first one found is selected. If none are found, the */
  501. /* last panel read is selectd. */
  502. for (i = panel_count - 1; i > 0; i--)
  503. {
  504. if ((intptr_t)(panel_data[i].element_values[PANEL_LOCKED].parsed_value))
  505. break;
  506. }
  507. panel.element_values = panel_data[i].element_values;
  508. /* Parse out additional panel element values */
  509. InitializeField (panel.element_values, PANEL_GEOMETRY, panel_parse_functions);
  510. InitializeField (panel.element_values, PANEL_DISPLAY_HANDLES, panel_parse_functions);
  511. InitializeField (panel.element_values, PANEL_DISPLAY_MENU, panel_parse_functions);
  512. InitializeField (panel.element_values, PANEL_DISPLAY_MINIMIZE, panel_parse_functions);
  513. InitializeField (panel.element_values, PANEL_RESOLUTION, panel_parse_functions);
  514. InitializeField (panel.element_values, PANEL_CONTROL_BEHAVIOR, panel_parse_functions);
  515. InitializeField (panel.element_values, PANEL_DISPLAY_CONTROL_LABELS, panel_parse_functions);
  516. InitializeField (panel.element_values, PANEL_SUBPANEL_UNPOST, panel_parse_functions);
  517. InitializeField (panel.element_values, PANEL_HELP_STRING, panel_parse_functions);
  518. InitializeField (panel.element_values, PANEL_HELP_TOPIC, panel_parse_functions);
  519. InitializeField (panel.element_values, PANEL_HELP_VOLUME, panel_parse_functions);
  520. XtFree ((char *) panel_data);
  521. /* Eliminate the records within the other component types that */
  522. /* are not part of this selected panel. */
  523. /* */
  524. /* This elimination occurs top down because boxes have to be */
  525. /* removed before controls can be removed... */
  526. name_list = (char **) XtMalloc (sizeof (char **) * 2);
  527. name_list[0] = panel.element_values[PANEL_NAME].parsed_value;
  528. name_list[1] = NULL;
  529. EliminateUnused (box_data, &box_count, name_list, BOX_CONTAINER_NAME,
  530. ANY_CONTAINER_TYPE, PANEL, BOX);
  531. XtFree ((char *) name_list);
  532. /* Remove entries that have the deleted keyword set to True unless */
  533. /* it is a locked file. */
  534. EliminateDeleted (box_data, &box_count, BOX_CONTAINER_NAME,
  535. BOX_NAME, BOX, BOX_DELETE, BOX_LOCKED);
  536. EliminateDeleted (switch_data, &switch_count, SWITCH_CONTAINER_NAME,
  537. SWITCH_NAME, SWITCH, SWITCH_DELETE, SWITCH_LOCKED);
  538. EliminateDeleted (subpanel_data, &subpanel_count, SUBPANEL_CONTAINER_NAME,
  539. SUBPANEL_NAME, SUBPANEL, SUBPANEL_DELETE, SUBPANEL_LOCKED);
  540. EliminateDeleted (control_data, &control_count, CONTROL_CONTAINER_NAME,
  541. CONTROL_NAME, CONTROL, CONTROL_DELETE, CONTROL_LOCKED);
  542. name_list = GetNameList (box_data, box_count,
  543. BOX_NAME, ANY_CONTAINER_TYPE, 0);
  544. EliminateUnused(switch_data, &switch_count, name_list,
  545. SWITCH_CONTAINER_NAME, ANY_CONTAINER_TYPE,
  546. BOX, SWITCH);
  547. EliminateUnused(control_data, &control_count, name_list,
  548. CONTROL_CONTAINER_NAME, CONTROL_CONTAINER_TYPE,
  549. BOX, CONTROL);
  550. XtFree ((char *) name_list);
  551. /* Once the elimination of superfluous switch definitions is complete, */
  552. /* make the selection of the single Switch. This makes the elimination */
  553. /* of the switch based controls efficient. */
  554. /* */
  555. /* This selection is done by first scanning the list to find a LOCKED */
  556. /* switch. The first one found is selected. If none are found, the */
  557. /* last switch read is selected. */
  558. if (switch_count != 0) {
  559. for (i = switch_count - 1; i > 0; i--)
  560. {
  561. if ((intptr_t)(switch_data[i].element_values[SWITCH_LOCKED].parsed_value))
  562. break;
  563. }
  564. switch1 = (SwitchData *) XtMalloc (sizeof (SwitchData));
  565. switch1->element_values = switch_data[i].element_values;
  566. switch1->control_data = NULL;
  567. switch1->control_data_count = 0;
  568. switch1->rc = NULL;
  569. switch1->buttons = NULL;
  570. switch1->atom_names = NULL;
  571. switch1->switch_names = NULL;
  572. switch1->switch_count = 0;
  573. switch1->active_switch = 0;
  574. switch1->popup_data = NULL;
  575. /* Parse the remaining database values for the switch */
  576. InitializeField (switch1->element_values, SWITCH_POSITION_HINTS, switch_parse_functions);
  577. InitializeField (switch1->element_values, SWITCH_NUMBER_OF_ROWS, switch_parse_functions);
  578. InitializeField (switch1->element_values, SWITCH_HELP_STRING, switch_parse_functions);
  579. InitializeField (switch1->element_values, SWITCH_HELP_TOPIC, switch_parse_functions);
  580. InitializeField (switch1->element_values, SWITCH_HELP_STRING, switch_parse_functions);
  581. }
  582. XtFree ((char *) switch_data);
  583. /* Continue the elimination of unused records */
  584. name_list = (char **) XtMalloc (sizeof (char *) * 2);
  585. if (switch_count != 0)
  586. name_list[0] = switch1->element_values[SWITCH_NAME].parsed_value;
  587. else
  588. name_list[0] = NULL;
  589. name_list[1] = NULL;
  590. EliminateUnused (control_data, &control_count, name_list,
  591. CONTROL_CONTAINER_NAME, CONTROL_CONTAINER_TYPE,
  592. SWITCH, CONTROL);
  593. XtFree ((char *)name_list);
  594. name_list = GetNameList (control_data, control_count,
  595. CONTROL_NAME, CONTROL_CONTAINER_TYPE, BOX);
  596. EliminateUnused (subpanel_data, &subpanel_count, name_list,
  597. SUBPANEL_CONTAINER_NAME, ANY_CONTAINER_TYPE,
  598. CONTROL, SUBPANEL);
  599. XtFree ((char *)name_list);
  600. name_list = GetNameList (subpanel_data, subpanel_count,
  601. SUBPANEL_NAME, ANY_CONTAINER_TYPE, SUBPANEL);
  602. EliminateUnused (control_data, &control_count, name_list,
  603. CONTROL_CONTAINER_NAME, CONTROL_CONTAINER_TYPE,
  604. SUBPANEL, CONTROL);
  605. XtFree ((char *)name_list);
  606. /* The record types of CONTROL, SUBPANEL and BOX still have need */
  607. /* several steps of processing. */
  608. ReorderByContainerType(control_data, control_count, CONTROL_CONTAINER_TYPE);
  609. ReorderByContainerName(control_data, control_count, CONTROL_CONTAINER_NAME,
  610. CONTROL_CONTAINER_TYPE);
  611. ReorderByName(box_data, box_count, BOX_NAME, BOX_CONTAINER_NAME);
  612. ReorderByName(control_data, control_count, CONTROL_NAME,
  613. CONTROL_CONTAINER_NAME);
  614. #ifdef DEBUG
  615. for (i = 0; i < control_count; i++) {
  616. printf("control %s, %d, %s\n",
  617. control_data[i].element_values[CONTROL_CONTAINER_NAME].parsed_value,
  618. control_data[i].element_values[CONTROL_CONTAINER_TYPE].parsed_value,
  619. control_data[i].element_values[CONTROL_NAME].parsed_value);
  620. }
  621. #endif
  622. /* Reprocess each of these groups to eliminate overridden */
  623. /* components. If a component is locked, use the first lock */
  624. /* encountered. Otherwise, use the last component read. */
  625. ResolveDuplicates (box_data, &box_count, BOX_NAME,
  626. ANY_CONTAINER_TYPE, BOX_CONTAINER_NAME,
  627. BOX_LOCKED, BOX);
  628. ResolveDuplicates (subpanel_data, &subpanel_count, SUBPANEL_NAME,
  629. ANY_CONTAINER_TYPE, SUBPANEL_CONTAINER_NAME,
  630. SUBPANEL_LOCKED, SUBPANEL);
  631. ResolveDuplicates (control_data, &control_count, CONTROL_NAME,
  632. CONTROL_CONTAINER_TYPE, CONTROL_CONTAINER_NAME,
  633. CONTROL_LOCKED, CONTROL);
  634. /* Now that the elimination has been completed, initialize the */
  635. /* remaining values for each of the components. */
  636. for (i = 0; i < box_count; i++)
  637. {
  638. InitializeField (box_data[i].element_values,
  639. BOX_POSITION_HINTS, box_parse_functions);
  640. InitializeField (box_data[i].element_values,
  641. BOX_HELP_STRING, box_parse_functions);
  642. InitializeField (box_data[i].element_values,
  643. BOX_HELP_TOPIC, box_parse_functions);
  644. InitializeField (box_data[i].element_values,
  645. BOX_HELP_VOLUME, box_parse_functions);
  646. }
  647. for (i = 0; i < subpanel_count; i++)
  648. {
  649. InitializeField (subpanel_data[i].element_values,
  650. SUBPANEL_CONTROL_INSTALL, subpanel_parse_functions);
  651. InitializeField (subpanel_data[i].element_values,
  652. SUBPANEL_TITLE, subpanel_parse_functions);
  653. InitializeField (subpanel_data[i].element_values,
  654. SUBPANEL_HELP_STRING, subpanel_parse_functions);
  655. InitializeField (subpanel_data[i].element_values,
  656. SUBPANEL_HELP_TOPIC, subpanel_parse_functions);
  657. InitializeField (subpanel_data[i].element_values,
  658. SUBPANEL_HELP_VOLUME, subpanel_parse_functions);
  659. }
  660. for (i = 0; i < control_count; i++)
  661. {
  662. InitializeSecondaryControlFields (control_data[i].element_values);
  663. InitializeFileControlFields (control_data[i].element_values, NULL);
  664. }
  665. #ifdef DEBUG
  666. for (i = 0; i < box_count; i++) {
  667. printf("box %d = %s\n",
  668. box_data[i].element_values[BOX_POSITION_HINTS].parsed_value,
  669. box_data[i].element_values[BOX_NAME].parsed_value);
  670. }
  671. for (i = 0; i < subpanel_count; i++) {
  672. printf("subpanel = %s\n",
  673. subpanel_data[i].element_values[SUBPANEL_NAME].parsed_value);
  674. }
  675. for (i = 0; i < control_count; i++) {
  676. printf("control %d = %s\n",
  677. control_data[i].element_values[CONTROL_POSITION_HINTS].parsed_value,
  678. control_data[i].element_values[CONTROL_NAME].parsed_value);
  679. }
  680. #endif
  681. /* Reorder subgroups according to position hints. */
  682. ReorderByPosition (box_data, box_count, BOX_POSITION_HINTS,
  683. ANY_CONTAINER_TYPE, BOX_CONTAINER_NAME);
  684. ReorderByPosition (control_data, control_count, CONTROL_POSITION_HINTS,
  685. CONTROL_CONTAINER_TYPE, CONTROL_CONTAINER_NAME);
  686. #ifdef DEBUG
  687. printf("**************************************************************\n\n");
  688. for (i = 0; i < box_count; i++) {
  689. printf("box %d = %s\n", (int)
  690. box_data[i].element_values[BOX_POSITION_HINTS].parsed_value,
  691. box_data[i].element_values[BOX_NAME].parsed_value);
  692. }
  693. for (i = 0; i < control_count; i++) {
  694. printf("control %d = %s\n", (int)
  695. control_data[i].element_values[CONTROL_POSITION_HINTS].parsed_value,
  696. control_data[i].element_values[CONTROL_NAME].parsed_value);
  697. }
  698. #endif
  699. /* Build hierarchical data structure from record sets, top-down. */
  700. /* Fully parse each record as the structure is built. */
  701. panel.box_data = (BoxData **) XtMalloc (sizeof (BoxData *) * box_count);
  702. panel.box_data_count = box_count;
  703. for (i = 0; i < box_count; i++)
  704. {
  705. BoxData * box;
  706. panel.box_data[i] = (BoxData *) XtMalloc (sizeof (BoxData));
  707. box = panel.box_data[i];
  708. box->element_values = box_data[i].element_values;
  709. box->control_data = NULL;
  710. box->control_data_count = 0;
  711. box->form = NULL;
  712. box->left_arrow_form = NULL;
  713. box->left_control_form = NULL;
  714. box->right_arrow_form = NULL;
  715. box->right_control_form = NULL;
  716. box->switch_data = NULL;
  717. box->switch_form = NULL;
  718. box->switch_edit = NULL;
  719. box->subpanel_count = 0;
  720. if (switch_count != 0 &&
  721. strcmp ((char *) box->element_values[BOX_NAME].parsed_value,
  722. (char *) switch1->element_values[SWITCH_CONTAINER_NAME].parsed_value) == 0)
  723. {
  724. box->switch_data = switch1;
  725. switch1->box_data = box;
  726. ProcessSwitch (box->switch_data);
  727. }
  728. /* Call a function to process each box, allocating the control */
  729. /* data structures needed for them and calling functions to */
  730. /* further process each control. */
  731. ProcessBox (box);
  732. }
  733. XtFree ((char *) box_data);
  734. _DtFreeDatabaseDirPaths (dir_paths);
  735. return True;
  736. }
  737. /************************************************************************
  738. *
  739. * PanelParseCB
  740. * Allocate a structure to contain the Panel record returned by
  741. * the database read code and copy the record information into the
  742. * structure.
  743. *
  744. ************************************************************************/
  745. static Boolean
  746. PanelParseCB (DtDtsDbField * fields,
  747. DtDbPathId path_id,
  748. char * host_prefix,
  749. Boolean rejection)
  750. {
  751. AllocateRecordData (&panel_data,
  752. sizeof (ElementValue) * PANEL_KEYWORD_COUNT,
  753. &panel_data_count, &panel_count);
  754. ProcessRecord (fields, (ElementValue *)
  755. panel_data[panel_count - 1].element_values);
  756. InitializeField (panel_data[panel_count - 1].element_values,
  757. PANEL_NAME, panel_parse_functions);
  758. InitializeField (panel_data[panel_count - 1].element_values,
  759. PANEL_LOCKED, panel_parse_functions);
  760. return (True);
  761. }
  762. /************************************************************************
  763. *
  764. * BoxParseCB
  765. * Allocate a structure to contain the Box record returned by
  766. * the database read code and copy the record information into the
  767. * structure.
  768. *
  769. ************************************************************************/
  770. static Boolean
  771. BoxParseCB (DtDtsDbField * fields,
  772. DtDbPathId path_id,
  773. char * host_prefix,
  774. Boolean rejection)
  775. {
  776. AllocateRecordData (&box_data,
  777. sizeof (ElementValue) * BOX_KEYWORD_COUNT,
  778. &box_data_count, &box_count);
  779. ProcessRecord (fields, box_data[box_count - 1].element_values);
  780. InitializeField (box_data[box_count - 1].element_values,
  781. BOX_NAME, box_parse_functions);
  782. InitializeField (box_data[box_count - 1].element_values,
  783. BOX_CONTAINER_NAME, box_parse_functions);
  784. InitializeField (box_data[box_count - 1].element_values,
  785. BOX_LOCKED, box_parse_functions);
  786. InitializeField (box_data[box_count - 1].element_values,
  787. BOX_DELETE, box_parse_functions);
  788. OrderRecord (box_data, box_count, BOX_CONTAINER_NAME);
  789. return (True);
  790. }
  791. /************************************************************************
  792. *
  793. * SubpanelParseCB
  794. * Allocate a structure to contain the Subpanel record returned by
  795. * the database read code and copy the record information into the
  796. * structure.
  797. *
  798. ************************************************************************/
  799. static Boolean
  800. SubpanelParseCB (DtDtsDbField * fields,
  801. DtDbPathId path_id,
  802. char * host_prefix,
  803. Boolean rejection)
  804. {
  805. AllocateRecordData (&subpanel_data,
  806. sizeof (ElementValue) * SUBPANEL_KEYWORD_COUNT,
  807. &subpanel_data_count, &subpanel_count);
  808. ProcessRecord (fields, subpanel_data[subpanel_count - 1].element_values);
  809. InitializeField (subpanel_data[subpanel_count - 1].element_values,
  810. SUBPANEL_NAME, subpanel_parse_functions);
  811. InitializeField (subpanel_data[subpanel_count - 1].element_values,
  812. SUBPANEL_CONTAINER_NAME, subpanel_parse_functions);
  813. InitializeField (subpanel_data[subpanel_count - 1].element_values,
  814. SUBPANEL_LOCKED, subpanel_parse_functions);
  815. InitializeField (subpanel_data[subpanel_count - 1].element_values,
  816. SUBPANEL_DELETE, subpanel_parse_functions);
  817. OrderRecord (subpanel_data, subpanel_count, SUBPANEL_CONTAINER_NAME);
  818. return (True);
  819. }
  820. /************************************************************************
  821. *
  822. * SwitchParseCB
  823. * Allocate a structure to contain the Switch record returned by
  824. * the database read code and copy the record information into the
  825. * structure.
  826. *
  827. ************************************************************************/
  828. static Boolean
  829. SwitchParseCB (DtDtsDbField * fields,
  830. DtDbPathId path_id,
  831. char * host_prefix,
  832. Boolean rejection)
  833. {
  834. AllocateRecordData (&switch_data,
  835. sizeof (ElementValue) * SWITCH_KEYWORD_COUNT,
  836. &switch_data_count, &switch_count);
  837. ProcessRecord (fields, switch_data[switch_count - 1].element_values);
  838. InitializeField (switch_data[switch_count - 1].element_values,
  839. SWITCH_NAME, switch_parse_functions);
  840. InitializeField (switch_data[switch_count - 1].element_values,
  841. SWITCH_CONTAINER_NAME, switch_parse_functions);
  842. InitializeField (switch_data[switch_count - 1].element_values,
  843. SWITCH_LOCKED, switch_parse_functions);
  844. InitializeField (switch_data[switch_count - 1].element_values,
  845. SWITCH_DELETE, switch_parse_functions);
  846. OrderRecord (switch_data, switch_count, SWITCH_CONTAINER_NAME);
  847. return (True);
  848. }
  849. /************************************************************************
  850. *
  851. * ControlParseCB
  852. * Allocate a structure to contain the Control record returned by
  853. * the database read code and copy the record information into the
  854. * structure.
  855. *
  856. ************************************************************************/
  857. static Boolean
  858. ControlParseCB (DtDtsDbField * fields,
  859. DtDbPathId path_id,
  860. char * host_prefix,
  861. Boolean rejection)
  862. {
  863. AllocateRecordData (&control_data,
  864. sizeof (ElementValue) * CONTROL_KEYWORD_COUNT,
  865. &control_data_count, &control_count);
  866. ProcessRecord (fields, control_data[control_count - 1].element_values);
  867. InitializePrimaryControlFields
  868. (control_data[control_count - 1].element_values);
  869. OrderRecord (control_data, control_count, CONTROL_CONTAINER_NAME);
  870. return (True);
  871. }
  872. /************************************************************************
  873. *
  874. * AnimationParseCB
  875. * Allocate a structure to contain the Animation records returned by
  876. * the database read code and copy the record information into the
  877. * structure.
  878. *
  879. ************************************************************************/
  880. static Boolean
  881. AnimationParseCB (DtDtsDbField * fields,
  882. DtDbPathId path_id,
  883. char * host_prefix,
  884. Boolean rejection)
  885. {
  886. unsigned char *string, *source, *head_ptr;
  887. char * field1;
  888. char * field2;
  889. int count = panel.animation_count;
  890. int field_count = 0;
  891. void * val_rtn;
  892. int i;
  893. XrmQuark animation_quark = XrmStringToQuark(ANIMATION);
  894. panel.animation_data = (AnimationData *)
  895. XtRealloc ((char *) panel.animation_data,
  896. sizeof (AnimationData) * (count + 1));
  897. panel.animation_data[count].name = strdup(fields[0].fieldValue);
  898. for (i = 1; fields[i].fieldName != NULLQUARK; i++)
  899. {
  900. if (fields[i].fieldName == animation_quark)
  901. field_count++;
  902. }
  903. panel.animation_data[count].item_count = field_count;
  904. panel.animation_data[count].items = (AnimationItem *)
  905. XtMalloc(sizeof(AnimationItem) * field_count);
  906. for (i = 0; i < field_count; i++)
  907. {
  908. if (fields[i+1].fieldName == animation_quark)
  909. {
  910. head_ptr = source =
  911. (unsigned char *) strdup((char *)fields[i+1].fieldValue);
  912. if ((string = _DtWmParseNextTokenC(&source, False)) != NULL)
  913. {
  914. panel.animation_data[count].items[i].image_name =
  915. strdup((char *) string);
  916. if ((string = _DtWmParseNextTokenC(&source, False)) != NULL)
  917. {
  918. StringToInt((char *)string, &val_rtn);
  919. panel.animation_data[count].items[i].delay = (int) (intptr_t) val_rtn;
  920. }
  921. else
  922. {
  923. panel.animation_data[count].items[i].delay = 0;
  924. }
  925. }
  926. free((char *)head_ptr);
  927. }
  928. }
  929. panel.animation_count++;
  930. return (True);
  931. }
  932. /************************************************************************
  933. *
  934. * ControlSingleParseCB
  935. * Allocate a structure to contain the Control record returned by
  936. * the database read code and copy the record information into the
  937. * structure.
  938. *
  939. ************************************************************************/
  940. static Boolean
  941. ControlSingleParseCB (DtDtsDbField * fields,
  942. DtDbPathId path_id,
  943. char * host_prefix,
  944. Boolean rejection)
  945. {
  946. if (control_element_value_found) {
  947. return (True);
  948. }
  949. control_element_values = (ElementValue *) XtMalloc (sizeof(ElementValue) *
  950. CONTROL_KEYWORD_COUNT);
  951. control_element_value_found = True;
  952. ProcessRecord (fields, control_element_values);
  953. InitializeControlFields(control_element_values, NULL);
  954. return (True);
  955. }
  956. /************************************************************************
  957. *
  958. * ProcessRecord
  959. * Extract the fields of a returned record and put them into an
  960. * allocated structure for latter processing.
  961. *
  962. ************************************************************************/
  963. static void
  964. ProcessRecord (DtDtsDbField * fields,
  965. ElementValue * element_values)
  966. {
  967. int i, j;
  968. int entry;
  969. int keyword_count = 0;
  970. char ** field_keywords;
  971. /* Find the position in the record structure for the value of */
  972. /* the entry keyword contained in the first position of the */
  973. /* fields array */
  974. for (entry = 0; entry < TOTAL_ENTRY_COUNT; entry++)
  975. {
  976. if (fields[0].fieldName == XrmStringToQuark(record_keywords[entry].record_keyword))
  977. {
  978. keyword_count = record_keywords[entry].keyword_count;
  979. field_keywords = record_keywords[entry].field_keywords;
  980. break;
  981. }
  982. }
  983. /* Initialize the element_values array */
  984. for (i = 0; i < keyword_count; i++)
  985. {
  986. (element_values + i)->use_default = True;
  987. (element_values + i)->string_value = NULL;
  988. (element_values + i)->parsed_value = NULL;
  989. }
  990. /* Loop through each read in keyword value pair, comparing it */
  991. /* to the keywords for this record type and when found, enter */
  992. /* it into the element values array for the component. */
  993. for (i = 0; fields[i].fieldName != NULLQUARK; i++)
  994. {
  995. XrmQuark field1 = fields[i].fieldName;
  996. char * field2 = fields[i].fieldValue;
  997. /* Search the field_keywords list and when the keyword is found */
  998. /* make a copy of field2 and place in its position. */
  999. for (j = 0; j < keyword_count; j++)
  1000. {
  1001. if (field1 == XrmStringToQuark(field_keywords[j]))
  1002. {
  1003. (element_values + j)->use_default = False;
  1004. (element_values + j)->string_value = strdup (field2);
  1005. break;
  1006. }
  1007. }
  1008. if (j == keyword_count)
  1009. _DtSimpleError (panel.app_name, DtWarning, NULL,
  1010. "Invalid keyword -- %s", XrmQuarkToString(field1));
  1011. }
  1012. }
  1013. /************************************************************************
  1014. *
  1015. * AllocateRecordData
  1016. * Allocate a structure to contain the values for a data base record
  1017. * and stuff it in an array for latter processing. Do all of this
  1018. * by indirection so that multiple record types can be handled.
  1019. *
  1020. ************************************************************************/
  1021. static void
  1022. AllocateRecordData (RecordData ** record_data,
  1023. int record_size,
  1024. int * record_data_count,
  1025. int * record_count)
  1026. {
  1027. if (*record_count >= *record_data_count)
  1028. {
  1029. *record_data_count += 10;
  1030. *record_data = (RecordData *)
  1031. XtRealloc ((char *) *record_data,
  1032. sizeof (RecordData) * (*record_data_count));
  1033. }
  1034. (*record_data)[*record_count].element_values =
  1035. (ElementValue *) XtMalloc (record_size);
  1036. (*record_count)++;
  1037. }
  1038. /************************************************************************
  1039. *
  1040. * OrderRecord
  1041. * Compare the value in the last element values struture referenced
  1042. * by value_define to previous element values. Move the element
  1043. * value structure to a new position defined by the comparison
  1044. * value being equal or greater the previous position and less
  1045. * than the next position
  1046. *
  1047. * The function works on string data.
  1048. *
  1049. ************************************************************************/
  1050. static void
  1051. OrderRecord (RecordData * record_data,
  1052. int record_count,
  1053. int value_define)
  1054. {
  1055. int i;
  1056. int new_loc;
  1057. char * position_value;
  1058. char * compare_value;
  1059. ElementValue * element_values;
  1060. /* If this is the first record, it is already in position */
  1061. if (record_count == 1)
  1062. return;
  1063. /* Extract the comparison value and loop backward through the */
  1064. /* record_data to find the correct */
  1065. element_values = record_data[record_count - 1].element_values;
  1066. position_value = element_values[value_define].parsed_value;
  1067. for (new_loc = record_count - 2; new_loc >= 0; new_loc--)
  1068. {
  1069. compare_value =
  1070. record_data[new_loc].element_values[value_define].parsed_value;
  1071. if (strcmp (position_value, compare_value) >= 0)
  1072. break;
  1073. record_data[new_loc + 1].element_values =
  1074. record_data[new_loc].element_values;
  1075. }
  1076. /* If any values have been moved, place the position value into */
  1077. /* the vacated spot. */
  1078. if (new_loc != record_count - 2)
  1079. record_data[new_loc + 1].element_values = element_values;
  1080. }
  1081. /************************************************************************
  1082. *
  1083. * SwapEntries
  1084. * Swap element value records based on positions.
  1085. *
  1086. ************************************************************************/
  1087. static void
  1088. SwapEntries (RecordData * rec_data,
  1089. int i,
  1090. int j)
  1091. {
  1092. ElementValue * temp_value;
  1093. temp_value = rec_data[i].element_values;
  1094. rec_data[i].element_values = rec_data[j].element_values;
  1095. rec_data[j].element_values = temp_value;
  1096. }
  1097. /************************************************************************
  1098. *
  1099. * QuickSort
  1100. * Reorder the records according to element index. This routine
  1101. * performs a quick sort. Positions that are equal will retain current
  1102. * positioning.
  1103. *
  1104. ************************************************************************/
  1105. #ifdef NOT_DEF
  1106. static void
  1107. QuickSort(RecordData * rec_data,
  1108. int left,
  1109. int right,
  1110. int elem_index,
  1111. int container)
  1112. {
  1113. int i, last;
  1114. if (left >= right)
  1115. return;
  1116. SwapEntries(rec_data, left, (left + right)/2);
  1117. last = left;
  1118. if (container == BOX && elem_index == BOX_POSITION_HINTS ||
  1119. (container == CONTROL && elem_index == CONTROL_POSITION_HINTS))
  1120. {
  1121. for (i = left + 1; i <= right; i++)
  1122. if (rec_data[i].element_values[elem_index].parsed_value <
  1123. rec_data[left].element_values[elem_index].parsed_value)
  1124. SwapEntries(rec_data, ++last, i);
  1125. }
  1126. else
  1127. {
  1128. for (i = left + 1; i <= right; i++)
  1129. if (strcmp(rec_data[i].element_values[elem_index].parsed_value,
  1130. rec_data[left].element_values[elem_index].parsed_value) < 0)
  1131. SwapEntries(rec_data, ++last, i);
  1132. }
  1133. SwapEntries(rec_data, left, last);
  1134. QuickSort(rec_data, left, last - 1, elem_index, container);
  1135. QuickSort(rec_data, last + 1, right, elem_index, container);
  1136. }
  1137. #endif /* NOT_DEF */
  1138. /************************************************************************
  1139. *
  1140. * BubbleSort
  1141. * Reorder the records according to element index. This routine
  1142. * performs a bubble sort. Positions that are equal will retain current
  1143. * positioning.
  1144. *
  1145. ************************************************************************/
  1146. static void
  1147. BubbleSort (RecordData * rec_data,
  1148. int start,
  1149. int rec_count,
  1150. int elem_index)
  1151. {
  1152. int bound, t, j;
  1153. Boolean is_string = False;
  1154. char *str1, *str2;
  1155. bound = rec_count;
  1156. if (elem_index == CONTROL_CONTAINER_NAME ||
  1157. elem_index == CONTROL_NAME)
  1158. is_string = True;
  1159. while (bound != 0)
  1160. {
  1161. t = 0;
  1162. for (j = start; j < bound; j++)
  1163. {
  1164. if (is_string)
  1165. {
  1166. str1 = (char *)rec_data[j].element_values[elem_index].parsed_value;
  1167. str2 = (char *)rec_data[j+1].element_values[elem_index].parsed_value;
  1168. if (strcmp(str1, str2) > 0)
  1169. {
  1170. SwapEntries(rec_data, j, j+1);
  1171. t = j;
  1172. }
  1173. }
  1174. else
  1175. {
  1176. if ((intptr_t) rec_data[j].element_values[elem_index].parsed_value >
  1177. (intptr_t) rec_data[j+1].element_values[elem_index].parsed_value)
  1178. {
  1179. SwapEntries(rec_data, j, j+1);
  1180. t = j;
  1181. }
  1182. }
  1183. }
  1184. bound = t;
  1185. }
  1186. }
  1187. /************************************************************************
  1188. *
  1189. * ReversePositions
  1190. * Reverse order of the records. This routine reverses the order of
  1191. * the records so that user records that have the same positioning
  1192. * will get a higher presidence.
  1193. *
  1194. *
  1195. ************************************************************************/
  1196. static void
  1197. ReversePositions (RecordData * rec_data,
  1198. int start,
  1199. int end)
  1200. {
  1201. int i, j;
  1202. for (i = start, j = end; i < j; i++, j--)
  1203. {
  1204. SwapEntries(rec_data, i, j);
  1205. }
  1206. }
  1207. /************************************************************************
  1208. *
  1209. * ReorderByContainerName
  1210. * Reorder the records according to container name. This will be done
  1211. * using a quick sort. Container type order must be retained. Matchinng
  1212. * names will retain current ordering.
  1213. *
  1214. *************************************************************************/
  1215. static void
  1216. ReorderByContainerName (RecordData * rec_data,
  1217. int rec_count,
  1218. int name,
  1219. int elem_type)
  1220. {
  1221. int i = 0, start = 0;
  1222. int cont_type;
  1223. while (i < rec_count)
  1224. {
  1225. cont_type = (int) (intptr_t)
  1226. (rec_data[start].element_values[elem_type].parsed_value);
  1227. while ((intptr_t)(rec_data[i].element_values[elem_type].parsed_value) ==
  1228. cont_type)
  1229. {
  1230. i++;
  1231. if (rec_count == i) break;
  1232. }
  1233. BubbleSort(rec_data, start, i - 1, name);
  1234. start = i;
  1235. }
  1236. }
  1237. /************************************************************************
  1238. *
  1239. * ReorderByName
  1240. * Reorder the records according to names. This will be done
  1241. * using a quick sort. Container name order must be retained.
  1242. * Matching names will retain current order.
  1243. *
  1244. *************************************************************************/
  1245. static void
  1246. ReorderByName (RecordData * rec_data,
  1247. int rec_count,
  1248. int name,
  1249. int elem_type)
  1250. {
  1251. int i = 0, start = 0;
  1252. char *cont_name;
  1253. while (i < rec_count)
  1254. {
  1255. cont_name = (char *)
  1256. (rec_data[start].element_values[elem_type].parsed_value);
  1257. while (strcmp((char *)rec_data[i].element_values[elem_type].parsed_value,
  1258. cont_name) == 0)
  1259. {
  1260. i++;
  1261. if (rec_count == i) break;
  1262. }
  1263. BubbleSort(rec_data, start, i - 1, name);
  1264. start = i;
  1265. }
  1266. }
  1267. /************************************************************************
  1268. *
  1269. * ReorderByPosition
  1270. * Reorder the records according to position_hints. This will be done
  1271. * using a quick sort. Positions that are equal will retain current
  1272. * positioning.
  1273. *************************************************************************/
  1274. static void
  1275. ReorderByPosition(RecordData *rec_data,
  1276. int rec_count,
  1277. int pos_hints,
  1278. int cont_type,
  1279. int cont_name)
  1280. {
  1281. int i = 0, start = 0;
  1282. int container_type;
  1283. char *container_name;
  1284. ReversePositions(rec_data, 0, rec_count - 1);
  1285. while (i < rec_count)
  1286. {
  1287. container_name = (char *)
  1288. (rec_data[start].element_values[cont_name].parsed_value);
  1289. if (cont_type == ANY_CONTAINER_TYPE)
  1290. {
  1291. while (strcmp((char *)
  1292. rec_data[i].element_values[cont_name].parsed_value,
  1293. container_name) == 0)
  1294. {
  1295. i++;
  1296. if (rec_count == i) break;
  1297. }
  1298. }
  1299. else
  1300. {
  1301. container_type = (int) (intptr_t)
  1302. (rec_data[start].element_values[cont_type].parsed_value);
  1303. while (((intptr_t)rec_data[i].element_values[cont_type].parsed_value ==
  1304. container_type) &&
  1305. (strcmp((char *)
  1306. rec_data[i].element_values[cont_name].parsed_value,
  1307. container_name) == 0))
  1308. {
  1309. i++;
  1310. if (rec_count == i) break;
  1311. }
  1312. }
  1313. BubbleSort(rec_data, start, i - 1, pos_hints);
  1314. start = i;
  1315. }
  1316. }
  1317. /************************************************************************
  1318. *
  1319. * ReorderByContainerType
  1320. * Reorder the records according to container type. This will be done
  1321. * using a bubble sort. Container types that are match must retain
  1322. * current positioning.
  1323. *
  1324. *************************************************************************/
  1325. static void
  1326. ReorderByContainerType (RecordData * rec_data,
  1327. int rec_count,
  1328. int container_type)
  1329. {
  1330. BubbleSort(rec_data, 0, rec_count - 1, container_type);
  1331. }
  1332. /************************************************************************
  1333. *
  1334. * RemoveEntry
  1335. *
  1336. ************************************************************************/
  1337. void
  1338. RemoveEntry (RecordData * record_data,
  1339. int record_type)
  1340. {
  1341. int i;
  1342. for (i = 0; i < record_descriptor[record_type].maxFields; i++)
  1343. {
  1344. if (record_keywords[record_type].parse_functions[i].free_function
  1345. != NULL &&
  1346. record_data->element_values[i].parsed_value != NULL &&
  1347. record_data->element_values[i].use_default == False)
  1348. {
  1349. (*(record_keywords[record_type].parse_functions[i].free_function))
  1350. (&(record_data->element_values[i].parsed_value));
  1351. }
  1352. if (record_data->element_values[i].use_default == False &&
  1353. record_data->element_values[i].string_value != NULL)
  1354. free(record_data->element_values[i].string_value);
  1355. }
  1356. XtFree((char *)record_data->element_values);
  1357. }
  1358. /************************************************************************
  1359. *
  1360. * EliminateEntries
  1361. * Given a container type and the indicies of the records to be deleted,
  1362. * delete any components which are within the specified container type
  1363. * and range.
  1364. *
  1365. ************************************************************************/
  1366. static void
  1367. EliminateEntries (RecordData * record_data,
  1368. int * record_count,
  1369. int start,
  1370. int end,
  1371. int * i,
  1372. int * count,
  1373. int record_type)
  1374. {
  1375. int j, k;
  1376. if (start > end) return;
  1377. for (j = start; j <= end; j++)
  1378. {
  1379. RemoveEntry(&(record_data[j]), record_type);
  1380. }
  1381. if (end + 1 < *record_count)
  1382. {
  1383. memmove((void *) &record_data[start], (void *) &record_data[end+1],
  1384. (size_t) ((*record_count - end) * sizeof(RecordData)));
  1385. }
  1386. *i += (end - start) + 1;
  1387. *count = *record_count -= (end - start) + 1;
  1388. }
  1389. /************************************************************************
  1390. *
  1391. * ResolveDuplicates
  1392. * Reprocess each group to eliminate overridden components.
  1393. * If a component is locked, use the first lock encountered.
  1394. * Otherwise, use the last component read.
  1395. *
  1396. ************************************************************************/
  1397. static void
  1398. ResolveDuplicates (RecordData * record_data,
  1399. int * record_count,
  1400. int name_type,
  1401. int container_type,
  1402. int container_name,
  1403. int lock_type,
  1404. int record_type)
  1405. {
  1406. int i, start_index, lock_index, last_index;
  1407. ElementValue * element_values;
  1408. int cont_type;
  1409. char *cont_name = NULL, *record_name;
  1410. int count = *record_count;
  1411. Boolean locked;
  1412. i = count - 1;
  1413. /* Go through the array of records */
  1414. while (i >= 0)
  1415. {
  1416. element_values = record_data[i].element_values;
  1417. if (ANY_CONTAINER_TYPE != container_type)
  1418. {
  1419. cont_type = (int) (intptr_t) (element_values[container_type].parsed_value);
  1420. cont_name = (char *) (element_values[container_name].parsed_value);
  1421. }
  1422. record_name = (char *) (element_values[name_type].parsed_value);
  1423. locked = (Boolean) (intptr_t) (element_values[lock_type].parsed_value);
  1424. if (locked)
  1425. {
  1426. i--;
  1427. if (i < 0) break;
  1428. start_index = last_index = i;
  1429. element_values = record_data[i].element_values;
  1430. if (ANY_CONTAINER_TYPE == container_type)
  1431. {
  1432. while ((strcmp((char *) (element_values[name_type].parsed_value),
  1433. cont_name) == 0))
  1434. {
  1435. last_index = i;
  1436. i--;
  1437. if (i < 0) break;
  1438. element_values = record_data[i].element_values;
  1439. }
  1440. }
  1441. else
  1442. {
  1443. while (((intptr_t)(element_values[container_type].parsed_value)
  1444. == cont_type) &&
  1445. (strcmp((char *)(element_values[container_name].parsed_value),
  1446. cont_name) == 0) &&
  1447. (strcmp((char *)(element_values[name_type].parsed_value),
  1448. record_name) == 0))
  1449. {
  1450. last_index = i;
  1451. i--;
  1452. if (i < 0) break;
  1453. element_values = record_data[i].element_values;
  1454. }
  1455. }
  1456. if (start_index != last_index)
  1457. EliminateEntries(record_data, record_count, last_index,
  1458. start_index - 1, &i, &count, record_type);
  1459. if (i < 0) break;
  1460. }
  1461. else
  1462. {
  1463. start_index = lock_index = last_index = i;
  1464. i--;
  1465. if (i < 0) continue;
  1466. element_values = record_data[i].element_values;
  1467. if (ANY_CONTAINER_TYPE == container_type)
  1468. {
  1469. while ((strcmp((char *) (element_values[name_type].parsed_value),
  1470. record_name) == 0))
  1471. {
  1472. locked = (Boolean) (intptr_t) (element_values[lock_type].parsed_value);
  1473. if (locked && start_index == lock_index)
  1474. lock_index = i;
  1475. last_index = i;
  1476. i--;
  1477. if (i < 0) break;
  1478. element_values = record_data[i].element_values;
  1479. }
  1480. }
  1481. else
  1482. {
  1483. while (((intptr_t)(element_values[container_type].parsed_value)
  1484. == cont_type) &&
  1485. (strcmp((char *)(element_values[container_name].parsed_value),
  1486. cont_name) == 0) &&
  1487. (strcmp((char *)(element_values[name_type].parsed_value),
  1488. record_name) == 0))
  1489. {
  1490. locked = (Boolean) (intptr_t) (element_values[lock_type].parsed_value);
  1491. if (locked && start_index == lock_index)
  1492. lock_index = i;
  1493. last_index = i;
  1494. i--;
  1495. if (i < 0) break;
  1496. element_values = record_data[i].element_values;
  1497. }
  1498. }
  1499. if (start_index != last_index)
  1500. {
  1501. if (start_index == lock_index)
  1502. EliminateEntries(record_data, record_count, last_index + 1,
  1503. start_index, &i, &count, record_type);
  1504. else
  1505. {
  1506. int diff = start_index - lock_index;
  1507. EliminateEntries(record_data, record_count, lock_index + 1,
  1508. start_index, &i, &count, record_type);
  1509. lock_index += diff;
  1510. last_index += diff;
  1511. if (lock_index != last_index)
  1512. EliminateEntries(record_data, record_count, last_index,
  1513. lock_index - 1, &i, &count, record_type);
  1514. }
  1515. }
  1516. if (i < 0) break;
  1517. }
  1518. }
  1519. }
  1520. /************************************************************************
  1521. *
  1522. * GetNameList
  1523. * Given a record_data array and a particular container type,
  1524. * allocate an array of pointers to strings and set to the component
  1525. * names of each component which matches the above criteria.
  1526. *
  1527. ************************************************************************/
  1528. static char **
  1529. GetNameList (RecordData * record_data,
  1530. int record_count,
  1531. int name_type,
  1532. int container_type,
  1533. int container)
  1534. {
  1535. int i;
  1536. char ** name_list = NULL;
  1537. int name_list_count = 0;
  1538. int found_count = 0;
  1539. for (i = 0; i < record_count; i++)
  1540. {
  1541. if (ANY_CONTAINER_TYPE == container_type ||
  1542. (intptr_t)(record_data[i].element_values[container_type].parsed_value) ==
  1543. container)
  1544. {
  1545. if (found_count >= name_list_count)
  1546. {
  1547. name_list_count += 10;
  1548. name_list =
  1549. (char **) XtRealloc ((char *) name_list,
  1550. sizeof (char *) * (name_list_count + 1));
  1551. }
  1552. name_list [found_count] =
  1553. record_data[i].element_values[name_type].parsed_value;
  1554. found_count++;
  1555. }
  1556. }
  1557. if (name_list != NULL)
  1558. name_list [found_count] = NULL;
  1559. return (name_list);
  1560. }
  1561. /************************************************************************
  1562. *
  1563. * EliminateUnused
  1564. * Given a record_data array, container name list and container type,
  1565. * delete any components which are within the specified container type
  1566. * but do not contain the container name.
  1567. *
  1568. ************************************************************************/
  1569. static void
  1570. EliminateUnused (RecordData * record_data,
  1571. int * record_count,
  1572. char ** cont_name_list,
  1573. int cont_name,
  1574. int cont_type,
  1575. int container,
  1576. int record_type)
  1577. {
  1578. int i, j, dummy = 0;
  1579. char * container_name;
  1580. int count = *record_count;
  1581. Boolean name_found = False;
  1582. ElementValue * element_values;
  1583. i = 0;
  1584. while (i < count)
  1585. {
  1586. element_values = record_data[i].element_values;
  1587. if (cont_type == ANY_CONTAINER_TYPE ||
  1588. (intptr_t)(element_values[cont_type].parsed_value) == container)
  1589. {
  1590. if (cont_name_list != NULL)
  1591. {
  1592. for (j = 0; cont_name_list[j] != NULL; j++)
  1593. {
  1594. container_name = cont_name_list[j];
  1595. if (strcmp((char *)element_values[cont_name].parsed_value,
  1596. container_name) == 0)
  1597. {
  1598. name_found = True;
  1599. break;
  1600. }
  1601. }
  1602. }
  1603. if (!name_found)
  1604. {
  1605. #ifdef DEBUG
  1606. printf("Entry Eliminated - %s\n",
  1607. (char *)element_values[cont_name].parsed_value);
  1608. #endif
  1609. EliminateEntries(record_data, record_count, i, i, &dummy, &count,
  1610. record_type);
  1611. }
  1612. else
  1613. {
  1614. name_found = False;
  1615. i++;
  1616. }
  1617. }
  1618. else
  1619. i++;
  1620. }
  1621. }
  1622. /************************************************************************
  1623. *
  1624. * EliminateDeleted
  1625. * Given a record_data array, delete any components which have the
  1626. * DELETE keyword set to True. Also delete any duplicates that match
  1627. * the container name, container type, record name, and record type
  1628. * but do not have the LOCKED keyword set to True.
  1629. *
  1630. ************************************************************************/
  1631. static void
  1632. EliminateDeleted (RecordData * record_data,
  1633. int * record_count,
  1634. int cont_name,
  1635. int record_name,
  1636. int record_type,
  1637. int delete_type,
  1638. int lock_type)
  1639. {
  1640. int i, j, start, dummy = 0;
  1641. int count;
  1642. ElementValue * element_values, * other_element_values;
  1643. char * container_name, * rec_name;
  1644. int container_type, rec_type;
  1645. count = *record_count;
  1646. i = 0;
  1647. while (i < count)
  1648. {
  1649. start = i;
  1650. element_values = record_data[i].element_values;
  1651. if ((intptr_t)element_values[delete_type].parsed_value)
  1652. {
  1653. Boolean delete_rest = False;
  1654. if (record_type == CONTROL)
  1655. {
  1656. rec_type = (intptr_t)element_values[CONTROL_TYPE].parsed_value;
  1657. container_type =
  1658. (intptr_t)element_values[CONTROL_CONTAINER_TYPE].parsed_value;
  1659. }
  1660. container_name =
  1661. XtNewString ((char *)element_values[cont_name].parsed_value);
  1662. rec_name =
  1663. XtNewString ((char *)element_values[record_name].parsed_value);
  1664. for (j = count - 1; j >= 0; j--)
  1665. {
  1666. other_element_values = record_data[j].element_values;
  1667. if ((record_type != CONTROL ||
  1668. ((intptr_t)other_element_values[CONTROL_CONTAINER_TYPE].parsed_value
  1669. == container_type &&
  1670. (intptr_t) other_element_values[CONTROL_TYPE].parsed_value
  1671. == rec_type)) &&
  1672. strcmp((char *)other_element_values[cont_name].parsed_value,
  1673. container_name) == 0 &&
  1674. strcmp((char *)other_element_values[record_name].parsed_value,
  1675. rec_name) == 0)
  1676. {
  1677. if ((intptr_t)other_element_values[lock_type].parsed_value)
  1678. {
  1679. if ((intptr_t)other_element_values[delete_type].parsed_value)
  1680. {
  1681. EliminateEntries(record_data, record_count, j, j, &dummy,
  1682. &count, record_type);
  1683. delete_rest = True;
  1684. }
  1685. else if (delete_rest)
  1686. {
  1687. EliminateEntries(record_data, record_count, j, j, &dummy,
  1688. &count, record_type);
  1689. }
  1690. }
  1691. else
  1692. EliminateEntries(record_data, record_count, j, j, &dummy,
  1693. &count, record_type);
  1694. }
  1695. }
  1696. XtFree(container_name);
  1697. XtFree(rec_name);
  1698. }
  1699. else
  1700. i++;
  1701. }
  1702. }
  1703. /************************************************************************
  1704. *
  1705. * InitializeField
  1706. * Given an ElementValues array, a particular keyword that references
  1707. * a single element and the parse function array for the record
  1708. * type: if the element has a value string, parse it otherwise
  1709. * set the parsed value to the default.
  1710. *
  1711. ************************************************************************/
  1712. static void
  1713. InitializeField (ElementValue * element_values,
  1714. int keyword,
  1715. ParseFunction * parse_functions)
  1716. {
  1717. if (element_values[keyword].string_value != NULL)
  1718. {
  1719. element_values[keyword].use_default = False;
  1720. if (!parse_functions[keyword].parse_function (
  1721. element_values[keyword].string_value,
  1722. &(element_values[keyword].parsed_value)))
  1723. {
  1724. XtFree(element_values[keyword].string_value);
  1725. element_values[keyword].string_value = NULL;
  1726. element_values[keyword].use_default = True;
  1727. element_values[keyword].parsed_value =
  1728. parse_functions[keyword].default_value;
  1729. }
  1730. }
  1731. else
  1732. {
  1733. element_values[keyword].use_default = True;
  1734. element_values[keyword].parsed_value =
  1735. parse_functions[keyword].default_value;
  1736. }
  1737. }
  1738. /************************************************************************
  1739. *
  1740. * CountElements
  1741. * Given a record_data array, a container name and container type
  1742. * count how many records match and return the value.
  1743. *
  1744. ************************************************************************/
  1745. static int
  1746. CountElements (RecordData * record_data,
  1747. int record_count,
  1748. char * container_name,
  1749. int name_type,
  1750. int container_type,
  1751. int container)
  1752. {
  1753. int i;
  1754. static int found_count = 0;
  1755. for (i = 0; i < record_count; i++)
  1756. {
  1757. if (ANY_CONTAINER_TYPE == container_type ||
  1758. (intptr_t)(record_data[i].element_values[container_type].parsed_value) ==
  1759. container)
  1760. {
  1761. if (strcmp (container_name,
  1762. record_data[i].element_values[name_type].parsed_value) ==0)
  1763. found_count++;
  1764. }
  1765. }
  1766. return (found_count);
  1767. }
  1768. /************************************************************************
  1769. *
  1770. * DeleteControlActionList
  1771. *
  1772. ************************************************************************/
  1773. void
  1774. DeleteControlActionList (ControlData * control_data)
  1775. {
  1776. int i;
  1777. if (control_data->move_action != NULL)
  1778. free(control_data->move_action);
  1779. if (control_data->copy_action != NULL)
  1780. free(control_data->copy_action);
  1781. if (control_data->link_action != NULL)
  1782. free(control_data->link_action);
  1783. if (control_data->actions != NULL)
  1784. {
  1785. for (i = 0; control_data->actions[i] != NULL; i++)
  1786. {
  1787. free (control_data->actions[i]->action_name);
  1788. if (control_data->actions[i]->action_label != NULL)
  1789. free (control_data->actions[i]->action_label);
  1790. XtFree ((char *) control_data->actions[i]);
  1791. }
  1792. XtFree((char *)control_data->actions);
  1793. }
  1794. }
  1795. /************************************************************************
  1796. *
  1797. * AddControlActionList
  1798. *
  1799. ************************************************************************/
  1800. void
  1801. AddControlActionList (ControlData * control_data)
  1802. {
  1803. char * data_type = NULL;
  1804. char * act_list = NULL;
  1805. char * file_name = NULL;
  1806. char * file_str;
  1807. char ** action_list = NULL;
  1808. int num_actions = 0;
  1809. int i = 0;
  1810. int result;
  1811. Boolean is_file_control = False;
  1812. PanelActionData * drop_action;
  1813. char * label;
  1814. int j = 0;
  1815. if ((intptr_t)control_data->element_values[CONTROL_TYPE].parsed_value ==
  1816. CONTROL_FILE)
  1817. {
  1818. file_name = (char *)
  1819. control_data->element_values[CONTROL_FILE_NAME].parsed_value;
  1820. data_type = DtDtsFileToDataType (file_name);
  1821. is_file_control = True;
  1822. }
  1823. if (data_type != NULL)
  1824. {
  1825. DtDtsAttribute ** attr_list;
  1826. char * attr[5];
  1827. attr_list = DtDtsDataTypeToAttributeList (data_type, file_name);
  1828. /* The attribute list is ordered alphabetically by name so */
  1829. /* do a linear search of the atr_list array and get the values */
  1830. /* as use run into them. Use the following array to get the */
  1831. /* values for these attributes. */
  1832. attr[0] = DtDTS_DA_ACTION_LIST;
  1833. attr[1] = DtDTS_DA_COPY_TO_ACTION;
  1834. attr[2] = DtDTS_DA_LINK_TO_ACTION;
  1835. attr[3] = DtDTS_DA_MOVE_TO_ACTION;
  1836. if (attr_list != NULL)
  1837. {
  1838. for (i = 0; attr_list[i] != NULL; i++)
  1839. {
  1840. for (j = 0; j < 4; j++)
  1841. if (strcmp (attr_list[i]->name, attr[j]) == 0)
  1842. break;
  1843. /* If we have found a match, find the appropriate attr */
  1844. /* and assign the value. */
  1845. switch (j)
  1846. {
  1847. /* DtDTS_DA_ACTION_LIST */
  1848. case 0:
  1849. free(act_list); /* Remove any previous loop run through */
  1850. act_list = (char *) strdup(attr_list[i]->value);
  1851. break;
  1852. /* DtDTS_DA_COPY_TO_ACTION */
  1853. case 1:
  1854. control_data->copy_action =
  1855. (char *) strdup(attr_list[i]->value);
  1856. break;
  1857. /* DtDTS_DA_LINK_TO_ACTION */
  1858. case 2:
  1859. control_data->link_action =
  1860. (char *) strdup(attr_list[i]->value);
  1861. break;
  1862. /* DtDTS_DA_MOVE_TO_ACTION */
  1863. case 3:
  1864. control_data->move_action =
  1865. (char *) strdup(attr_list[i]->value);
  1866. break;
  1867. /* No Match */
  1868. case 4:
  1869. break;
  1870. }
  1871. }
  1872. }
  1873. if (act_list)
  1874. {
  1875. action_list = _DtVectorizeInPlace (act_list, ',');
  1876. for (i = 0; action_list[i] != NULL; i++)
  1877. num_actions++;
  1878. }
  1879. if (DtDtsDataTypeIsAction(data_type) && is_file_control)
  1880. control_data->is_action = True;
  1881. if (attr_list != NULL)
  1882. DtDtsFreeAttributeList(attr_list);
  1883. }
  1884. if (action_list == NULL)
  1885. {
  1886. if (control_data->element_values[CONTROL_PUSH_ACTION].string_value != NULL)
  1887. {
  1888. action_list = (char **) XtMalloc(sizeof(char *) * 2);
  1889. action_list[0] =
  1890. control_data->element_values[CONTROL_PUSH_ACTION].string_value;
  1891. action_list[1] = NULL;
  1892. num_actions = 1;
  1893. }
  1894. else
  1895. num_actions = 0;
  1896. }
  1897. control_data->actions = (PanelActionData **)
  1898. XtMalloc(sizeof(PanelActionData *) *
  1899. (num_actions + 1));
  1900. for (i = 0, j = 0; j < num_actions; i++, j++)
  1901. {
  1902. /* Remove the OpenInPlace action from the list of actions */
  1903. if (strcmp(action_list[j],"OpenInPlace") == 0)
  1904. {
  1905. i--;
  1906. continue;
  1907. }
  1908. control_data->actions[i] = (PanelActionData *)
  1909. XtMalloc(sizeof(PanelActionData));
  1910. control_data->actions[i]->action_name = strdup(action_list[j]);
  1911. control_data->actions[i]->aap = NULL;
  1912. control_data->actions[i]->count = 0;
  1913. label = DtActionLabel (action_list[j]);
  1914. if (label != NULL)
  1915. control_data->actions[i]->action_label = label;
  1916. else
  1917. control_data->actions[i]->action_label = strdup (action_list[j]);
  1918. }
  1919. control_data->actions[i] = NULL;
  1920. if (act_list)
  1921. free (act_list);
  1922. if (action_list)
  1923. XtFree ((char *) action_list);
  1924. if ((data_type != NULL) && is_file_control)
  1925. DtDtsFreeDataType (data_type);
  1926. }
  1927. /************************************************************************
  1928. *
  1929. * ProcessBox
  1930. * For a box structure, find the control set that is to be contained
  1931. * by it, allocate a ControlData array and reassign the element
  1932. * values pointers. Further process each control.
  1933. *
  1934. * Inputs: box_data - a pointer the BoxData structure to be initialized.
  1935. *
  1936. ************************************************************************/
  1937. static void
  1938. ProcessBox (BoxData * box_data)
  1939. {
  1940. ElementValue * element_values;
  1941. int box_control_count = 0;
  1942. int i;
  1943. /* Loop the control array and check each control to see if it belongs */
  1944. /* in this box. If so, call a function to add it and then see if the */
  1945. /* control has a subpanel to process. */
  1946. for (i = 0; i < control_count; i++)
  1947. {
  1948. element_values = control_data[i].element_values;
  1949. if ((intptr_t) element_values[CONTROL_CONTAINER_TYPE].parsed_value == BOX &&
  1950. strcmp ((char *) box_data->element_values[BOX_NAME].parsed_value,
  1951. (char *) element_values[CONTROL_CONTAINER_NAME].parsed_value) == 0)
  1952. {
  1953. ProcessControl ((XtPointer) box_data, BOX, &(box_data->control_data),
  1954. &box_control_count, element_values);
  1955. box_data->subpanel_count +=
  1956. ProcessBoxControl (box_data->control_data[box_control_count - 1]);
  1957. }
  1958. }
  1959. box_data->control_data_count = box_control_count;
  1960. }
  1961. /************************************************************************
  1962. *
  1963. * ProcessControl
  1964. * For each control that is created, reallocate the array of
  1965. * pointer that hold the control and allocate a control structure.
  1966. * Initialize the control fields. This is called for BOX, SUBPANEL
  1967. * and SWITCH controls.
  1968. *
  1969. * Inputs: parent - a pointer to the head of the structure that is to
  1970. * contain this control.
  1971. * parent_type - the type of parent of the control.
  1972. * control_data_ptr - a pointer to the array of control pointers.
  1973. * control_count - the current count of controls within the array.
  1974. * element_values - the new controls database values.
  1975. *
  1976. ************************************************************************/
  1977. static void
  1978. ProcessControl (XtPointer parent,
  1979. char parent_type,
  1980. ControlData *** control_data_ptr,
  1981. int * control_count,
  1982. ElementValue * element_values)
  1983. {
  1984. ControlData * control;
  1985. *control_data_ptr =
  1986. (ControlData **) XtRealloc ((char *) *control_data_ptr,
  1987. sizeof (ControlData *) * (*control_count + 1));
  1988. (*control_data_ptr)[*control_count] =
  1989. (ControlData *) XtMalloc (sizeof (ControlData));
  1990. control = (*control_data_ptr)[*control_count];
  1991. control->element_values = element_values;
  1992. control->parent_data = parent;
  1993. control->parent_type = parent_type;
  1994. control->subpanel_data = NULL;
  1995. control->icon = NULL;
  1996. control->arrow = NULL;
  1997. control->arrow_separator = NULL;
  1998. control->indicator = NULL;
  1999. control->actions = NULL;
  2000. control->is_action = False;
  2001. control->move_action = NULL;
  2002. control->copy_action = NULL;
  2003. control->link_action = NULL;
  2004. control->operation = 0;
  2005. AddControlActionList (control);
  2006. *control_count = *control_count + 1;
  2007. }
  2008. /************************************************************************
  2009. *
  2010. * ProcessBoxControl
  2011. * For a control structure within a box, see if there is a subpanel
  2012. * attached to it and if so, process the subpanel and its controls.
  2013. * Return the subpanel count to be stored as part of the box data.
  2014. *
  2015. * Inputs: control_data - a pointer to the control to be processed
  2016. *
  2017. ************************************************************************/
  2018. static int
  2019. ProcessBoxControl (ControlData * control_data)
  2020. {
  2021. int i;
  2022. ElementValue * element_values;
  2023. int box_subpanel_count = 0;
  2024. SubpanelData * subpanel;
  2025. /* Loop through the subpanel data and find one that is attached */
  2026. /* to the provided control. */
  2027. for (i = 0; i < subpanel_count; i++)
  2028. {
  2029. element_values = subpanel_data[i].element_values;
  2030. if (strcmp ((char *) control_data->element_values[CONTROL_NAME].parsed_value,
  2031. (char *) element_values[SUBPANEL_CONTAINER_NAME].parsed_value) == 0)
  2032. {
  2033. box_subpanel_count = 1;
  2034. control_data->subpanel_data =
  2035. (SubpanelData *) XtMalloc (sizeof (SubpanelData));
  2036. subpanel = control_data->subpanel_data;
  2037. subpanel->element_values = element_values;
  2038. subpanel->control_data = NULL;
  2039. subpanel->control_data_count = 0;
  2040. subpanel->parent_control_data = control_data;
  2041. subpanel->default_control = NULL;
  2042. subpanel->shell = NULL;
  2043. subpanel->form = NULL;
  2044. subpanel->dropzone = NULL;
  2045. subpanel->separator = NULL;
  2046. subpanel->main_panel_icon_copy = NULL;
  2047. subpanel->torn = False;
  2048. ProcessSubpanel (subpanel);
  2049. }
  2050. }
  2051. return (box_subpanel_count);
  2052. }
  2053. /************************************************************************
  2054. *
  2055. * ProcessSubpanel
  2056. * For a Subpanel, find all of the controls within it an allocate
  2057. * a ControlData array and move the element values for the controls.
  2058. *
  2059. * Inputs: subpanel_data - A pointer the the subpanel structure to be
  2060. * processed.
  2061. *
  2062. ************************************************************************/
  2063. static void
  2064. ProcessSubpanel (SubpanelData * subpanel_data)
  2065. {
  2066. ElementValue * element_values;
  2067. int subpanel_control_count = 0;
  2068. int i;
  2069. /* Loop the control array and check each control to see if it belongs */
  2070. /* in this subpanel. If so, call a function to add it. */
  2071. for (i = 0; i < control_count; i++)
  2072. {
  2073. element_values = control_data[i].element_values;
  2074. if ((intptr_t) element_values[CONTROL_CONTAINER_TYPE].parsed_value == SUBPANEL &&
  2075. strcmp ((char *) subpanel_data->element_values[SUBPANEL_NAME].parsed_value,
  2076. (char *) element_values[CONTROL_CONTAINER_NAME].parsed_value) == 0)
  2077. {
  2078. ProcessControl ((XtPointer) subpanel_data, SUBPANEL,
  2079. &(subpanel_data->control_data),
  2080. &subpanel_control_count, element_values);
  2081. }
  2082. }
  2083. subpanel_data->control_data_count = subpanel_control_count;
  2084. }
  2085. /************************************************************************
  2086. *
  2087. * ProcessSwitch
  2088. * For a Switch, find all of the controls within it an allocate
  2089. * a ControlData array and move the element values for the controls.
  2090. *
  2091. * Inputs: switch_data - a pointer to the switch data structure to be
  2092. * processed.
  2093. *
  2094. ************************************************************************/
  2095. static void
  2096. ProcessSwitch (SwitchData * switch_data)
  2097. {
  2098. ElementValue * element_values;
  2099. int switch_control_count = 0;
  2100. int i;
  2101. /* Count the number of controls that are to go into this switch */
  2102. /* and allocate a ControlData array to hold the controls. */
  2103. for (i = 0; i < control_count; i++)
  2104. {
  2105. element_values = control_data[i].element_values;
  2106. if ((intptr_t) element_values[CONTROL_CONTAINER_TYPE].parsed_value == SWITCH &&
  2107. strcmp ((char *) switch_data->element_values[SWITCH_NAME].parsed_value,
  2108. (char *) element_values[CONTROL_CONTAINER_NAME].parsed_value) == 0)
  2109. {
  2110. ProcessControl ((XtPointer) switch_data, SWITCH,
  2111. &(switch_data->control_data),
  2112. &switch_control_count, element_values);
  2113. }
  2114. }
  2115. switch_data->control_data_count = switch_control_count;
  2116. }
  2117. /************************************************************************
  2118. *
  2119. * CreateComponentFileName
  2120. * Create a file name in which to store a component file. This is
  2121. * accomplished by using the components name with an integer value
  2122. * appended.
  2123. *
  2124. * Inputs: record_data - a pointer to the struture that contains the
  2125. * components name, as well as other values.
  2126. *
  2127. ************************************************************************/
  2128. static char *
  2129. CreateComponentFileName (RecordData * record_data)
  2130. {
  2131. char * file_name;
  2132. char * component_name;
  2133. struct stat stat_info;
  2134. int i;
  2135. component_name = XtMalloc(9);
  2136. strncpy (component_name, record_data->element_values[0].string_value, 8);
  2137. component_name[8] = '\0';
  2138. file_name = XtMalloc (strlen (HOME_DIR) + strlen (TYPES_DIR) + 14);
  2139. for (i = 1; i < 1000; i++)
  2140. {
  2141. sprintf(file_name, "%s%s%s%d.fp", HOME_DIR, TYPES_DIR, component_name, i);
  2142. if (lstat (file_name, &stat_info) != 0)
  2143. break;
  2144. }
  2145. XtFree(component_name);
  2146. return (file_name);
  2147. }
  2148. /************************************************************************
  2149. *
  2150. * WriteComponentToFile
  2151. * Write a component (contained within record_data) to a .fp file.
  2152. *
  2153. * Inputs: record_data - a pointer to the data for the component,
  2154. * including its element values.
  2155. * record_type - the type of component (CONTROL, SUBPANEL, ...)
  2156. * keywords - the ordered array of keywords for the component
  2157. * type, used to reference into the element values array.
  2158. * container_name - the parent of the component.
  2159. * container_type - the type of parent of the component.
  2160. * delete - whether the component is be added or deleted.
  2161. *
  2162. ************************************************************************/
  2163. static void
  2164. WriteComponentToFile (RecordData * record_data,
  2165. int record_type,
  2166. char ** keywords,
  2167. char * container_name,
  2168. int container_type,
  2169. Boolean delete)
  2170. {
  2171. FILE * fd;
  2172. char * file_name = CreateComponentFileName (record_data);
  2173. int k;
  2174. if ((fd = fopen(file_name, "w")) != NULL)
  2175. {
  2176. fprintf (fd, "%s %s\n{\n", keywords[0],
  2177. record_data->element_values[0].string_value);
  2178. if (delete)
  2179. {
  2180. if (record_type == CONTROL)
  2181. {
  2182. fprintf(fd, " TYPE %s\n",
  2183. record_data->element_values[CONTROL_TYPE].string_value);
  2184. fprintf(fd, " CONTAINER_TYPE %s\n",
  2185. record_data->element_values[CONTROL_CONTAINER_TYPE].string_value);
  2186. }
  2187. fprintf(fd, " CONTAINER_NAME %s\n", container_name);
  2188. fprintf(fd, " DELETE True\n");
  2189. }
  2190. else
  2191. {
  2192. for (k = 1; k < record_descriptor[record_type].maxFields; k++)
  2193. {
  2194. if (record_data->element_values[k].string_value != NULL &&
  2195. record_data->element_values[k].use_default == False)
  2196. {
  2197. if (record_type == CONTROL &&
  2198. (intptr_t) record_data->element_values[CONTROL_TYPE].parsed_value == CONTROL_FILE &&
  2199. (k == CONTROL_PUSH_ACTION ||
  2200. k == CONTROL_LABEL || k == CONTROL_DROP_ACTION))
  2201. continue;
  2202. fprintf (fd, " %s %s\n", keywords[k],
  2203. record_data->element_values[k].string_value);
  2204. }
  2205. }
  2206. }
  2207. fprintf(fd, "}\n");
  2208. fflush(fd);
  2209. fclose(fd);
  2210. if (record_type == CONTROL)
  2211. SessionAddFileData(file_name,
  2212. record_data->element_values[CONTROL_NAME].string_value,
  2213. (int) CONTROL,
  2214. container_name, container_type, delete);
  2215. else
  2216. SessionAddFileData(file_name,
  2217. record_data->element_values[0].string_value,
  2218. record_type, container_name, container_type,delete);
  2219. }
  2220. WmFrontPanelSessionSaveData ();
  2221. XtFree (file_name);
  2222. }
  2223. /************************************************************************
  2224. *
  2225. * RemoveComponentFile
  2226. * Find the dynamic .fp file name of a file in the session data and
  2227. * unlink the file to remove the component. If no file name is
  2228. * found or the unlink fails, Call a function to write a .fp for
  2229. * the file which will have the DELETE keyword set to True.
  2230. *
  2231. ************************************************************************/
  2232. static void
  2233. RemoveComponentFile (RecordData * record_data,
  2234. int record_type,
  2235. char ** keywords,
  2236. char * container_name,
  2237. int container_type)
  2238. {
  2239. char * file_name;
  2240. file_name =
  2241. SessionFileNameLookup (record_data->element_values[0].string_value,
  2242. record_type, container_name, container_type);
  2243. if (file_name == NULL || unlink (file_name) < 0)
  2244. WriteComponentToFile (record_data, record_type, keywords,
  2245. container_name, container_type, True);
  2246. else
  2247. {
  2248. SessionDeleteFileData (file_name);
  2249. WmFrontPanelSessionSaveData ();
  2250. }
  2251. }
  2252. /************************************************************************
  2253. *
  2254. * WriteControlComponentFile
  2255. * Set up the parameters to call a function which will write out
  2256. * to a .fp file a control description.
  2257. *
  2258. * Inputs: control_data - a pointer to the control to be written.
  2259. *
  2260. ************************************************************************/
  2261. void
  2262. WriteControlComponentFile (ControlData * control_data)
  2263. {
  2264. ElementValue * element_values;
  2265. element_values = control_data->element_values;
  2266. WriteComponentToFile ((RecordData *) control_data, CONTROL, control_keywords,
  2267. (char *) element_values[CONTROL_CONTAINER_NAME].parsed_value,
  2268. (int) (intptr_t) element_values[CONTROL_CONTAINER_TYPE].parsed_value,
  2269. False);
  2270. }
  2271. /************************************************************************
  2272. *
  2273. * WriteSubpanelComponentFile
  2274. * Set up the parameters to call a function which will write out
  2275. * to a .fp file a subpanel description.
  2276. *
  2277. * Inputs: subpanel_data - a pointer to the subpanel to be written.
  2278. *
  2279. ************************************************************************/
  2280. void
  2281. WriteSubpanelComponentFile (SubpanelData * subpanel_data)
  2282. {
  2283. ElementValue * element_values = subpanel_data->element_values;
  2284. WriteComponentToFile ((RecordData *) subpanel_data, SUBPANEL, subpanel_keywords,
  2285. (char *) element_values[SUBPANEL_CONTAINER_NAME].parsed_value,
  2286. CONTROL, False);
  2287. }
  2288. /************************************************************************
  2289. *
  2290. * RemoveControlComponentFile
  2291. * Set up the parameters to call a function which delete a control's
  2292. * .fp file.
  2293. *
  2294. * Inputs: control_data - a pointer to the control to be deleted.
  2295. *
  2296. ************************************************************************/
  2297. void
  2298. RemoveControlComponentFile (ControlData * control_data)
  2299. {
  2300. ElementValue * element_values = control_data->element_values;
  2301. RemoveComponentFile ((RecordData *) control_data, CONTROL, control_keywords,
  2302. (char *) element_values[CONTROL_CONTAINER_NAME].parsed_value,
  2303. (int) (intptr_t) element_values[CONTROL_CONTAINER_TYPE].parsed_value);
  2304. }
  2305. /************************************************************************
  2306. *
  2307. * RemoveSubpanelComponentFile
  2308. * Set up the parameters to call a function which delete a subpanel's
  2309. * .fp file.
  2310. *
  2311. * Inputs: subpanel_data - a pointer to the subpanel to be deleted.
  2312. *
  2313. ************************************************************************/
  2314. void
  2315. RemoveSubpanelComponentFile (SubpanelData * subpanel_data)
  2316. {
  2317. ElementValue * element_values = subpanel_data->element_values;
  2318. RemoveComponentFile ((RecordData *) subpanel_data, SUBPANEL, subpanel_keywords,
  2319. (char *) element_values[SUBPANEL_CONTAINER_NAME].parsed_value,
  2320. CONTROL);
  2321. }
  2322. /************************************************************************
  2323. *
  2324. * _WriteControlElementValues
  2325. * Set up a loop which write out all of the values that define
  2326. * a control. These are written as normal keyword, value pairs.
  2327. *
  2328. * Inputs: element_values - a pointer to the array of element value
  2329. * strutures each of which contain a value for a keyword.
  2330. *
  2331. ************************************************************************/
  2332. void
  2333. _WriteControlElementValues (ElementValue * element_values)
  2334. {
  2335. int k;
  2336. printf("%s %s\n{\n", control_keywords[0], element_values[0].string_value);
  2337. for (k = 1; k < record_descriptor[CONTROL].maxFields; k++)
  2338. {
  2339. if (element_values[k].string_value != NULL)
  2340. printf(" %s %s\n",
  2341. control_keywords[k], element_values[k].string_value);
  2342. }
  2343. printf("}\n");
  2344. }
  2345. /************************************************************************
  2346. *
  2347. * InitParse
  2348. *
  2349. ************************************************************************/
  2350. void
  2351. InitParse (char * file_name,
  2352. ElementValue ** elem_vals)
  2353. {
  2354. char * tmpPath;
  2355. char * tmpDir;
  2356. char * hostName;
  2357. char * tmpName;
  2358. char * baseName;
  2359. char * tmpFile;
  2360. DtDirPaths * dirPath;
  2361. /* create directory for dir path */
  2362. tmpPath = XtMalloc (strlen(HOME_DIR) + strlen(TYPES_DIR) + 34);
  2363. sprintf (tmpPath, "%s%s%s%d", HOME_DIR, TYPES_DIR, "fp", (int) getpid());
  2364. mkdir (tmpPath, S_IRUSR | S_IWUSR | S_IXUSR);
  2365. /* create symbolic link to file_name */
  2366. tmpName = XtNewString(file_name);
  2367. baseName = strrchr(tmpName, '/');
  2368. tmpFile = XtMalloc(strlen(tmpPath) + strlen(baseName) + 1);
  2369. sprintf(tmpFile, "%s%s", tmpPath, baseName);
  2370. symlink(file_name, tmpFile);
  2371. hostName = XtMalloc((Cardinal)(MAXHOSTNAMELEN + 1));
  2372. DtGetShortHostname (hostName, MAXHOSTNAMELEN + 1);
  2373. tmpDir = XtMalloc(strlen(hostName) + strlen(tmpPath) + 2);
  2374. sprintf(tmpDir, "%s:%s", hostName, tmpPath);
  2375. dirPath = (DtDirPaths *) XtMalloc(sizeof(DtDirPaths));
  2376. dirPath->dirs = (char **) XtMalloc(sizeof(char *) * 2);
  2377. dirPath->paths = (char **) XtMalloc(sizeof(char *) * 2);
  2378. dirPath->dirs[0] = tmpDir;
  2379. dirPath->dirs[1] = NULL;
  2380. dirPath->paths[0] = tmpPath;
  2381. dirPath->paths[1] = NULL;
  2382. _DtDbRead (dirPath, FILE_TYPE_SUFFIX, control_record_descriptor, 2);
  2383. control_element_value_found = False;
  2384. /* remove link and directory */
  2385. unlink(tmpFile);
  2386. rmdir(tmpPath);
  2387. XtFree((char *) dirPath->dirs);
  2388. XtFree((char *) dirPath->paths);
  2389. XtFree((char *) dirPath);
  2390. XtFree(hostName);
  2391. XtFree(tmpName);
  2392. XtFree(tmpDir);
  2393. XtFree(tmpPath);
  2394. XtFree(tmpFile);
  2395. *elem_vals = control_element_values;
  2396. }
  2397. /************************************************************************
  2398. *
  2399. * FreeFileControlField
  2400. *
  2401. ************************************************************************/
  2402. static void
  2403. FreeFileControlField (ElementValue * element_values,
  2404. int indx)
  2405. {
  2406. if (control_parse_functions[indx].free_function != NULL &&
  2407. element_values[indx].parsed_value != NULL &&
  2408. element_values[indx].use_default == False)
  2409. {
  2410. (*(control_parse_functions[indx].free_function))
  2411. (&(element_values[indx].parsed_value));
  2412. element_values[indx].parsed_value = NULL;
  2413. }
  2414. if (element_values[indx].use_default == False &&
  2415. element_values[indx].string_value != NULL)
  2416. {
  2417. free(element_values[indx].string_value);
  2418. element_values[indx].string_value = NULL;
  2419. }
  2420. }
  2421. /************************************************************************
  2422. *
  2423. * InitializePrimaryControlFields
  2424. *
  2425. ************************************************************************/
  2426. static void
  2427. InitializePrimaryControlFields (ElementValue * element_values)
  2428. {
  2429. InitializeField (element_values,
  2430. CONTROL_NAME, control_parse_functions);
  2431. InitializeField (element_values,
  2432. CONTROL_CONTAINER_NAME, control_parse_functions);
  2433. InitializeField (element_values,
  2434. CONTROL_CONTAINER_TYPE, control_parse_functions);
  2435. InitializeField (element_values,
  2436. CONTROL_LOCKED, control_parse_functions);
  2437. InitializeField (element_values,
  2438. CONTROL_DELETE, control_parse_functions);
  2439. }
  2440. /************************************************************************
  2441. *
  2442. * InitializeSecondaryControlFields
  2443. *
  2444. ************************************************************************/
  2445. static void
  2446. InitializeSecondaryControlFields (ElementValue * element_values)
  2447. {
  2448. InitializeField (element_values,
  2449. CONTROL_TYPE, control_parse_functions);
  2450. InitializeField (element_values,
  2451. CONTROL_POSITION_HINTS, control_parse_functions);
  2452. InitializeField (element_values,
  2453. CONTROL_ALTERNATE_ICON, control_parse_functions);
  2454. InitializeField (element_values,
  2455. CONTROL_PUSH_ANIMATION, control_parse_functions);
  2456. InitializeField (element_values,
  2457. CONTROL_DROP_ANIMATION, control_parse_functions);
  2458. InitializeField (element_values,
  2459. CONTROL_PUSH_RECALL, control_parse_functions);
  2460. InitializeField (element_values,
  2461. CONTROL_MONITOR_TYPE, control_parse_functions);
  2462. InitializeField (element_values,
  2463. CONTROL_CLIENT_NAME, control_parse_functions);
  2464. InitializeField (element_values,
  2465. CONTROL_CLIENT_GEOMETRY, control_parse_functions);
  2466. InitializeField (element_values,
  2467. CONTROL_FILE_NAME, control_parse_functions);
  2468. InitializeField (element_values,
  2469. CONTROL_DATE_FORMAT, control_parse_functions);
  2470. InitializeField (element_values,
  2471. CONTROL_HELP_STRING, control_parse_functions);
  2472. InitializeField (element_values,
  2473. CONTROL_HELP_VOLUME, control_parse_functions);
  2474. InitializeField (element_values,
  2475. CONTROL_HELP_TOPIC, control_parse_functions);
  2476. }
  2477. /************************************************************************
  2478. *
  2479. * InitializeFileControlFields
  2480. *
  2481. ************************************************************************/
  2482. static void
  2483. InitializeFileControlFields (ElementValue * element_values,
  2484. char * data_type)
  2485. {
  2486. if ((intptr_t)element_values[CONTROL_TYPE].parsed_value == CONTROL_FILE)
  2487. {
  2488. Boolean free_data_type = False;
  2489. char * act_list;
  2490. char ** action_list = NULL;
  2491. char * icon_name;
  2492. char * file_name;
  2493. char * description;
  2494. char * file_str;
  2495. char * label = NULL;
  2496. int i, j, result;
  2497. struct stat stat_info;
  2498. Boolean valid_file = True;
  2499. file_name = (char *) element_values[CONTROL_FILE_NAME].parsed_value;
  2500. if (lstat (file_name, &stat_info) != 0)
  2501. valid_file = False;
  2502. if (data_type == NULL && file_name != NULL)
  2503. {
  2504. data_type = DtDtsFileToDataType (file_name);
  2505. free_data_type = True;
  2506. }
  2507. if (data_type != NULL)
  2508. {
  2509. if (valid_file)
  2510. {
  2511. icon_name = DtDtsDataTypeToAttributeValue (data_type,
  2512. DtDTS_DA_ICON, NULL);
  2513. if (element_values[CONTROL_NORMAL_ICON].string_value != NULL)
  2514. {
  2515. XtFree (element_values[CONTROL_NORMAL_ICON].string_value);
  2516. element_values[CONTROL_NORMAL_ICON].string_value = NULL;
  2517. }
  2518. element_values[CONTROL_NORMAL_ICON].string_value =
  2519. XtNewString (icon_name);
  2520. DtDtsFreeAttributeValue(icon_name);
  2521. }
  2522. description =
  2523. DtDtsDataTypeToAttributeValue(data_type, DtDTS_DA_DESCRIPTION, NULL);
  2524. if (element_values[CONTROL_HELP_STRING].string_value != NULL)
  2525. {
  2526. XtFree (element_values[CONTROL_HELP_STRING].string_value);
  2527. element_values[CONTROL_HELP_STRING].string_value = NULL;
  2528. }
  2529. element_values[CONTROL_HELP_STRING].string_value = XtNewString (description);
  2530. DtDtsFreeAttributeValue (description);
  2531. act_list = DtDtsDataTypeToAttributeValue (data_type,
  2532. DtDTS_DA_ACTION_LIST,
  2533. NULL);
  2534. if (act_list)
  2535. action_list = _DtVectorizeInPlace (act_list, ',');
  2536. if (action_list && action_list[0] != NULL)
  2537. {
  2538. element_values[CONTROL_PUSH_ACTION].string_value =
  2539. strdup (action_list[0]);
  2540. element_values[CONTROL_DROP_ACTION].string_value =
  2541. strdup (action_list[0]);
  2542. if (DtDtsDataTypeIsAction (data_type))
  2543. label = DtActionLabel (action_list[0]);
  2544. }
  2545. /* try to set it to the name of the type */
  2546. if (label == NULL) {
  2547. label = DtDtsDataTypeToAttributeValue (data_type,
  2548. DtDTS_DA_LABEL, NULL);
  2549. /* copy & correctly free the memory */
  2550. if (label) {
  2551. char *t = label;
  2552. label = XtNewString(t);
  2553. DtDtsFreeAttributeValue(t);
  2554. }
  2555. }
  2556. if (label == NULL && file_name != NULL)
  2557. {
  2558. if ((file_str = (char *)strrchr(file_name, '/')) == NULL)
  2559. file_str = file_name;
  2560. else
  2561. file_str++;
  2562. label = XtNewString(file_str);
  2563. }
  2564. if (label != NULL)
  2565. element_values[CONTROL_LABEL].string_value = label;
  2566. if (data_type != NULL)
  2567. {
  2568. if (act_list)
  2569. {
  2570. DtDtsFreeAttributeValue (act_list);
  2571. XtFree ((char *) action_list);
  2572. }
  2573. if (free_data_type)
  2574. DtDtsFreeDataType (data_type);
  2575. }
  2576. }
  2577. }
  2578. InitializeField (element_values,
  2579. CONTROL_NORMAL_ICON, control_parse_functions);
  2580. InitializeField (element_values,
  2581. CONTROL_HELP_STRING, control_parse_functions);
  2582. InitializeField (element_values,
  2583. CONTROL_LABEL, control_parse_functions);
  2584. InitializeField (element_values,
  2585. CONTROL_PUSH_ACTION, control_parse_functions);
  2586. InitializeField (element_values,
  2587. CONTROL_DROP_ACTION, control_parse_functions);
  2588. }
  2589. /************************************************************************
  2590. *
  2591. * InitializeControlFields
  2592. *
  2593. ************************************************************************/
  2594. void
  2595. InitializeControlFields (ElementValue * element_values,
  2596. char * data_type)
  2597. {
  2598. InitializePrimaryControlFields (element_values);
  2599. InitializeSecondaryControlFields (element_values);
  2600. InitializeFileControlFields (element_values, data_type);
  2601. }
  2602. /************************************************************************
  2603. *
  2604. * UpdateFileType
  2605. *
  2606. ************************************************************************/
  2607. static void
  2608. UpdateFileType (ControlData * control_data)
  2609. {
  2610. char * icon_name;
  2611. char * control_label;
  2612. XmString icon_label;
  2613. Arg al[2];
  2614. FreeFileControlField (control_data->element_values, CONTROL_NORMAL_ICON);
  2615. FreeFileControlField (control_data->element_values, CONTROL_PUSH_ACTION);
  2616. FreeFileControlField (control_data->element_values, CONTROL_DROP_ACTION);
  2617. FreeFileControlField (control_data->element_values, CONTROL_LABEL);
  2618. InitializeFileControlFields (control_data->element_values, NULL);
  2619. DeleteControlActionList (control_data);
  2620. AddControlActionList (control_data);
  2621. icon_name =
  2622. (char *)control_data->element_values[CONTROL_NORMAL_ICON].parsed_value;
  2623. if ((intptr_t)control_data->element_values[CONTROL_CONTAINER_TYPE].parsed_value ==
  2624. SUBPANEL)
  2625. {
  2626. icon_name = GetIconName (icon_name, panel.sub_icon_size);
  2627. }
  2628. else
  2629. {
  2630. icon_name = GetIconName (icon_name, panel.main_icon_size);
  2631. if (icon_name == NULL)
  2632. icon_name = GetIconName (icon_name, panel.sub_icon_size);
  2633. }
  2634. control_label = (char *)
  2635. control_data->element_values[CONTROL_LABEL].parsed_value;
  2636. icon_label = XmStringCreateLocalized (control_label);
  2637. XtSetArg(al[0], XmNimageName, icon_name);
  2638. XtSetArg(al[1], XmNstring, icon_label);
  2639. XtSetValues(control_data->icon, al, 2);
  2640. }
  2641. /************************************************************************
  2642. *
  2643. * UpdateFileTypeControlFields
  2644. *
  2645. ************************************************************************/
  2646. void
  2647. UpdateFileTypeControlFields (void)
  2648. {
  2649. BoxData * box_data;
  2650. ControlData * control_data;
  2651. SubpanelData * subpanel_data;
  2652. SwitchData * switch_data;
  2653. int i, j, k;
  2654. if (panel_count == 0) return;
  2655. for (i = 0; i < panel.box_data_count; i++)
  2656. {
  2657. box_data = panel.box_data[i];
  2658. for (j = 0; j < box_data->control_data_count; j++)
  2659. {
  2660. control_data = box_data->control_data[j];
  2661. if ((intptr_t)control_data->element_values[CONTROL_TYPE].parsed_value ==
  2662. CONTROL_FILE)
  2663. UpdateFileType(control_data);
  2664. if (control_data->subpanel_data != NULL)
  2665. {
  2666. subpanel_data = control_data->subpanel_data;
  2667. for (k = 0; k < subpanel_data->control_data_count; k++)
  2668. {
  2669. control_data = subpanel_data->control_data[k];
  2670. if ((intptr_t)control_data->element_values[CONTROL_TYPE].parsed_value
  2671. == CONTROL_FILE)
  2672. UpdateFileType(control_data);
  2673. }
  2674. }
  2675. }
  2676. if (box_data->switch_data != NULL)
  2677. {
  2678. switch_data = box_data->switch_data;
  2679. for (j = 0; j < switch_data->control_data_count; j++)
  2680. {
  2681. control_data = switch_data->control_data[j];
  2682. if ((intptr_t)control_data->element_values[CONTROL_TYPE].parsed_value ==
  2683. CONTROL_FILE)
  2684. UpdateFileType(control_data);
  2685. }
  2686. }
  2687. }
  2688. }
  2689. /************************************************************************
  2690. *
  2691. * InitializeSubpanelFields
  2692. *
  2693. ************************************************************************/
  2694. void
  2695. InitializeSubpanelFields (ElementValue * element_values)
  2696. {
  2697. InitializeField (element_values,
  2698. SUBPANEL_NAME, subpanel_parse_functions);
  2699. InitializeField (element_values,
  2700. SUBPANEL_CONTAINER_NAME, subpanel_parse_functions);
  2701. InitializeField (element_values,
  2702. SUBPANEL_LOCKED, subpanel_parse_functions);
  2703. InitializeField (element_values,
  2704. SUBPANEL_CONTROL_INSTALL, subpanel_parse_functions);
  2705. InitializeField (element_values,
  2706. SUBPANEL_TITLE, subpanel_parse_functions);
  2707. InitializeField (element_values,
  2708. SUBPANEL_DELETE, subpanel_parse_functions);
  2709. InitializeField (element_values,
  2710. SUBPANEL_HELP_STRING, subpanel_parse_functions);
  2711. InitializeField (element_values,
  2712. SUBPANEL_HELP_TOPIC, subpanel_parse_functions);
  2713. InitializeField (element_values,
  2714. SUBPANEL_HELP_VOLUME, subpanel_parse_functions);
  2715. }