addToRes.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  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. * (c) Copyright 1993, 1994 Hewlett-Packard Company *
  25. * (c) Copyright 1993, 1994 International Business Machines Corp. *
  26. * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
  27. * (c) Copyright 1993, 1994 Novell, Inc. *
  28. */
  29. /*Add a string to the XA_RESOURCE_MANAGER*/
  30. /*
  31. * COPYRIGHT 1987
  32. * DIGITAL EQUIPMENT CORPORATION
  33. * MAYNARD, MASSACHUSETTS
  34. * ALL RIGHTS RESERVED.
  35. *
  36. * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
  37. * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
  38. * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR
  39. * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
  40. *
  41. * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS,
  42. * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT
  43. * SET FORTH ABOVE.
  44. *
  45. *
  46. * Permission to use, copy, modify, and distribute this software and its
  47. * documentation for any purpose and without fee is hereby granted, provided
  48. * that the above copyright notice appear in all copies and that both that
  49. * copyright notice and this permission notice appear in supporting
  50. * documentation, and that the name of Digital Equipment Corporation not be
  51. * used in advertising or publicity pertaining to distribution of the software
  52. * without specific, written prior permission.
  53. */
  54. /*Lifted from xrdb(1X)*/
  55. /* -*-C-*-
  56. *******************************************************************************
  57. *
  58. * File: addToResource.c
  59. * RCS: $TOG: addToRes.c /main/8 1999/10/14 16:01:17 mgreess $
  60. * Description: Source code for adding strings to RESOURCE_PROPERTY on
  61. default root window
  62. * Author: DEC, Robert Williams
  63. * Created: Thu Apr 26 14:42:08 PDT 1990
  64. * Modified: Kim Dronesen
  65. * Language: C
  66. * Package: N/A
  67. * Status: Experimental (Do Not Distribute)
  68. *
  69. * (C) Copyright 1990, Hewlett-Packard, all rights reserved.
  70. *
  71. *******************************************************************************
  72. */
  73. /*$TOG: addToRes.c /main/8 1999/10/14 16:01:17 mgreess $ */
  74. #include <X11/Xlib.h>
  75. #include <X11/Xatom.h>
  76. #include <X11/Xos.h>
  77. #include <stdio.h>
  78. #include <stdlib.h>
  79. #include <ctype.h>
  80. #include <Dt/DtP.h>
  81. #include <Dt/SessionM.h>
  82. #include "DtSvcLock.h"
  83. /****************************************/
  84. /* Global variables */
  85. /****************************************/
  86. typedef struct _Entry {
  87. char *tag, *value;
  88. int lineno;
  89. Bool usable;
  90. } Entry;
  91. typedef struct _Buffer {
  92. char *buff;
  93. int room, used;
  94. Bool freebuff;
  95. } Buffer;
  96. typedef struct _Entries {
  97. Entry *entry;
  98. int room, used;
  99. } Entries;
  100. #define INIT_BUFFER_SIZE 10000
  101. #define INIT_ENTRY_SIZE 500
  102. /******** Public Function Declarations ********/
  103. static Buffer * _DtAllocBuffer(const char **buff);
  104. static void _DtFreeBuffer(Buffer *b);
  105. static void _DtAppendToBuffer(
  106. Buffer *b,
  107. char *str,
  108. int len) ;
  109. static void _DtAppendEntryToBuffer(
  110. Buffer *buffer,
  111. Entry entry) ;
  112. static Entries * _DtAllocEntries( void) ;
  113. static void _DtFreeEntries( Entries *) ;
  114. static void _DtAddEntry(
  115. Entries *e,
  116. Entry entry) ;
  117. static int _DtCompareEntries(
  118. Entry *e1,
  119. Entry *e2) ;
  120. static char * _DtFindFirst(
  121. char *string,
  122. char dest) ;
  123. static void _DtGetEntries(
  124. Entries *entries,
  125. Buffer *buff,
  126. int dosort) ;
  127. static void _DtMergeEntries(
  128. Buffer *buffer,
  129. Entries new,
  130. Entries old) ;
  131. static void _DtAddToResProp(
  132. Display *dpy,
  133. unsigned int id,
  134. Entries db) ;
  135. static void _getWinProp(
  136. Display *dpy,
  137. unsigned int id,
  138. Window *win,
  139. Atom *prop);
  140. /******** End Public Function Declarations ********/
  141. /****************************************/
  142. /*The meat*/
  143. /****************************************/
  144. static Buffer *
  145. _DtAllocBuffer(
  146. const char **buff )
  147. {
  148. Buffer *b = (Buffer *)malloc(sizeof(Buffer));
  149. b->room = INIT_BUFFER_SIZE;
  150. b->buff = buff ? (char*) *buff :
  151. (char *)malloc(INIT_BUFFER_SIZE*sizeof(char));
  152. b->used = buff && *buff ? strlen(*buff) : 0;
  153. b->freebuff = buff ? False : True;
  154. return(b);
  155. }
  156. static void
  157. _DtFreeBuffer(
  158. Buffer *b)
  159. {
  160. if (b->freebuff == True) free(b->buff);
  161. free(b);
  162. }
  163. static void
  164. _DtAppendToBuffer(
  165. Buffer *b,
  166. char *str,
  167. int len )
  168. {
  169. while (b->used + len > b->room) {
  170. b->buff = (char *)realloc(b->buff, 2*b->room*(sizeof(char)));
  171. b->room *= 2;
  172. }
  173. strncpy(b->buff + b->used, str, len);
  174. b->used += len;
  175. }
  176. static Entries *
  177. _DtAllocEntries( void )
  178. {
  179. Entries *e = (Entries *)malloc(sizeof(Entries));
  180. e->room = INIT_ENTRY_SIZE;
  181. e->used = 0;
  182. e->entry = (Entry *)malloc(INIT_ENTRY_SIZE*sizeof(Entry));
  183. return(e);
  184. }
  185. static void
  186. _DtFreeEntries(
  187. Entries *e)
  188. {
  189. int n = 0;
  190. while (n < e->used)
  191. {
  192. free(e->entry[n].tag);
  193. free(e->entry[n].value);
  194. n++;
  195. }
  196. free(e->entry);
  197. free(e);
  198. }
  199. static void
  200. _DtAddEntry(
  201. Entries *e,
  202. Entry entry )
  203. {
  204. int n;
  205. for (n = 0; n < e->used; n++)
  206. {
  207. if (strcmp(e->entry[n].tag, entry.tag) == 0)
  208. { /* overwrite old entry - free its memory first*/
  209. free(e->entry[n].tag);
  210. free(e->entry[n].value);
  211. e->entry[n] = entry;
  212. return ; /* ok to leave, now there's only one of each tag in db */
  213. }
  214. }
  215. if (e->used == e->room) {
  216. e->entry = (Entry *)realloc(e->entry, 2*e->room*(sizeof(Entry)));
  217. e->room *= 2;
  218. }
  219. entry.usable = True;
  220. e->entry[e->used++] = entry;
  221. }
  222. static int
  223. _DtCompareEntries(
  224. Entry *e1,
  225. Entry *e2 )
  226. {
  227. return strcmp(e1->tag, e2->tag);
  228. }
  229. static void
  230. _DtAppendEntryToBuffer(
  231. Buffer *buffer,
  232. Entry entry )
  233. {
  234. _DtAppendToBuffer(buffer, entry.tag, strlen(entry.tag));
  235. _DtAppendToBuffer(buffer, ":\t", 2);
  236. _DtAppendToBuffer(buffer, entry.value, strlen(entry.value));
  237. _DtAppendToBuffer(buffer, "\n", 1);
  238. }
  239. static char *
  240. _DtFindFirst(
  241. char *string,
  242. char dest )
  243. {
  244. int len;
  245. for (;;) {
  246. if((len = mblen(string, MB_CUR_MAX)) > 1) {
  247. string += len;
  248. continue;
  249. }
  250. if (*string == '\0')
  251. return NULL;
  252. if (*string == '\\') {
  253. if (*++string == '\0')
  254. return NULL;
  255. }
  256. else if (*string == dest)
  257. return string;
  258. string++;
  259. }
  260. }
  261. static void
  262. _DtGetEntries(
  263. Entries *entries,
  264. Buffer *buff,
  265. int dosort )
  266. {
  267. char *line, *colon, *temp, *str, *temp2;
  268. Entry entry;
  269. int length;
  270. int lineno = 0;
  271. str = buff->buff;
  272. if (!str) return;
  273. for (; str < buff->buff + buff->used; str = line + 1)
  274. {
  275. line = _DtFindFirst(str, '\n');
  276. lineno++;
  277. if (line == NULL)
  278. break;
  279. if (str[0] == '!')
  280. continue;
  281. if (str[0] == '\n')
  282. continue;
  283. if (str[0] == '#')
  284. {
  285. int dummy;
  286. if (sscanf (str, "# %d", &dummy) == 1) lineno = dummy - 1;
  287. continue;
  288. }
  289. for (temp = str;
  290. *temp && *temp != '\n' && isascii(*temp) && isspace((u_char)*temp);
  291. temp++) ;
  292. if (!*temp || *temp == '\n') continue;
  293. colon = _DtFindFirst(str, ':');
  294. if (colon == NULL)
  295. break;
  296. if (colon > line)
  297. {
  298. line[0] = '\0';
  299. fprintf (stderr,
  300. "%s: colon missing on line %d, ignoring entry \"%s\"\n",
  301. "dtprefs", lineno, str);
  302. continue;
  303. }
  304. temp2 = str;
  305. while (temp2[0] == ' ' || temp2[0] == '\t')
  306. {
  307. temp2++;
  308. }
  309. temp = (char *)malloc((length = colon - temp2) + 1);
  310. strncpy(temp, temp2, length);
  311. temp[length] = '\0';
  312. while (temp[length-1] == ' ' || temp[length-1] == '\t')
  313. temp[--length] = '\0';
  314. entry.tag = temp;
  315. temp2 = colon + 1;
  316. while (temp2[0] == ' ' || temp2[0] == '\t')
  317. {
  318. temp2++;
  319. }
  320. temp = (char *)malloc((length = line - temp2) + 1);
  321. strncpy(temp, temp2, length);
  322. temp[length] = '\0';
  323. entry.value = temp;
  324. entry.lineno = lineno;
  325. _DtAddEntry(entries, entry);
  326. }
  327. if (dosort && (entries->used > 0))
  328. qsort(entries->entry, entries->used, sizeof(Entry),
  329. (int (*)(const void *, const void *))_DtCompareEntries);
  330. }
  331. static void
  332. _DtMergeEntries(
  333. Buffer *buffer,
  334. Entries new,
  335. Entries old )
  336. {
  337. int n, o, cmp;
  338. buffer->used = 0;
  339. n = o = 0;
  340. while ((n < new.used) && (o < old.used))
  341. {
  342. cmp = strcmp(new.entry[n].tag, old.entry[o].tag);
  343. if (cmp > 0)
  344. {
  345. _DtAppendEntryToBuffer(buffer, old.entry[o]);
  346. o++;
  347. }
  348. else
  349. {
  350. _DtAppendEntryToBuffer(buffer, new.entry[n]);
  351. n++;
  352. if (cmp == 0)
  353. {
  354. o++;
  355. }
  356. }
  357. }
  358. while (n < new.used)
  359. {
  360. _DtAppendEntryToBuffer(buffer, new.entry[n]);
  361. n++;
  362. }
  363. while (o < old.used)
  364. {
  365. _DtAppendEntryToBuffer(buffer, old.entry[o]);
  366. o++;
  367. }
  368. _DtAppendToBuffer(buffer, "\0", 1);
  369. }
  370. static void
  371. _getWinProp(
  372. Display *dpy,
  373. unsigned int id,
  374. Window *win,
  375. Atom *prop)
  376. {
  377. static Bool init = True;
  378. static Window winprop;
  379. static Atom xa_resmgr;
  380. static Atom xa_prefs;
  381. _DtSvcProcessLock();
  382. if (init == True)
  383. {
  384. winprop = XRootWindow(dpy, 0);
  385. xa_resmgr = XA_RESOURCE_MANAGER;
  386. xa_prefs = XInternAtom (dpy, _XA_DT_SM_PREFERENCES, False);
  387. init = False;
  388. }
  389. _DtSvcProcessUnlock();
  390. *win = winprop;
  391. *prop = id == _DT_ATR_RESMGR ? xa_resmgr : xa_prefs;
  392. }
  393. static void
  394. _DtAddToResProp(
  395. Display *dpy,
  396. unsigned int id,
  397. Entries db)
  398. {
  399. char *xdefs;
  400. Buffer *oldBuffer, *newBuffer;
  401. Entries *oldDB;
  402. int defStatus;
  403. Atom actualType;
  404. int actualFormat;
  405. unsigned long nitems, leftover;
  406. Window win;
  407. Atom prop;
  408. /*
  409. * Get window and property
  410. */
  411. _getWinProp(dpy, id, &win, &prop);
  412. if (win == (Window)0)
  413. {
  414. return;
  415. }
  416. /*
  417. * Get resource database from specified window and property.
  418. */
  419. defStatus = XGetWindowProperty(dpy, win,
  420. prop, 0L,
  421. 100000000L,False,XA_STRING,&actualType,
  422. &actualFormat,&nitems,&leftover,
  423. (unsigned char**) &xdefs);
  424. /*
  425. * Allocate oldBuffer and init from resource database string
  426. */
  427. oldBuffer = _DtAllocBuffer((const char**) &xdefs);
  428. /*
  429. * Allocate oldDB
  430. */
  431. oldDB = _DtAllocEntries();
  432. /*
  433. * Convert oldBuffer to oldDB.
  434. */
  435. _DtGetEntries(oldDB, oldBuffer, 1);
  436. /*
  437. * Init empty newBuffer, then populate by merging db into oldDB.
  438. */
  439. newBuffer = _DtAllocBuffer(NULL);
  440. _DtMergeEntries(newBuffer, db, *oldDB);
  441. /*
  442. * Finally, store newBuffer into resource database.
  443. */
  444. XChangeProperty (dpy, win, prop,
  445. XA_STRING, 8, PropModeReplace,
  446. (unsigned char *)newBuffer->buff, newBuffer->used);
  447. XSync(dpy, False);
  448. /*
  449. * Free buffer memory
  450. */
  451. if (oldBuffer->buff) XFree(oldBuffer->buff);
  452. _DtFreeBuffer(oldBuffer);
  453. _DtFreeBuffer(newBuffer);
  454. _DtFreeEntries(oldDB);
  455. }
  456. char *
  457. _DtGetResString(
  458. Display *dpy,
  459. unsigned int id)
  460. {
  461. char *xdefs;
  462. Buffer *oldBuffer, *newBuffer;
  463. Entries *oldDB;
  464. int defStatus;
  465. Atom actualType;
  466. int actualFormat;
  467. unsigned long nitems, leftover;
  468. Window win;
  469. Atom prop;
  470. /*
  471. * Get window and property
  472. */
  473. _getWinProp(dpy, id, &win, &prop);
  474. if (win == (Window)0)
  475. {
  476. return NULL;
  477. }
  478. /*
  479. * Get resource database from specified window and property.
  480. */
  481. defStatus = XGetWindowProperty(dpy, win,
  482. prop, 0L,
  483. 100000000L,False,XA_STRING,&actualType,
  484. &actualFormat,&nitems,&leftover,
  485. (unsigned char**) &xdefs);
  486. return(xdefs);
  487. }
  488. void
  489. _DtAddToResource(
  490. Display *dpy,
  491. const char *data )
  492. {
  493. _DtAddResString( dpy, data, _DT_ATR_RESMGR|_DT_ATR_PREFS);
  494. }
  495. void
  496. _DtAddResString(
  497. Display *dpy,
  498. const char *data,
  499. unsigned int flags)
  500. {
  501. char *xdefs;
  502. int i;
  503. Buffer *buffer;
  504. Entries *newDB;
  505. int defStatus;
  506. Atom actualType;
  507. int actualFormat;
  508. unsigned long nitems, leftover;
  509. if((data == NULL) || (*data == '\0'))
  510. {
  511. return;
  512. }
  513. /*
  514. * Init buffer with input data
  515. */
  516. buffer = _DtAllocBuffer(&data);
  517. /*
  518. * Init, then populate, newDB from buffer
  519. */
  520. newDB = _DtAllocEntries();
  521. _DtGetEntries(newDB, buffer, 1);
  522. if (flags & _DT_ATR_RESMGR)
  523. {
  524. /*
  525. * Merge newDB into RESOURCE_MANAGER
  526. */
  527. _DtAddToResProp(dpy, _DT_ATR_RESMGR, *newDB);
  528. }
  529. if (flags & _DT_ATR_PREFS)
  530. {
  531. /*
  532. * Merge newDB into _DT_SM_PREFERENCES
  533. */
  534. _DtAddToResProp(dpy, _DT_ATR_PREFS, *newDB);
  535. }
  536. /*
  537. * Free objects
  538. */
  539. _DtFreeBuffer(buffer);
  540. _DtFreeEntries(newDB);
  541. }