LinkMgr.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  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. /* $XConsortium: LinkMgr.c /main/10 1996/11/01 10:10:59 drk $ */
  24. /************************************<+>*************************************
  25. ****************************************************************************
  26. **
  27. ** File: LinkMgr.c
  28. **
  29. ** Project: Cde Help System
  30. **
  31. ** Description: Hypertext manager for the core engine of the help
  32. ** system. Processes requests from the UI to move, turn
  33. ** on, or turn off the traversal indicator, to return
  34. ** information about a hypertext link and to determine
  35. ** if a spot selected contains a hypertext link.
  36. **
  37. ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
  38. **
  39. ** (c) Copyright 1993, 1994 Hewlett-Packard Company
  40. ** (c) Copyright 1993, 1994 International Business Machines Corp.
  41. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  42. ** (c) Copyright 1993, 1994 Novell, Inc.
  43. **
  44. ****************************************************************************
  45. ************************************<+>*************************************/
  46. /*
  47. * system includes
  48. */
  49. #include <errno.h>
  50. #include <stdio.h>
  51. #include <stdlib.h>
  52. #include <string.h>
  53. #include <X11/Xos.h>
  54. #ifdef X_NOT_STDC_ENV
  55. extern int errno;
  56. #endif
  57. /*
  58. * Canvas Engine Includes
  59. */
  60. #include "CanvasP.h"
  61. /*
  62. * private includes
  63. */
  64. #include "CanvasOsI.h"
  65. #include "CvStringI.h"
  66. #include "LinkMgrI.h"
  67. #include "LinkMgrP.h"
  68. #ifdef NLS16
  69. #endif
  70. /******** Private Function Declarations ********/
  71. /******** End Private Function Declarations ********/
  72. /*****************************************************************************
  73. * Private Defines
  74. *****************************************************************************/
  75. #define GROW_SIZE 3
  76. /*****************************************************************************
  77. * Private Variables
  78. *****************************************************************************/
  79. const static struct _dtCvLinkDb DefLinkDb = { 0, NULL };
  80. /*****************************************************************************
  81. * Private Functions
  82. *****************************************************************************/
  83. /*****************************************************************************
  84. * Function: FindLink (
  85. *
  86. * Purpose:
  87. *****************************************************************************/
  88. static int
  89. FindLink (
  90. _DtCvLinkDb link_db,
  91. char *id,
  92. int *ret_no,
  93. int *ret_hint)
  94. {
  95. int result = -1;
  96. int i;
  97. for (i = 0; -1 == result && i < link_db->max; i++)
  98. {
  99. if (_DtLinkTypeNone != link_db->list[i].type
  100. && NULL != link_db->list[i].id
  101. && 0 == _DtCvStrCaseCmpLatin1(link_db->list[i].id, id))
  102. {
  103. /*
  104. * return a valid index
  105. */
  106. *ret_no = i;
  107. /*
  108. * check to see if the hint changes
  109. */
  110. if (_DtLinkTypeLink == link_db->list[i].type &&
  111. _DtCvWindowHint_Original != link_db->list[i].info.link.hint)
  112. *ret_hint = link_db->list[i].info.link.hint;
  113. /*
  114. * clear the error return
  115. */
  116. result = 0;
  117. }
  118. }
  119. return result;
  120. }
  121. /*****************************************************************************
  122. * Function: ResolveSwitch (_DtCvLinkDb link_db, int *ret_link)
  123. *
  124. * Purpose:
  125. *****************************************************************************/
  126. static int
  127. ResolveSwitch (
  128. _DtCvLinkDb link_db,
  129. int link_no,
  130. int iterations,
  131. int (*filter)(),
  132. void *client_data,
  133. int *ret_link,
  134. int *ret_hint)
  135. {
  136. int result = -1;
  137. char *valueData = NULL;
  138. if (iterations < 100)
  139. {
  140. result = _DtCvRunInterp(filter, client_data,
  141. link_db->list[link_no].info.swtch.interp,
  142. link_db->list[link_no].info.swtch.cmd,
  143. &valueData);
  144. if (result == 0)
  145. {
  146. int value = atoi(valueData);
  147. char *idRefs = link_db->list[link_no].info.swtch.branches;
  148. char *rid;
  149. iterations++;
  150. while (value > 0 && *idRefs != '\0')
  151. {
  152. /*
  153. * skip this id.
  154. */
  155. while(*idRefs != ' ' && *idRefs != '\0')
  156. idRefs++;
  157. /*
  158. * skip the spaces
  159. */
  160. while(*idRefs == ' ')
  161. idRefs++;
  162. /*
  163. * decrement the index.
  164. */
  165. value--;
  166. }
  167. /*
  168. * if the value returned is more than the id list or we hit
  169. * the end, back up to the first idref
  170. */
  171. if (value > 0 || *idRefs == '\0')
  172. idRefs = link_db->list[link_no].info.swtch.branches;
  173. /*
  174. * duplicate the id and null out the
  175. * extraneous ids.
  176. */
  177. rid = strdup (idRefs);
  178. idRefs = rid;
  179. while(*idRefs != ' ' && *idRefs != '\0')
  180. idRefs++;
  181. *idRefs = '\0';
  182. result = FindLink(link_db, rid, &link_no, ret_hint);
  183. if (0 == result && _DtLinkTypeSwitch == link_db->list[link_no].type)
  184. result = ResolveSwitch (link_db, link_no, iterations, filter,
  185. client_data, &link_no, ret_hint);
  186. free (rid);
  187. }
  188. if (valueData != NULL)
  189. free(valueData);
  190. }
  191. *ret_link = link_no;
  192. return result;
  193. }
  194. /*****************************************************************************
  195. * Function: GetNextEntry (
  196. *
  197. * Purpose:
  198. *****************************************************************************/
  199. static int
  200. GetNextEntry (
  201. _DtCvLinkDb link_db)
  202. {
  203. int i = 0;
  204. while (i < link_db->max && _DtLinkTypeNone != link_db->list[i].type)
  205. i++;
  206. if (i >= link_db->max)
  207. {
  208. link_db->max += GROW_SIZE;
  209. if (link_db->list != NULL)
  210. link_db->list = (_DtCvLinkEntry *) realloc(link_db->list,
  211. (sizeof (_DtCvLinkEntry) * link_db->max));
  212. else
  213. link_db->list = (_DtCvLinkEntry *) malloc(
  214. sizeof (_DtCvLinkEntry) * link_db->max);
  215. if (link_db->list == NULL)
  216. return -1;
  217. while (i < link_db->max)
  218. {
  219. link_db->list[i ].id = NULL;
  220. link_db->list[i++].type = _DtLinkTypeNone;
  221. }
  222. i -= GROW_SIZE;
  223. }
  224. return i;
  225. }
  226. /*****************************************************************************
  227. * Semi-Public Functions
  228. *****************************************************************************/
  229. /******************************************************************************
  230. * Function: int _DtLinkDbGetLinkType (link_index)
  231. *
  232. * Parameters:
  233. *
  234. * Returns:
  235. *
  236. * errno Values:
  237. *
  238. * Purpose: Return the hypertext link type.
  239. *
  240. *****************************************************************************/
  241. int
  242. _DtLinkDbGetLinkType (
  243. _DtCvLinkDb link_db,
  244. int link_index )
  245. {
  246. int value = -1;
  247. if (link_index < link_db->max &&
  248. _DtLinkTypeNone != link_db->list[link_index].type)
  249. value = link_db->list[link_index].info.link.lnk_type;
  250. return value;
  251. }
  252. /******************************************************************************
  253. * Function: int _DtLinkDbGetHint (link_index)
  254. *
  255. * Parameters:
  256. *
  257. * Returns:
  258. *
  259. * errno Values:
  260. *
  261. * Purpose: Return the hypertext link type.
  262. *
  263. *****************************************************************************/
  264. int
  265. _DtLinkDbGetHint (
  266. _DtCvLinkDb link_db,
  267. int link_index )
  268. {
  269. int value = -1;
  270. if (link_index < link_db->max &&
  271. _DtLinkTypeNone != link_db->list[link_index].type)
  272. value = link_db->list[link_index].info.link.hint;
  273. return value;
  274. }
  275. /******************************************************************************
  276. * Function: char *_DtLinkDbGetLinkSpec (link_index)
  277. *
  278. * Parameters:
  279. *
  280. * Returns:
  281. *
  282. * errno Values:
  283. *
  284. * Purpose: Return the hypertext link type.
  285. *
  286. *****************************************************************************/
  287. char *
  288. _DtLinkDbGetLinkSpec (
  289. _DtCvLinkDb link_db,
  290. int link_index )
  291. {
  292. char *ptr = NULL;
  293. if (link_index < link_db->max &&
  294. _DtLinkTypeNone != link_db->list[link_index].type)
  295. ptr = link_db->list[link_index].info.link.spec;
  296. return ptr;
  297. }
  298. /******************************************************************************
  299. * Function: int _DtLinkDbGetLinkInfo (link_index, ret_info)
  300. *
  301. * Parameters:
  302. *
  303. * Returns:
  304. *
  305. * errno Values:
  306. *
  307. * Purpose: Return the hypertext link type.
  308. *
  309. *****************************************************************************/
  310. int
  311. _DtLinkDbGetLinkInfo (
  312. _DtCvLinkDb link_db,
  313. int link_index,
  314. int (*filter)(),
  315. void *client_data,
  316. _DtCvLinkInfo *ret_info)
  317. {
  318. int hint;
  319. int result = -1;
  320. char *spec;
  321. if (link_index < link_db->max &&
  322. _DtLinkTypeNone != link_db->list[link_index].type)
  323. {
  324. result = 0;
  325. spec = link_db->list[link_index].info.link.spec;
  326. hint = link_db->list[link_index].info.link.hint;
  327. /*
  328. * is this a link to a switch? Check the switches for
  329. * the spec (id) and resolve to another link if so.
  330. */
  331. if (_DtLinkTypeSwitch == link_db->list[link_index].type ||
  332. (0 == FindLink(link_db, spec, &link_index, &hint)
  333. && _DtLinkTypeSwitch == link_db->list[link_index].type))
  334. result = ResolveSwitch(link_db, link_index, 0, filter, client_data,
  335. &link_index, &hint);
  336. if (0 == result)
  337. {
  338. ret_info->win_hint = hint;
  339. ret_info->hyper_type =
  340. link_db->list[link_index].info.link.lnk_type;
  341. ret_info->specification =
  342. link_db->list[link_index].info.link.spec;
  343. ret_info->description =
  344. link_db->list[link_index].info.link.descrip;
  345. }
  346. }
  347. return result;
  348. }
  349. /*****************************************************************************
  350. * Public Functions
  351. *****************************************************************************/
  352. /*****************************************************************************
  353. * Function: _DtCvLinkDb _DtLinkDbCreate ()
  354. *
  355. * Parameters:
  356. *
  357. * Returns: A link data base handle.
  358. *
  359. * Purpose: Create a link data base.
  360. *
  361. *****************************************************************************/
  362. _DtCvLinkDb
  363. _DtLinkDbCreate (void)
  364. {
  365. _DtCvLinkDb newDb = (_DtCvLinkDb) malloc (sizeof(struct _dtCvLinkDb));
  366. if (NULL != newDb)
  367. *newDb = DefLinkDb;
  368. return (newDb);
  369. }
  370. /*****************************************************************************
  371. * Function: void _DtLinkDbDestroy (_DtCvLinkDb link_db)
  372. *
  373. * Parameters:
  374. * canvas Specifies the handle for the canvas.
  375. *
  376. * Returns: A handle to the canvas or NULL if an error occurs.
  377. *
  378. * Purpose:
  379. *
  380. *****************************************************************************/
  381. void
  382. _DtLinkDbDestroy (
  383. _DtCvLinkDb link_db)
  384. {
  385. int i;
  386. if (NULL != link_db)
  387. {
  388. for (i = 0; i < link_db->max; i++)
  389. {
  390. if (_DtLinkTypeLink == link_db->list[i].type)
  391. {
  392. if (NULL != link_db->list[i].id)
  393. free(link_db->list[i].id);
  394. free(link_db->list[i].info.link.spec);
  395. if (NULL != link_db->list[i].info.link.descrip)
  396. free(link_db->list[i].info.link.descrip);
  397. }
  398. else if (_DtLinkTypeSwitch == link_db->list[i].type)
  399. {
  400. free(link_db->list[i].id);
  401. free(link_db->list[i].info.swtch.interp);
  402. free(link_db->list[i].info.swtch.cmd);
  403. free(link_db->list[i].info.swtch.branches);
  404. }
  405. }
  406. if (NULL != link_db->list)
  407. free(link_db->list);
  408. free(link_db);
  409. }
  410. }
  411. /******************************************************************************
  412. * Function: int _DtLinkDbAddLink (link_data, char *link, int type,
  413. * char *description)
  414. *
  415. * Parameters:
  416. * link Specifies the hypertext link specification.
  417. * type Specifies the type of hypertext link.
  418. * link Specifies the hypertext link description.
  419. *
  420. * Returns The index into the list of hypertext links.
  421. * -1 for errors.
  422. *
  423. * errno Values:
  424. * DtErrorMalloc
  425. *
  426. * Purpose: Place a hypertext link into an array.
  427. *
  428. * Note: The link and description pointers are hereafter owned by
  429. * the hypertext list. The caller should not free or realloc
  430. * these pointers.
  431. *
  432. *****************************************************************************/
  433. int
  434. _DtLinkDbAddLink (
  435. _DtCvLinkDb link_db,
  436. char *id,
  437. char *spec,
  438. int type,
  439. int hint,
  440. char *description)
  441. {
  442. int i = GetNextEntry(link_db);
  443. if (spec == NULL || 0 > i)
  444. return -1;
  445. /*
  446. * copy the information
  447. */
  448. if (NULL != id)
  449. {
  450. id = strdup(id);
  451. if (NULL == id)
  452. return -1;
  453. }
  454. spec = strdup(spec);
  455. if (NULL == spec)
  456. {
  457. if (NULL != id) free (id);
  458. return -1;
  459. }
  460. if (NULL != description)
  461. {
  462. description = strdup(description);
  463. if (NULL == description)
  464. {
  465. if (NULL != id) free (id);
  466. free(spec);
  467. return -1;
  468. }
  469. }
  470. /*
  471. * assign the link
  472. */
  473. link_db->list[i].type = _DtLinkTypeLink;
  474. link_db->list[i].id = id;
  475. link_db->list[i].info.link.spec = spec;
  476. link_db->list[i].info.link.lnk_type = type;
  477. link_db->list[i].info.link.hint = hint;
  478. link_db->list[i].info.link.descrip = description;
  479. return i;
  480. }
  481. /******************************************************************************
  482. * Function: void _DtLinkDbRemoveLink (link_index)
  483. *
  484. * Parameters:
  485. *
  486. * Returns:
  487. *
  488. * errno Values:
  489. *
  490. * Purpose: Remove a hypertext link from the array.
  491. *
  492. *****************************************************************************/
  493. void
  494. _DtLinkDbRemoveLink (
  495. _DtCvLinkDb link_db,
  496. int link_index )
  497. {
  498. if (link_index < link_db->max &&
  499. _DtLinkTypeNone != link_db->list[link_index].type)
  500. {
  501. if (NULL != link_db->list[link_index].id)
  502. free(link_db->list[link_index].id);
  503. if (_DtLinkTypeLink == link_db->list[link_index].type)
  504. {
  505. free(link_db->list[link_index].info.link.spec);
  506. if (NULL != link_db->list[link_index].info.link.descrip)
  507. free(link_db->list[link_index].info.link.descrip);
  508. }
  509. else if (_DtLinkTypeSwitch == link_db->list[link_index].type)
  510. {
  511. free(link_db->list[link_index].info.swtch.interp);
  512. free(link_db->list[link_index].info.swtch.cmd);
  513. free(link_db->list[link_index].info.swtch.branches);
  514. }
  515. link_db->list[link_index].type = _DtLinkTypeNone;
  516. link_db->list[link_index].id = NULL;
  517. }
  518. }
  519. /******************************************************************************
  520. * Function: int _DtLinkDbAddSwitch (
  521. *
  522. * Parameters:
  523. *
  524. * Returns:
  525. *
  526. * errno Values:
  527. *
  528. * Purpose: Add a switch to the link database
  529. *
  530. *****************************************************************************/
  531. int
  532. _DtLinkDbAddSwitch (
  533. _DtCvLinkDb link_db,
  534. char *id,
  535. char *interp,
  536. char *cmd,
  537. char *branches)
  538. {
  539. int i = GetNextEntry(link_db);
  540. if (NULL == id || NULL == interp || NULL == cmd
  541. || NULL == branches || 0 > i)
  542. return -1;
  543. /*
  544. * copy the information
  545. */
  546. id = strdup(id);
  547. interp = strdup(interp);
  548. cmd = strdup(cmd);
  549. branches = strdup(branches);
  550. if (NULL == id || NULL == interp || NULL == cmd || NULL == branches)
  551. {
  552. if (NULL != id) free(id);
  553. if (NULL != interp) free(interp);
  554. if (NULL != cmd) free(cmd);
  555. if (NULL != branches) free(branches);
  556. return -1;
  557. }
  558. link_db->list[i].type = _DtLinkTypeSwitch;
  559. link_db->list[i].id = id;
  560. link_db->list[i].info.swtch.interp = interp;
  561. link_db->list[i].info.swtch.cmd = cmd;
  562. link_db->list[i].info.swtch.branches = branches;
  563. return i;
  564. }