1 /* $XConsortium: LinkMgr.c /main/10 1996/11/01 10:10:59 drk $ */
2 /************************************<+>*************************************
3 ****************************************************************************
7 ** Project: Cde Help System
9 ** Description: Hypertext manager for the core engine of the help
10 ** system. Processes requests from the UI to move, turn
11 ** on, or turn off the traversal indicator, to return
12 ** information about a hypertext link and to determine
13 ** if a spot selected contains a hypertext link.
15 ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
17 ** (c) Copyright 1993, 1994 Hewlett-Packard Company
18 ** (c) Copyright 1993, 1994 International Business Machines Corp.
19 ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
20 ** (c) Copyright 1993, 1994 Novell, Inc.
22 ****************************************************************************
23 ************************************<+>*************************************/
39 * Canvas Engine Includes
46 #include "CanvasOsI.h"
47 #include "CvStringI.h"
55 /******** Private Function Declarations ********/
56 /******** End Private Function Declarations ********/
58 /*****************************************************************************
60 *****************************************************************************/
63 /*****************************************************************************
65 *****************************************************************************/
66 const static struct _dtCvLinkDb DefLinkDb = { 0, NULL };
68 /*****************************************************************************
70 *****************************************************************************/
71 /*****************************************************************************
72 * Function: FindLink (
75 *****************************************************************************/
86 for (i = 0; -1 == result && i < link_db->max; i++)
88 if (_DtLinkTypeNone != link_db->list[i].type
89 && NULL != link_db->list[i].id
90 && 0 == _DtCvStrCaseCmpLatin1(link_db->list[i].id, id))
93 * return a valid index
98 * check to see if the hint changes
100 if (_DtLinkTypeLink == link_db->list[i].type &&
101 _DtCvWindowHint_Original != link_db->list[i].info.link.hint)
102 *ret_hint = link_db->list[i].info.link.hint;
105 * clear the error return
114 /*****************************************************************************
115 * Function: ResolveSwitch (_DtCvLinkDb link_db, int *ret_link)
118 *****************************************************************************/
130 char *valueData = NULL;
132 if (iterations < 100)
134 result = _DtCvRunInterp(filter, client_data,
135 link_db->list[link_no].info.swtch.interp,
136 link_db->list[link_no].info.swtch.cmd,
141 int value = atoi(valueData);
142 char *idRefs = link_db->list[link_no].info.swtch.branches;
147 while (value > 0 && *idRefs != '\0')
152 while(*idRefs != ' ' && *idRefs != '\0')
158 while(*idRefs == ' ')
162 * decrement the index.
168 * if the value returned is more than the id list or we hit
169 * the end, back up to the first idref
171 if (value > 0 || *idRefs == '\0')
172 idRefs = link_db->list[link_no].info.swtch.branches;
175 * duplicate the id and null out the
178 rid = strdup (idRefs);
180 while(*idRefs != ' ' && *idRefs != '\0')
184 result = FindLink(link_db, rid, &link_no, ret_hint);
185 if (0 == result && _DtLinkTypeSwitch == link_db->list[link_no].type)
186 result = ResolveSwitch (link_db, link_no, iterations, filter,
187 client_data, &link_no, ret_hint);
191 if (valueData != NULL)
199 /*****************************************************************************
200 * Function: GetNextEntry (
203 *****************************************************************************/
210 while (i < link_db->max && _DtLinkTypeNone != link_db->list[i].type)
213 if (i >= link_db->max)
215 link_db->max += GROW_SIZE;
216 if (link_db->list != NULL)
217 link_db->list = (_DtCvLinkEntry *) realloc(link_db->list,
218 (sizeof (_DtCvLinkEntry) * link_db->max));
220 link_db->list = (_DtCvLinkEntry *) malloc(
221 sizeof (_DtCvLinkEntry) * link_db->max);
223 if (link_db->list == NULL)
226 while (i < link_db->max)
228 link_db->list[i ].id = NULL;
229 link_db->list[i++].type = _DtLinkTypeNone;
238 /*****************************************************************************
239 * Semi-Public Functions
240 *****************************************************************************/
241 /******************************************************************************
242 * Function: int _DtLinkDbGetLinkType (link_index)
250 * Purpose: Return the hypertext link type.
252 *****************************************************************************/
254 _DtLinkDbGetLinkType (
260 if (link_index < link_db->max &&
261 _DtLinkTypeNone != link_db->list[link_index].type)
262 value = link_db->list[link_index].info.link.lnk_type;
267 /******************************************************************************
268 * Function: int _DtLinkDbGetHint (link_index)
276 * Purpose: Return the hypertext link type.
278 *****************************************************************************/
286 if (link_index < link_db->max &&
287 _DtLinkTypeNone != link_db->list[link_index].type)
288 value = link_db->list[link_index].info.link.hint;
293 /******************************************************************************
294 * Function: char *_DtLinkDbGetLinkSpec (link_index)
302 * Purpose: Return the hypertext link type.
304 *****************************************************************************/
306 _DtLinkDbGetLinkSpec (
312 if (link_index < link_db->max &&
313 _DtLinkTypeNone != link_db->list[link_index].type)
314 ptr = link_db->list[link_index].info.link.spec;
319 /******************************************************************************
320 * Function: int _DtLinkDbGetLinkInfo (link_index, ret_info)
328 * Purpose: Return the hypertext link type.
330 *****************************************************************************/
332 _DtLinkDbGetLinkInfo (
337 _DtCvLinkInfo *ret_info)
343 if (link_index < link_db->max &&
344 _DtLinkTypeNone != link_db->list[link_index].type)
348 spec = link_db->list[link_index].info.link.spec;
349 hint = link_db->list[link_index].info.link.hint;
352 * is this a link to a switch? Check the switches for
353 * the spec (id) and resolve to another link if so.
355 if (_DtLinkTypeSwitch == link_db->list[link_index].type ||
356 (0 == FindLink(link_db, spec, &link_index, &hint)
357 && _DtLinkTypeSwitch == link_db->list[link_index].type))
358 result = ResolveSwitch(link_db, link_index, 0, filter, client_data,
363 ret_info->win_hint = hint;
364 ret_info->hyper_type =
365 link_db->list[link_index].info.link.lnk_type;
366 ret_info->specification =
367 link_db->list[link_index].info.link.spec;
368 ret_info->description =
369 link_db->list[link_index].info.link.descrip;
376 /*****************************************************************************
378 *****************************************************************************/
379 /*****************************************************************************
380 * Function: _DtCvLinkDb _DtLinkDbCreate ()
384 * Returns: A link data base handle.
386 * Purpose: Create a link data base.
388 *****************************************************************************/
390 _DtLinkDbCreate (void)
392 _DtCvLinkDb newDb = (_DtCvLinkDb) malloc (sizeof(struct _dtCvLinkDb));
400 /*****************************************************************************
401 * Function: void _DtLinkDbDestroy (_DtCvLinkDb link_db)
404 * canvas Specifies the handle for the canvas.
406 * Returns: A handle to the canvas or NULL if an error occurs.
410 *****************************************************************************/
419 for (i = 0; i < link_db->max; i++)
421 if (_DtLinkTypeLink == link_db->list[i].type)
423 if (NULL != link_db->list[i].id)
424 free(link_db->list[i].id);
425 free(link_db->list[i].info.link.spec);
426 if (NULL != link_db->list[i].info.link.descrip)
427 free(link_db->list[i].info.link.descrip);
429 else if (_DtLinkTypeSwitch == link_db->list[i].type)
431 free(link_db->list[i].id);
432 free(link_db->list[i].info.swtch.interp);
433 free(link_db->list[i].info.swtch.cmd);
434 free(link_db->list[i].info.swtch.branches);
437 if (NULL != link_db->list)
444 /******************************************************************************
445 * Function: int _DtLinkDbAddLink (link_data, char *link, int type,
449 * link Specifies the hypertext link specification.
450 * type Specifies the type of hypertext link.
451 * link Specifies the hypertext link description.
453 * Returns The index into the list of hypertext links.
459 * Purpose: Place a hypertext link into an array.
461 * Note: The link and description pointers are hereafter owned by
462 * the hypertext list. The caller should not free or realloc
465 *****************************************************************************/
475 int i = GetNextEntry(link_db);
477 if (spec == NULL || 0 > i)
481 * copy the information
493 if (NULL != id) free (id);
497 if (NULL != description)
499 description = strdup(description);
500 if (NULL == description)
502 if (NULL != id) free (id);
511 link_db->list[i].type = _DtLinkTypeLink;
512 link_db->list[i].id = id;
514 link_db->list[i].info.link.spec = spec;
515 link_db->list[i].info.link.lnk_type = type;
516 link_db->list[i].info.link.hint = hint;
517 link_db->list[i].info.link.descrip = description;
522 /******************************************************************************
523 * Function: void _DtLinkDbRemoveLink (link_index)
531 * Purpose: Remove a hypertext link from the array.
533 *****************************************************************************/
535 _DtLinkDbRemoveLink (
539 if (link_index < link_db->max &&
540 _DtLinkTypeNone != link_db->list[link_index].type)
542 if (NULL != link_db->list[link_index].id)
543 free(link_db->list[link_index].id);
545 if (_DtLinkTypeLink == link_db->list[link_index].type)
547 free(link_db->list[link_index].info.link.spec);
548 if (NULL != link_db->list[link_index].info.link.descrip)
549 free(link_db->list[link_index].info.link.descrip);
551 else if (_DtLinkTypeSwitch == link_db->list[link_index].type)
553 free(link_db->list[link_index].info.swtch.interp);
554 free(link_db->list[link_index].info.swtch.cmd);
555 free(link_db->list[link_index].info.swtch.branches);
558 link_db->list[link_index].type = _DtLinkTypeNone;
559 link_db->list[link_index].id = NULL;
563 /******************************************************************************
564 * Function: int _DtLinkDbAddSwitch (
572 * Purpose: Add a switch to the link database
574 *****************************************************************************/
583 int i = GetNextEntry(link_db);
585 if (NULL == id || NULL == interp || NULL == cmd
586 || NULL == branches || 0 > i)
590 * copy the information
593 interp = strdup(interp);
595 branches = strdup(branches);
597 if (NULL == id || NULL == interp || NULL == cmd || NULL == branches)
599 if (NULL != id) free(id);
600 if (NULL != interp) free(interp);
601 if (NULL != cmd) free(cmd);
602 if (NULL != branches) free(branches);
606 link_db->list[i].type = _DtLinkTypeSwitch;
607 link_db->list[i].id = id;
609 link_db->list[i].info.swtch.interp = interp;
610 link_db->list[i].info.swtch.cmd = cmd;
611 link_db->list[i].info.swtch.branches = branches;