2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: GlobSearch.c /main/21 1999/11/11 10:59:15 mgreess $ */
24 /************************************<+>*************************************
25 ****************************************************************************
29 ** Project: DtHelp Project
31 ** Description: Builds and displays an instance of a DtHelp GlobSearch
34 ** (c) Copyright 1993, 1994 Hewlett-Packard Company
35 ** (c) Copyright 1993, 1994 International Business Machines Corp.
36 ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
37 ** (c) Copyright 1993, 1994 Novell, Inc.
41 ****************************************************************************
42 ************************************<+>*************************************/
43 #include <sys/param.h>
47 #include <sys/utsname.h>
50 #include <stdlib.h> /* for MB_CUR_MAX */
51 #include <unistd.h> /* R_OK */
52 #include <locale.h> /* getlocale(), LOCALE_STATUS */
56 # include <libgen.h> /* for regcmp, regex */
59 # include <regex.h> /* for regcomp, regexec */
68 #include <Xm/LabelG.h>
69 #include <Xm/ScrolledW.h>
70 #include <Xm/SeparatoG.h>
71 #include <Xm/PushBG.h>
73 #include <Xm/DialogS.h>
74 #include <Xm/MwmUtil.h>
75 #include <Xm/Protocols.h>
76 #include <Xm/RowColumn.h>
77 #include <Xm/SelectioB.h>
78 #include <Xm/ToggleBG.h>
80 #include <X11/Intrinsic.h>
81 #include <X11/Shell.h>
82 #include <X11/ShellP.h>
83 #include <X11/Xutil.h>
84 #include <X11/keysymdef.h>
87 #include <Dt/HelpDialog.h>
95 #include "StringFuncsI.h"
96 #include "DisplayAreaI.h"
97 #include "HelpDialogP.h"
98 #include "HelpDialogI.h"
99 #include "HelpAccessI.h"
100 #include "HelpUtilI.h"
102 #include "HourGlassI.h"
103 #include "GlobSearchI.h"
104 #include "FileListUtilsI.h"
105 #include "FileUtilsI.h"
107 #include "HelpXlate.h"
108 #include "VolSelectI.h"
111 /******** TYPES ***********/
113 SEARCH_RESULTS_STATUS = 1,
118 FIRST_PROMPT_STATUS = 6
121 static Boolean VolumeHasIndexP (
122 _DtHelpGlobSrchSources srchSource,
125 static void DeleteListContents(
126 _DtHelpGlobSearchStuff * srch);
127 static void StatusLabelUpdate(
128 DtHelpDialogWidget hw,
129 ResultsStatus status,
132 static void ResultsListUpdate(
133 DtHelpDialogWidget hw,
134 _DtHelpFileEntry newFile);
135 static void StopSearchCB(
137 XtPointer clientData,
139 static void VolNameDisplay(
140 DtHelpDialogWidget hw,
141 _DtHelpFileEntry file,
143 static int VolHitsDisplay (
144 DtHelpDialogWidget hw,
145 _DtHelpFileEntry file);
146 static void UpdateSearchVolumesCB(
148 XtPointer clientData,
150 static void UpdateSearchStartStatusCB(
152 XtPointer clientData,
155 /********** CONSTANTS *************/
156 #define DIR_SLASH '/'
159 /* message catalog set number for GlobSearch.c */
162 #define DONT_SET (-1) /* used as third value of a Boolean */
164 #define HIT_FONT_RES_NAME "*helpSearchMonoFont"
165 #define HIT_FONT_RES_CLASS "*HelpSearchMonoFont"
166 #define PREFIX_FONT_SPEC "-dt-interface user-bold-r-normal-m*-*-*-*-*-m-*-iso8859-1"
167 #define PREFIX_FONT_SPEC1 "-dt-application-bold-r-normal-*-*-140-*-*-m-*-iso8859-1"
168 #define PREFIX_FONT_SPEC2 "-dt-interface user-bold-r-normal-m*-*-*-*-*-m-*-iso8859-1"
169 #define PREFIX_FONT_SPEC3 "courb14" /* non CDE platforms */
170 #define PREFIX_FONT_TAG "prefixFontTag"
172 #define START_SEARCH_CAT s_GlobSrchDlgBtnCatNum[0]
173 #define START_SEARCH_STR s_GlobSrchDlgBtnStrs[0]
174 #define START_SEARCH_MNEM "S"
175 #define CONT_SEARCH_CAT s_GlobSrchDlgBtnCatNum[1]
176 #define CONT_SEARCH_STR s_GlobSrchDlgBtnStrs[1]
177 #define CONT_SEARCH_MNEM "S"
178 #define STOP_SEARCH_CAT s_GlobSrchDlgBtnCatNum[2]
179 #define STOP_SEARCH_STR s_GlobSrchDlgBtnStrs[2]
180 #define STOP_SEARCH_MNEM "S"
181 #define CLOSE_BTN_CAT s_GlobSrchDlgBtnCatNum[3]
182 #define CLOSE_BTN_STR s_GlobSrchDlgBtnStrs[3]
183 #define CLOSE_BTN_MNEM "C"
184 #define HELP_BTN_CAT s_GlobSrchDlgBtnCatNum[4]
185 #define HELP_BTN_STR s_GlobSrchDlgBtnStrs[4]
186 #define HELP_BTN_MNEM "H"
189 /********** MACROS ************/
190 #define max(a,b) ((a) > (b) ? (a) : (b))
192 /********** Global VARIABLES ************/
193 char _DtHelpDefaultSrchHitPrefixFont[] = PREFIX_FONT_SPEC;
195 /********** VARIABLES ************/
196 static const char *DirSlash = "/";
197 static char * s_GlobSrchDlgBtnStrs[] = {
204 /* catalog index numbers for the strings */
205 static unsigned char s_GlobSrchDlgBtnCatNum[] = {
206 12, 13, 14, 15, 16 };
208 static char * s_PrefixFontListTag = NULL;
210 /* Setup for the Retrun Translation set for the text field */
211 static char defaultBtnTranslations[] = "<Key>Return: Activate()";
212 /* static char defaultListTranslations[] = "<Key>Return: Activate()"; */
213 /* static char defaultMgrTranslations[] = "<Key>Return: ManagerParentActivate()"; */
216 /************************************************************************
217 The startPosition and nextVolPosition values of the DtHelpGlobSrchVol
218 structure are used as follows:
220 startPosition: the position of the volume in the results list
221 if hitCnt == 0, startPosition is the same value as the
222 most recent volume with hits
223 nextVolPosition: the position of the next volume in the results list
224 if hitCnt == 0, nextVolPosition is the same value as the
225 most recent volume with hits
226 The value must be adjusted to include the positions
227 occupied by hits and topics that are listed for the volume
229 These variables are maintained using the AdjustPositionValues()
230 routine, which increment/decrement the position values of all
231 files after the start. So, when doing a search and display,
232 as results are added to the list, the position values of volumes
233 later in the list are always up to date.
234 ************************************************************************/
237 /*======================================================================*/
238 /*======================================================================*/
239 /*======================================================================*/
240 /*======================================================================*/
243 /*****************************************************************************
244 * Function: void MergeFontListIntoWidgetFonts()
246 * Parameters: widget a widget with a XmNfontList resource
247 * newFontsList font list with fonts to merge into widget
251 * Purpose: Merges the fonts from the newFontsList into the fontlist
254 *****************************************************************************/
255 static void MergeFontListIntoWidgetFonts(
257 XmFontList newFontsList)
259 XmFontList fontList = NULL;
260 XmFontContext context;
261 XmFontListEntry entry;
264 /* get current resultList fontlist */
265 XtSetArg(args[0], XmNfontList, &fontList);
266 XtGetValues(widget,args,1);
268 if (NULL == fontList) return; /* RETURN on error */
270 /* work with copy, because FontListAppendEntry() destroys input FL */
271 fontList = XmFontListCopy(fontList);
273 /* walk through the volTitlesFontList entries and add them in */
274 XmFontListInitFontContext(&context,newFontsList);
275 for ( entry = XmFontListNextEntry(context);
277 entry = XmFontListNextEntry(context) )
279 fontList = XmFontListAppendEntry(fontList,entry);
281 if (context) XmFontListFreeFontContext(context);
283 /* install the changed list */
284 XtSetArg(args[0], XmNfontList, fontList);
285 XtSetValues(widget,args,1);
287 if (fontList) XmFontListFree(fontList);
291 /*****************************************************************************
292 * Function: void UpdateCurVolBtnSens()
294 * Parameters: new the help widget
296 * Return Value: True if cur vol has an index
299 * Purpose: Checks on current volume for an index
300 and sets buttons appropriately
302 *****************************************************************************/
303 static Boolean UpdateCurVolBtnSens(
304 DtHelpDialogWidget hw,
305 Boolean selectVolBtn)
307 XmToggleButtonCallbackStruct status; /* the call data */
311 /* set the cur vol btn sensitivity */
312 /* set the volumes/show selection btns by generating a false event */
313 status.reason = XmCR_VALUE_CHANGED;
315 status.event = (XEvent *) 1; /* thwart == NULL test in Update...() */
318 if ( VolumeHasIndexP (
319 hw->help_dialog.srch.srchSources,
320 hw->help_dialog.display.helpType,
321 hw->help_dialog.display.helpVolume) )
324 sourceBtn = hw->help_dialog.srch.curVolRadBtn;
329 sourceBtn = hw->help_dialog.srch.allVolRadBtn;
331 /* ??? XtSetSensitive(hw->help_dialog.srch.curVolRadBtn,curState); */
332 hw->help_dialog.srch.curVolRadBtnSens = curState;
333 if (selectVolBtn) UpdateSearchVolumesCB(sourceBtn,hw,&status);
337 sourceBtn = hw->help_dialog.srch.curVolRadBtn;
339 hw->help_dialog.srch.curVolRadBtnSens = curState;
341 UpdateSearchVolumesCB(sourceBtn,(XtPointer)hw,(XtPointer)&status);
349 /************************************************************************
350 * Function: LoadPrefixFont()
352 * Loads the prefix font, if that hasn't yet occurred
354 ************************************************************************/
355 static void LoadPrefixFont(
356 DtHelpDialogWidget hw)
358 XmFontListEntry entry;
359 XmFontList curFontList = NULL;
360 XmFontList newFontList = NULL;
361 char * fontSpec = NULL;
364 if (hw->help_dialog.srch.hitsFontLoaded) return; /* RETURN */
366 /* this code is for when the resource is part of the widget */
367 fontSpec = hw->help_dialog.srch.hitPrefixFont;
369 /* get current font list */
370 XtSetArg(args[0], XmNfontList, &curFontList);
371 XtGetValues(hw->help_dialog.srch.resultList,args,1);
373 /* work with copy, because FontListAppendEntry() destroys input FL */
374 newFontList = XmFontListCopy(curFontList);
376 /* load and merge fonts */
377 s_PrefixFontListTag = PREFIX_FONT_TAG;
378 entry = XmFontListEntryLoad(XtDisplay(hw->help_dialog.srch.srchForm),
379 fontSpec,XmFONT_IS_FONT, s_PrefixFontListTag);
380 newFontList = XmFontListAppendEntry(newFontList,entry);
381 XmFontListEntryFree(&entry);
384 if (NULL == newFontList)
386 s_PrefixFontListTag = XmFONTLIST_DEFAULT_TAG;
390 /* set new font list */
391 XtSetArg(args[0], XmNfontList, newFontList);
392 XtSetValues(hw->help_dialog.srch.resultList,args,1);
393 if (newFontList) XmFontListFree(newFontList);
395 hw->help_dialog.srch.hitsFontLoaded = True;
400 /************************************************************************
401 * Function: VolumeHasIndexP()
403 * Looks for the specified volume in the file system and
404 * tests whether the volume has an index associated with it.
406 ************************************************************************/
407 static Boolean VolumeHasIndexP (
408 _DtHelpGlobSrchSources srchSource,
413 _DtHelpVolumeHdl vol;
414 int keyWordCount = 0;
415 char **currentKeyList = NULL;
417 /* if help content isn't a volume, it has no index */
418 if ( _DtHelpGlobSrchCurVolume == srchSource
419 && helpType != DtHELP_TYPE_TOPIC )
420 return False; /* RETURN */
422 /* try to locate file and its entry, if present */
423 path = _DtHelpFileLocate(DtHelpVOLUME_TYPE, baseName,
424 _DtHelpFileSuffixList,False,R_OK);
425 if (_DtHelpOpenVolume(path, &vol) == 0 )
427 /* Get the keyword list values */
428 keyWordCount = _DtHelpCeGetKeywordList(vol,&(currentKeyList));
430 /* no need to free currentKeyList because these are mgd by CE */
431 _DtHelpCloseVolume(vol);
435 return (keyWordCount > 0);
440 /************************************************************************
441 * Function: GetVolumeInfoCB()
443 * Get the info on the volume and return it
444 * Any of the 'out' parameters may be NULL.
446 ************************************************************************/
447 static Boolean GetVolumeInfoCB (
448 XtPointer pDisplayArea, /* in: display area in use */
449 char * volumePath, /* in: full path to file */
450 char ** ret_title, /* out: mallocd doc title text string */
451 XmString * ret_titleXmStr,/* out: mallocd doc title string */
452 char ** ret_docId, /* out: mallocd doc Id string */
453 char ** ret_timeStamp, /* out: mallocd doc time string */
454 int * ret_nameKey, /* out: hash value for fast discimination */
455 XmFontList * io_fontList, /* io: fontList for title */
456 Boolean * ret_mod) /* out: has font list been changed */
459 _DtHelpVolumeHdl vol;
460 char * baseName = volumePath; /* no path component */
463 if(_DtHelpCeStrrchr(volumePath, DirSlash, MB_CUR_MAX, &baseName)==0)
467 if ( _DtHelpOpenVolume(volumePath, &vol) != 0 )
468 { /* if can't open, do best possible */
470 *ret_titleXmStr = XmStringCreateLocalized(baseName);
471 if (ret_title) *ret_title= XtNewString(baseName);
472 if (ret_nameKey) *ret_nameKey = _DtHelpCeStrHashToKey(baseName);
476 /** volume is open, now get the data **/
480 char * locTitle = NULL;
482 /* locTitle is owned by caller */
483 _DtHelpGetAsciiVolumeTitle(pDisplayArea, vol, &locTitle);
484 if (locTitle == NULL)
485 locTitle = XtNewString(baseName);
486 *ret_title = locTitle;
491 XmString locTitleXmStr = NULL;
493 /* locTitle is owned by caller */
494 _DtHelpFormatVolumeTitle(pDisplayArea,vol,
495 &locTitleXmStr,io_fontList,ret_mod);
496 if (locTitleXmStr == NULL)
497 locTitleXmStr = XmStringCreateLocalized(baseName);
498 *ret_titleXmStr = locTitleXmStr;
501 if (ret_docId || ret_timeStamp)
503 char * locDocId = NULL;
504 char * locTimeStamp = NULL;
506 /* locDocId & locTimeStamp will point to private memory; do not modify */
507 _DtHelpCeGetDocStamp(vol,&locDocId, &locTimeStamp);
510 *ret_docId = locDocId ? locDocId : XtNewString(&empty);
512 *ret_timeStamp = locTimeStamp?locTimeStamp:XtNewString(&empty);
517 *ret_nameKey = _DtHelpCeStrHashToKey(baseName);
520 _DtHelpCloseVolume(vol);
526 /************************************************************************
527 * Function: AdjustPositionValues()
529 * Adjust the position values of all volumes in the list by the amount given
531 ************************************************************************/
532 static void AdjustPositionValues(
533 _DtHelpFileList fileList,
538 _DtHelpGlobSrchVol * curVol;
540 if ( NULL == fileList
541 || NULL == (curVol = (_DtHelpGlobSrchVol *) fileList->clientData) )
544 /* do we need to find first next file that has hits and is in list? */
545 if(False == adjustThisFile)
547 curVol->nextVolPosition += adjNextAmount;
548 for ( fileList = _DtHelpFileListGetNext(NULL,fileList); /* begin with next */
550 fileList = _DtHelpFileListGetNext(NULL,fileList) )
552 register _DtHelpGlobSrchVol * vol=(_DtHelpGlobSrchVol *)fileList->clientData;
553 if (vol->showVolInList && (vol->hitCnt > 0 || vol->zeroHitsOk) )
555 vol->nextVolPosition += adjNextAmount;
557 /* all further files require same adj amts */
558 adjStartAmount = adjNextAmount;
562 /* add in the adjust amount to all files */
563 for ( /* do nothing */;
565 fileList = _DtHelpFileListGetNext(NULL,fileList) )
567 register _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) fileList->clientData;
570 vol->startPosition += adjStartAmount;
571 vol->nextVolPosition += adjNextAmount;
573 /* overwrite, once we've done the first file, if haven't already */
574 adjStartAmount = adjNextAmount;
579 /************************************************************************
580 * Function: HitLoadTopics()
582 * Loads the topics referred to by a hit
583 * Returns: 0 if loaded ok, -1 otherwise
584 ************************************************************************/
585 static int HitLoadTopics (
586 DtHelpDialogWidget hw,
587 _DtHelpFileEntry file,
588 _DtHelpGlobSrchHit * hit)
590 _DtHelpVolumeHdl volHandle;
591 char * * origTopicIdList = NULL;
594 XmString * titlesList = NULL;
595 char * * idList = NULL;
596 char * * fileList = NULL;
597 XmFontList fontList = NULL;
599 Boolean allMods = False;
602 if (hit->topicsLoaded) return 0; /* RETURN: ok */
604 if (_DtHelpOpenVolume(file->fullFilePath, &volHandle) != 0 )
605 return -1; /* RETURN: error */
607 topicCnt = _DtHelpCeFindKeyword(volHandle,hit->indexEntry,&origTopicIdList);
608 if (topicCnt <= 0) return -1; /* RETURN: error */
610 /* get results font list */
611 XtSetArg(args[0], XmNfontList, &fontList);
612 XtGetValues(hw->help_dialog.srch.resultList,args,1);
614 #if defined(DONT_USE_CDExc22774)
615 /* Don't need to copy, _DtHelpFormatVolumeTitle copies
619 /* FIX: check whether this is a memory leak. It isn't if the
620 GetValues of XmFontList returns its own list, not a copy */
621 /* work with copy, because FontListAppendEntry() destroys input FL */
622 fontList = XmFontListCopy(fontList);
625 /* get the titles of all topics */
626 for (i=0; i<topicCnt; i++)
628 XmString titleStr = NULL;
629 Boolean valid = False;
630 XmFontList lastFontList = NULL;
633 * mod==True indicates _DtHelpFormatTopicTitle copied fontList
634 * once already. Save a pointer to it so we can free the font list
635 * if _DtHelpFormatTopicTitle copies it again.
637 lastFontList = fontList;
639 valid = _DtHelpFormatTopicTitle(hw->help_dialog.help.pDisplayArea,
640 volHandle,origTopicIdList[i], &titleStr, &fontList, &mod);
642 if (mod && NULL != lastFontList) XmFontListFree(lastFontList);
644 allMods |= mod; /* track for all iterations */
646 if(valid!=0 || NULL==titleStr)
648 titleStr=XmStringCreateLocalized(origTopicIdList[i]);
649 } /* if couldn't get title */
651 /* note that titleStr is an XmString, not an (Xt) String */
652 titlesList = (XmString *)_DtHelpCeAddPtrToArray (
653 (void **)titlesList, (void *) titleStr);
654 idList = (char **)_DtHelpCeAddPtrToArray (
656 (void *) XtNewString(origTopicIdList[i]));
657 fileList = (char **)_DtHelpCeAddPtrToArray (
659 (void *) XtNewString(file->fullFilePath));
660 } /* for all topics of this index entry */
662 /* install font list, if changed */
665 XtSetArg(args[0], XmNfontList, fontList);
666 XtSetValues(hw->help_dialog.srch.resultList,args,1);
667 if (fontList) XmFontListFree(fontList);
670 /* put results into hit */
671 hit->topicTitles = titlesList;
672 hit->topicIdList = idList;
673 hit->topicFileList = fileList;
674 hit->topicCnt = topicCnt;
675 hit->topicsLoaded = True;
677 _DtHelpCloseVolume(volHandle);
684 /************************************************************************
685 * Function: HitNameDisplay()
687 * Updates the name of the hit, not delete or insert
688 ************************************************************************/
689 static int HitNameDisplay (
690 DtHelpDialogWidget hw,
691 _DtHelpFileEntry file,
692 _DtHelpGlobSrchHit * hit,
697 char * contractPrefix;
699 XmString prefixString;
700 XmString labelString;
704 /* FIX: this method of getting/using the prefixes
705 is a performance nightmare; plus subject to font variability */
706 expandPrefix = (char *)_DTGETMESSAGE (GSSET, 28," +");
707 contractPrefix = (char *)_DTGETMESSAGE (GSSET, 29," -");
708 gotoPrefix = (char *)_DTGETMESSAGE (GSSET, 30," ");
710 /* if more than one topic for this index, signal it */
711 tmpStr = gotoPrefix; /* index entry has one topic */
712 if ( hit->topicCnt > 1 )
714 if (hit->topicsDisplayed) /* topics currently displayed */
715 tmpStr = contractPrefix;
716 else /* topics not displayed */
717 tmpStr = expandPrefix;
718 sprintf(buf, "%s%3d ", tmpStr, hit->topicCnt); /* 4d too spacy */
722 prefixString = XmStringGenerate(tmpStr, s_PrefixFontListTag,
723 XmCHARSET_TEXT, NULL);
724 labelString = XmStringConcat(prefixString,hit->indexTitle);
725 /* recall indexTitle is an XmString in the volume's indexXmStrsList */
727 /* install/insert the item */
729 XmListAddItemUnselected(hw->help_dialog.srch.resultList,
732 XmListReplaceItemsPosUnselected(hw->help_dialog.srch.resultList,
733 &labelString,1,hitPos);
735 XmStringFree(prefixString);
736 XmStringFree(labelString);
737 return (insertHit ? 1 : 0);
742 /************************************************************************
743 * Function: HitTopicsDisplay()
745 * Loads the topics referred to by a hit and displays them
746 * Returns the number of topics displayed
747 ************************************************************************/
748 static int HitTopicsDisplay (
749 DtHelpDialogWidget hw,
750 _DtHelpFileEntry file,
751 _DtHelpGlobSrchHit * hit,
752 int firstTopicListPosition)
754 XmString * pTopicString;
755 XmString prefixString;
760 if ( False == hit->topicsLoaded && HitLoadTopics(hw,file,hit) < 0 )
761 return 0; /* RETURN: error */
762 if ( hit->topicsDisplayed ) return 0; /* RETURN: ok */
765 /*tmpStr = (char *)_DTGETMESSAGE (GSSET, 32," * ");*/
766 tmpStr = (char *)_DTGETMESSAGE (GSSET, 31," ");
767 prefixString = XmStringGenerate(tmpStr, s_PrefixFontListTag,
768 XmCHARSET_TEXT, NULL);
770 if (hit->topicCnt > 0)
772 items = (XmString *) XtMalloc (sizeof (XmString) * hit->topicCnt);
774 /* put XmString-formatted topic titles into list */
775 for (i = 0, pTopicString = hit->topicTitles; NULL != *pTopicString;
776 pTopicString++, i++ )
777 items[i] = XmStringConcat(prefixString,*pTopicString);
779 XmListAddItemsUnselected(hw->help_dialog.srch.resultList, items,
780 hit->topicCnt, firstTopicListPosition);
781 for (i = 0; i < hit->topicCnt; i++)
782 XmStringFree(items[i]);
783 XtFree((char *) items);
786 XmStringFree(prefixString);
789 hit->topicsDisplayed = True;
790 hit->showTopicsWithHit = True;
791 return hit->topicCnt;
797 /************************************************************************
798 * Function: HitTopicsUndisplay()
800 * Releases the topics referred to by a hit and undisplays them
801 * Returns number of topics removed from display and hit.
802 ************************************************************************/
803 static int HitTopicsUndisplay (
804 DtHelpDialogWidget hw,
805 _DtHelpFileEntry file,
806 _DtHelpGlobSrchHit * hit,
807 int firstTopicListPosition)
812 if ( False == hit->topicsDisplayed ) return 0; /* RETURN */
814 XtSetArg(args[0], XmNtopItemPosition, &topPos);
815 XtGetValues(hw->help_dialog.srch.resultList,args,1);
817 /* count the topics -- they are also being collapsed */
818 if (hit->topicCnt > 0)
819 XmListDeleteItemsPos(hw->help_dialog.srch.resultList,
820 hit->topicCnt, firstTopicListPosition);
822 hit->topicsDisplayed = False;
823 /* NOTE: don't reset hit->showTopicsWithHit here; require that
824 to be explicitly reset in ProcessResultSelection() */
826 XmListSetPos(hw->help_dialog.srch.resultList, topPos);
828 return hit->topicCnt;
834 /************************************************************************
835 * Function: HitFree()
837 * Frees the memory associated with a hit and returns the next hit
838 * member of the structure
839 ************************************************************************/
840 static _DtHelpGlobSrchHit * HitFree (
841 _DtHelpGlobSrchHit * hit,
842 Boolean freeHitItself)
845 _DtHelpGlobSrchHit * nextHit;
847 if (NULL == hit) return NULL;
851 /* Free the mem of the topics id list */
852 _DtHelpCeFreeStringArray(hit->topicIdList);
853 hit->topicIdList = NULL; /* mem not owned by me */
855 /* Free the mem of the topics files list */
856 _DtHelpCeFreeStringArray(hit->topicFileList);
857 hit->topicFileList = NULL;
859 /* topicTitles are XmStrings and we can't use FreeStringArray() */
860 for ( nextStr = hit->topicTitles;
861 NULL != nextStr && NULL != *nextStr;
863 XmStringFree (*nextStr);
864 XtFree((char *) hit->topicTitles); /* its an XmString * */
865 hit->topicTitles = NULL;
868 hit->topicsLoaded = False;
869 hit->topicsDisplayed = False;
873 /* Free the index entry */
874 XtFree(hit->indexEntry);
882 /************************************************************************
883 * Function: HitListFree()
885 * Walks along a hit list and frees its contents
886 ************************************************************************/
887 static void HitListFree(
888 _DtHelpGlobSrchVol * vol,
889 Boolean freeHitsThemselves)
891 register _DtHelpGlobSrchHit * hit;
893 if (NULL == vol) return; /* RETURN */
895 for ( hit = vol->hitListHead;
897 hit = HitFree(hit,freeHitsThemselves) )
900 /* reset search flags */
901 vol->nothingDone = True;
902 vol->topicSearchDone = False;
903 vol->indexSearchDone = False;
904 vol->searchCompleted = False;
905 vol->searchedCnt = 0;
906 vol->gatheredFullIndex = False;
908 /* reset hit flags */
909 vol->hitsDisplayed = False;
910 vol->showHitsWithVol = False;
911 vol->zeroHitsOk = False;
914 /* reset list display flags */
915 vol->startPosition = 1;
916 vol->nextVolPosition = 1;
918 /* dont free indexXmStrsList here because they
919 are reused for every search on this volume */
920 vol->curIndexXmStr = vol->indexXmStrsList;
922 /* indexEntriesList,volhandle inited elsewhere */
924 if (freeHitsThemselves)
926 vol->hitListHead = NULL;
927 vol->hitListTail = NULL;
932 /************************************************************************
933 * Function: HitListFreeAllVolHits()
935 * Walks along all the volumes and frees their hits
936 ************************************************************************/
938 HitListFreeAllVolHits (
939 DtHelpDialogWidget hw,
940 Boolean freeFullIndex)
942 _DtHelpGlobSrchVol * vol;
943 _DtHelpFileEntry curFile;
945 /* walk the files, freeing all hits and their data */
946 for ( curFile = hw->help_dialog.srch.volListHead;
948 curFile = _DtHelpFileListGetNext(NULL,curFile) )
950 vol = (_DtHelpGlobSrchVol *) curFile->clientData;
952 if (NULL == vol) continue; /* CONTINUE */
953 if (vol->gatheredFullIndex && freeFullIndex == False) continue;
954 HitListFree(vol,True); /* True: free hits themselves */
956 hw->help_dialog.srch.hitsFound = False;
960 /************************************************************************
961 * Function: HitListGetNth()
963 * Retrieves the Nth entry from the hits contained in the VolList
965 * This code follows the same counting paradigm used when adding
966 * the items to the srchResultList widget, so that we can just use the
967 * position value returned by it to retrieve the selected item.
969 * This paradigm also counts the presence of a volume as an item
970 * if it contains any hits, and doesn't count it if it contains
971 * no hits. It also counts the topicTitles that are associated
972 * with a hit and displayed indented beneath it.
974 * The position count is 1 based, which corresponds with the
978 * ret_hit: retuns NULL if an error or a pointer to the hit structure.
979 * ret_locationId: returns NULL is position is for the hit
980 * structure itself, returns a pointer to private
981 * memory containing the location id if position
982 * is a topic belonging to the hit.
984 * Returns: 0 if ok, -1 if error
985 ************************************************************************/
986 static int HitListGetNth (
987 _DtHelpFileList volListHead,
989 _DtHelpFileEntry * ret_file,
990 _DtHelpGlobSrchHit * * ret_hit,
991 char * * ret_locationId,
992 char * * ret_helpFile)
994 _DtHelpGlobSrchHit * hit = NULL;
995 _DtHelpGlobSrchVol * curVol;
996 _DtHelpFileEntry curFile = NULL;
997 _DtHelpFileEntry posFile = NULL;
998 char * * locationIdList = NULL;
999 char * * fileNameList = NULL;
1002 if (NULL == volListHead) goto done; /* GOTO on error */
1004 /* walk along the volumes to find the one containing the position
1005 Because we need the most recent file with hits before the
1006 nextFile that has too high a position, only set posFile when
1007 we aren't ready to stop yet and we're on a file with hits. */
1008 for ( curFile = volListHead;
1010 curFile = _DtHelpFileListGetNext(curFile,curFile) )
1012 /* it is impt to use > test so that multiple volumes with the same
1013 start position are properly handled. This occurs when they
1014 have no hits in them. */
1015 curVol = (_DtHelpGlobSrchVol *) curFile->clientData;
1016 if (NULL == curVol) continue;
1018 if (curVol->startPosition > position) break; /* BREAK */
1019 if (curVol->hitCnt > 0) posFile = curFile; /* recent with hits */
1021 if (curVol->showVolInList && curVol->nextVolPosition > position)
1028 if(NULL == posFile) goto done; /* GOTO on error */
1030 /*** walk along the hits to find the one matching the position ***/
1031 curVol = (_DtHelpGlobSrchVol *) posFile->clientData;
1032 curPos = curVol->startPosition;
1034 locationIdList = NULL;
1035 fileNameList = NULL;
1037 /* (position == curPos) ==> volume name itself was selected */
1038 if ( curPos < position )
1039 { /* a hit inside the volume */
1040 if ( curVol->hitsDisplayed )
1042 for ( curPos++, hit = curVol->hitListHead;
1043 curPos < position && NULL != hit;
1044 curPos++, hit = hit->next )
1046 if (False == hit->topicsDisplayed) continue; /* CONTINUE */
1048 /* walk all displayed topics to see if the position is here */
1049 for ( locationIdList=hit->topicIdList,fileNameList=hit->topicFileList;
1050 NULL != locationIdList[0];
1051 locationIdList++, fileNameList++ )
1053 /* use GOTO to escape with all pointers correct and
1054 without introducing an additional flag variable */
1055 if (++curPos == position) goto done; /* GOTO */
1056 } /* for all locations of a hit before the position */
1057 } /* for all members of the hit list before the position */
1058 } /* if hits are currently shown */
1059 else posFile = NULL; /* an error occurred */
1060 } /* if position is in the hit list */
1063 if (ret_hit) *ret_hit = hit;
1064 if (ret_file) *ret_file = posFile;
1067 if ( locationIdList ) *ret_locationId = locationIdList[0];
1068 else *ret_locationId = NULL;
1072 if ( fileNameList ) *ret_helpFile = fileNameList[0];
1073 else *ret_helpFile = NULL;
1075 /* WARNING: depends on pointers and integers the same size */
1077 return (0 == ((int64_t)hit|(int64_t)posFile|(int64_t)locationIdList)) ? -1 : 0;
1079 return (0 == ((int)hit|(int)posFile|(int)locationIdList)) ? -1 : 0;
1085 /************************************************************************
1086 * Function: HitListAddFound()
1088 * Adds a hit to the hit list of the specified volume
1089 * The hits are added either to the end of the list,
1090 * so that the srchResultList presents the items in the order found,
1091 * or in a sorted order.
1092 * If a hit on that topic already exists, just the existing
1093 * hit structure is returned.
1095 * Return Parameters:
1096 * Ret_hit points to the hit data. This is not a copy--do not
1100 * Returns 0 if no error, -1 if an error occurred.
1101 ************************************************************************/
1102 static int HitListAddFound (
1103 _DtHelpFileEntry curFile,
1104 XmString indexTitle,
1106 Boolean insertSorted,
1107 _DtHelpGlobSrchHit **ret_hit)
1109 _DtHelpGlobSrchHit * prev;
1110 _DtHelpGlobSrchHit * next;
1111 _DtHelpGlobSrchHit * srcHit;
1112 _DtHelpGlobSrchVol * vol;
1114 extern _CEStrcollProc _DtHelpCeGetStrcollProc();
1115 _CEStrcollProc strcollfn = _DtHelpCeGetStrcollProc();
1117 if (NULL == curFile) return -1; /* RETURN */
1118 vol = (_DtHelpGlobSrchVol *) curFile->clientData;
1119 if (NULL == vol) return -1; /* RETURN */
1121 /* walk along the hits, looking for one matching the new hit */
1122 /* recall that position is 1-based */
1123 newKey = _DtHelpCeStrHashToKey(indexEntry);
1125 if ( insertSorted ) /* find position and check for duplicates */
1127 /* walk along list */
1128 for( next = vol->hitListHead;
1130 prev = next, next = next->next )
1134 /* do a NLS case insensitive compare using NLS collating */
1135 if ( (ret = (*strcollfn)(next->indexEntry,indexEntry)) >= 0 )
1139 if(ret_hit) *ret_hit = next;
1140 return 0; /* RETURN */
1142 /* prev and next are set correctly */
1147 else /* check for duplicates */
1149 /* walk along list */
1150 for( next = vol->hitListHead;
1152 prev = next, next = next->next )
1154 if ( newKey == next->indexKey /* quick compare */
1155 && strcmp(indexEntry,next->indexEntry) == 0 ) /* long compare */
1157 if(ret_hit) *ret_hit = next;
1158 return 0; /* RETURN */
1161 /* prev and next are set correctly (at end of list) */
1164 /* handle a new hit */
1165 srcHit = (_DtHelpGlobSrchHit *)XtCalloc(1,sizeof(_DtHelpGlobSrchHit));
1166 if (NULL == srcHit) return -1; /* RETURN */
1168 /* init hit values */
1169 /* leave srcHit->hitCnt == 0 here */
1170 if (NULL == indexTitle)
1171 srcHit->indexTitle = XmStringCreateLocalized(indexEntry);
1173 srcHit->indexTitle = indexTitle;
1174 srcHit->indexEntry = XtNewString(indexEntry);
1175 srcHit->indexKey = newKey;
1176 srcHit->volume = curFile;
1178 /* integrate hit into the list */
1179 srcHit->next = next;
1180 if (prev) prev->next = srcHit;
1181 else vol->hitListHead = srcHit;
1182 if (!next) vol->hitListTail = srcHit;
1184 /* add in the volume contribution */
1188 if(ret_hit) *ret_hit = srcHit;
1194 /************************************************************************
1195 * Function: CountSelectedVolumes()
1197 * Counts the number volumes with the searchThisVolume flag set
1198 * for which the search has yet to complete
1200 ************************************************************************/
1201 static int CountSelectedVolumes (
1202 _DtHelpFileList volListHead,
1203 Boolean countSearchCompletedVolumes)
1207 /* walk all volumes */
1208 for ( /* nothing */;
1209 NULL != volListHead;
1210 volListHead = _DtHelpFileListGetNext(NULL, volListHead) )
1212 register _DtHelpGlobSrchVol * vol;
1214 /* get the volume info */
1215 vol = (_DtHelpGlobSrchVol *) volListHead->clientData;
1216 /* if (NULL != vol && vol->searchThisVolume && False == vol->searchCompleted)*/
1217 if (vol && vol->searchThisVolume)
1219 if ( (False == vol->searchCompleted)
1220 || (countSearchCompletedVolumes && vol->searchCompleted) )
1223 } /* walk all volumes */
1229 /************************************************************************
1230 * Function: GetNextSearchFileAndDisplayCompleted()
1232 * Scans list for next file ready for searching
1233 * If it encounters a file that has completed it's search
1234 * and for which the results should be displayed, they are displayed
1236 ************************************************************************/
1237 static _DtHelpFileEntry GetNextSearchFileAndDisplayCompleted(
1238 DtHelpDialogWidget hw,
1239 _DtHelpFileList listHead,
1240 _DtHelpFileEntry curFile)
1242 /* get first file needing work */
1243 for ( curFile = _DtHelpFileListGetNext(listHead, curFile);
1245 curFile = _DtHelpFileListGetNext(NULL, curFile) )
1247 register _DtHelpGlobSrchVol * vol;
1249 vol = (_DtHelpGlobSrchVol *) curFile->clientData;
1250 if (NULL == vol) continue; /* CONTINUE */
1252 /* if file already searched and should be displayed, then do so */
1253 if ( vol->searchThisVolume && vol->searchCompleted
1254 && vol->showVolInList && (vol->hitCnt > 0 || vol->zeroHitsOk) )
1256 /* record that a hit found */
1257 if ( vol->hitCnt > 0
1258 || ( vol->zeroHitsOk
1259 && _DtHelpGlobSrchSelectedVolumes == hw->help_dialog.srch.srchSources))
1260 hw->help_dialog.srch.hitsFound = True;
1262 /* True: adjust count beginning with this file */
1263 AdjustPositionValues(curFile,0,1,True);
1264 ResultsListUpdate(hw,curFile);
1266 /* display the hits as well? */
1267 if ( vol->showHitsWithVol
1268 || hw->help_dialog.srch.srchSources == _DtHelpGlobSrchCurVolume)
1270 VolHitsDisplay(hw,curFile);
1272 /* update the volume label to show state; False--dont insert */
1273 VolNameDisplay(hw,curFile,False);
1277 /* if want to search, and need to, then return it */
1278 if ( vol->searchThisVolume && False == vol->searchCompleted
1279 && vol->showVolInList ) /* don' search unless results will be shown */
1283 XmUpdateDisplay((Widget) hw->help_dialog.srch.resultList);
1289 /************************************************************************
1290 * Function: AddVolInfoToFile
1292 * Creates a volume info entry for each member of the list
1293 * and initializes its values
1294 * If searchStatus is False, all volumes are set. If its True,
1295 * all are set if selectedFilesOnly is false, otherwise only
1296 * selected files are set to true.
1298 ************************************************************************/
1299 static void AddVolInfoToFile(
1300 _DtHelpFileEntry file,
1301 Boolean initialSearchStatus,
1302 Boolean displayStatus,
1303 Boolean selectedFilesOnly)
1305 _DtHelpGlobSrchVol * vol;
1307 if (NULL == file) return; /* RETURN */
1309 vol = (_DtHelpGlobSrchVol *) file->clientData;
1312 vol = (_DtHelpGlobSrchVol *) XtCalloc(1,sizeof(_DtHelpGlobSrchVol));
1313 file->clientData = (XtPointer) vol;
1314 if (NULL == vol) return; /* RETURN: memory alloc error */
1316 /* calloc() inited almost everything inside to 0 */
1317 /* set first time creation values */
1318 vol->nothingDone = True;
1321 /* now set search and display flags */
1322 vol->searchThisVolume = initialSearchStatus;
1323 vol->showVolInList = displayStatus;
1324 if ( False == file->fileSelected && True == selectedFilesOnly )
1326 vol->searchThisVolume = False;
1327 vol->showVolInList = False;
1332 /************************************************************************
1333 * Function: AddVolInfoToList
1335 * Creates a volume info entry for each member of the list
1336 * and initializes its values
1337 * If searchStatus is False, all volumes are set. If its True,
1338 * all are set if selectedFilesOnly is false, otherwise only
1339 * selected files are set to true.
1341 ************************************************************************/
1342 static void AddVolInfoToList(
1343 _DtHelpFileList listHead,
1344 Boolean initialSearchStatus,
1345 Boolean displayStatus,
1346 Boolean selectedFilesOnly)
1348 /* walk the files and allocate the vol info as needed */
1351 listHead = _DtHelpFileListGetNext(listHead,listHead) )
1353 AddVolInfoToFile(listHead,
1354 initialSearchStatus, displayStatus, selectedFilesOnly);
1360 /************************************************************************
1361 * Function: SetVolStatus()
1363 * Sets all volumes in the list to the specified search and/or display
1366 * If searchThisVolume is False, all volumes are set. If its True,
1367 * all are set if selectedFilesOnly is false, otherwise only
1368 * selected files are set to true. If searchThisVolume is False,
1369 * then the settings remain unchanged in all volumes.
1371 ************************************************************************/
1372 static void SetVolStatus(
1373 _DtHelpFileList listHead,
1374 Boolean searchThisVolume,
1375 Boolean showVolInList,
1377 Boolean selectedFilesOnly)
1379 /* walk the files and set the status */
1382 listHead = _DtHelpFileListGetNext(listHead,listHead) )
1384 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) listHead->clientData;
1386 if (NULL == vol) continue;
1388 if ( (False == selectedFilesOnly)
1389 || (True == listHead->fileSelected && True == selectedFilesOnly) )
1391 /* just set the inclusion and/or display flags;
1392 don't reset the search progress flags */
1393 vol->searchThisVolume = searchThisVolume;
1394 vol->showVolInList = showVolInList;
1395 vol->zeroHitsOk = zeroHitsOk;
1401 /************************************************************************
1402 * Function: VolNameDisplay()
1404 * Updates the display of the volume name
1405 ************************************************************************/
1406 static void VolNameDisplay(
1407 DtHelpDialogWidget hw,
1408 _DtHelpFileEntry file,
1411 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) file->clientData;
1412 XmString prefixString;
1413 XmString labelString;
1417 if ( NULL == vol || (False == vol->zeroHitsOk && 0 == vol->hitCnt) )
1418 return; /* RETURN */
1420 /* put volume name into list */
1421 if (vol->hitCnt <= 0) tmpStr = (char *)_DTGETMESSAGE (GSSET, 25," ");
1422 else if (vol->hitsDisplayed) tmpStr = (char *)_DTGETMESSAGE (GSSET, 27,"-");
1423 else tmpStr = (char *)_DTGETMESSAGE (GSSET, 26,"+"); /* >0 hits */
1424 sprintf(buf, "%s%3d ", tmpStr, vol->hitCnt); /* 4d too spacy */
1427 prefixString = XmStringGenerate(buf, s_PrefixFontListTag,
1428 XmCHARSET_TEXT, NULL);
1429 labelString = XmStringConcat(prefixString,file->fileTitleXmStr);
1431 /* replace or insert to reflect changed contents */
1433 XmListAddItemUnselected(hw->help_dialog.srch.resultList,
1434 labelString, vol->startPosition);
1436 XmListReplaceItemsPosUnselected(hw->help_dialog.srch.resultList,
1437 &labelString, 1, vol->startPosition);
1439 XmStringFree(prefixString);
1440 XmStringFree(labelString);
1444 /************************************************************************
1445 * Function: VolHitsDisplay()
1447 * displays the hits associated with a volume
1448 * Returns the number of new items added to the list
1449 ************************************************************************/
1450 static int VolHitsDisplay (
1451 DtHelpDialogWidget hw,
1452 _DtHelpFileEntry file)
1454 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) file->clientData;
1455 _DtHelpGlobSrchHit * hit;
1456 int listPos = vol->startPosition; /* vol item position */
1459 if (True == vol->hitsDisplayed ) return 0; /* RETURN */
1461 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.srchForm));
1462 if (hw->help_dialog.srch.selectionDlg)
1463 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
1465 /*** walk through the hits and count and display any open hits ***/
1466 for ( hit = vol->hitListHead, itemCnt = 0;
1470 itemCnt++; /* True: insert Hit into list */
1471 HitNameDisplay (hw,file,hit,listPos + itemCnt,True);
1473 /* display topics too? */
1474 if (hit->showTopicsWithHit)
1477 newItems = HitTopicsDisplay(hw,file,hit, listPos + itemCnt + 1);
1478 HitNameDisplay (hw,file,hit,listPos + itemCnt,False);
1479 itemCnt += newItems;
1484 vol->hitsDisplayed = True;
1485 vol->showHitsWithVol = True;
1487 /* adjust count beginning with next file with hits */
1488 AdjustPositionValues(file, 0, itemCnt, True);
1490 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.srchForm));
1491 if (hw->help_dialog.srch.selectionDlg)
1492 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
1499 /************************************************************************
1500 * Function: VolHitsUndisplay()
1502 * undisplays the hits associated with a volume
1503 ************************************************************************/
1504 static int VolHitsUndisplay (
1505 DtHelpDialogWidget hw,
1506 _DtHelpFileEntry file)
1508 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) file->clientData;
1509 _DtHelpGlobSrchHit * hit;
1510 Boolean nonVisibleItems;
1511 int listPos = vol->startPosition; /* vol item position */
1520 if (False == vol->hitsDisplayed) return 0; /* RETURN */
1522 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.srchForm));
1523 if (hw->help_dialog.srch.selectionDlg)
1524 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
1526 XtSetArg(args[0], XmNtopItemPosition, &topPos);
1527 XtSetArg(args[1], XmNvisibleItemCount, &visItemCnt);
1528 XtGetValues(hw->help_dialog.srch.resultList,args,2);
1530 /* these are the num visible items below the volume name */
1531 topNonVisPos = topPos + visItemCnt; /* 1st non vis pos */
1533 /* num of items that will be undisplayed */
1534 undisItemCnt = vol->nextVolPosition - (vol->startPosition + 1);
1536 /* find out if any items aren't visible */
1537 nonVisibleItems = False;
1538 if ( vol->nextVolPosition > topNonVisPos )
1539 nonVisibleItems = True;
1541 /*** walk through the hits and count and delete any open topics ***/
1542 /* Make two passes: the first pass deletes all non-visible
1543 items. The second pass deletes the remaining visible items.
1544 The objective is to make collapse as fast and smooth as expand. */
1545 if (nonVisibleItems)
1546 { /* delete all items with a position > topNonVisPos */
1547 curDelPos = listPos + 1; /* starting position */
1548 for ( hit = vol->hitListHead, itemCnt = 0;
1552 /* are we still in the visible region? */
1553 if (curDelPos < topNonVisPos)
1555 /* move down the list to next hit */
1556 curDelPos++; /* this hit's item */
1557 /* plus any open topics */
1558 if (hit->topicsDisplayed) curDelPos += hit->topicCnt;
1559 continue; /* CONTINUE */
1561 /* we're in non-visible region--undisplay hit */
1562 XmListDeletePos(hw->help_dialog.srch.resultList, curDelPos);
1563 /* undisplay any topics */
1564 if ( hit->topicsDisplayed )
1565 itemCnt += HitTopicsUndisplay(hw,file,hit,curDelPos);
1567 } /* if non visible items */
1569 /* now delete the remaining visible items */
1570 /* Note that curDelPos is a virtual cursor that helps us
1571 figure out when to stop undisplaying. Virtually, we''re
1572 moving the cursor down the list with every delete. Actually,
1573 the rest of the list bumps up one--that''s why we delete
1576 curDelPos = listPos + 1; /* starting position */
1577 for ( hit = vol->hitListHead, itemCnt = 0;
1578 (NULL != hit) && (curDelPos < topNonVisPos);
1581 curDelPos++; /* undisplay hit item */
1582 XmListDeletePos(hw->help_dialog.srch.resultList, listPos + 1);
1583 /* undipslay any open topics */
1584 if ( hit->topicsDisplayed )
1586 curDelPos += HitTopicsUndisplay(hw,file,hit,listPos + 1);
1587 XmListSetPos(hw->help_dialog.srch.resultList, topPos);
1592 vol->hitsDisplayed = False;
1593 /* NOTE: don't reset vol->showHitsWithVol here; require that
1594 to be explicitly reset in ProcessResultSelection() */
1596 /* adjust count beginning with next file with hits */
1597 AdjustPositionValues(file, 0, -undisItemCnt, True);
1599 XmListSetPos(hw->help_dialog.srch.resultList, topPos);
1601 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.srchForm));
1602 if (hw->help_dialog.srch.selectionDlg)
1603 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
1605 return undisItemCnt;
1610 /************************************************************************
1611 * Function: VolListFree()
1613 * Releases all memory used by the volume list
1615 ************************************************************************/
1616 static void VolListFree (
1617 _DtHelpGlobSearchStuff * srch)
1619 _DtHelpFileList nextFile;
1621 /* walk all volumes */
1622 nextFile = srch->volListHead;
1623 while ( NULL != nextFile )
1625 _DtHelpGlobSrchVol * vol;
1626 _DtHelpFileList tmpFile;
1629 /* get the volume info */
1630 vol = (_DtHelpGlobSrchVol *) nextFile->clientData;
1632 /** free vol entry contents and container **/
1633 XtFree(vol->stdLocale);
1634 XtFree(vol->iconv3Codeset);
1635 HitListFree(vol,True); /* True: free hits themselves */
1637 /* no need to free indexEntriesList because these aren't owned by vol */
1638 vol->indexEntriesList = NULL;
1640 /* free indexXmStrsList */
1641 /* indexXmStrs are XmStrings and we can't use FreeStringArray() */
1642 for ( nextStr = vol->indexXmStrsList;
1643 NULL != nextStr && NULL != *nextStr;
1645 XmStringFree (*nextStr);
1646 XtFree((char *) vol->indexXmStrsList); /* its a XmString * */
1647 vol->indexXmStrsList = NULL;
1650 nextFile = _DtHelpFileListGetNext(NULL, nextFile);
1651 _DtHelpFileFreeEntry(tmpFile); /* also frees the clientData (vol) */
1652 } /* walk all volumes */
1654 /* reset related values */
1655 srch->volListHead = NULL;
1656 srch->curSrchVol = NULL;
1657 srch->volLeftCnt = 0;
1659 /* delete the results */
1660 DeleteListContents(srch);
1665 /************************************************************************
1666 * Function: ScanStatusCB
1668 * Updates the status display with the number of volumes found
1669 * as the scan progresses
1671 ************************************************************************/
1672 static void ScanStatusCB(
1674 XtPointer clientData)
1676 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
1678 StatusLabelUpdate(hw,SCANNING_STATUS,True,count);
1682 /************************************************************************
1683 * Function: VolListBuild
1685 * Frees the old list and builds a new one by scanning the
1686 * help directories for volumes and adding the associated
1687 * volume information used for searching.
1689 ************************************************************************/
1690 static void VolListBuild(
1691 DtHelpDialogWidget hw,
1692 Boolean searchStatus,
1693 Boolean displayStatus,
1694 Boolean selectedVolumesOnly)
1697 XmFontList origFontList;
1699 /* turn on hour glass */
1700 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.srchForm));
1701 if (hw->help_dialog.srch.selectionDlg)
1702 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
1704 StatusLabelUpdate(hw,SCANNING_STATUS,True,0);
1706 origFontList = hw->help_dialog.srch.volTitlesFontList;
1708 /* and rescan the volumes for the new list */
1709 _DtHelpFileListScanPaths( &hw->help_dialog.srch.volListHead,
1710 &hw->help_dialog.srch.volTitlesFontList,&mod,
1711 DtHelpVOLUME_TYPE, _DtHelpFileSuffixList, False,
1712 GetVolumeInfoCB,hw->help_dialog.help.pDisplayArea,
1713 /* sysPathCompare */ _DtHELP_FILE_NAME,
1714 /*otherPathCompare*/ _DtHELP_FILE_NAME|_DtHELP_FILE_TIME| _DtHELP_FILE_IDSTR,
1715 /* sortBy */ _DtHELP_FILE_TITLE, ScanStatusCB, (XtPointer)hw);
1717 /* if new fonts added to list, add them to the resultList */
1720 MergeFontListIntoWidgetFonts(
1721 hw->help_dialog.srch.resultList,
1722 hw->help_dialog.srch.volTitlesFontList);
1724 if (origFontList) XmFontListFree(origFontList);
1727 /* Add on the Vol info and (T,F) allow search on all volumes */
1728 AddVolInfoToList(hw->help_dialog.srch.volListHead,
1729 searchStatus, displayStatus, selectedVolumesOnly);
1731 hw->help_dialog.srch.volScanDone = True;
1733 StatusLabelUpdate(hw,BLANK_STATUS,True,0);
1735 /* turn off hour glass */
1736 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.srchForm));
1737 if (hw->help_dialog.srch.selectionDlg)
1738 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
1743 #if 0 || defined(DEBUG) /* for debug, set to 1 */
1744 /************************************************************************
1745 * Function: OutputVolInfo()
1747 * Output info on all volumes in the list
1749 ************************************************************************/
1750 static void OutputVolInfo(
1751 _DtHelpFileList listHead)
1755 listHead = _DtHelpFileListGetNext(listHead,listHead) )
1757 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) listHead->clientData;
1758 if (NULL == vol) continue;
1760 /* output the info */
1761 printf("==================\n");
1762 printf("fileName: %s, %s\npathName: %s\n",
1763 listHead->fileName, listHead->fileTitle, listHead->fullFilePath);
1764 printf("searchThisVolume = %d, hitCnt = %d, startPos = %d\n",
1765 (int) listHead->fileSelected,
1767 (int) vol->startPosition);
1773 /************************************************************************
1774 * Function: SearchContinuePossible()
1776 * Test whether the search can be continued from the
1779 ************************************************************************/
1780 static Boolean SearchContinuePossible(
1781 DtHelpDialogWidget hw,
1784 char * normSrchWord;
1785 Boolean possible = False;
1787 normSrchWord = XtNewString(srchWord);
1788 _DtHelpCeCompressSpace(normSrchWord);
1789 _DtHelpCeUpperCase(normSrchWord);
1791 /* are we searching on the same word as previous search ? */
1792 /* comparison with srchNormWordStr is correct, given calls to this fn */
1793 /* FIX: use CheckSearchWord()? */
1794 if ( ( hw->help_dialog.srch.fullIndex
1795 || ( NULL != hw->help_dialog.srch.normWordStr
1796 && NULL != normSrchWord
1797 && strcmp(normSrchWord, hw->help_dialog.srch.normWordStr) == 0) )
1798 && NULL != hw->help_dialog.srch.volListHead
1799 && hw->help_dialog.srch.volLeftCnt > 0 )
1802 XtFree(normSrchWord);
1808 /************************************************************************
1809 * Function: SearchOnSameCriteria()
1811 * Test whether the search criteria have changed
1813 ************************************************************************/
1814 static Boolean SearchOnSameCriteria(
1815 DtHelpDialogWidget hw,
1818 char * normSrchWord;
1819 Boolean sameCrit = False;
1821 normSrchWord = XtNewString(srchWord);
1822 _DtHelpCeCompressSpace(normSrchWord);
1823 _DtHelpCeUpperCase(normSrchWord);
1825 /* are we searching on the same word as previous search ? */
1826 /* comparison with srchNormWordStr is correct, given calls to this fn */
1827 if ( hw->help_dialog.srch.fullIndex
1828 || ( NULL != hw->help_dialog.srch.normWordStr
1829 && NULL != normSrchWord
1830 && strcmp(normSrchWord, hw->help_dialog.srch.normWordStr) == 0) )
1833 XtFree(normSrchWord);
1836 #endif /* not_used */
1841 /************************************************************************
1842 * Function: UpdateActionButtonLabel()
1844 * Sets the start button label properly
1846 ************************************************************************/
1847 static void UpdateActionButtonLabel(
1848 DtHelpDialogWidget hw,
1850 Boolean startContAction)
1853 XmString labelString;
1854 XmString curLabelString;
1856 /* char * mnemonic; */
1858 /* if action label is to start or continue */
1859 _DtHelpProcessLock();
1860 if (startContAction)
1862 if ( SearchContinuePossible(hw,srchWord) )
1863 { /* then continue search */
1864 textString=(char *)_DTGETMESSAGE (GSSET,
1865 CONT_SEARCH_CAT,CONT_SEARCH_STR);
1866 labelString = XmStringCreateLocalized(textString);
1867 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 22,CONT_SEARCH_MNEM));*/
1870 { /* otherwise start it */
1871 textString=(char *)_DTGETMESSAGE (GSSET,
1872 START_SEARCH_CAT,START_SEARCH_STR);
1873 labelString = XmStringCreateLocalized(textString);
1874 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 20,START_SEARCH_MNEM));*/
1877 else /* action label is to stop */
1879 textString = (char *)_DTGETMESSAGE (GSSET,
1880 STOP_SEARCH_CAT,STOP_SEARCH_STR);
1881 labelString = XmStringCreateLocalized(textString);
1882 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, ??,STOP_SEARCH_MNEM));*/
1884 _DtHelpProcessUnlock();
1886 /* get the current state of the button */
1887 XtSetArg(args[0],XmNlabelString,&curLabelString);
1888 XtGetValues (hw->help_dialog.srch.actionBtn, args, 1);
1890 /* update label if it is different; avoid flashing this way */
1891 if ( XmStringCompare(labelString,curLabelString) == False )
1893 XtSetArg(args[0],XmNlabelString,labelString);
1894 XtSetArg(args[1], XmNalignment, XmALIGNMENT_CENTER);
1895 /* XtSetArg(args[2], XmNmnemonic, mnemonic[0]);*/
1896 XtSetValues (hw->help_dialog.srch.actionBtn, args, 2);
1897 XmUpdateDisplay(hw->help_dialog.srch.actionBtn);
1900 /* release the memory */
1901 XmStringFree(labelString);
1902 XmStringFree(curLabelString);
1906 /*****************************************************************************
1907 * Function: CheckSearchWord()
1911 * Return Value: True: word has changed
1912 * False: word is same
1914 * Purpose: Checks whether the search word is a new
1915 * one or the same as before. If the same, it frees
1916 * the word and returns False. If new, it moves the
1917 * previous word to another variable and installs
1918 * the new word in its place, using the srchWord mem.
1919 * ...but only if updateWidgetFields is True
1921 *****************************************************************************/
1922 static Boolean CheckSearchWord(
1923 DtHelpDialogWidget hw,
1925 Boolean updateWidgetFields)
1930 /* avoid a core dump */
1931 if ( NULL == srchWord )
1933 if ( NULL == hw->help_dialog.srch.normWordStr
1934 || hw->help_dialog.srch.normWordStr[0] == 0)
1935 return False; /* word hasn't changed */
1936 return True; /* RETURN: word has changed */
1939 _DtHelpCeCompressSpace(srchWord);
1940 rawSrchWord = XtNewString(srchWord);
1941 _DtHelpCeUpperCase(srchWord);
1942 /* FIX: to support regcomp(3), do that here */
1944 /* are we searching on the same word? */
1945 if ( NULL != hw->help_dialog.srch.normWordStr
1946 && strcmp(srchWord, hw->help_dialog.srch.normWordStr) == 0 )
1949 XtFree(rawSrchWord);
1951 /* output a message */
1952 if ( NULL != hw->help_dialog.srch.normWordStr
1953 && EOS != hw->help_dialog.srch.normWordStr[0])
1954 StatusLabelUpdate(hw,FIRST_PROMPT_STATUS,False,0);
1957 return False; /* RETURN: no change */
1960 if (False == updateWidgetFields) return True; /* RETURN */
1962 /* update search word fields */
1963 XtFree(hw->help_dialog.srch.normWordStr);
1964 XtFree(hw->help_dialog.srch.rawWordStr);
1965 hw->help_dialog.srch.normWordStr = srchWord;
1966 hw->help_dialog.srch.rawWordStr = rawSrchWord;
1967 hw->help_dialog.srch.wordFieldLen = strlen(srchWord); /* note: not nl_strlen
1968 because used on strncmp not nl_strncmp */
1970 /* convert first char to a value for easy access for _DtHelpStrchr() */
1971 if ( mbtowc(&firstChar,srchWord,1) <= 0 ) firstChar = 0;
1972 hw->help_dialog.srch.wordFieldFirstChar = firstChar;
1974 /* output a message */
1975 if ( NULL != hw->help_dialog.srch.normWordStr
1976 && EOS != hw->help_dialog.srch.normWordStr[0])
1977 StatusLabelUpdate(hw,FIRST_PROMPT_STATUS,False,0);
1979 return True; /* word changed */
1984 /*****************************************************************************
1985 * Function: PrepSearchSourceData()
1989 * Return Value: Void.
1991 * Purpose: Based on the current settings of the volume
1992 * selection buttons construct or utilitize an
1993 * existing volume list for processing.
1994 * Determine whether to continue search or
1995 * restart by comparing search words and states.
1997 *****************************************************************************/
1998 static void PrepSearchSourceData(
1999 DtHelpDialogWidget hw,
2002 /* try to install the new word; if returns False, word is same
2003 as before. True = also update widget fields. */
2004 /* This test determines whether we might need to continue. */
2005 if ( hw->help_dialog.srch.fullIndex
2006 || CheckSearchWord(hw,srchWord,True) == False )
2008 /* check to see if CheckSearchWord() was called. If it wasn't
2009 then srchWord has not been freed or saved. We will lose the
2010 memory unless we free it here. */
2011 if (hw->help_dialog.srch.fullIndex)
2014 /* are we continuing an interrupted search? */
2015 if ( hw->help_dialog.srch.volLeftCnt > 0
2016 && NULL != hw->help_dialog.srch.volListHead )
2017 return; /* RETURN: continue with search */
2019 /* if searching full index, False=dont free vol with full index */
2020 if (hw->help_dialog.srch.fullIndex)
2021 HitListFreeAllVolHits(hw,False);
2022 /* else we're searching on the same word, but completed
2023 previous search. So reset the volumes to search/display
2024 according to the current settings of the Volumes radio buttons,
2025 but leave the results intact.
2027 /* fall thru to do prep */
2029 else /* searching for a different word */
2031 /* free all hit-related data and reset flags */
2032 HitListFreeAllVolHits(hw,True); /*True=free everything*/
2035 /*** It's not just a continue. So, we may be beginning a new search
2036 or continuing a search based on new volume selection params ***/
2038 /* update display area */
2039 DeleteListContents(&hw->help_dialog.srch);
2040 StatusLabelUpdate(hw,WORKING_STATUS,False,0);
2042 /*** update the volumes list according to sources selected ***/
2043 if ( _DtHelpGlobSrchSelectedVolumes == hw->help_dialog.srch.srchSources )
2045 /* volume list already built when opening selection dialog */
2046 /* (F,F,F,F): disable search,disable display,no 0 hits,for all vols */
2047 SetVolStatus(hw->help_dialog.srch.volListHead,False,False,False,False);
2048 /* (T,T,T,T): enable search, enable display,
2049 zero hits ok, only for selected volumes */
2050 SetVolStatus(hw->help_dialog.srch.volListHead,True,True,True,True);
2051 } /* if selected volumes button */
2052 else if ( _DtHelpGlobSrchAllVolumes == hw->help_dialog.srch.srchSources )
2054 /* Scan directories for volumes if necessary */
2055 if ( False == hw->help_dialog.srch.volScanDone
2056 || NULL == hw->help_dialog.srch.volListHead)
2058 /* Add on the Vol info; (T,T,F) search, display, all */
2059 VolListBuild(hw,True,True,False);
2062 /* (T,T,F,F): enable search,enable display,no 0 hits,for all vols */
2063 SetVolStatus(hw->help_dialog.srch.volListHead,True,True,False,False);
2064 } /* if all volumes button */
2065 else /*** current volume button ***/
2068 _DtHelpFileEntry cur;
2070 /* (F,F,F,F): disable search,disable display,no 0 hits,for all vols */
2071 SetVolStatus(hw->help_dialog.srch.volListHead,False,False,False,False);
2073 /* try to locate file and its entry, if present */
2074 path = _DtHelpFileLocate(DtHelpVOLUME_TYPE, hw->help_dialog.display.helpVolume,
2075 _DtHelpFileSuffixList,False,R_OK);
2076 cur = _DtHelpFileListGetMatch(hw->help_dialog.srch.volListHead,path,
2077 GetVolumeInfoCB, _DtHELP_FILE_NAME,
2078 hw->help_dialog.help.pDisplayArea);
2080 if (NULL == cur && NULL != path) /*file was located but isn't in list*/
2081 { /* add it to the list */
2083 XmFontList origFontList;
2085 origFontList = hw->help_dialog.srch.volTitlesFontList;
2087 _DtHelpFileListAddFile(&hw->help_dialog.srch.volListHead,
2088 &hw->help_dialog.srch.volTitlesFontList,&mod,path,NULL,
2089 GetVolumeInfoCB, _DtHELP_FILE_NAME, _DtHELP_FILE_TITLE,
2090 hw->help_dialog.help.pDisplayArea);
2093 MergeFontListIntoWidgetFonts(
2094 hw->help_dialog.srch.resultList,
2095 hw->help_dialog.srch.volTitlesFontList);
2097 if (origFontList) XmFontListFree(origFontList);
2100 /* (F,F,F): disable search, disable display, for all volumes */
2101 AddVolInfoToList(hw->help_dialog.srch.volListHead,False,False,False);
2102 cur = _DtHelpFileListGetMatch(hw->help_dialog.srch.volListHead,path,
2103 GetVolumeInfoCB, _DtHELP_FILE_NAME,
2104 hw->help_dialog.help.pDisplayArea);
2107 if (cur) /* file present in list */
2109 /* enable search and display on this volume */
2110 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) cur->clientData;
2112 vol->searchThisVolume = True;
2113 vol->showVolInList = True;
2114 vol->zeroHitsOk = True; /* show zero hits for search of cur vol */
2116 else /* file not found */
2118 /* FIX: put up error dialog and disable the button */
2119 /*printf("Current volume %s not found\n",
2120 hw->help_dialog.display.helpVolume);*/
2121 } /* if file found */
2123 XtFree(path); /* tests for NULL */
2124 } /* if selected/all/cur volumes sources */
2126 #if 0 || defined(DEBUG) /* for debug, set to 1 */
2127 OutputVolInfo(hw->help_dialog.srch.volListHead);
2130 /* get num volumes to process */
2131 hw->help_dialog.srch.volLeftCnt =
2132 CountSelectedVolumes(hw->help_dialog.srch.volListHead,True);
2134 /* empty the results list */
2135 XmUpdateDisplay(hw->help_dialog.srch.resultList);
2139 /************************************************************************
2140 * Function: CloseSearchCB()
2142 * Close the Global Search Dialog
2144 ************************************************************************/
2145 static void CloseSearchCB (
2147 XtPointer clientData,
2150 _DtHelpGlobSearchStuff * srch = (_DtHelpGlobSearchStuff *) clientData;
2152 /* stop any work proc */
2153 if(srch->workProcId)
2155 XtRemoveWorkProc(srch->workProcId);
2156 srch->workProcId = 0;
2159 /* unmanage the srchForm dialog but dont destroy it */
2160 if (NULL != srch->srchForm)
2162 XtUnmanageChild(srch->srchForm);
2163 XtUnmapWidget(srch->srchForm);
2168 /*****************************************************************************
2169 * Function: void DeleteListContents()
2173 * Return Value: Void.
2175 * Purpose: empties list and resets position values
2177 *****************************************************************************/
2178 static void DeleteListContents(
2179 _DtHelpGlobSearchStuff * srch)
2181 _DtHelpFileEntry curFile;
2183 if (NULL != srch->resultList)
2184 XmListDeleteAllItems(srch->resultList);
2186 for ( curFile = srch->volListHead;
2188 curFile = _DtHelpFileListGetNext(NULL,curFile) )
2190 register _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) curFile->clientData;
2191 if (NULL == vol) continue; /* CONTINUE */
2193 /* if any hits are displayed and any have open topics,
2194 walk through and close them */
2195 if ( vol->hitsDisplayed
2196 && ((vol->nextVolPosition - vol->startPosition) != vol->hitCnt) )
2198 register _DtHelpGlobSrchHit * hit;
2199 for ( hit = vol->hitListHead;
2203 hit->topicsDisplayed = False;
2207 vol->startPosition = 1;
2208 vol->nextVolPosition = 1;
2209 vol->hitsDisplayed = False;
2214 /*****************************************************************************
2215 * Function: void StatusLabelUpdate()
2219 * Return Value: Void.
2221 * Purpose: Installs proper label over results list
2223 *****************************************************************************/
2224 static void StatusLabelUpdate(
2225 DtHelpDialogWidget hw,
2226 ResultsStatus status,
2227 Boolean forceUpdate,
2231 XmString labelString;
2232 XmString curLabelString;
2237 /* only update if necessary */
2238 if (status == hw->help_dialog.srch.statusLineUsage && !forceUpdate)
2242 /* order up the right message */
2243 hw->help_dialog.srch.statusLineUsage = status;
2246 case SCANNING_STATUS:
2247 labelMsg = (char *)_DTGETMESSAGE(GSSET, 17,"Scanning for volumes... Found %d");
2248 sprintf(buf,labelMsg,intArg);
2251 case WORKING_STATUS:
2252 labelMsg = (char *)_DTGETMESSAGE(GSSET, 18,
2253 "Searching... Volumes remaining: %d");
2254 /* we need +1 because of when this message is used */
2255 sprintf(buf,labelMsg,hw->help_dialog.srch.volLeftCnt + 1);
2258 case SEARCH_RESULTS_STATUS:
2259 /* if no hits found */
2260 if (hw->help_dialog.srch.hitsFound == False) /*dont use == True*/
2262 if (hw->help_dialog.srch.fullIndex)
2264 if (hw->help_dialog.srch.srchSources == _DtHelpGlobSrchAllVolumes)
2265 labelMsg = (char *)_DTGETMESSAGE (GSSET,19,
2266 "No index entries found.");
2268 labelMsg = (char *)_DTGETMESSAGE (GSSET,50,
2269 "No index entries found. Try All Volumes.");
2271 else /* searched on a pattern */
2273 labelMsg = (char *)_DTGETMESSAGE (GSSET,51,
2274 "No index entries found. Try another word.");
2276 /* change focus to the search word. Traversal is ignored
2277 if srchWord is desensitized (Contains btn not selected) */
2279 if (XtIsSensitive(hw->help_dialog.srch.wordField))
2282 * make sure the text field is editable before sending
2283 * the traversal there.
2285 XtSetArg(args[0],XmNeditable,True);
2286 XtSetValues(hw->help_dialog.srch.wordField, args, 1);
2288 (hw->help_dialog.srch.wordField,XmTRAVERSE_CURRENT);
2292 (hw->help_dialog.srch.allVolRadBtn,XmTRAVERSE_CURRENT);
2295 else /* if hits found */
2297 /* select the appropriate message */
2298 if (hw->help_dialog.srch.fullIndex)
2300 labelMsg = (char *)_DTGETMESSAGE(GSSET, 20,"Complete Index");
2305 labelMsg = (char *)_DTGETMESSAGE(GSSET, 21,"Entries with \"%s\"");
2306 sprintf(buf,labelMsg,hw->help_dialog.srch.rawWordStr);
2310 /* change focus to the results list */
2312 hw->help_dialog.srch.resultList,XmTRAVERSE_CURRENT);
2315 } /* if no hits found else */
2319 labelMsg = (char *)_DTGETMESSAGE (GSSET, 22,"No volumes selected");
2321 case FIRST_PROMPT_STATUS:
2322 labelMsg = (char *)_DTGETMESSAGE(GSSET,23,"Select search options above");
2326 /* DBG: when an empty string, form constraints are wrong; make a space */
2331 /* make a label string */
2332 labelString = XmStringCreateLocalized(labelMsg);
2334 /* get the current string of the label */
2335 curLabelString = NULL;
2336 XtSetArg(args[0],XmNlabelString,&curLabelString);
2337 XtGetValues (hw->help_dialog.srch.statusLabel, args, 1);
2339 /* update label if it is different; avoid flashing this way */
2340 if ( NULL != curLabelString && NULL != labelString
2341 && XmStringCompare(labelString,curLabelString) == False )
2343 /* update msg over results list */
2344 XtSetArg(args[0],XmNlabelString,labelString);
2345 XtSetValues(hw->help_dialog.srch.statusLabel,args,1);
2348 XmStringFree(labelString);
2349 XmStringFree(curLabelString);
2351 XmUpdateDisplay(hw->help_dialog.srch.statusLabel);
2357 /*****************************************************************************
2358 * Function: void ResultsListUpdate()
2362 * Return Value: Void.
2364 * Purpose: empty list and display results status message
2366 *****************************************************************************/
2367 static void ResultsListUpdate(
2368 DtHelpDialogWidget hw,
2369 _DtHelpFileEntry newFile)
2371 _DtHelpFileEntry testFile;
2373 /* check that in fact, there are no results that will be overwritten */
2374 for ( testFile = hw->help_dialog.srch.volListHead;
2376 testFile = _DtHelpFileListGetNext(NULL,testFile) )
2378 register _DtHelpGlobSrchVol * vol;
2379 vol = (_DtHelpGlobSrchVol *)testFile->clientData;
2380 if (vol && vol->showVolInList && (vol->hitCnt > 0 || vol->zeroHitsOk))
2384 /* clean the list out if this is the first new result */
2385 /* this presumes that files are processed in order in the list */
2386 if (testFile == newFile)
2388 DeleteListContents(&hw->help_dialog.srch);
2389 AdjustPositionValues(newFile,0,1,True);
2391 /* True: insert new item */
2392 VolNameDisplay(hw,newFile,True);
2394 /* Update status label */
2395 StatusLabelUpdate(hw,SEARCH_RESULTS_STATUS,True,0); /* FIX: False */
2400 /*****************************************************************************
2401 * Function: void SearchForPattern()
2405 * Return Value: True if pattern found, False if not found
2407 * Purpose: Find a pattern in a string
2409 * WARNING: may convert string to uppercase in place
2410 * depending on which code is compiled.
2411 *****************************************************************************/
2412 static Boolean SearchForPattern(
2417 #if defined(NO_REGEX) /* don't support regex in string searches */
2420 _DtHelpCeUpperCase(string);
2421 /* FIX: make this code much faster by using an improved
2422 pattern search algorithm, such as Rabin-Karp. */
2423 /* hit is set to NULL if no matching char is found */
2424 while (_DtHelpCeStrchr(string, pattern, MB_CUR_MAX, &hit) == 0)
2426 if ( strncmp(hit,pattern,patternLen) == 0 )
2429 string = hit + mblen(hit,1);
2431 return (NULL != hit); /* RETURN True or False */
2432 #else /* if NO_REGEX */
2437 /* use regexec to pattern match */
2438 /* a 0 return value indicates success */
2439 if ( regcomp(&re,pattern,REG_NOSUB|REG_ICASE|REG_EXTENDED) == 0 )
2441 /* a 0 return value indicates success */
2442 ret = regexec(&re,string,0,NULL,0);
2445 return (ret == 0); /* RETURN True or False */
2446 # else /* NO_REGCOMP */
2450 /* a non NULL return value indicates success */
2451 compiledRE = (char *)regcmp(pattern, (char *) NULL);
2454 /* a non NULL return value indicates success */
2455 ret = regex(compiledRE, string);
2458 return (ret != NULL); /* RETURN True or False */
2459 # endif /* NO_REGCOMP */
2460 #endif /* if NO_REGEX */
2464 /*****************************************************************************
2465 * Function: void OpenVolForSearch()
2469 * Return Value: False if an error
2472 * Purpose: Opens a volume for searching,
2473 * gets the volume locale, if
2474 * different from system locale,
2475 * saves system locale in vol,
2476 * installs volume locale
2478 * Note that the system locale
2479 *****************************************************************************/
2480 static Boolean OpenVolForSearch(
2481 DtHelpDialogWidget hw,
2482 char * fullFilePath,
2483 _DtHelpGlobSrchVol * curVol)
2485 Boolean openedVolume = False;
2487 /* open the volume if not open */
2488 if ( NULL == curVol->volHandle )
2490 _DtHelpOpenVolume(fullFilePath, &curVol->volHandle);
2491 if (NULL == curVol->volHandle) return False; /* RETURN */
2493 if (curVol->gotLocale == False)
2495 curVol->stdLocale = _DtHelpGetVolumeLocale(curVol->volHandle);
2496 /* get the op-specific locales; the strings are default values */
2497 _DtHelpCeXlateStdToOpLocale(DtLCX_OPER_ICONV3,curVol->stdLocale,
2498 "iso88591",&curVol->iconv3Codeset);
2499 curVol->gotLocale = True;
2501 openedVolume = True;
2503 /* get the codeset of the application's locale, if haven't gotten it */
2504 if ( NULL == hw->help_dialog.srch.iconv3Codeset )
2506 char * locale = NULL;
2507 _DtHelpCeXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,
2508 setlocale(LC_CTYPE,NULL),&locale,NULL,NULL);
2509 /* get the op-specific locales; the strings are default values */
2510 /* impt: XlateStdToOpLocale() call requires a locale, not a codeset */
2511 _DtHelpCeXlateStdToOpLocale(DtLCX_OPER_ICONV3,locale,
2512 "iso88591",&hw->help_dialog.srch.iconv3Codeset);
2516 /** only saves or changes the locale if necessary **/
2517 /* create an iconv3 context to convert codeset of */
2518 /* the volume to the codeset of the application */
2519 if ( _DtHelpCeIconvContextSuitable(hw->help_dialog.srch.iconv3Context,
2520 curVol->iconv3Codeset,hw->help_dialog.srch.iconv3Codeset) == False )
2522 /* close old, open new */
2523 _DtHelpCeIconvClose(&hw->help_dialog.srch.iconv3Context);
2524 _DtHelpCeIconvOpen(&hw->help_dialog.srch.iconv3Context,
2525 curVol->iconv3Codeset,hw->help_dialog.srch.iconv3Codeset,' ',' ');
2528 /* else volume already open */
2530 /* if just opened volume */
2533 /* we just share pointers; when freeing localeWordStr, we need to
2534 test whether they are different before freeing */
2535 hw->help_dialog.srch.localeWordStr = hw->help_dialog.srch.normWordStr;
2538 /* get the str coll function, iff needed */
2539 if (NULL == curVol->strcollProc)
2541 /* get strcollProc for vol locale */
2542 curVol->strcollProc = _DtHelpCeGetStrcollProc();
2549 /*****************************************************************************
2550 * Function: void CloseVolAfterSearch()
2554 * Return Value: Void.
2556 * Purpose: Closes a volume opened for searching,
2557 * installs system locale, if diff from volume.
2559 *****************************************************************************/
2560 static void CloseVolAfterSearch(
2561 DtHelpDialogWidget hw,
2562 _DtHelpGlobSrchVol * curVol)
2564 /* close the volume if open */
2565 if ( NULL != curVol->volHandle )
2567 _DtHelpCloseVolume(curVol->volHandle);
2568 curVol->volHandle = NULL;
2569 /* free the locale word string, if allocated */
2570 if(hw->help_dialog.srch.localeWordStr!=hw->help_dialog.srch.normWordStr)
2572 XtFree(hw->help_dialog.srch.localeWordStr);
2573 hw->help_dialog.srch.localeWordStr = NULL;
2577 /* don't free the iconv context...may apply to the next volume */
2582 /*****************************************************************************
2583 * Function: void SearchTopic()
2587 * Return Value: Void.
2589 * Purpose: Get a single topic and search for the search word in it
2591 *****************************************************************************/
2592 static void SearchTopic(
2593 DtHelpDialogWidget hw,
2594 _DtHelpFileEntry curFile,
2595 _DtHelpGlobSrchVol * curVol,
2603 /* if the volume is not open; don't continue */
2604 if ( NULL == curVol->volHandle )
2605 return; /* RETURN */
2607 if ( NULL == curVol->indexEntriesList )
2608 _CEVolumeTopicList(curVol->volHandle,&curVol->indexEntriesList);
2609 if ( NULL == curVol->volHandle || NULL == curVol->indexEntriesList )
2611 curVol->topicSearchInProgress = False;
2612 curVol->topicSearchDone = True;
2613 curVol->indexSearchInProgress = True;
2614 if ( NULL == curVol->volHandle ) curVol->searchCompleted = True;
2615 return; /* RETURN */
2618 curVol->topicSearchInProgress = True;
2621 /* search the topics */
2622 /* note that indexEntriesList[0] is correct; ptr is incremented */
2623 /* we can increment the pointer because we don't own this memory;
2624 the open volume does. */
2626 i < numSearches && NULL != curVol->indexEntriesList[0];
2627 i++, curVol->indexEntriesList++ )
2629 char * topicTitle = NULL;
2632 validTopic = _DtHelpGetTopicTitle( curVol->volHandle,
2633 curVol->indexEntriesList[0],&topicTitle);
2636 /* look for a hit and process if there was one */
2637 if (SearchForPattern(topicTitle,srchWord,srchWordLen) == True)
2639 HitListAddFound(curFile, curVol->indexEntriesList[0], True, NULL);
2643 /* clean up and advance to next topic */
2645 curVol->searchedCnt++;
2646 } /* for all topics to search */
2649 if ( NULL == curVol->indexEntriesList /* no topics queried */
2650 || NULL == curVol->indexEntriesList[0] ) /* no more topics available */
2652 /* hand off to next stage */
2653 curVol->indexEntriesList = NULL;
2654 curVol->topicSearchInProgress = False;
2655 curVol->topicSearchDone = True;
2656 curVol->indexSearchInProgress = True;
2663 /*****************************************************************************
2664 * Function: void SearchIndex()
2668 * Return Value: void
2670 * Purpose: Get a single Index and search for the search word in it
2672 * Commentary: There are two strings for each index entry.
2673 * One string is the straight text in
2674 * the codeset of the volume. The
2675 * other string is a XmString that
2676 * has a font tag that will allow
2677 * it to be displayed in the
2680 * Preconditions: This code requires that the volume to be search
2681 * has already been opened [OpenVolForSearch()],
2682 * that the locale of the volume has been installed,
2683 * and that the search word is in the same code
2684 * set as the volume and has been converted to
2687 *****************************************************************************/
2688 static void SearchIndex(
2689 DtHelpDialogWidget hw,
2690 _DtHelpFileEntry curFile,
2691 _DtHelpGlobSrchVol * curVol,
2692 _DtHelpCeIconvContext iconvContext,
2698 char * indexEntry = NULL;
2699 size_t entryLen = 100; /* starting size */
2702 /* if the volume is not open; don't continue */
2703 if ( NULL == curVol->volHandle )
2704 return; /* RETURN */
2706 /* get the XmStrings of the entries */
2707 if ( NULL == curVol->indexXmStrsList )
2709 XmFontList fontList = NULL;
2710 Boolean mod = False;
2713 /* get results font list */
2714 XtSetArg(args[0], XmNfontList, &fontList);
2715 XtGetValues(hw->help_dialog.srch.resultList,args,1);
2718 /* Don't need to copy, _DtHelpFormatVolumeTitle copies
2722 /* work with copy, because FontListAppendEntry() destroys input FL */
2723 fontList = XmFontListCopy(fontList);
2726 /* get the entries */
2727 _DtHelpFormatIndexEntries(hw->help_dialog.help.pDisplayArea,
2728 curVol->volHandle,&numEntries, &curVol->indexXmStrsList,
2731 /* install the changed list */
2734 XtSetArg(args[0], XmNfontList, fontList);
2735 XtSetValues(hw->help_dialog.srch.resultList,args,1);
2736 if (fontList) XmFontListFree(fontList);
2740 /* get the pure strings for searching */
2741 if ( NULL == curVol->indexEntriesList )
2743 /* recall that the array and strings pointed to by
2744 the indexEntriesList is owned by the open volume */
2745 _DtHelpCeGetKeywordList(curVol->volHandle,&curVol->indexEntriesList);
2747 /* and re-init curIndexXmStr */
2748 curVol->curIndexXmStr = curVol->indexXmStrsList;
2751 if ( NULL == curVol->volHandle
2752 || NULL == curVol->indexEntriesList
2753 || NULL == curVol->indexXmStrsList )
2755 curVol->indexSearchInProgress = False;
2756 curVol->indexSearchDone = True;
2757 curVol->searchCompleted = True;
2758 if ( NULL == curVol->volHandle ) curVol->searchCompleted = True;
2759 return; /* RETURN */
2762 curVol->indexSearchInProgress = True;
2764 /* alloc memory for index processing */
2765 indexEntry = XtMalloc(sizeof(char)*(entryLen+1));
2766 if (NULL == indexEntry) return; /* RETURN */
2768 /* get a index entry */
2770 i < numSearches && NULL != curVol->indexEntriesList[0];
2771 i++, curVol->indexEntriesList++, curVol->curIndexXmStr++ )
2773 /* prevent overflow of buffer */
2774 if (strlen(curVol->indexEntriesList[0]) > entryLen)
2776 entryLen = strlen(curVol->indexEntriesList[0]) + 50;
2777 indexEntry = XtRealloc(indexEntry,entryLen+1);
2778 if (NULL == indexEntry) break; /* BREAK */
2780 indexEntry[0] = EOS; /* init to empty string */
2782 /* look for a hit and process if there was one */
2783 /* if srchWord is NULL, all entries are hits */
2784 /* copy, and possible iconv, the index string into the */
2785 /* the codeset of srchWord (the application) */
2786 if ( NULL == srchWord
2787 || ( _DtHelpCeIconvStr(iconvContext,curVol->indexEntriesList[0],
2788 &indexEntry, &entryLen,indexEntry,entryLen) == 0
2789 && SearchForPattern(indexEntry, srchWord, srchWordLen) == True ) )
2791 _DtHelpGlobSrchHit * hit;
2792 char * * topicIdList;
2794 HitListAddFound ( curFile, curVol->curIndexXmStr[0],
2795 curVol->indexEntriesList[0], True, &hit);
2797 /* topicIdList is set but not allocated & need not be freed */
2798 hit->topicCnt = _DtHelpCeFindKeyword(curVol->volHandle,
2799 hit->indexEntry,&topicIdList);
2802 /* clean up and advance to next topic */
2803 curVol->searchedCnt++;
2806 if ( NULL == curVol->indexEntriesList /*no topics queried*/
2807 || NULL == curVol->indexEntriesList[0] )/*no more index entries avail*/
2809 /* hand off to next stage */
2810 curVol->indexEntriesList = NULL; /* init */
2811 curVol->curIndexXmStr = curVol->indexXmStrsList; /* re-init */
2812 curVol->indexSearchInProgress = False;
2813 curVol->indexSearchDone = True;
2814 curVol->searchCompleted = True;
2821 /*****************************************************************************
2822 * Function: void SearchVolume()
2826 * Return Value: Void.
2828 * Purpose: do the search operation
2829 * This routine does incremental search--it searchs
2830 * a little, then returns to allow further processing.
2831 * It is called whenever Xt detects no other events.
2833 *****************************************************************************/
2834 static void SearchVolume(
2835 DtHelpDialogWidget hw,
2836 _DtHelpFileEntry curFile,
2837 _DtHelpGlobSrchVol * curVol,
2840 XmString labelString;
2844 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.srchForm));
2845 if (hw->help_dialog.srch.selectionDlg)
2846 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
2848 /* Process according to state */
2849 if ( curVol->nothingDone )
2851 curVol->nothingDone = False;
2852 curVol->topicSearchInProgress = True;
2854 /* Update the search status string */
2855 sprintf(buf,(char *)_DTGETMESSAGE(GSSET,18,
2856 "Searching... Volumes remaining: %d"),
2857 hw->help_dialog.srch.volLeftCnt);
2858 labelString = XmStringCreateLocalized(buf);
2859 XtSetArg(args[0],XmNlabelString,labelString);
2860 XtSetValues (hw->help_dialog.srch.statusLabel, args, 1);
2861 XmStringFree(labelString);
2863 XmUpdateDisplay((Widget) hw->help_dialog.srch.statusLabel);
2866 OpenVolForSearch(hw,curFile->fullFilePath,curVol);
2868 if ( curVol->topicSearchInProgress )
2870 SearchTopic(hw, curFile,curVol,hw->help_dialog.srch.localeWordStr,
2871 hw->help_dialog.srch.wordFieldLen, numSearches);
2874 /* NOTE: because this isn't an "else if", we could potentially
2875 search for 2*numSearches; but I know that I've disabled the
2876 topic search. Furthermore, my code depends upon the possibility
2877 of searching an entire volume in one call to the routine, if
2878 desired, and having an else if would break that.
2880 if ( curVol->indexSearchInProgress )
2883 srchWord = hw->help_dialog.srch.localeWordStr;
2884 /* FullIndex search indicated by a null search word string */
2885 if (hw->help_dialog.srch.fullIndex) srchWord = NULL;
2886 SearchIndex(hw, curFile, curVol, hw->help_dialog.srch.iconv3Context,
2887 srchWord, hw->help_dialog.srch.wordFieldLen, numSearches);
2890 /* If search was completed, update dependent stuff */
2891 if (curVol->searchCompleted)
2893 /* handle completion */
2894 CloseVolAfterSearch(hw,curVol);
2895 curVol->indexEntriesList = NULL; /* mem not owned by GlobSrch */
2896 if (hw->help_dialog.srch.fullIndex)
2897 curVol->gatheredFullIndex = True;
2898 hw->help_dialog.srch.volLeftCnt--;
2899 if (hw->help_dialog.srch.volLeftCnt < 0)
2900 hw->help_dialog.srch.volLeftCnt = 0;
2903 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.srchForm));
2904 if (hw->help_dialog.srch.selectionDlg)
2905 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
2910 /*****************************************************************************
2911 * Function: void SearchFile()
2915 * Return Value: Void.
2917 * Purpose: do the search operation on an entire file
2918 * It searches the entire file at once
2919 * and displays the results in the list.
2921 *****************************************************************************/
2922 static void SearchFile(
2923 DtHelpDialogWidget hw,
2924 _DtHelpFileEntry file)
2926 register _DtHelpGlobSrchVol * vol;
2928 /* get volume info, adding if necessary */
2929 vol = (_DtHelpGlobSrchVol *) file->clientData;
2930 /* (T,T,F): enable search, enable display, any volume */
2931 if (NULL == vol) AddVolInfoToFile(file, True, True, False);
2932 vol = (_DtHelpGlobSrchVol *) file->clientData;
2933 if (NULL == vol) return;
2935 /* conduct search of entire volume in one call */
2936 hw->help_dialog.srch.volLeftCnt = 1;
2937 vol->searchThisVolume = True;
2938 vol->showVolInList = True;
2939 vol->zeroHitsOk = True;
2940 SearchVolume(hw,file,vol,INT_MAX);
2943 StatusLabelUpdate(hw,SEARCH_RESULTS_STATUS,True,0);/*FIX: False*/
2945 /* update the list to show the volume */
2946 AdjustPositionValues(file,0,1,True);
2947 /* True: do insert new item */
2948 VolNameDisplay(hw,file,True);
2950 if (vol->showHitsWithVol)
2952 VolHitsDisplay(hw,file);
2953 /* False: don't insert new item */
2954 VolNameDisplay(hw,file,False);
2961 /*****************************************************************************
2962 * Function: void DoBackgroundSearchWP(
2963 * XtPointer clientData)
2969 * Return Value: Void.
2971 * Purpose: do the search operation in the background
2972 * This routine does incremental search--it searchs
2973 * a little, then returns to allow further processing.
2974 * It is called whenever Xt detects no other events.
2976 *****************************************************************************/
2977 static Boolean DoBackgroundSearchWP(
2978 XtPointer clientData)
2980 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
2981 _DtHelpFileEntry curFile;
2982 _DtHelpGlobSrchVol * curVol = NULL;
2984 if ( 0 == hw->help_dialog.srch.volLeftCnt )
2985 goto searchComplete; /* GOTO: done! */
2987 /* get file to work on */
2988 curFile = hw->help_dialog.srch.curSrchVol;
2989 if ( NULL == curFile )
2991 curFile = GetNextSearchFileAndDisplayCompleted(
2992 hw, hw->help_dialog.srch.volListHead, NULL);
2993 if ( NULL == curFile ) goto searchComplete; /* GOTO: done */
2994 hw->help_dialog.srch.curSrchVol = curFile;
2995 } /* if no current file */
2997 /* get volume info */
2998 curVol = (_DtHelpGlobSrchVol *) curFile->clientData;
3000 #define NUM_SEARCHES_PER_CALL 30
3001 SearchVolume(hw,curFile,curVol,NUM_SEARCHES_PER_CALL);
3003 /* If search was completed, update dependent stuff */
3004 if (curVol->searchCompleted)
3006 /* update the search results list */
3007 /* True: adjust count beginning with this file */
3008 if (curVol->hitCnt > 0 || curVol->zeroHitsOk)
3010 /* record that a hit found */
3011 if ( curVol->hitCnt > 0
3012 || ( curVol->zeroHitsOk
3013 && _DtHelpGlobSrchSelectedVolumes == hw->help_dialog.srch.srchSources))
3014 hw->help_dialog.srch.hitsFound = True;
3016 /* update the list to show the volume */
3017 AdjustPositionValues(curFile,0,1,True);
3018 ResultsListUpdate(hw,curFile);
3020 /* update the list to show the hits? */
3021 if (hw->help_dialog.srch.srchSources == _DtHelpGlobSrchCurVolume)
3023 VolHitsDisplay(hw,curFile);
3024 /* False: don't insert new item */
3025 VolNameDisplay(hw,curFile,False);
3027 XmUpdateDisplay((Widget) hw->help_dialog.srch.resultList);
3030 /* prepare for next search */
3031 hw->help_dialog.srch.curSrchVol =
3032 GetNextSearchFileAndDisplayCompleted(hw,NULL,curFile);
3034 } /* if search completed */
3037 if ( hw->help_dialog.srch.volLeftCnt > 0
3038 || False == curVol->searchCompleted )
3039 return False; /* RETURN: False ==> continue processing */
3041 /* Do this when no more files are left to search */
3044 XmPushButtonCallbackStruct status;
3046 /* zero search data before stopping */
3047 hw->help_dialog.srch.volLeftCnt = 0; /* just in case */
3048 hw->help_dialog.srch.curSrchVol = NULL; /* just in case */
3050 /* generate a fake event to reset the dialog */
3051 status.reason = XmCR_ACTIVATE;
3052 status.event = NULL;
3053 status.click_count = 1;
3054 StopSearchCB(hw->help_dialog.srch.actionBtn,
3055 (XtPointer)hw,(XtPointer)&status);
3057 return True; /* RETURN: True ==> stop processing */
3063 /*****************************************************************************
3064 * Function: void StartSearchCB(Widget w,
3065 * XtPointer clientData,
3066 * XtPointer callData);
3072 * Return Value: Void.
3074 * Purpose: Create a new user bookmark
3076 * Warning: This CB is also used by the volume selection buttons
3077 * to activate a search when they are selected. The routine
3078 * cannot rely upon the w or callData params. The clientData
3079 * will always be the help widget.
3080 *****************************************************************************/
3081 static void StartSearchCB(
3082 Widget w, /* dont use */
3083 XtPointer clientData,
3084 XtPointer callData) /* dont use */
3086 char *srchWord = NULL;
3087 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3088 XtAppContext appCntx;
3092 /* set state of start button correctly */
3093 UpdateSearchStartStatusCB(NULL, (XtPointer) hw, NULL);
3095 /* if help content isn't a volume, it has no index */
3096 if ( _DtHelpGlobSrchCurVolume == hw->help_dialog.srch.srchSources
3097 && hw->help_dialog.display.helpType != DtHELP_TYPE_TOPIC )
3098 return; /* RETURN */
3100 /* retrieve the name */
3101 srchWord = XmTextFieldGetString(hw->help_dialog.srch.wordField);
3103 /* test for empty (also emtpy spaces) and only process if not emtpy */
3104 _DtHelpCeCompressSpace(srchWord);
3105 if ( (strlen(srchWord) > (size_t) 0 || hw->help_dialog.srch.fullIndex)
3106 && hw->help_dialog.srch.workProcId == 0)
3107 /* test on workProcId prevents multiple activations due to
3108 race condition on desensitizing the start button */
3110 _DtHelpTurnOnHourGlass(XtParent(hw));
3111 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.srchForm));
3112 if (hw->help_dialog.srch.selectionDlg)
3113 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
3115 /*XtSetSensitive (hw->help_dialog.srch.actionBtn,False);*/
3116 XtSetSensitive (hw->help_dialog.srch.curVolRadBtn,False);
3117 XtSetSensitive (hw->help_dialog.srch.allVolRadBtn,False);
3118 XtSetSensitive (hw->help_dialog.srch.selVolRadBtn,False);
3119 XtSetSensitive (hw->help_dialog.srch.selectBtn,False);
3121 /* 9/26/94: these two XtSetArgs (and following SetValues) cause a core dump
3122 for the SunOS 5.3 optimized executable. It isn't a problem for the
3123 non-optimized or debuggable versions or any versions on AIX 3.2 or
3125 #if !defined(sun) && !defined(__osf__)
3127 XtSetArg(args[n],XmNeditable,False); n++;
3128 XtSetArg(args[n],XmNcursorPositionVisible,False); n++;
3129 XtSetValues (hw->help_dialog.srch.wordField, args, n);
3131 XmUpdateDisplay(hw->help_dialog.srch.srchForm);
3133 /* process the source selection and retain in widget srchWord memory */
3134 PrepSearchSourceData(hw, srchWord);
3136 /* activate search thread; do it even with a 0 count, because the
3137 process reactivates the dialog after search is completed */
3138 appCntx = XtWidgetToApplicationContext((Widget) hw);
3139 hw->help_dialog.srch.workProcId =
3140 XtAppAddWorkProc(appCntx,DoBackgroundSearchWP, (XtPointer) hw);
3142 hw->help_dialog.srch.searchInProgress = True;
3144 /* dont free srchWord */
3146 /* turn on "Stop" label */
3147 UpdateActionButtonLabel(hw,NULL,False);
3149 _DtHelpTurnOffHourGlass(XtParent(hw));
3150 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.srchForm));
3151 if (hw->help_dialog.srch.selectionDlg)
3152 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
3156 if ( strlen(srchWord) == 0 )
3157 StatusLabelUpdate(hw,FIRST_PROMPT_STATUS,False,0);
3165 /*****************************************************************************
3166 * Function: void StartSelectedVolumeSearchCB(Widget w,
3167 * XtPointer clientData,
3168 * XtPointer callData);
3174 * Return Value: Void.
3176 * Purpose: Begin a search on the selected volume
3178 *****************************************************************************/
3179 static void StartSelectedVolumeSearchCB(
3181 XtPointer clientData,
3184 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3185 _DtHelpFileEntry file;
3187 Boolean noSelectedFiles = True;
3189 /* if not full index search */
3190 if (hw->help_dialog.srch.fullIndex == False)
3192 /* get the current contents of the search word field */
3193 srchWord = XmTextFieldGetString(hw->help_dialog.srch.wordField);
3195 /* test the word ; False=dontUpdate--do this in PrepSearchSourceData() */
3196 if ( CheckSearchWord(hw,srchWord,False) == True )
3197 { /* word has changed since last search; do a whole new search */
3198 StartSearchCB(NULL,(XtPointer) hw, NULL);
3199 return; /* RETURN */
3202 /* if the text field is empty, do nothing */
3203 if ( strlen(hw->help_dialog.srch.normWordStr) == 0 )
3204 return; /* RETURN */
3207 /* set this to true to counteract False if no hits */
3208 hw->help_dialog.srch.hitsFound = True;
3210 /* Word is the same, just the selection has changed. */
3211 /* Determine which one was selected or deselected */
3212 for ( file = hw->help_dialog.srch.volListHead;
3214 file = _DtHelpFileListGetNext(NULL,file) )
3216 register _DtHelpGlobSrchVol * vol;
3217 vol = (_DtHelpGlobSrchVol *) file->clientData;
3218 if (NULL == vol) continue;
3221 if (file->fileSelected) noSelectedFiles = False;
3223 /* test for contradictory flags; fileSelected reflects dialog list */
3224 if (file->fileSelected != vol->showVolInList)
3226 /* file has been deselected */
3227 if (False == file->fileSelected)
3229 if (vol->showVolInList)
3231 /* update list: delete hits, topics, and volume title */
3232 if (vol->hitsDisplayed) VolHitsUndisplay(hw,file);
3234 /* delete hits first, then volume */
3236 hw->help_dialog.srch.resultList,vol->startPosition);
3237 AdjustPositionValues(file, 0, -1, True);
3238 vol->showVolInList = False;
3239 vol->searchThisVolume = False;
3242 else /* file has been selected */
3244 SearchFile(hw,file);
3245 } /* if file de/selected */
3246 } /* if contradictory flags */
3247 } /* for all volumes */
3250 if (noSelectedFiles) StatusLabelUpdate(hw,NO_VOL_STATUS,True,0);
3255 /*****************************************************************************
3256 * Function: void UpdateSearchStartStatusCB(Widget w,
3257 * XtPointer clientData,
3258 * XtPointer callData);
3264 * Return Value: Void.
3266 * Purpose: update the status of the search status button
3267 * Routine is called whenever text is changed in the search
3270 *****************************************************************************/
3271 static void UpdateSearchStartStatusCB(
3273 XtPointer clientData,
3276 char *srchWord = NULL;
3277 /*XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) callData;*/
3278 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3281 /* retrieve the name */
3282 srchWord = XmTextFieldGetString(hw->help_dialog.srch.wordField);
3284 /* test for empty (also emtpy spaces) */
3285 _DtHelpCeCompressSpace(srchWord);
3287 /* FIX: change the locale from the volume locale back to the system
3288 locale temporarily (if not already in that locale) */
3289 _DtHelpCeUpperCase(srchWord);
3291 /* only sensitize if working on a help volume and word is not emtpy
3294 if ( ( _DtHelpGlobSrchCurVolume == hw->help_dialog.srch.srchSources
3295 && hw->help_dialog.display.helpType != DtHELP_TYPE_TOPIC)
3296 || ( strlen(srchWord) == (size_t) 0
3297 && hw->help_dialog.srch.fullIndex == False))
3299 XtSetSensitive (hw->help_dialog.srch.actionBtn,newState);
3301 /* if word has changed from word of previous search, change to Start */
3302 UpdateActionButtonLabel(hw,srchWord,True);
3308 /*****************************************************************************
3309 * Function: void StopSearchCB(Widget w,
3310 * XtPointer clientData,
3311 * XtPointer callData);
3317 * Return Value: Void.
3319 * Purpose: Stop the search
3321 *****************************************************************************/
3322 static void StopSearchCB(
3324 XtPointer clientData,
3327 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3332 /* stop the search thread */
3333 if(hw->help_dialog.srch.workProcId != 0)
3334 XtRemoveWorkProc(hw->help_dialog.srch.workProcId);
3335 hw->help_dialog.srch.workProcId = 0;
3337 hw->help_dialog.srch.searchInProgress = False;
3339 /* update statuses */
3341 XtSetSensitive (hw->help_dialog.srch.curVolRadBtn,
3342 hw->help_dialog.srch.curVolRadBtnSens);
3344 XtSetSensitive (hw->help_dialog.srch.curVolRadBtn, TRUE);
3347 XtSetSensitive (hw->help_dialog.srch.allVolRadBtn,True);
3348 XtSetSensitive (hw->help_dialog.srch.selVolRadBtn,True);
3350 XtSetArg(args[n],XmNeditable,True); n++;
3351 XtSetArg(args[n],XmNcursorPositionVisible,True); n++;
3352 XtSetValues (hw->help_dialog.srch.wordField, args, n);
3354 /* update select btn status; only when selected and dialog closed */
3355 XtSetArg(args[0],XmNset,&cur);
3356 XtGetValues(hw->help_dialog.srch.selVolRadBtn,args,1);
3357 XtSetSensitive(hw->help_dialog.srch.selectBtn,
3358 cur && ( NULL == hw->help_dialog.srch.selectionDlg
3359 || !XtIsManaged(hw->help_dialog.srch.selectionDlg) ) );
3361 /* set the action button label appropriately */
3362 UpdateActionButtonLabel(hw,hw->help_dialog.srch.normWordStr,True);
3364 /* post message of results */
3365 StatusLabelUpdate(hw,SEARCH_RESULTS_STATUS,True,0);
3371 /*****************************************************************************
3372 * Function: void ActionButtonCB(Widget w,
3373 * XtPointer clientData,
3374 * XtPointer callData);
3380 * Return Value: Void.
3382 * Purpose: Act upon the action
3384 *****************************************************************************/
3385 static void ActionButtonCB(
3387 XtPointer clientData,
3390 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3392 if ( hw->help_dialog.srch.searchInProgress == False )
3393 StartSearchCB(w,clientData,callData);
3395 StopSearchCB(w,clientData,callData);
3401 /*****************************************************************************
3402 * Function: void GotoResultCB(Widget w,
3403 * XtPointer clientData,
3404 * XtPointer callData);
3410 * Return Value: Void.
3412 * Purpose: Goto a result topic
3414 *****************************************************************************/
3415 static void GotoResultCB(
3417 XtPointer clientData,
3420 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3421 char * helpFile = NULL;
3422 int * topicPosList=NULL;
3427 /* Determine the item selected and find that item in our list */
3428 status = XmListGetSelectedPos(hw->help_dialog.srch.resultList, &topicPosList,&i);
3430 /* if true, an item selected */
3431 if (status && topicPosList)
3433 _DtHelpGlobSrchHit * entry = NULL;
3434 _DtHelpFileEntry file = NULL;
3435 char * locationId = NULL;
3436 topicPosition = topicPosList[0] - 1; /* convert to 0 based */
3437 XtFree((String)topicPosList);
3440 HitListGetNth(hw->help_dialog.srch.volListHead,
3441 topicPosition,&file,&entry,&locationId,&helpFile);
3443 /* jump to selected location */
3444 XtFree(hw->help_dialog.display.locationId);
3445 hw->help_dialog.display.locationId = XtNewString(locationId);
3446 XtFree(hw->help_dialog.display.helpVolume);
3447 hw->help_dialog.display.helpVolume = XtNewString(helpFile);
3448 hw->help_dialog.ghelp.volumeFlag = False; /* force search for volume */
3449 hw->help_dialog.display.helpType = DtHELP_TYPE_TOPIC;
3451 _DtHelpSetupDisplayType(hw, TRUE, DtHISTORY_AND_JUMP);
3455 if (topicPosList) XtFree((String)topicPosList);
3457 /* FIX: Put up a message to suggest selecting an item first */
3458 /* Don't close the dialog */
3461 #endif /* not_used */
3463 #if 0 /* save--used in code commented out elsewhere in this file */
3465 /*****************************************************************************
3466 * Function: void CloseHelpCB()
3470 * Return Value: Void.
3472 * Purpose: Close and destroy the help widget
3474 *****************************************************************************/
3475 static void CloseHelpCB(
3477 XtPointer clientData,
3483 #endif /* save--used in code commented out elsewhere in this file */
3486 /*****************************************************************************
3487 * Function: void GotoLocation(hw,helpVolume,location)
3491 * Return Value: Void.
3493 * Purpose: Goto a topic by opening a new help dialog window
3495 *****************************************************************************/
3496 static void GotoLocation(
3497 DtHelpDialogWidget hw,
3501 #if 0 /* don't delete...useful as reference */
3507 /* This opens a new help window on the topic */
3509 XtSetArg( args[n], XmNtitle, "Help" ); n++;
3510 XtSetArg( args[n], DtNhelpType, DtHELP_TYPE_TOPIC ); n++;
3511 XtSetArg( args[n], DtNlocationId, locationId ); n++;
3512 XtSetArg( args[n], DtNhelpVolume, helpVolume ); n++;
3513 helpDlg = DtCreateHelpDialog(XtParent(hw),"mainHelpDialog",args,n);
3514 XtAddCallback(helpDlg,DtNcloseCallback,CloseHelpCB,helpDlg);
3515 XtManageChild(helpDlg);
3519 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.srchForm));
3520 if (hw->help_dialog.srch.selectionDlg)
3521 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
3523 /* jump to selected location in same window */
3524 XtFree(hw->help_dialog.display.locationId);
3525 hw->help_dialog.display.locationId = XtNewString(locationId);
3526 XtFree(hw->help_dialog.display.helpVolume);
3527 hw->help_dialog.display.helpVolume = XtNewString(helpVolume);
3528 hw->help_dialog.ghelp.volumeFlag = False; /* force search for volume */
3529 hw->help_dialog.display.helpType = DtHELP_TYPE_TOPIC;
3531 _DtHelpSetupDisplayType(hw, TRUE, DtHISTORY_AND_JUMP);
3533 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.srchForm));
3534 if (hw->help_dialog.srch.selectionDlg)
3535 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
3542 /*****************************************************************************
3543 * Function: void ProcessResultSelectionCB(Widget w,
3544 * XtPointer clientData,
3545 * XtPointer callData);
3551 * Return Value: Void.
3553 * Purpose: Process user selection of an item in the result List.
3555 *****************************************************************************/
3556 static void ProcessResultSelectionCB(
3558 XtPointer clientData,
3561 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3562 int * topicPosList = NULL;
3567 /* Determine the item selected and find that item in our list */
3568 status = XmListGetSelectedPos(
3569 hw->help_dialog.srch.resultList, &topicPosList,&n);
3571 /* if true, an item selected */
3572 if (status && topicPosList)
3574 _DtHelpFileEntry file = NULL;
3575 _DtHelpGlobSrchHit * hit = NULL;
3576 char * locationId = NULL;
3577 char * helpFile = NULL;
3579 topicPosition = topicPosList[0]; /* 1 based */
3580 XtFree((String)topicPosList);
3583 if ( HitListGetNth(hw->help_dialog.srch.volListHead,
3584 topicPosition,&file,&hit,&locationId,&helpFile) == 0 )
3586 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.srchForm));
3589 XmListDeselectPos(hw->help_dialog.srch.resultList,topicPosition);
3591 /* was a volume item selected? */
3594 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) file->clientData;
3595 if (vol->hitCnt > 0)
3597 if (False == vol->hitsDisplayed)
3599 VolHitsDisplay(hw,file); /* toggle state */
3603 VolHitsUndisplay(hw,file);
3604 vol->showHitsWithVol = False;
3606 /* update the volume label to show the state */
3607 /* False: dont insert hw item */
3608 VolNameDisplay(hw,file,False);
3610 /* else don't otherwise handle a 0-hits volume */
3612 /* was an expandable index selected */
3613 else if (NULL == locationId && hit->topicCnt > 1)
3617 /* if we're turning them on, build a list */
3618 if (False == hit->topicsDisplayed)
3620 topicCnt = HitTopicsDisplay(hw,file,hit,topicPosition+1);
3624 topicCnt = - HitTopicsUndisplay(hw,file,hit,topicPosition+1);
3625 hit->showTopicsWithHit = False;
3627 /* update the hit label to show the state; False--dont insert */
3628 HitNameDisplay(hw,file,hit,topicPosition,False);
3630 /* add to all the following */
3633 /* adjust count beginning with next file with hits */
3634 AdjustPositionValues(file, 0, topicCnt, True);
3637 /* a location or index with one topic was selected */
3640 /* if a single click, goto the location */
3641 if (hit->topicCnt == 1)
3643 if ( HitLoadTopics(hw,file,hit) == 0 )
3645 GotoLocation(hw, file->fullFilePath, hit->topicIdList[0]);
3646 HitFree(hit,False); /*release what was loaded 3 lines up*/
3649 { /* volume couldn't be opened or some other error */
3650 /* FIX: error message */
3652 } /* if an index with a single topic */
3654 { /* a location from an open multi-topic index entry */
3655 GotoLocation(hw, file->fullFilePath, locationId);
3657 } /* else index with one topic or topic was selected */
3659 /* finish up processing a selection */
3660 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.srchForm));
3662 } /* got the nth item */
3664 else /* could not find the nth hit */
3666 if (topicPosList) XtFree((String)topicPosList);
3673 /*****************************************************************************
3674 * Function: void CloseVolSelDialogCB(Widget w,
3675 * XtPointer clientData,
3676 * XtPointer callData);
3680 * Return Value: Void.
3682 * Purpose: Resets the selection dialog variable to NULL
3684 *****************************************************************************/
3685 static void CloseVolSelDialogCB(
3687 XtPointer clientData,
3690 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3692 /* unmanage & destroy the dialog zero the variable */
3693 if ( hw->help_dialog.srch.selectionDlg
3694 && XtIsManaged(hw->help_dialog.srch.selectionDlg) )
3695 XtUnmanageChild(hw->help_dialog.srch.selectionDlg);
3697 /* start a search to be sure we got all changes; FIX: need this??? */
3698 /*StartSearchCB(NULL,hw,NULL);*/
3699 XtSetSensitive(hw->help_dialog.srch.selectBtn,True);
3702 if (hw->help_dialog.srch.hitsFound == True)
3703 XmProcessTraversal(hw->help_dialog.srch.resultList,XmTRAVERSE_CURRENT);
3705 XmProcessTraversal(hw->help_dialog.srch.allVolRadBtn,XmTRAVERSE_CURRENT);
3710 /*****************************************************************************
3711 * Function: void CreateVolSelDialog(
3715 * Return Value: Void.
3717 * Purpose: Creates selection dialog to chose volumes
3719 *****************************************************************************/
3720 static void CreateVolSelDialog(
3721 DtHelpDialogWidget hw)
3724 _DtHelpFileDlgChildren dlgChld;
3725 Atom wm_delete_window;
3728 /* desensitize the button */
3729 XtSetSensitive(hw->help_dialog.srch.selectBtn,False);
3731 /* only create one */
3732 if ( NULL != hw->help_dialog.srch.selectionDlg )
3734 XtManageChild(hw->help_dialog.srch.selectionDlg);
3738 /* open the modal dialog and let user select the volumes */
3739 selDlg = _DtHelpFileListCreateSelectionDialog(
3740 hw, hw->help_dialog.srch.srchForm, False,
3741 (char *)_DTGETMESSAGE (GSSET, 40,
3742 "Help - Search Volume Selection"),
3743 &hw->help_dialog.srch.volTitlesFontList,
3744 hw->help_dialog.srch.volListHead, &dlgChld);
3745 hw->help_dialog.srch.selectionDlg = selDlg;
3747 XtAddCallback(dlgChld.closeBtn, XmNactivateCallback,
3748 CloseVolSelDialogCB,(XtPointer)hw);
3749 XtAddCallback(dlgChld.form, XmNunmapCallback,
3750 CloseVolSelDialogCB,(XtPointer)hw);
3752 /* set the default response to a WM_DELETE_WINDOW message
3753 to no response instead of UNMAP. */
3754 XtSetArg(args[0], XmNdeleteResponse, XmDO_NOTHING);
3755 XtSetValues(dlgChld.shell, args, 1);
3756 wm_delete_window = XmInternAtom(XtDisplay(dlgChld.shell),
3757 "WM_DELETE_WINDOW", FALSE);
3758 XmAddWMProtocolCallback(dlgChld.shell,wm_delete_window,
3759 (XtCallbackProc)CloseVolSelDialogCB, (XtPointer)hw);
3761 XtAddCallback(dlgChld.list, XmNsingleSelectionCallback,
3762 StartSelectedVolumeSearchCB, (XtPointer) hw);
3763 XtAddCallback(dlgChld.list, XmNmultipleSelectionCallback,
3764 StartSelectedVolumeSearchCB, (XtPointer) hw);
3765 XtAddCallback(dlgChld.list, XmNextendedSelectionCallback,
3766 StartSelectedVolumeSearchCB, (XtPointer) hw);
3767 XtAddCallback(dlgChld.list, XmNdefaultActionCallback,
3768 StartSelectedVolumeSearchCB, (XtPointer) hw);
3773 /*****************************************************************************
3774 * Function: void OpenSelectDialogCB(Widget w,
3775 * XtPointer clientData,
3776 * XtPointer callData);
3782 * Return Value: Void.
3784 * Purpose: Process user selection of the select button
3786 *****************************************************************************/
3787 static void OpenSelectDialogCB(
3789 XtPointer clientData,
3792 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3794 /* only build the list of files if it hasn't been done */
3795 if ( False == hw->help_dialog.srch.volScanDone
3796 || NULL == hw->help_dialog.srch.volListHead)
3798 /* Add on the Vol info; (T,T,T) search, display, selected only */
3799 VolListBuild(hw,True,True,True);
3802 /* FIX: the modal behaviour doesn't seem to be set; is it desired/needed? */
3803 /* don't need to worry about having open twice, since
3804 the dialog is always opened in modal mode from the search dialog */
3805 /* open the dialog and let user select the volumes */
3806 CreateVolSelDialog(hw);
3810 /*****************************************************************************
3811 * Function: void UpdateSearchVolumesCB(Widget w,
3812 * XtPointer clientData,
3813 * XtPointer callData);
3819 * Return Value: Void.
3821 * Purpose: Process user selection of a button in the Volumes Radio box
3823 *****************************************************************************/
3824 static void UpdateSearchVolumesCB(
3826 XtPointer clientData,
3829 XmToggleButtonCallbackStruct *status = (XmToggleButtonCallbackStruct *) callData;
3830 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3836 if (hw->help_dialog.srch.hitsFound == True)
3837 XmProcessTraversal(hw->help_dialog.srch.resultList,XmTRAVERSE_CURRENT);
3839 XmProcessTraversal(hw->help_dialog.srch.allVolRadBtn,XmTRAVERSE_CURRENT);
3843 /* if turning off the button, just reinforce the current settings.
3844 This message occurs when an on button is hit again. */
3845 if ( False == status->set )
3847 XtSetArg(args[0], XmNset, hw->help_dialog.srch.allVolRadBtn == widget);
3848 XtSetValues(hw->help_dialog.srch.allVolRadBtn,args,1);
3849 XtSetArg(args[0], XmNset, hw->help_dialog.srch.selVolRadBtn == widget);
3850 XtSetValues(hw->help_dialog.srch.selVolRadBtn,args,1);
3851 XtSetArg(args[0], XmNset, hw->help_dialog.srch.curVolRadBtn == widget);
3852 XtSetValues(hw->help_dialog.srch.curVolRadBtn,args,1);
3856 /*** if work when something is turned on; ignore the off messages
3857 except when the button is the selected volumes button; we
3858 want to catch every click on that button */
3859 if ( XmCR_VALUE_CHANGED == status->reason
3860 && True == status->set
3861 && NULL != status->event ) /* event is NULL for 1st of the two calls
3862 to this routine that are made when a
3863 button is pressed. */
3865 /*** now update the sources value according to button selected ***/
3866 hw->help_dialog.srch.volLeftCnt = 0; /* change invalidates prior search */
3867 UpdateActionButtonLabel(hw,NULL,True);
3869 XtSetArg(args[0], XmNset, hw->help_dialog.srch.allVolRadBtn == widget);
3870 XtSetValues(hw->help_dialog.srch.allVolRadBtn,args,1);
3871 XtSetArg(args[0], XmNset, hw->help_dialog.srch.curVolRadBtn == widget);
3872 XtSetValues(hw->help_dialog.srch.curVolRadBtn,args,1);
3873 XtSetArg(args[0], XmNset, hw->help_dialog.srch.selVolRadBtn == widget);
3874 XtSetValues(hw->help_dialog.srch.selVolRadBtn,args,1);
3876 /*** selected volumes button activated ***/
3877 if (hw->help_dialog.srch.selVolRadBtn == widget)
3880 hw->help_dialog.srch.srchSources = _DtHelpGlobSrchSelectedVolumes;
3882 /* only build the list of files if it hasn't been done */
3883 if ( False == hw->help_dialog.srch.volScanDone
3884 || NULL == hw->help_dialog.srch.volListHead)
3886 /* Add on the Vol info; (T,T,T) search, display, selected only */
3887 VolListBuild(hw,True,True,True);
3890 /* (F,F,F,F): disable search,disable display,no 0 hits,for all vols */
3891 SetVolStatus(hw->help_dialog.srch.volListHead,False,False,False,False);
3892 /* (T,T,T,T): enable search, enable display,
3893 zero hits ok, only for selected volumes */
3894 /* Set these here so that the CountSelectedVolumes() works right */
3895 SetVolStatus(hw->help_dialog.srch.volListHead,True,True,True,True);
3897 /* count all volumes selected, including those already searched */
3898 if (CountSelectedVolumes(hw->help_dialog.srch.volListHead,True)==0)
3900 StatusLabelUpdate(hw,NO_VOL_STATUS,False,0);
3901 DeleteListContents(&hw->help_dialog.srch);
3902 CreateVolSelDialog(hw);
3903 /* NOTE: don't start search here, start it from the callback */
3904 /* set state of start button correctly */
3905 UpdateSearchStartStatusCB(NULL, (XtPointer) hw, NULL);
3907 else /* volumes already selected; just display */
3909 hw->help_dialog.srch.hitsFound = False; /*DBG*/
3910 StartSearchCB(NULL,(XtPointer) hw, NULL);
3912 } /* if selected volumes button */
3914 /*** all volumes button ***/
3915 else if (hw->help_dialog.srch.allVolRadBtn == widget)
3917 /* close the selection dialog, if open */
3918 if (hw->help_dialog.srch.selectionDlg)
3919 XtUnmanageChild(hw->help_dialog.srch.selectionDlg);
3921 /* set sources state */
3922 hw->help_dialog.srch.srchSources = _DtHelpGlobSrchAllVolumes;
3923 hw->help_dialog.srch.hitsFound = False; /*DBG*/
3924 StartSearchCB(NULL,(XtPointer) hw, NULL);
3926 /*** current volume button ***/
3929 /* close the selection dialog, if open */
3930 if (hw->help_dialog.srch.selectionDlg)
3931 XtUnmanageChild(hw->help_dialog.srch.selectionDlg);
3933 /* set sources state */
3934 hw->help_dialog.srch.srchSources = _DtHelpGlobSrchCurVolume;
3935 hw->help_dialog.srch.hitsFound = False; /*DBG*/
3936 StartSearchCB(NULL,(XtPointer) hw, NULL);
3939 /* update the Select... button status */
3940 /* do this last, so that while searching for volumes (VolListBuild),
3941 the button is not active. */
3942 XtSetSensitive(hw->help_dialog.srch.selectBtn,
3943 (hw->help_dialog.srch.selVolRadBtn == widget)
3944 && ( NULL == hw->help_dialog.srch.selectionDlg
3945 || !XtIsManaged(hw->help_dialog.srch.selectionDlg) ) );
3947 } /* if value changed */
3952 /*****************************************************************************
3953 * Function: void UpdateIndexSelectionCB(Widget w,
3954 * XtPointer clientData,
3955 * XtPointer callData);
3961 * Return Value: Void.
3963 * Purpose: Process user selection of a button in the Entries Radio box
3965 *****************************************************************************/
3966 static void UpdateIndexSelectionCB(
3968 XtPointer clientData,
3971 XmToggleButtonCallbackStruct *status = (XmToggleButtonCallbackStruct *) callData;
3972 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3973 Boolean containsState;
3978 if (hw->help_dialog.srch.hitsFound == True)
3979 XmProcessTraversal(hw->help_dialog.srch.resultList,XmTRAVERSE_CURRENT);
3981 XmProcessTraversal(hw->help_dialog.srch.allVolRadBtn,XmTRAVERSE_CURRENT);
3984 /* if turning off the button, just reinforce the current settings.
3985 This message occurs when an on button is hit again. */
3986 if ( False == status->set )
3988 containsState = (hw->help_dialog.srch.containsRadBtn == widget);
3989 XtSetArg(args[0], XmNset, !containsState);
3990 XtSetValues(hw->help_dialog.srch.fullIndexRadBtn,args,1);
3991 XtSetArg(args[0], XmNset, containsState);
3992 XtSetValues(hw->help_dialog.srch.containsRadBtn,args,1);
3996 /*** if work when something is turned on; ignore the off messages
3997 except when the button is the selected volumes button; we
3998 want to catch every click on that button */
3999 if ( XmCR_VALUE_CHANGED == status->reason
4000 && True == status->set
4001 && NULL != status->event ) /* event is NULL for 1st of the two calls
4002 to this routine that are made when a
4003 button is pressed. */
4005 /* if search in progress, stop it */
4006 if(hw->help_dialog.srch.searchInProgress||hw->help_dialog.srch.workProcId)
4008 XmPushButtonCallbackStruct status;
4010 /* generate a fake event to reset the dialog */
4011 status.reason = XmCR_ACTIVATE;
4012 status.event = NULL;
4013 status.click_count = 1;
4014 StopSearchCB(hw->help_dialog.srch.actionBtn,
4015 (XtPointer)hw,(XtPointer)&status);
4018 containsState = (hw->help_dialog.srch.containsRadBtn == widget);
4019 XtSetArg(args[0], XmNset, !containsState);
4020 XtSetValues(hw->help_dialog.srch.fullIndexRadBtn,args,1);
4021 XtSetArg(args[0], XmNset, containsState);
4022 XtSetValues(hw->help_dialog.srch.containsRadBtn,args,1);
4024 /* sensitize/desensitize the Contains text field */
4025 XtSetSensitive(hw->help_dialog.srch.wordField,containsState);
4027 XtSetArg(args[n],XmNeditable,containsState); n++;
4028 XtSetArg(args[n],XmNcursorPositionVisible,containsState); n++;
4029 XtSetValues(hw->help_dialog.srch.wordField,args,n);
4031 /* set widget status here; do this way bec. srchFullIndex is a bit flag */
4032 hw->help_dialog.srch.fullIndex = (containsState ? False : True); /*flag*/
4034 /* set state of start button correctly */
4035 UpdateSearchStartStatusCB(NULL, (XtPointer) hw, NULL);
4038 { /* if changing to "Containing" */
4039 /* change focus to the search word */
4040 XmProcessTraversal(hw->help_dialog.srch.wordField,XmTRAVERSE_CURRENT);
4041 /* user will need to hit CR to initiate search */
4044 { /* if changing to full index */
4045 /* indicate that no contains word is valid by deleting it */
4046 /* FIX: I'm concerned that normWordStr & localeWordStr aren't in synch */
4047 XtFree(hw->help_dialog.srch.normWordStr);
4048 hw->help_dialog.srch.normWordStr = NULL;
4049 /* search full index */
4050 StartSearchCB(NULL,(XtPointer) hw, NULL);
4053 /* and search to update results to the new state */
4054 } /* if value changed */
4059 /*****************************************************************************
4060 * Function: void ContainsDisarmCB(Widget w,
4061 * XtPointer clientData,
4062 * XtPointer callData);
4068 * Return Value: Void.
4070 * Purpose: Process disarm of the contains radio button
4072 *****************************************************************************/
4073 static void ContainsDisarmCB(
4075 XtPointer clientData,
4078 XmToggleButtonCallbackStruct *status = (XmToggleButtonCallbackStruct *) callData;
4079 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
4081 /* Force focus to the word field if set. */
4082 if (True==status->set)
4083 XmProcessTraversal(hw->help_dialog.srch.wordField,XmTRAVERSE_CURRENT);
4088 /*****************************************************************************
4089 * Function: CreateCurVolBtnLabel()
4094 * Return Value: True or False if current vol has an index
4096 * Purpose: Creates the label for the current volume button
4098 *****************************************************************************/
4099 static Boolean CreateCurVolBtnLabel(
4100 DtHelpDialogWidget hw,
4101 Boolean * out_curVolAvailable,
4102 XmString * out_labelString,
4103 char * * out_mnemonic)
4108 XmString volTitleString = NULL;
4109 XmString preTitleString = NULL;
4110 XmString postTitleString = NULL;
4112 XmString labelString;
4114 Boolean curVolAvail;
4119 if (out_curVolAvailable)
4120 *out_curVolAvailable = False;
4121 if (out_labelString)
4122 *out_labelString = XmStringCreateLocalized("dum");
4128 /* if help content is a volume, get the title */
4129 if ( hw->help_dialog.display.helpType == DtHELP_TYPE_TOPIC )
4131 /* determine whether a current volume index is available */
4132 curVolAvail = VolumeHasIndexP(
4133 hw->help_dialog.srch.srchSources,
4134 hw->help_dialog.display.helpType,
4135 hw->help_dialog.display.helpVolume);
4137 /* change False to True to search home dir; may want this */
4138 path = _DtHelpFileLocate(DtHelpVOLUME_TYPE, hw->help_dialog.display.helpVolume,
4139 _DtHelpFileSuffixList,False,R_OK);
4141 /* title needs to be an XmString to use volume's font */
4144 XmFontList fontList = NULL;
4145 Boolean mod = False;
4147 /* get the font list of the btn */
4149 XtSetArg (args[n], XmNfontList, &fontList); n++;
4150 XtGetValues (hw->help_dialog.srch.curVolRadBtn, args, n);
4152 #if defined(DONT_USE_CDExc22774)
4153 /* copy the list before passing it in for modification */
4154 fontList = XmFontListCopy (fontList);
4157 GetVolumeInfoCB(hw->help_dialog.help.pDisplayArea,path,
4158 NULL,&volTitleString,NULL,NULL,NULL,&fontList,&mod);
4160 /* if font list was changed, install it */
4163 /* set the font list of the btn */
4165 XtSetArg (args[n], XmNfontList, fontList); n++;
4166 XtSetValues (hw->help_dialog.srch.curVolRadBtn, args, n);
4167 if (fontList) XmFontListFree (fontList);
4172 if (NULL == volTitleString)
4173 volTitleString = XmStringCreateLocalized(
4174 hw->help_dialog.display.helpVolume);
4175 } /* if helpType == TOPIC */
4177 { /* if helpType != TOPIC */
4178 curVolAvail = False;
4179 switch (hw->help_dialog.display.helpType)
4181 case DtHELP_TYPE_STRING:
4182 case DtHELP_TYPE_DYNAMIC_STRING:
4183 volTitleString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4184 (GSSET, 32,"Help Message")));
4186 case DtHELP_TYPE_FILE:
4187 volTitleString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4188 (GSSET, 33,"Help File")));
4190 case DtHELP_TYPE_MAN_PAGE:
4191 volTitleString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4192 (GSSET, 34,"Manual Page")));
4195 volTitleString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4196 (GSSET, 35,"Unknown Format")));
4198 } /* switch on helpType */
4199 } /* if helpType != TOPIC */
4201 /* record path in the widget */
4202 XtFree(hw->help_dialog.srch.curVolPath);
4203 hw->help_dialog.srch.curVolPath = path;
4206 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4207 (GSSET, 3,"Current")));
4208 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 4,"r"));*/
4211 /* append volume name to title */
4212 preTitle = (char *)_DTGETMESSAGE(GSSET, 60," (");
4213 preTitleString = XmStringCreateLocalized(preTitle);
4214 postTitle = (char *)_DTGETMESSAGE(GSSET, 61,")");
4215 postTitleString = XmStringCreateLocalized(postTitle);
4217 newTitle = XmStringConcat(labelString,preTitleString);
4218 XmStringFree(labelString);
4219 XmStringFree(preTitleString);
4220 labelString = newTitle;
4222 newTitle = XmStringConcat(labelString,volTitleString);
4223 XmStringFree(labelString);
4224 XmStringFree(volTitleString);
4225 labelString = newTitle;
4227 newTitle = XmStringConcat(labelString,postTitleString);
4228 XmStringFree(labelString);
4229 XmStringFree(postTitleString);
4230 labelString = newTitle;
4232 /* set the out values */
4233 if (out_curVolAvailable) *out_curVolAvailable = curVolAvail;
4234 if (out_mnemonic) *out_mnemonic = mnemonic;
4235 if (out_labelString) *out_labelString = labelString;
4236 else XmStringFree(labelString);
4244 /*****************************************************************************
4245 * Function: void CreateGlobSrchDialog()
4252 * Purpose: Creates and displays an instance of the search dialog.
4254 *****************************************************************************/
4255 static void CreateGlobSrchDialog(
4262 /* Widget topWidget; */
4263 Widget volumesFrame;
4268 XmString labelString;
4269 /* char * mnemonic; */
4270 Dimension widgetHeight;
4271 Dimension widgetBorderHeight;
4273 DtHelpListStruct *pHelpInfo;
4274 Atom wm_delete_window;
4275 DtHelpDialogWidget hw = (DtHelpDialogWidget) nw ;
4276 XtTranslations btnTransTable;
4277 /* XtTranslations listTransTable; */
4278 /* XtTranslations mgrTransTable; */
4279 Boolean curVolAvailable;
4283 /* get state of the volume */
4284 curVolAvailable = VolumeHasIndexP (
4285 hw->help_dialog.srch.srchSources,
4286 hw->help_dialog.display.helpType,
4287 hw->help_dialog.display.helpVolume);
4289 /* Set up the translations table stuff */
4290 btnTransTable = XtParseTranslationTable(defaultBtnTranslations);
4291 /* listTransTable = XtParseTranslationTable(defaultListTranslations); */
4292 /* mgrTransTable = XtParseTranslationTable(defaultMgrTranslations); */
4294 /* Create the shell used for the dialog. */
4295 title = XtNewString(((char *)_DTGETMESSAGE(GSSET,1,"Help - Index Search")));
4297 XtSetArg (args[n], XmNtitle, title); n++;
4298 XtSetArg (args[n], XmNallowShellResize, True); n++;
4299 srchShell = XmCreateDialogShell((Widget) hw, "searchShell", args, n);
4302 /* Set the useAsyncGeo on the shell */
4304 XtSetArg (args[n], XmNuseAsyncGeometry, True); n++;
4305 XtSetValues (XtParent(srchShell), args, n); /* parent is new's shell */
4307 /* Adjust the decorations for the dialog shell of the dialog */
4309 XtSetArg(args[n], XmNmwmFunctions, 0); n++;
4310 XtSetArg (args[n], XmNmwmDecorations,
4311 MWM_DECOR_BORDER | MWM_DECOR_TITLE); n++;
4312 XtSetValues (srchShell, args, n);
4315 /* Grab the window mgr close and install a close dialog
4316 callback when closed from dialog WM menu; this prevents
4317 the dialog from closing the host application. */
4318 wm_delete_window = XmInternAtom(XtDisplay(srchShell),
4319 "WM_DELETE_WINDOW", FALSE);
4320 XtSetArg(args[0], XmNdeleteResponse, XmDO_NOTHING);
4321 XmAddWMProtocolCallback(srchShell,wm_delete_window,
4322 CloseSearchCB, (XtPointer)&hw->help_dialog.srch);
4323 XtSetValues(srchShell, args, 1);
4325 /* set the callback that positions the dialog when popped up */
4326 XtAddCallback (srchShell, XmNpopupCallback,
4327 (XtCallbackProc)_DtHelpMapCB, (XtPointer) XtParent(hw));
4329 /*** Create the form used for the dialog. ***/
4330 /* setting RESIZE_NONE is important to prevent the resultList from
4331 dynamically resizing as items with various fonts are added and
4334 XtSetArg (args[n], XmNmarginWidth, 1); n++;
4335 XtSetArg (args[n], XmNmarginHeight, 1); n++;
4336 XtSetArg (args[n], XmNshadowThickness, 1); n++;
4337 XtSetArg (args[n], XmNshadowType, XmSHADOW_OUT); n++;
4338 XtSetArg (args[n], XmNautoUnmanage, False); n++;
4339 XtSetArg (args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
4340 parentForm = XmCreateForm (srchShell, "parentForm", args, n);
4341 hw->help_dialog.srch.srchForm = parentForm;
4343 /*==============================================================*/
4344 /****** Create the volumes region ******/
4346 XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
4347 XtSetArg (args[n], XmNtopOffset, 5); n++;
4348 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4349 XtSetArg (args[n], XmNrightOffset, 5); n++;
4350 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4351 XtSetArg (args[n], XmNleftOffset, 5); n++;
4352 XtSetArg (args[n], XmNmarginWidth, 5); n++;
4353 XtSetArg (args[n], XmNmarginHeight, 2); n++;
4354 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;/*EXP*/
4355 volumesFrame = XmCreateFrame(parentForm, "volFrame", args, n);
4356 XtManageChild (volumesFrame);
4358 /* put form inside frame */
4359 volumesForm = XmCreateForm (volumesFrame, "volumesForm", args, 0);
4360 XtManageChild (volumesForm);
4362 /* create the frame title */
4363 labelString = XmStringCreateLocalized ((_DTGETMESSAGE(GSSET,2, "Search")));
4365 XtSetArg (args[n], XmNlabelString, labelString); n++;
4366 XtSetArg (args[n], XmNchildType, XmFRAME_TITLE_CHILD); n++;
4367 XtSetArg (args[n], XmNtraversalOn, False); n++;
4368 frameTitle = XmCreateLabelGadget(volumesFrame, "volFrameTitle", args, n);
4369 XtManageChild (frameTitle);
4370 XmStringFree (labelString);
4372 /* create Current Volume radio button */
4373 /* Use a dummy label until CreateCurVolBtnLabel can be used.
4374 It refs the srchCurVolRadBtn widget and other things that need
4377 labelString = XmStringCreateLocalized (" ");
4379 XtSetArg (args[n], XmNindicatorType, XmONE_OF_MANY); n++;
4380 XtSetArg (args[n], XmNset, TRUE); n++;
4382 XtSetArg(args[n], XmNlabelString, labelString); n++;
4383 XtSetArg (args[n], XmNmarginHeight, 0); n++;
4384 XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
4385 XtSetArg (args[n], XmNtopOffset, 0); n++;
4386 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4387 XtSetArg (args[n], XmNleftOffset, 5); n++;
4388 /* Attaching to form causes the hilite outline of the button to
4389 stretch to the form edge when selected. But it also forces
4390 the form to resize when the current volume title is too big
4391 for the available space. */
4392 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4393 XtSetArg (args[n], XmNrightOffset, 10); n++;
4394 XtSetArg (args[n], XmNbottomOffset, 0); n++;
4395 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
4396 XtSetArg (args[n], XmNhighlightOnEnter, True); n++;
4397 hw->help_dialog.srch.curVolRadBtn =
4398 XmCreateToggleButtonGadget(volumesForm,"srchCurVolRadBtn",args,n);
4399 XtAddCallback(hw->help_dialog.srch.curVolRadBtn,XmNvalueChangedCallback,
4400 UpdateSearchVolumesCB, (XtPointer) hw);
4401 /* ??? XtSetSensitive (hw->help_dialog.srch.curVolRadBtn,False); */
4402 XtManageChild (hw->help_dialog.srch.curVolRadBtn);
4403 XmStringFree (labelString);
4405 /* create All Volumes radio button */
4406 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4407 (GSSET, 5,"All Volumes")));
4408 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 7,"A"));*/
4411 XtSetArg (args[n], XmNindicatorType, XmONE_OF_MANY); n++;
4412 XtSetArg (args[n], XmNset, FALSE); n++;
4413 XtSetArg (args[n], XmNlabelString, labelString); n++;
4414 XtSetArg (args[n], XmNmarginHeight, 0); n++;
4415 XtSetArg (args[n], XmNmarginWidth, 2); n++;
4416 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4417 XtSetArg (args[n], XmNtopWidget, hw->help_dialog.srch.curVolRadBtn); n++;
4418 XtSetArg (args[n], XmNtopOffset, 1); n++;
4419 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4420 XtSetArg (args[n], XmNleftOffset, 5); n++;
4421 XtSetArg(args[n], XmNhighlightOnEnter, True); n++;
4422 hw->help_dialog.srch.allVolRadBtn =
4423 XmCreateToggleButtonGadget(volumesForm,"srchAllVolRadBtn",args, n);
4424 XtAddCallback(hw->help_dialog.srch.allVolRadBtn,XmNvalueChangedCallback,
4425 UpdateSearchVolumesCB, (XtPointer) hw);
4426 XtManageChild (hw->help_dialog.srch.allVolRadBtn);
4427 XmStringFree (labelString);
4429 /* create Selected Volumes radio button */
4430 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4431 (GSSET, 6,"Selected")));
4432 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 9,"d"));*/
4435 XtSetArg (args[n], XmNindicatorType, XmONE_OF_MANY); n++;
4436 XtSetArg (args[n], XmNlabelString, labelString); n++;
4437 XtSetArg (args[n], XmNmarginHeight, 0); n++;
4438 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4439 XtSetArg (args[n], XmNtopWidget, hw->help_dialog.srch.allVolRadBtn); n++;
4440 XtSetArg (args[n], XmNtopOffset, 1); n++;
4441 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4442 XtSetArg (args[n], XmNleftOffset, 5); n++;
4443 XtSetArg (args[n], XmNbottomOffset, 2); n++;
4444 XtSetArg(args[n], XmNhighlightOnEnter, True); n++;
4445 hw->help_dialog.srch.selVolRadBtn =
4446 XmCreateToggleButtonGadget(volumesForm,"srchSelVolRadBtn", args, n);
4447 XtAddCallback(hw->help_dialog.srch.selVolRadBtn,XmNvalueChangedCallback,
4448 UpdateSearchVolumesCB, (XtPointer) hw);
4449 XtManageChild (hw->help_dialog.srch.selVolRadBtn);
4450 XmStringFree (labelString);
4453 /* Create Selected... button */
4454 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4455 (GSSET, 7,"Select Volumes...")));
4458 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4459 XtSetArg (args[n], XmNtopOffset, 0); n++;
4460 XtSetArg (args[n], XmNtopWidget, hw->help_dialog.srch.allVolRadBtn); n++;
4461 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4462 XtSetArg (args[n], XmNrightOffset, 10); n++;
4463 XtSetArg (args[n], XmNbottomOffset, 2); n++;
4464 XtSetArg (args[n], XmNmarginTop, 0); n++;
4465 XtSetArg (args[n], XmNmarginHeight, 3); n++;
4466 XtSetArg (args[n], XmNlabelString, labelString); n++;
4467 hw->help_dialog.srch.selectBtn =
4468 XmCreatePushButtonGadget(volumesForm,"selectBtn", args, n);
4469 XtAddCallback (hw->help_dialog.srch.selectBtn, XmNactivateCallback,
4470 OpenSelectDialogCB, (XtPointer) hw);
4471 XtManageChild (hw->help_dialog.srch.selectBtn);
4472 XtSetSensitive (hw->help_dialog.srch.selectBtn,False);
4473 XmStringFree (labelString);
4475 /****** Create the show selection region ******/
4477 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4478 XtSetArg (args[n], XmNtopWidget, volumesFrame); n++;
4479 XtSetArg (args[n], XmNtopOffset, 5); n++;
4480 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4481 XtSetArg (args[n], XmNrightOffset, 5); n++;
4482 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4483 XtSetArg (args[n], XmNleftOffset, 5); n++;
4484 XtSetArg (args[n], XmNmarginWidth, 5); n++;
4485 XtSetArg (args[n], XmNmarginHeight, 2); n++;
4486 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;/*EXP*/
4487 showFrame = XmCreateFrame(parentForm, "showFrame", args, n);
4488 XtManageChild (showFrame);
4490 /* FIX: is this doing enough? Goal: CR activation of FullIndex */
4491 /* Setup the proper translation on the title box widget */
4492 /* XtAugmentTranslations(showFrame, mgrTransTable); */
4494 /* put form inside frame */
4495 showForm = XmCreateForm (showFrame, "showForm", args, 0);
4496 XtManageChild (showForm);
4498 /* create the frame title */
4499 labelString = XmStringCreateLocalized ((_DTGETMESSAGE(GSSET,8, "Show")));
4501 XtSetArg (args[n], XmNlabelString, labelString); n++;
4502 XtSetArg (args[n], XmNtraversalOn, False); n++;
4503 XtSetArg (args[n], XmNchildType, XmFRAME_TITLE_CHILD); n++;
4504 frameTitle = XmCreateLabelGadget(showFrame, "showFrameTitle", args, n);
4505 XtManageChild (frameTitle);
4506 XmStringFree (labelString);
4508 /* create the All Entries button */
4509 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4510 (GSSET, 9,"Complete Index")));
4513 XtSetArg (args[n], XmNindicatorType, XmONE_OF_MANY); n++;
4514 XtSetArg (args[n], XmNset, True); n++;
4515 XtSetArg (args[n], XmNlabelString, labelString); n++;
4516 XtSetArg (args[n], XmNmarginHeight, 1); n++;
4517 XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
4518 XtSetArg (args[n], XmNtopOffset, 0); n++;
4519 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4520 XtSetArg (args[n], XmNleftOffset, 5); n++;
4521 XtSetArg (args[n], XmNbottomOffset, 0); n++;
4522 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
4523 XtSetArg (args[n], XmNhighlightOnEnter, True); n++;
4524 hw->help_dialog.srch.fullIndexRadBtn =
4525 XmCreateToggleButtonGadget(showForm,"srchFullIndexRadBtn",args,n);
4526 XtAddCallback(hw->help_dialog.srch.fullIndexRadBtn,XmNvalueChangedCallback,
4527 UpdateIndexSelectionCB, (XtPointer) hw);
4528 XtManageChild (hw->help_dialog.srch.fullIndexRadBtn);
4529 XmStringFree (labelString);
4531 /* create Contains radio button */
4532 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4533 (GSSET, 10,"Entries with:")));
4534 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 16,"n"));*/
4537 XtSetArg (args[n], XmNindicatorType, XmONE_OF_MANY); n++;
4538 XtSetArg (args[n], XmNset, False); n++;
4539 XtSetArg (args[n], XmNlabelString, labelString); n++;
4540 XtSetArg (args[n], XmNmarginHeight, 1); n++;
4541 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4542 XtSetArg (args[n], XmNtopWidget,hw->help_dialog.srch.fullIndexRadBtn);n++;
4543 XtSetArg (args[n], XmNtopOffset, 1); n++;
4544 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4545 XtSetArg (args[n], XmNleftOffset, 5); n++;
4546 XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
4547 XtSetArg (args[n], XmNbottomOffset, 4); n++;
4548 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
4549 XtSetArg (args[n], XmNhighlightOnEnter, True); n++;
4550 hw->help_dialog.srch.containsRadBtn =
4551 XmCreateToggleButtonGadget(showForm,"srchContainsRadBtn",args,n);
4552 XtAddCallback(hw->help_dialog.srch.containsRadBtn,XmNvalueChangedCallback,
4553 UpdateIndexSelectionCB, (XtPointer) hw);
4554 XtAddCallback(hw->help_dialog.srch.containsRadBtn,XmNdisarmCallback,
4555 ContainsDisarmCB, (XtPointer) hw);
4556 XtManageChild (hw->help_dialog.srch.containsRadBtn);
4557 XmStringFree (labelString);
4559 /* create the search name text field */
4561 XtSetArg (args[n], XmNvalue, ""); n++;
4562 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4563 XtSetArg (args[n], XmNtopWidget,hw->help_dialog.srch.fullIndexRadBtn); n++;
4564 XtSetArg (args[n], XmNtopOffset, 0); n++;
4565 XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
4566 XtSetArg (args[n], XmNleftWidget,hw->help_dialog.srch.containsRadBtn); n++;
4567 XtSetArg (args[n], XmNleftOffset, 5); n++;
4568 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4569 XtSetArg (args[n], XmNrightOffset, 10); n++;
4570 XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
4571 XtSetArg (args[n], XmNbottomOffset, 3); n++;
4572 XtSetArg (args[n], XmNhighlightOnEnter, True); n++;
4573 XtSetArg (args[n], XmNcursorPositionVisible, False); n++;
4574 hw->help_dialog.srch.wordField =
4575 XmCreateTextField (showForm,"srchWord",args, n);
4576 XtSetSensitive(hw->help_dialog.srch.wordField,False);
4577 XtManageChild (hw->help_dialog.srch.wordField);
4578 /* Because the actionBtn is the default button on the form,
4579 and it activates a search, we do not need to (nor do we want
4580 to, since ActionButtonCB toggles between states) make it
4581 a callback on activation of the text field */
4582 XtAddCallback (hw->help_dialog.srch.wordField, XmNvalueChangedCallback,
4583 UpdateSearchStartStatusCB, (XtPointer) hw);
4585 /* Setup the proper translation on the text field widget */
4586 XtAugmentTranslations(hw->help_dialog.srch.wordField, btnTransTable);
4589 /* Create a separator search specs and result area */
4591 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4592 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4593 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4594 XtSetArg (args[n], XmNtopWidget, showFrame); n++;
4595 XtSetArg (args[n], XmNtopOffset, 10); n++;
4596 separator = XmCreateSeparatorGadget (parentForm, "separator", args, n);
4597 XtManageChild (separator);
4599 /*==============================================================*/
4600 /****** result related stuff *******/
4601 /* Create result List Label */
4603 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4604 XtSetArg (args[n], XmNtopWidget, separator); n++;
4605 XtSetArg (args[n], XmNtopOffset, 10); n++;
4606 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4607 XtSetArg (args[n], XmNleftOffset, 10); n++;
4608 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4609 XtSetArg (args[n], XmNrightOffset, 10); n++;
4610 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
4611 hw->help_dialog.srch.statusLabel =
4612 XmCreateLabelGadget (parentForm, "resultListLabel", args, n);
4613 StatusLabelUpdate(hw,FIRST_PROMPT_STATUS,True,0); /* installs a label */
4614 XtManageChild (hw->help_dialog.srch.statusLabel);
4616 /* Create our result topics scrolled list (not placed on form) */
4618 XtSetArg (args[n], XmNlistSizePolicy, XmCONSTANT); n++;
4619 XtSetArg (args[n], XmNselectionPolicy, XmSINGLE_SELECT); n++;
4620 XtSetArg (args[n], XmNhighlightOnEnter, True); n++;
4621 XtSetArg (args[n], XmNscrollBarDisplayPolicy, XmSTATIC); n++;
4622 hw->help_dialog.srch.resultList =
4623 XmCreateScrolledList (parentForm, "resultList", args, n);
4624 XtManageChild (hw->help_dialog.srch.resultList);
4626 XtAddCallback (hw->help_dialog.srch.resultList, XmNsingleSelectionCallback,
4627 ProcessResultSelectionCB, (XtPointer) hw);
4628 XtAddCallback (hw->help_dialog.srch.resultList, XmNdefaultActionCallback,
4629 ProcessResultSelectionCB, (XtPointer) hw);
4631 /* Set the constraints on our scrolled list (place on form) */
4633 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4634 XtSetArg (args[n], XmNtopWidget, hw->help_dialog.srch.statusLabel); n++;
4635 XtSetArg (args[n], XmNtopOffset, 5); n++;
4636 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4637 XtSetArg (args[n], XmNleftOffset, 10); n++;
4638 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4639 XtSetArg (args[n], XmNrightOffset, 10); n++;
4640 XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
4641 XtSetArg (args[n], XmNbottomOffset, 70); n++;
4642 /* 70 is just a rough value that will be updated with a calculated
4643 value below, after we know the height of the buttons */
4644 XtSetValues (XtParent (hw->help_dialog.srch.resultList), args, n);
4646 /* Create a separator between the buttons */
4648 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4649 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4650 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4651 XtSetArg (args[n], XmNtopWidget,
4652 XtParent (hw->help_dialog.srch.resultList)); n++;
4653 XtSetArg (args[n], XmNtopOffset, 5); n++;
4654 separator = XmCreateSeparatorGadget (parentForm, "separator", args, n);
4655 XtManageChild (separator);
4657 /***** search spec-related stuff *****/
4658 /* Create start button (left of stop button)*/
4659 _DtHelpProcessLock();
4660 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4661 (GSSET, START_SEARCH_CAT,START_SEARCH_STR)));
4662 _DtHelpProcessUnlock();
4663 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 20,START_SEARCH_MNEM));*/
4666 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4667 XtSetArg (args[n], XmNtopWidget, separator); n++;
4668 XtSetArg (args[n], XmNtopOffset, 5); n++;
4669 /* L & R position set below */
4670 XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
4671 XtSetArg (args[n], XmNbottomOffset, 5); n++;
4672 /*XtSetArg (args[n], XmNmarginHeight, 3); n++;*/
4673 XtSetArg (args[n], XmNlabelString, labelString); n++;
4674 XtSetArg(args[n], XmNhighlightOnEnter, True); n++;
4675 hw->help_dialog.srch.actionBtn =
4676 XmCreatePushButtonGadget(parentForm,"actionBtn", args, n);
4677 XtAddCallback (hw->help_dialog.srch.actionBtn, XmNactivateCallback,
4678 ActionButtonCB, (XtPointer) hw);
4679 XtSetSensitive (hw->help_dialog.srch.actionBtn,False);
4680 XtManageChild (hw->help_dialog.srch.actionBtn);
4681 XmStringFree (labelString);
4683 XtSetArg (args[0], XmNdefaultButton, hw->help_dialog.srch.actionBtn);
4684 XtSetValues (parentForm, args, 1);
4686 /* Build the Cancel Button */
4687 _DtHelpProcessLock();
4688 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4689 (GSSET, CLOSE_BTN_CAT,CLOSE_BTN_STR)));
4690 _DtHelpProcessUnlock();
4691 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 25,CLOSE_BTN_MNEM));*/
4693 XtSetArg (args[n], XmNlabelString, labelString); n++;
4694 /* L & R position set below */
4695 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4696 XtSetArg (args[n], XmNtopWidget, separator); n++;
4697 XtSetArg (args[n], XmNtopOffset, 5); n++;
4698 XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
4699 XtSetArg (args[n], XmNbottomOffset, 5); n++;
4700 XtSetArg (args[n], XmNmarginHeight, 3); n++;
4701 XtSetArg(args[n], XmNhighlightOnEnter, True); n++;
4702 hw->help_dialog.srch.closeBtn =
4703 XmCreatePushButtonGadget (parentForm, "srchCloseBtn", args, n);
4705 XtAddCallback(hw->help_dialog.srch.closeBtn,
4706 XmNactivateCallback, CloseSearchCB,(XtPointer) &hw->help_dialog.srch);
4708 XtManageChild (hw->help_dialog.srch.closeBtn);
4709 XmStringFree (labelString);
4711 /* Build the Help button */
4712 _DtHelpProcessLock();
4713 labelString = XmStringCreateLocalized((char *)_DTGETMESSAGE
4714 (GSSET, HELP_BTN_CAT,HELP_BTN_STR));
4715 _DtHelpProcessUnlock();
4716 /*mnemonic = (char *)_DTGETMESSAGE(GSSET, 27,HELP_BTN_MNEM);*/
4719 XtSetArg (args[n], XmNlabelString, labelString); n++;
4720 /* L & R position set below */
4721 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4722 XtSetArg (args[n], XmNtopWidget, separator); n++;
4723 XtSetArg (args[n], XmNtopOffset, 5); n++;
4724 XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
4725 XtSetArg (args[n], XmNbottomOffset, 5); n++;
4726 XtSetArg (args[n], XmNmarginHeight, 3); n++;
4727 XtSetArg(args[n], XmNhighlightOnEnter, True); n++;
4728 hw->help_dialog.srch.helpBtn =
4729 XmCreatePushButtonGadget (parentForm, "srchHelpBtn", args, n);
4730 XtManageChild (hw->help_dialog.srch.helpBtn);
4731 XmStringFree (labelString);
4733 pHelpInfo = _DtHelpListAdd(DtHELP_srchIndexHelpBtn_STR,
4734 (Widget) hw, &hw->help_dialog.help,
4735 &hw->help_dialog.help.pHelpListHead);
4736 XtAddCallback(hw->help_dialog.srch.helpBtn, XmNactivateCallback,
4737 _DtHelpCB, (XtPointer) pHelpInfo);
4739 /*==============================================================*/
4740 /****** finishing touches *******/
4741 /* set the Form cancel button (for KCancel) */
4743 XtSetArg (args[n], XmNcancelButton, hw->help_dialog.srch.closeBtn); n++;
4744 XtSetValues (parentForm, args, n);
4746 { /* position buttons */
4747 /* This code adds up the sizes of the buttons to go into
4748 the bottom row and calculates the form position percentages.
4749 All buttons are the same size, and are able to hold all
4750 the strings that may be dynamically placed in them.
4751 All buttons are 5% apart. */
4752 /* This code is specifically written to handle 3 buttons
4753 and assumes that the first 3 strings are to the ActionBtn */
4755 Dimension maxWidth = 0;
4756 Dimension borderWidth = 0;
4757 Dimension sumWidth = 0;
4759 float posList[11]; /* need 11 due to algorithm, which uses index 10 */
4760 XmFontList fontList = NULL;
4763 /* get the fontList for the button */
4764 XtSetArg (args[0], XmNborderWidth, &borderWidth);
4765 XtSetArg (args[1], XmNfontList, &fontList);
4766 XtGetValues (hw->help_dialog.srch.actionBtn, args, 2);
4768 #define BETBUTSPACE 5 /* pixels */
4769 sumWidth = BETBUTSPACE; /* left side space */
4770 posList[0] = (float) sumWidth;
4771 for (i=0; i<NUMSTRS; i++)
4773 XmString labelString;
4775 _DtHelpProcessLock();
4776 s_GlobSrchDlgBtnStrs[i] = (char *) _DTGETMESSAGE(GSSET,
4777 s_GlobSrchDlgBtnCatNum[i],s_GlobSrchDlgBtnStrs[i]);
4778 labelString = XmStringCreateLocalized(s_GlobSrchDlgBtnStrs[i]);
4779 _DtHelpProcessUnlock();
4780 #define MARGINS 4 /* pixel margins: 2=L, 2=R */
4781 width = XmStringWidth(fontList,labelString) + borderWidth + MARGINS;
4782 if (i<=2) maxWidth = max(width,maxWidth);
4783 if (i==2) width = maxWidth; /* 1st three labels go in 1st button */
4784 if (i>=2) /* after scanning just labels, do buttons */
4787 posList[i*2+1] = (float) sumWidth;
4788 sumWidth += BETBUTSPACE;
4789 posList[i*2+2] = (float) sumWidth;
4791 XmStringFree(labelString);
4792 } /* for calcing widths */
4794 /* scale pixels to percent */
4795 scale = 100.0 / (float) sumWidth;
4798 XtSetArg (args[n], XmNwidth, maxWidth); n++;
4799 XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
4800 XtSetArg (args[n], XmNleftPosition, (Dimension) (posList[0]*scale)); n++;
4801 XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
4802 XtSetArg (args[n], XmNrightPosition,(Dimension) (posList[5]*scale)); n++;
4803 XtSetValues (hw->help_dialog.srch.actionBtn, args, n);
4806 XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
4807 XtSetArg (args[n], XmNleftPosition, (Dimension) (posList[6]*scale)); n++;
4808 XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
4809 XtSetArg (args[n], XmNrightPosition,(Dimension) (posList[7]*scale)); n++;
4810 XtSetValues (hw->help_dialog.srch.closeBtn, args, n);
4813 XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
4814 XtSetArg (args[n], XmNleftPosition, (Dimension) (posList[8]*scale)); n++;
4815 XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
4816 XtSetArg (args[n], XmNrightPosition,(Dimension) (posList[9]*scale)); n++;
4817 XtSetValues (hw->help_dialog.srch.helpBtn, args, n);
4820 { /* set the proper offset between the bottom of the results list
4821 and the bottom of the form to maintain a constant sized
4825 /* first calc offset of list to form bottom based on earlier sizes */
4826 #define KNOWN_OFFSETS_BELOW_LIST 20 /* actually only 15, but 15 fails */
4828 XtSetArg(args[n], XmNborderWidth, &widgetBorderHeight); n++;
4829 XtSetArg(args[n], XmNheight, &widgetHeight); n++;
4830 XtGetValues(hw->help_dialog.srch.actionBtn, args, n);
4831 offset = widgetHeight + 2 * widgetBorderHeight;
4832 XtGetValues(separator, args, n);
4833 offset += widgetHeight + 2 * widgetBorderHeight;
4834 XtGetValues(XtParent(hw->help_dialog.srch.resultList), args, 1);
4835 offset += widgetBorderHeight;
4836 offset += KNOWN_OFFSETS_BELOW_LIST;
4838 /* then set the offset */
4840 XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
4841 XtSetArg (args[n], XmNbottomOffset, offset); n++;
4842 XtSetValues (XtParent (hw->help_dialog.srch.resultList), args, n);
4845 /** force tabs to go to each widget and in right order **/
4846 XtSetArg (args[0], XmNnavigationType, XmSTICKY_TAB_GROUP);
4847 XtSetValues (hw->help_dialog.srch.curVolRadBtn,args,1);
4848 XtSetValues (hw->help_dialog.srch.allVolRadBtn,args,1);
4849 XtSetValues (hw->help_dialog.srch.selVolRadBtn,args,1);
4850 XtSetValues (hw->help_dialog.srch.selectBtn,args,1);
4851 XtSetValues (hw->help_dialog.srch.fullIndexRadBtn,args,1);
4852 XtSetValues (hw->help_dialog.srch.containsRadBtn,args,1);
4853 XtSetValues (hw->help_dialog.srch.wordField,args,1);
4854 XtSetValues (hw->help_dialog.srch.resultList,args,1);
4855 XtSetValues (hw->help_dialog.srch.actionBtn,args,1);
4856 XtSetValues (hw->help_dialog.srch.closeBtn,args,1);
4857 XtSetValues (hw->help_dialog.srch.helpBtn,args,1);
4859 /** put focus on the text field **/
4860 XtSetArg (args[0], XmNinitialFocus, hw->help_dialog.srch.wordField);
4861 XtSetValues (parentForm,args,1);
4863 /* Add the proper help callback to the print dialog shell "F1" support */
4864 pHelpInfo = _DtHelpListAdd(DtHELP_srchIndexShell_STR,
4865 (Widget) hw, &hw->help_dialog.help,
4866 &hw->help_dialog.help.pHelpListHead);
4867 XtAddCallback(parentForm, XmNhelpCallback,
4868 _DtHelpCB, (XtPointer) pHelpInfo);
4872 /*****************************************************************************
4873 * Function: updateDisplay()
4876 * Parameters: hw: the help widget
4880 * Purpose: forces an update on index search dialog widgets
4882 *****************************************************************************/
4883 static int updateDisplay(
4884 DtHelpDialogWidget hw)
4886 XmUpdateDisplay((Widget)hw->help_dialog.srch.actionBtn);/*DBG*/
4887 XmUpdateDisplay((Widget)hw->help_dialog.srch.curVolRadBtn);/*DBG*/
4888 XmUpdateDisplay((Widget)hw->help_dialog.srch.allVolRadBtn);/*DBG*/
4889 XmUpdateDisplay((Widget)hw->help_dialog.srch.selVolRadBtn);/*DBG*/
4890 XmUpdateDisplay((Widget)hw->help_dialog.srch.selectBtn);/*DBG*/
4891 XmUpdateDisplay((Widget)hw->help_dialog.srch.fullIndexRadBtn);/*DBG*/
4892 XmUpdateDisplay((Widget)hw->help_dialog.srch.containsRadBtn);/*DBG*/
4893 XmUpdateDisplay((Widget)hw->help_dialog.srch.wordField);/*DBG*/
4894 XmUpdateDisplay((Widget)hw->help_dialog.srch.statusLabel);/*DBG*/
4895 XmUpdateDisplay((Widget)hw->help_dialog.srch.resultList);/*DBG*/
4896 XmUpdateDisplay((Widget)hw->help_dialog.srch.closeBtn);/*DBG*/
4897 XmUpdateDisplay((Widget)hw->help_dialog.srch.helpBtn);/*DBG*/
4898 XmUpdateDisplay(XtParent((Widget)hw->help_dialog.srch.srchForm));/*DBG*/
4904 /*****************************************************************************
4905 * Function: void _DtHelpGlobSrchDisplayDialog()
4908 * Parameters: parent Specifies the parent widget
4909 * searchWord word to put into searchWord field
4910 * remove this when integrated into DtHelp:
4911 * curVolume volume considered the current volume
4915 * Purpose: Setsup the proper data in the search dialog and
4916 * displays an instance of the search dialog.
4918 *****************************************************************************/
4919 void _DtHelpGlobSrchDisplayDialog(
4924 DtHelpDialogWidget hw = (DtHelpDialogWidget) w;
4925 XmToggleButtonCallbackStruct status; /* the call data */
4926 Widget sourceBtn; /* widget owning event */
4932 XmString labelString = NULL;
4935 /* make the dialog itself */
4936 if (NULL == hw->help_dialog.srch.srchForm)
4938 CreateGlobSrchDialog((Widget) hw,searchWord);
4940 /* create the button label */
4941 CreateCurVolBtnLabel(hw, NULL, &labelString, NULL);
4942 XtSetArg (args[0], XmNlabelString, labelString);
4943 XtSetValues (hw->help_dialog.srch.curVolRadBtn, args, 1);
4944 XmStringFree (labelString);
4946 /*** map widget and update display before doing any searching ***/
4947 /* Make sure the Search Dialog is managed */
4948 XtManageChild(hw->help_dialog.srch.srchForm);
4949 XtMapWidget(hw->help_dialog.srch.srchForm);
4951 /* set focus to contains word */
4952 XmProcessTraversal(hw->help_dialog.srch.wordField,XmTRAVERSE_CURRENT);
4954 /* force several updates to make sure it is fully displayed and
4955 that height/width are correctly inited */
4956 XmUpdateDisplay(XtParent((Widget)hw->help_dialog.srch.srchForm));
4957 XmUpdateDisplay(XtParent((Widget)hw->help_dialog.srch.srchForm));
4958 XmUpdateDisplay(XtParent((Widget)hw->help_dialog.srch.srchForm));
4960 /*** now update settings, which may also invoke a search ***/
4961 /* set the cur vol btn sensitivity */
4962 UpdateCurVolBtnSens(hw,True);
4964 /* set default show index state */
4965 /* set full index if current vol has an index, contains word if not */
4966 if (hw->help_dialog.srch.curVolRadBtnSens) /* set in UpdateCurVolBtnSens*/
4967 sourceBtn = hw->help_dialog.srch.fullIndexRadBtn;
4969 sourceBtn = hw->help_dialog.srch.containsRadBtn;
4971 /* set the show index state */
4972 status.reason = XmCR_VALUE_CHANGED;
4974 status.event = (XEvent *) 1; /* thwart == NULL test in Update...() */
4975 UpdateIndexSelectionCB(sourceBtn,(XtPointer)hw,(XtPointer)&status);
4976 StatusLabelUpdate(hw,FIRST_PROMPT_STATUS,False,0);
4978 updateDisplay(hw); /* DBG */
4980 #if 0 /* 11/23/94 */
4981 /** Set min size for the dialog **/
4983 XtSetArg(args[n], XmNheight, &height); ++n;
4984 XtSetArg(args[n], XmNwidth, &width); ++n;
4985 XtGetValues(XtParent((Widget)hw->help_dialog.srch.srchForm), args, n);
4987 XtSetArg(args[n], XmNminHeight, height - 200); ++n; /* 200: arbitrary */
4988 XtSetArg(args[n], XmNminWidth, width); ++n;
4989 XtSetValues(XtParent((Widget)hw->help_dialog.srch.srchForm), args, n);
4992 else /* properly update dialog to support new word and cur vol */
4994 /* fixup current volume, if need be */
4995 _DtHelpGlobSrchUpdateCurVol((Widget)hw);
4997 /* fixup search word, if need be */
4998 if (NULL != searchWord)
5000 String srchWord = XtNewString(searchWord);
5001 /* srchWord is freed or used in CheckSearchWord() */
5002 if (CheckSearchWord(hw,srchWord,True) == True)
5003 { /* words are different */
5004 /* free all hit-related data and reset flags */
5005 HitListFreeAllVolHits(hw,True); /*True=free everything*/
5009 /* if its not managed, manage it */
5010 if ( XtIsManaged(hw->help_dialog.srch.srchForm) == False )
5012 /* manage and map the Search Dialog */
5013 XtManageChild(hw->help_dialog.srch.srchForm);
5014 XtMapWidget((Widget)hw->help_dialog.srch.srchForm);
5016 /* see if the selection dialog was already open */
5017 if ( hw->help_dialog.srch.selectionDlg
5018 && XtIsManaged(hw->help_dialog.srch.selectionDlg) )
5020 XtManageChild(hw->help_dialog.srch.selectionDlg);
5021 XtMapWidget(hw->help_dialog.srch.selectionDlg);
5024 else /* if it is managed, bring it forward */
5026 Widget parent = XtParent(hw->help_dialog.srch.srchForm);
5027 XRaiseWindow ( XtDisplay(parent), XtWindow(parent) );
5032 if (hw->help_dialog.srch.hitsFound == True)
5033 XmProcessTraversal(hw->help_dialog.srch.resultList,XmTRAVERSE_CURRENT);
5035 XmProcessTraversal(hw->help_dialog.srch.allVolRadBtn,XmTRAVERSE_CURRENT);
5039 } /* end if create a new dialog */
5044 /*****************************************************************************
5045 * Function: void _DtHelpGlobSrchUpdateCurVol()
5047 * Parameters: new the help widget
5051 * Purpose: Adjusts the current volume of the dialog
5053 *****************************************************************************/
5054 void _DtHelpGlobSrchUpdateCurVol(
5058 DtHelpDialogWidget hw = (DtHelpDialogWidget) w;
5061 if ( NULL == hw->help_dialog.srch.srchForm )
5063 if ( NULL == hw->help_dialog.srch.srchForm
5064 || XtIsManaged(hw->help_dialog.srch.srchForm) == False )
5066 return; /* RETURN */
5068 /* get full pathname for the volume */
5070 if (hw->help_dialog.display.helpVolume)
5071 path = _DtHelpFileLocate(DtHelpVOLUME_TYPE,
5072 /* FIX: will helpVolume have matching path? */
5073 hw->help_dialog.display.helpVolume,
5074 _DtHelpFileSuffixList,False,R_OK);
5076 if ( _DtHelpGlobSrchCurVolume == hw->help_dialog.srch.srchSources
5077 && hw->help_dialog.display.helpType == DtHELP_TYPE_TOPIC
5079 && NULL != hw->help_dialog.srch.curVolPath
5080 && _DtHelpFileIsSameP(path,hw->help_dialog.srch.curVolPath,
5081 GetVolumeInfoCB, _DtHELP_FILE_NAME,
5082 hw->help_dialog.help.pDisplayArea) )
5084 /* leave current status as is */
5086 return; /* RETURN */
5090 /* a different current volume or change of topic */
5092 XmString labelString;
5095 /* if still searching previous cur volume, stop any search in progress */
5096 if ( _DtHelpGlobSrchCurVolume == hw->help_dialog.srch.srchSources
5097 && hw->help_dialog.srch.workProcId)
5099 /* cancel the search */
5100 StopSearchCB(NULL,(XtPointer) hw, NULL);
5102 /* (F,F,F,F): disable search,disable display,no 0 hits,for all vols */
5103 SetVolStatus(hw->help_dialog.srch.volListHead,False,False,False,False);
5105 /* zero search data */
5106 hw->help_dialog.srch.volLeftCnt = 0;
5107 hw->help_dialog.srch.curSrchVol = NULL;
5109 /* assumption is, that even though the search was incomplete,
5110 nothing bad will happen if we don't free the hit data,
5111 and the search could resume where left off, if necessary. */
5114 CreateCurVolBtnLabel(hw, NULL, &labelString, NULL);
5115 XtSetArg(args[0],XmNlabelString,labelString);
5116 XtSetValues(hw->help_dialog.srch.curVolRadBtn,args,1);
5117 XmStringFree(labelString);
5119 /* set the cur vol btn sensitivity */
5120 UpdateCurVolBtnSens(hw,False);
5122 /* set state of start button correctly */
5123 UpdateSearchStartStatusCB(NULL, (XtPointer) hw, NULL);
5125 /* and search if needed */
5126 if ( _DtHelpGlobSrchCurVolume == hw->help_dialog.srch.srchSources )
5128 /* if to search a volume, start the search */
5129 if (hw->help_dialog.display.helpType == DtHELP_TYPE_TOPIC)
5130 StartSearchCB(NULL,(XtPointer) hw, NULL);
5131 else /* if current isn't a volume, clear the display & update status */
5133 DeleteListContents(&hw->help_dialog.srch);
5134 StatusLabelUpdate(hw,NO_VOL_STATUS,False,0);
5142 /*****************************************************************************
5143 * Function: void _DtHelpGlobSrchInitVars()
5145 * Parameters: srch search main data structure
5149 * Purpose: Init the contents of the control data structure
5151 *****************************************************************************/
5152 void _DtHelpGlobSrchInitVars(
5153 _DtHelpGlobSearchStuff * srch)
5155 /* set the font resource */
5156 if (srch->hitPrefixFont != _DtHelpDefaultSrchHitPrefixFont)
5157 srch->hitPrefixFont = XtNewString(srch->hitPrefixFont);
5159 /* File Selection Dialog font list */
5160 srch->volTitlesFontList = NULL;
5162 /* Set our search dialog widgets to NULL */
5163 srch->srchForm = NULL;
5164 srch->actionBtn = NULL;
5165 srch->curVolRadBtn = NULL;
5166 srch->allVolRadBtn = NULL;
5167 srch->selVolRadBtn = NULL;
5168 srch->selectBtn = NULL;
5169 srch->fullIndexRadBtn = NULL;
5170 srch->containsRadBtn = NULL;
5171 srch->wordField = NULL;
5172 srch->statusLabel = NULL;
5173 srch->resultList = NULL;
5174 srch->gotoBtn = NULL;
5175 srch->closeBtn = NULL;
5176 srch->helpBtn = NULL;
5177 srch->selectionDlg = NULL;
5179 /* init dialog content variables */
5180 srch->curVolPath = NULL;
5181 srch->rawWordStr = NULL;
5182 srch->normWordStr = NULL;
5183 srch->localeWordStr = NULL;
5184 srch->wordFieldFirstChar = 0;
5185 srch->wordFieldLen = 0;
5186 srch->statusLineUsage = 0; /* empty */
5188 /* init srch processing variables */
5189 srch->iconv3Codeset = NULL; /* iconv(3)-compatible code set of current locale */
5190 srch->iconv3Context = NULL;
5191 srch->srchSources = _DtHelpGlobSrchVolumeUndef; /* radio btn usage */
5192 srch->curSrchVol = NULL; /* volume currently in search */
5193 srch->hitsFontLoaded= False; /* is font loaded? */
5194 srch->volScanDone = False; /* is the volume list complete? */
5195 srch->fullIndex = False;
5196 srch->hitsFound = False; /* state of search */
5197 srch->readyToStart = False; /* state of search */
5198 srch->searchInProgress= False; /* state of search */
5199 srch->curVolRadBtnSens = False;
5200 srch->volLeftCnt = 0;
5201 srch->volListHead = NULL; /* info on search topics found */
5202 srch->workProcId = 0;
5206 /*****************************************************************************
5207 * Function: void _DtHelpGlobSrchCleanAndClose()
5209 * Parameters: srch search main data structure
5210 * destroy flag to signal srch dialog should be destroyed
5214 * Purpose: Free the contents of the control data structure
5216 *****************************************************************************/
5217 void _DtHelpGlobSrchCleanAndClose(
5218 _DtHelpGlobSearchStuff * srch,
5221 /* close conversion context */
5222 _DtHelpCeIconvClose(&srch->iconv3Context);
5224 /* free the font list */
5225 if(srch->volTitlesFontList)
5227 XmFontListFree(srch->volTitlesFontList);
5228 srch->volTitlesFontList = NULL;
5232 * Make sure CloseSearchCB does not try using an invalid
5233 * widget id in its XtUnmanageChild and XtUnmapWidget calls.
5236 srch->srchForm = NULL;
5238 /* make dialog invisible; update sensitivities */
5239 CloseSearchCB(NULL,(XtPointer)srch, NULL);
5241 /* Destroy our index search dialog? */
5244 /* set the font resource */
5245 if (srch->hitPrefixFont != _DtHelpDefaultSrchHitPrefixFont)
5246 XtFree(srch->hitPrefixFont);
5249 * mark widgets as destroyed.
5250 * The XtDestroyWidget that called me will have called the destroy
5251 * callback of the widgets. So I don't have to do anything except
5252 * make sure I know they are destroyed.
5254 srch->selectionDlg = NULL;
5255 srch->srchForm = NULL;
5256 srch->resultList = NULL;
5258 /* free other data released to search dialog */
5261 /* free the locale word string, if allocated
5262 * (i.e. diff from normWordStr) */
5263 if(srch->localeWordStr!=srch->normWordStr)
5265 XtFree(srch->localeWordStr);
5266 srch->localeWordStr=NULL;
5268 XtFree(srch->normWordStr);
5269 srch->normWordStr=NULL;
5270 XtFree(srch->rawWordStr);
5271 srch->rawWordStr=NULL;
5272 XtFree(srch->curVolPath);
5273 srch->curVolPath=NULL;
5274 XtFree(srch->iconv3Codeset);
5275 srch->iconv3Codeset = NULL;