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 libraries 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);
520 *ret_nameKey = _DtHelpCeStrHashToKey(baseName);
523 _DtHelpCloseVolume(vol);
529 /************************************************************************
530 * Function: AdjustPositionValues()
532 * Adjust the position values of all volumes in the list by the amount given
534 ************************************************************************/
535 static void AdjustPositionValues(
536 _DtHelpFileList fileList,
541 _DtHelpGlobSrchVol * curVol;
543 if ( NULL == fileList
544 || NULL == (curVol = (_DtHelpGlobSrchVol *) fileList->clientData) )
547 /* do we need to find first next file that has hits and is in list? */
548 if(False == adjustThisFile)
550 curVol->nextVolPosition += adjNextAmount;
551 for ( fileList = _DtHelpFileListGetNext(NULL,fileList); /* begin with next */
553 fileList = _DtHelpFileListGetNext(NULL,fileList) )
555 _DtHelpGlobSrchVol * vol=(_DtHelpGlobSrchVol *)fileList->clientData;
556 if (vol->showVolInList && (vol->hitCnt > 0 || vol->zeroHitsOk) )
558 vol->nextVolPosition += adjNextAmount;
560 /* all further files require same adj amts */
561 adjStartAmount = adjNextAmount;
565 /* add in the adjust amount to all files */
566 for ( /* do nothing */;
568 fileList = _DtHelpFileListGetNext(NULL,fileList) )
570 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) fileList->clientData;
573 vol->startPosition += adjStartAmount;
574 vol->nextVolPosition += adjNextAmount;
576 /* overwrite, once we've done the first file, if haven't already */
577 adjStartAmount = adjNextAmount;
582 /************************************************************************
583 * Function: HitLoadTopics()
585 * Loads the topics referred to by a hit
586 * Returns: 0 if loaded ok, -1 otherwise
587 ************************************************************************/
588 static int HitLoadTopics (
589 DtHelpDialogWidget hw,
590 _DtHelpFileEntry file,
591 _DtHelpGlobSrchHit * hit)
593 _DtHelpVolumeHdl volHandle;
594 char * * origTopicIdList = NULL;
597 XmString * titlesList = NULL;
598 char * * idList = NULL;
599 char * * fileList = NULL;
600 XmFontList fontList = NULL;
602 Boolean allMods = False;
605 if (hit->topicsLoaded) return 0; /* RETURN: ok */
607 if (_DtHelpOpenVolume(file->fullFilePath, &volHandle) != 0 )
608 return -1; /* RETURN: error */
610 topicCnt = _DtHelpCeFindKeyword(volHandle,hit->indexEntry,&origTopicIdList);
611 if (topicCnt <= 0) return -1; /* RETURN: error */
613 /* get results font list */
614 XtSetArg(args[0], XmNfontList, &fontList);
615 XtGetValues(hw->help_dialog.srch.resultList,args,1);
617 #if defined(DONT_USE_CDExc22774)
618 /* Don't need to copy, _DtHelpFormatVolumeTitle copies
622 /* FIX: check whether this is a memory leak. It isn't if the
623 GetValues of XmFontList returns its own list, not a copy */
624 /* work with copy, because FontListAppendEntry() destroys input FL */
625 fontList = XmFontListCopy(fontList);
628 /* get the titles of all topics */
629 for (i=0; i<topicCnt; i++)
631 XmString titleStr = NULL;
632 Boolean valid = False;
633 XmFontList lastFontList = NULL;
636 * mod==True indicates _DtHelpFormatTopicTitle copied fontList
637 * once already. Save a pointer to it so we can free the font list
638 * if _DtHelpFormatTopicTitle copies it again.
640 lastFontList = fontList;
642 valid = _DtHelpFormatTopicTitle(hw->help_dialog.help.pDisplayArea,
643 volHandle,origTopicIdList[i], &titleStr, &fontList, &mod);
645 if (mod && NULL != lastFontList) XmFontListFree(lastFontList);
647 allMods |= mod; /* track for all iterations */
649 if(valid!=0 || NULL==titleStr)
651 titleStr=XmStringCreateLocalized(origTopicIdList[i]);
652 } /* if couldn't get title */
654 /* note that titleStr is an XmString, not an (Xt) String */
655 titlesList = (XmString *)_DtHelpCeAddPtrToArray (
656 (void **)titlesList, (void *) titleStr);
657 idList = (char **)_DtHelpCeAddPtrToArray (
659 (void *) XtNewString(origTopicIdList[i]));
660 fileList = (char **)_DtHelpCeAddPtrToArray (
662 (void *) XtNewString(file->fullFilePath));
663 } /* for all topics of this index entry */
665 /* install font list, if changed */
668 XtSetArg(args[0], XmNfontList, fontList);
669 XtSetValues(hw->help_dialog.srch.resultList,args,1);
670 if (fontList) XmFontListFree(fontList);
673 /* put results into hit */
674 hit->topicTitles = titlesList;
675 hit->topicIdList = idList;
676 hit->topicFileList = fileList;
677 hit->topicCnt = topicCnt;
678 hit->topicsLoaded = True;
680 _DtHelpCloseVolume(volHandle);
687 /************************************************************************
688 * Function: HitNameDisplay()
690 * Updates the name of the hit, not delete or insert
691 ************************************************************************/
692 static int HitNameDisplay (
693 DtHelpDialogWidget hw,
694 _DtHelpFileEntry file,
695 _DtHelpGlobSrchHit * hit,
700 char * contractPrefix;
702 XmString prefixString;
703 XmString labelString;
707 /* FIX: this method of getting/using the prefixes
708 is a performance nightmare; plus subject to font variability */
709 expandPrefix = (char *)_DTGETMESSAGE (GSSET, 28," +");
710 contractPrefix = (char *)_DTGETMESSAGE (GSSET, 29," -");
711 gotoPrefix = (char *)_DTGETMESSAGE (GSSET, 30," ");
713 /* if more than one topic for this index, signal it */
714 tmpStr = gotoPrefix; /* index entry has one topic */
715 if ( hit->topicCnt > 1 )
717 if (hit->topicsDisplayed) /* topics currently displayed */
718 tmpStr = contractPrefix;
719 else /* topics not displayed */
720 tmpStr = expandPrefix;
721 sprintf(buf, "%s%3d ", tmpStr, hit->topicCnt); /* 4d too spacy */
725 prefixString = XmStringGenerate(tmpStr, s_PrefixFontListTag,
726 XmCHARSET_TEXT, NULL);
727 labelString = XmStringConcat(prefixString,hit->indexTitle);
728 /* recall indexTitle is an XmString in the volume's indexXmStrsList */
730 /* install/insert the item */
732 XmListAddItemUnselected(hw->help_dialog.srch.resultList,
735 XmListReplaceItemsPosUnselected(hw->help_dialog.srch.resultList,
736 &labelString,1,hitPos);
738 XmStringFree(prefixString);
739 XmStringFree(labelString);
740 return (insertHit ? 1 : 0);
745 /************************************************************************
746 * Function: HitTopicsDisplay()
748 * Loads the topics referred to by a hit and displays them
749 * Returns the number of topics displayed
750 ************************************************************************/
751 static int HitTopicsDisplay (
752 DtHelpDialogWidget hw,
753 _DtHelpFileEntry file,
754 _DtHelpGlobSrchHit * hit,
755 int firstTopicListPosition)
757 XmString * pTopicString;
758 XmString prefixString;
763 if ( False == hit->topicsLoaded && HitLoadTopics(hw,file,hit) < 0 )
764 return 0; /* RETURN: error */
765 if ( hit->topicsDisplayed ) return 0; /* RETURN: ok */
768 /*tmpStr = (char *)_DTGETMESSAGE (GSSET, 32," * ");*/
769 tmpStr = (char *)_DTGETMESSAGE (GSSET, 31," ");
770 prefixString = XmStringGenerate(tmpStr, s_PrefixFontListTag,
771 XmCHARSET_TEXT, NULL);
773 if (hit->topicCnt > 0)
775 items = (XmString *) XtMalloc (sizeof (XmString) * hit->topicCnt);
777 /* put XmString-formatted topic titles into list */
778 for (i = 0, pTopicString = hit->topicTitles; NULL != *pTopicString;
779 pTopicString++, i++ )
780 items[i] = XmStringConcat(prefixString,*pTopicString);
782 XmListAddItemsUnselected(hw->help_dialog.srch.resultList, items,
783 hit->topicCnt, firstTopicListPosition);
784 for (i = 0; i < hit->topicCnt; i++)
785 XmStringFree(items[i]);
786 XtFree((char *) items);
789 XmStringFree(prefixString);
792 hit->topicsDisplayed = True;
793 hit->showTopicsWithHit = True;
794 return hit->topicCnt;
800 /************************************************************************
801 * Function: HitTopicsUndisplay()
803 * Releases the topics referred to by a hit and undisplays them
804 * Returns number of topics removed from display and hit.
805 ************************************************************************/
806 static int HitTopicsUndisplay (
807 DtHelpDialogWidget hw,
808 _DtHelpFileEntry file,
809 _DtHelpGlobSrchHit * hit,
810 int firstTopicListPosition)
815 if ( False == hit->topicsDisplayed ) return 0; /* RETURN */
817 XtSetArg(args[0], XmNtopItemPosition, &topPos);
818 XtGetValues(hw->help_dialog.srch.resultList,args,1);
820 /* count the topics -- they are also being collapsed */
821 if (hit->topicCnt > 0)
822 XmListDeleteItemsPos(hw->help_dialog.srch.resultList,
823 hit->topicCnt, firstTopicListPosition);
825 hit->topicsDisplayed = False;
826 /* NOTE: don't reset hit->showTopicsWithHit here; require that
827 to be explicitly reset in ProcessResultSelection() */
829 XmListSetPos(hw->help_dialog.srch.resultList, topPos);
831 return hit->topicCnt;
837 /************************************************************************
838 * Function: HitFree()
840 * Frees the memory associated with a hit and returns the next hit
841 * member of the structure
842 ************************************************************************/
843 static _DtHelpGlobSrchHit * HitFree (
844 _DtHelpGlobSrchHit * hit,
845 Boolean freeHitItself)
848 _DtHelpGlobSrchHit * nextHit;
850 if (NULL == hit) return NULL;
854 /* Free the mem of the topics id list */
855 _DtHelpCeFreeStringArray(hit->topicIdList);
856 hit->topicIdList = NULL; /* mem not owned by me */
858 /* Free the mem of the topics files list */
859 _DtHelpCeFreeStringArray(hit->topicFileList);
860 hit->topicFileList = NULL;
862 /* topicTitles are XmStrings and we can't use FreeStringArray() */
863 for ( nextStr = hit->topicTitles;
864 NULL != nextStr && NULL != *nextStr;
866 XmStringFree (*nextStr);
867 XtFree((char *) hit->topicTitles); /* its an XmString * */
868 hit->topicTitles = NULL;
871 hit->topicsLoaded = False;
872 hit->topicsDisplayed = False;
876 /* Free the index entry */
877 XtFree(hit->indexEntry);
885 /************************************************************************
886 * Function: HitListFree()
888 * Walks along a hit list and frees its contents
889 ************************************************************************/
890 static void HitListFree(
891 _DtHelpGlobSrchVol * vol,
892 Boolean freeHitsThemselves)
894 _DtHelpGlobSrchHit * hit;
896 if (NULL == vol) return; /* RETURN */
898 for ( hit = vol->hitListHead;
900 hit = HitFree(hit,freeHitsThemselves) )
903 /* reset search flags */
904 vol->nothingDone = True;
905 vol->topicSearchDone = False;
906 vol->indexSearchDone = False;
907 vol->searchCompleted = False;
908 vol->searchedCnt = 0;
909 vol->gatheredFullIndex = False;
911 /* reset hit flags */
912 vol->hitsDisplayed = False;
913 vol->showHitsWithVol = False;
914 vol->zeroHitsOk = False;
917 /* reset list display flags */
918 vol->startPosition = 1;
919 vol->nextVolPosition = 1;
921 /* don't free indexXmStrsList here because they
922 are reused for every search on this volume */
923 vol->curIndexXmStr = vol->indexXmStrsList;
925 /* indexEntriesList,volhandle inited elsewhere */
927 if (freeHitsThemselves)
929 vol->hitListHead = NULL;
930 vol->hitListTail = NULL;
935 /************************************************************************
936 * Function: HitListFreeAllVolHits()
938 * Walks along all the volumes and frees their hits
939 ************************************************************************/
941 HitListFreeAllVolHits (
942 DtHelpDialogWidget hw,
943 Boolean freeFullIndex)
945 _DtHelpGlobSrchVol * vol;
946 _DtHelpFileEntry curFile;
948 /* walk the files, freeing all hits and their data */
949 for ( curFile = hw->help_dialog.srch.volListHead;
951 curFile = _DtHelpFileListGetNext(NULL,curFile) )
953 vol = (_DtHelpGlobSrchVol *) curFile->clientData;
955 if (NULL == vol) continue; /* CONTINUE */
956 if (vol->gatheredFullIndex && freeFullIndex == False) continue;
957 HitListFree(vol,True); /* True: free hits themselves */
959 hw->help_dialog.srch.hitsFound = False;
963 /************************************************************************
964 * Function: HitListGetNth()
966 * Retrieves the Nth entry from the hits contained in the VolList
968 * This code follows the same counting paradigm used when adding
969 * the items to the srchResultList widget, so that we can just use the
970 * position value returned by it to retrieve the selected item.
972 * This paradigm also counts the presence of a volume as an item
973 * if it contains any hits, and doesn't count it if it contains
974 * no hits. It also counts the topicTitles that are associated
975 * with a hit and displayed indented beneath it.
977 * The position count is 1 based, which corresponds with the
981 * ret_hit: retuns NULL if an error or a pointer to the hit structure.
982 * ret_locationId: returns NULL is position is for the hit
983 * structure itself, returns a pointer to private
984 * memory containing the location id if position
985 * is a topic belonging to the hit.
987 * Returns: 0 if ok, -1 if error
988 ************************************************************************/
989 static int HitListGetNth (
990 _DtHelpFileList volListHead,
992 _DtHelpFileEntry * ret_file,
993 _DtHelpGlobSrchHit * * ret_hit,
994 char * * ret_locationId,
995 char * * ret_helpFile)
997 _DtHelpGlobSrchHit * hit = NULL;
998 _DtHelpGlobSrchVol * curVol;
999 _DtHelpFileEntry curFile = NULL;
1000 _DtHelpFileEntry posFile = NULL;
1001 char * * locationIdList = NULL;
1002 char * * fileNameList = NULL;
1005 if (NULL == volListHead) goto done; /* GOTO on error */
1007 /* walk along the volumes to find the one containing the position
1008 Because we need the most recent file with hits before the
1009 nextFile that has too high a position, only set posFile when
1010 we aren't ready to stop yet and we're on a file with hits. */
1011 for ( curFile = volListHead;
1013 curFile = _DtHelpFileListGetNext(curFile,curFile) )
1015 /* it is impt to use > test so that multiple volumes with the same
1016 start position are properly handled. This occurs when they
1017 have no hits in them. */
1018 curVol = (_DtHelpGlobSrchVol *) curFile->clientData;
1019 if (NULL == curVol) continue;
1021 if (curVol->startPosition > position) break; /* BREAK */
1022 if (curVol->hitCnt > 0) posFile = curFile; /* recent with hits */
1024 if (curVol->showVolInList && curVol->nextVolPosition > position)
1031 if(NULL == posFile) goto done; /* GOTO on error */
1033 /*** walk along the hits to find the one matching the position ***/
1034 curVol = (_DtHelpGlobSrchVol *) posFile->clientData;
1035 curPos = curVol->startPosition;
1037 locationIdList = NULL;
1038 fileNameList = NULL;
1040 /* (position == curPos) ==> volume name itself was selected */
1041 if ( curPos < position )
1042 { /* a hit inside the volume */
1043 if ( curVol->hitsDisplayed )
1045 for ( curPos++, hit = curVol->hitListHead;
1046 curPos < position && NULL != hit;
1047 curPos++, hit = hit->next )
1049 if (False == hit->topicsDisplayed) continue; /* CONTINUE */
1051 /* walk all displayed topics to see if the position is here */
1052 for ( locationIdList=hit->topicIdList,fileNameList=hit->topicFileList;
1053 NULL != locationIdList[0];
1054 locationIdList++, fileNameList++ )
1056 /* use GOTO to escape with all pointers correct and
1057 without introducing an additional flag variable */
1058 if (++curPos == position) goto done; /* GOTO */
1059 } /* for all locations of a hit before the position */
1060 } /* for all members of the hit list before the position */
1061 } /* if hits are currently shown */
1062 else posFile = NULL; /* an error occurred */
1063 } /* if position is in the hit list */
1066 if (ret_hit) *ret_hit = hit;
1067 if (ret_file) *ret_file = posFile;
1070 if ( locationIdList ) *ret_locationId = locationIdList[0];
1071 else *ret_locationId = NULL;
1075 if ( fileNameList ) *ret_helpFile = fileNameList[0];
1076 else *ret_helpFile = NULL;
1078 /* WARNING: depends on pointers and integers the same size */
1080 return (0 == ((int64_t)hit|(int64_t)posFile|(int64_t)locationIdList)) ? -1 : 0;
1082 return (0 == ((int)hit|(int)posFile|(int)locationIdList)) ? -1 : 0;
1088 /************************************************************************
1089 * Function: HitListAddFound()
1091 * Adds a hit to the hit list of the specified volume
1092 * The hits are added either to the end of the list,
1093 * so that the srchResultList presents the items in the order found,
1094 * or in a sorted order.
1095 * If a hit on that topic already exists, just the existing
1096 * hit structure is returned.
1098 * Return Parameters:
1099 * Ret_hit points to the hit data. This is not a copy--do not
1103 * Returns 0 if no error, -1 if an error occurred.
1104 ************************************************************************/
1105 static int HitListAddFound (
1106 _DtHelpFileEntry curFile,
1107 XmString indexTitle,
1109 Boolean insertSorted,
1110 _DtHelpGlobSrchHit **ret_hit)
1112 _DtHelpGlobSrchHit * prev;
1113 _DtHelpGlobSrchHit * next;
1114 _DtHelpGlobSrchHit * srcHit;
1115 _DtHelpGlobSrchVol * vol;
1117 extern _CEStrcollProc _DtHelpCeGetStrcollProc();
1118 _CEStrcollProc strcollfn = _DtHelpCeGetStrcollProc();
1120 if (NULL == curFile) return -1; /* RETURN */
1121 vol = (_DtHelpGlobSrchVol *) curFile->clientData;
1122 if (NULL == vol) return -1; /* RETURN */
1124 /* walk along the hits, looking for one matching the new hit */
1125 /* recall that position is 1-based */
1126 newKey = _DtHelpCeStrHashToKey(indexEntry);
1128 if ( insertSorted ) /* find position and check for duplicates */
1130 /* walk along list */
1131 for( next = vol->hitListHead;
1133 prev = next, next = next->next )
1137 /* do a NLS case insensitive compare using NLS collating */
1138 if ( (ret = (*strcollfn)(next->indexEntry,indexEntry)) >= 0 )
1142 if(ret_hit) *ret_hit = next;
1143 return 0; /* RETURN */
1145 /* prev and next are set correctly */
1150 else /* check for duplicates */
1152 /* walk along list */
1153 for( next = vol->hitListHead;
1155 prev = next, next = next->next )
1157 if ( newKey == next->indexKey /* quick compare */
1158 && strcmp(indexEntry,next->indexEntry) == 0 ) /* long compare */
1160 if(ret_hit) *ret_hit = next;
1161 return 0; /* RETURN */
1164 /* prev and next are set correctly (at end of list) */
1167 /* handle a new hit */
1168 srcHit = (_DtHelpGlobSrchHit *)XtCalloc(1,sizeof(_DtHelpGlobSrchHit));
1169 if (NULL == srcHit) return -1; /* RETURN */
1171 /* init hit values */
1172 /* leave srcHit->hitCnt == 0 here */
1173 if (NULL == indexTitle)
1174 srcHit->indexTitle = XmStringCreateLocalized(indexEntry);
1176 srcHit->indexTitle = indexTitle;
1177 srcHit->indexEntry = XtNewString(indexEntry);
1178 srcHit->indexKey = newKey;
1179 srcHit->volume = curFile;
1181 /* integrate hit into the list */
1182 srcHit->next = next;
1183 if (prev) prev->next = srcHit;
1184 else vol->hitListHead = srcHit;
1185 if (!next) vol->hitListTail = srcHit;
1187 /* add in the volume contribution */
1191 if(ret_hit) *ret_hit = srcHit;
1197 /************************************************************************
1198 * Function: CountSelectedVolumes()
1200 * Counts the number volumes with the searchThisVolume flag set
1201 * for which the search has yet to complete
1203 ************************************************************************/
1204 static int CountSelectedVolumes (
1205 _DtHelpFileList volListHead,
1206 Boolean countSearchCompletedVolumes)
1210 /* walk all volumes */
1211 for ( /* nothing */;
1212 NULL != volListHead;
1213 volListHead = _DtHelpFileListGetNext(NULL, volListHead) )
1215 _DtHelpGlobSrchVol * vol;
1217 /* get the volume info */
1218 vol = (_DtHelpGlobSrchVol *) volListHead->clientData;
1219 /* if (NULL != vol && vol->searchThisVolume && False == vol->searchCompleted)*/
1220 if (vol && vol->searchThisVolume)
1222 if ( (False == vol->searchCompleted)
1223 || (countSearchCompletedVolumes && vol->searchCompleted) )
1226 } /* walk all volumes */
1232 /************************************************************************
1233 * Function: GetNextSearchFileAndDisplayCompleted()
1235 * Scans list for next file ready for searching
1236 * If it encounters a file that has completed it's search
1237 * and for which the results should be displayed, they are displayed
1239 ************************************************************************/
1240 static _DtHelpFileEntry GetNextSearchFileAndDisplayCompleted(
1241 DtHelpDialogWidget hw,
1242 _DtHelpFileList listHead,
1243 _DtHelpFileEntry curFile)
1245 /* get first file needing work */
1246 for ( curFile = _DtHelpFileListGetNext(listHead, curFile);
1248 curFile = _DtHelpFileListGetNext(NULL, curFile) )
1250 _DtHelpGlobSrchVol * vol;
1252 vol = (_DtHelpGlobSrchVol *) curFile->clientData;
1253 if (NULL == vol) continue; /* CONTINUE */
1255 /* if file already searched and should be displayed, then do so */
1256 if ( vol->searchThisVolume && vol->searchCompleted
1257 && vol->showVolInList && (vol->hitCnt > 0 || vol->zeroHitsOk) )
1259 /* record that a hit found */
1260 if ( vol->hitCnt > 0
1261 || ( vol->zeroHitsOk
1262 && _DtHelpGlobSrchSelectedVolumes == hw->help_dialog.srch.srchSources))
1263 hw->help_dialog.srch.hitsFound = True;
1265 /* True: adjust count beginning with this file */
1266 AdjustPositionValues(curFile,0,1,True);
1267 ResultsListUpdate(hw,curFile);
1269 /* display the hits as well? */
1270 if ( vol->showHitsWithVol
1271 || hw->help_dialog.srch.srchSources == _DtHelpGlobSrchCurVolume)
1273 VolHitsDisplay(hw,curFile);
1275 /* update the volume label to show state; False--don't insert */
1276 VolNameDisplay(hw,curFile,False);
1280 /* if want to search, and need to, then return it */
1281 if ( vol->searchThisVolume && False == vol->searchCompleted
1282 && vol->showVolInList ) /* don' search unless results will be shown */
1286 XmUpdateDisplay((Widget) hw->help_dialog.srch.resultList);
1292 /************************************************************************
1293 * Function: AddVolInfoToFile
1295 * Creates a volume info entry for each member of the list
1296 * and initializes its values
1297 * If searchStatus is False, all volumes are set. If its True,
1298 * all are set if selectedFilesOnly is false, otherwise only
1299 * selected files are set to true.
1301 ************************************************************************/
1302 static void AddVolInfoToFile(
1303 _DtHelpFileEntry file,
1304 Boolean initialSearchStatus,
1305 Boolean displayStatus,
1306 Boolean selectedFilesOnly)
1308 _DtHelpGlobSrchVol * vol;
1310 if (NULL == file) return; /* RETURN */
1312 vol = (_DtHelpGlobSrchVol *) file->clientData;
1315 vol = (_DtHelpGlobSrchVol *) XtCalloc(1,sizeof(_DtHelpGlobSrchVol));
1316 file->clientData = (XtPointer) vol;
1317 if (NULL == vol) return; /* RETURN: memory alloc error */
1319 /* calloc() inited almost everything inside to 0 */
1320 /* set first time creation values */
1321 vol->nothingDone = True;
1324 /* now set search and display flags */
1325 vol->searchThisVolume = initialSearchStatus;
1326 vol->showVolInList = displayStatus;
1327 if ( False == file->fileSelected && True == selectedFilesOnly )
1329 vol->searchThisVolume = False;
1330 vol->showVolInList = False;
1335 /************************************************************************
1336 * Function: AddVolInfoToList
1338 * Creates a volume info entry for each member of the list
1339 * and initializes its values
1340 * If searchStatus is False, all volumes are set. If its True,
1341 * all are set if selectedFilesOnly is false, otherwise only
1342 * selected files are set to true.
1344 ************************************************************************/
1345 static void AddVolInfoToList(
1346 _DtHelpFileList listHead,
1347 Boolean initialSearchStatus,
1348 Boolean displayStatus,
1349 Boolean selectedFilesOnly)
1351 /* walk the files and allocate the vol info as needed */
1354 listHead = _DtHelpFileListGetNext(listHead,listHead) )
1356 AddVolInfoToFile(listHead,
1357 initialSearchStatus, displayStatus, selectedFilesOnly);
1363 /************************************************************************
1364 * Function: SetVolStatus()
1366 * Sets all volumes in the list to the specified search and/or display
1369 * If searchThisVolume is False, all volumes are set. If its True,
1370 * all are set if selectedFilesOnly is false, otherwise only
1371 * selected files are set to true. If searchThisVolume is False,
1372 * then the settings remain unchanged in all volumes.
1374 ************************************************************************/
1375 static void SetVolStatus(
1376 _DtHelpFileList listHead,
1377 Boolean searchThisVolume,
1378 Boolean showVolInList,
1380 Boolean selectedFilesOnly)
1382 /* walk the files and set the status */
1385 listHead = _DtHelpFileListGetNext(listHead,listHead) )
1387 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) listHead->clientData;
1389 if (NULL == vol) continue;
1391 if ( (False == selectedFilesOnly)
1392 || (True == listHead->fileSelected && True == selectedFilesOnly) )
1394 /* just set the inclusion and/or display flags;
1395 don't reset the search progress flags */
1396 vol->searchThisVolume = searchThisVolume;
1397 vol->showVolInList = showVolInList;
1398 vol->zeroHitsOk = zeroHitsOk;
1404 /************************************************************************
1405 * Function: VolNameDisplay()
1407 * Updates the display of the volume name
1408 ************************************************************************/
1409 static void VolNameDisplay(
1410 DtHelpDialogWidget hw,
1411 _DtHelpFileEntry file,
1414 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) file->clientData;
1415 XmString prefixString;
1416 XmString labelString;
1420 if ( NULL == vol || (False == vol->zeroHitsOk && 0 == vol->hitCnt) )
1421 return; /* RETURN */
1423 /* put volume name into list */
1424 if (vol->hitCnt <= 0) tmpStr = (char *)_DTGETMESSAGE (GSSET, 25," ");
1425 else if (vol->hitsDisplayed) tmpStr = (char *)_DTGETMESSAGE (GSSET, 27,"-");
1426 else tmpStr = (char *)_DTGETMESSAGE (GSSET, 26,"+"); /* >0 hits */
1427 sprintf(buf, "%s%3d ", tmpStr, vol->hitCnt); /* 4d too spacy */
1430 prefixString = XmStringGenerate(buf, s_PrefixFontListTag,
1431 XmCHARSET_TEXT, NULL);
1432 labelString = XmStringConcat(prefixString,file->fileTitleXmStr);
1434 /* replace or insert to reflect changed contents */
1436 XmListAddItemUnselected(hw->help_dialog.srch.resultList,
1437 labelString, vol->startPosition);
1439 XmListReplaceItemsPosUnselected(hw->help_dialog.srch.resultList,
1440 &labelString, 1, vol->startPosition);
1442 XmStringFree(prefixString);
1443 XmStringFree(labelString);
1447 /************************************************************************
1448 * Function: VolHitsDisplay()
1450 * displays the hits associated with a volume
1451 * Returns the number of new items added to the list
1452 ************************************************************************/
1453 static int VolHitsDisplay (
1454 DtHelpDialogWidget hw,
1455 _DtHelpFileEntry file)
1457 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) file->clientData;
1458 _DtHelpGlobSrchHit * hit;
1459 int listPos = vol->startPosition; /* vol item position */
1462 if (True == vol->hitsDisplayed ) return 0; /* RETURN */
1464 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.srchForm));
1465 if (hw->help_dialog.srch.selectionDlg)
1466 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
1468 /*** walk through the hits and count and display any open hits ***/
1469 for ( hit = vol->hitListHead, itemCnt = 0;
1473 itemCnt++; /* True: insert Hit into list */
1474 HitNameDisplay (hw,file,hit,listPos + itemCnt,True);
1476 /* display topics too? */
1477 if (hit->showTopicsWithHit)
1480 newItems = HitTopicsDisplay(hw,file,hit, listPos + itemCnt + 1);
1481 HitNameDisplay (hw,file,hit,listPos + itemCnt,False);
1482 itemCnt += newItems;
1487 vol->hitsDisplayed = True;
1488 vol->showHitsWithVol = True;
1490 /* adjust count beginning with next file with hits */
1491 AdjustPositionValues(file, 0, itemCnt, True);
1493 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.srchForm));
1494 if (hw->help_dialog.srch.selectionDlg)
1495 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
1502 /************************************************************************
1503 * Function: VolHitsUndisplay()
1505 * undisplays the hits associated with a volume
1506 ************************************************************************/
1507 static int VolHitsUndisplay (
1508 DtHelpDialogWidget hw,
1509 _DtHelpFileEntry file)
1511 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) file->clientData;
1512 _DtHelpGlobSrchHit * hit;
1513 Boolean nonVisibleItems;
1514 int listPos = vol->startPosition; /* vol item position */
1523 if (False == vol->hitsDisplayed) return 0; /* RETURN */
1525 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.srchForm));
1526 if (hw->help_dialog.srch.selectionDlg)
1527 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
1529 XtSetArg(args[0], XmNtopItemPosition, &topPos);
1530 XtSetArg(args[1], XmNvisibleItemCount, &visItemCnt);
1531 XtGetValues(hw->help_dialog.srch.resultList,args,2);
1533 /* these are the num visible items below the volume name */
1534 topNonVisPos = topPos + visItemCnt; /* 1st non vis pos */
1536 /* num of items that will be undisplayed */
1537 undisItemCnt = vol->nextVolPosition - (vol->startPosition + 1);
1539 /* find out if any items aren't visible */
1540 nonVisibleItems = False;
1541 if ( vol->nextVolPosition > topNonVisPos )
1542 nonVisibleItems = True;
1544 /*** walk through the hits and count and delete any open topics ***/
1545 /* Make two passes: the first pass deletes all non-visible
1546 items. The second pass deletes the remaining visible items.
1547 The objective is to make collapse as fast and smooth as expand. */
1548 if (nonVisibleItems)
1549 { /* delete all items with a position > topNonVisPos */
1550 curDelPos = listPos + 1; /* starting position */
1551 for ( hit = vol->hitListHead, itemCnt = 0;
1555 /* are we still in the visible region? */
1556 if (curDelPos < topNonVisPos)
1558 /* move down the list to next hit */
1559 curDelPos++; /* this hit's item */
1560 /* plus any open topics */
1561 if (hit->topicsDisplayed) curDelPos += hit->topicCnt;
1562 continue; /* CONTINUE */
1564 /* we're in non-visible region--undisplay hit */
1565 XmListDeletePos(hw->help_dialog.srch.resultList, curDelPos);
1566 /* undisplay any topics */
1567 if ( hit->topicsDisplayed )
1568 itemCnt += HitTopicsUndisplay(hw,file,hit,curDelPos);
1570 } /* if non visible items */
1572 /* now delete the remaining visible items */
1573 /* Note that curDelPos is a virtual cursor that helps us
1574 figure out when to stop undisplaying. Virtually, we''re
1575 moving the cursor down the list with every delete. Actually,
1576 the rest of the list bumps up one--that''s why we delete
1579 curDelPos = listPos + 1; /* starting position */
1580 for ( hit = vol->hitListHead, itemCnt = 0;
1581 (NULL != hit) && (curDelPos < topNonVisPos);
1584 curDelPos++; /* undisplay hit item */
1585 XmListDeletePos(hw->help_dialog.srch.resultList, listPos + 1);
1586 /* undipslay any open topics */
1587 if ( hit->topicsDisplayed )
1589 curDelPos += HitTopicsUndisplay(hw,file,hit,listPos + 1);
1590 XmListSetPos(hw->help_dialog.srch.resultList, topPos);
1595 vol->hitsDisplayed = False;
1596 /* NOTE: don't reset vol->showHitsWithVol here; require that
1597 to be explicitly reset in ProcessResultSelection() */
1599 /* adjust count beginning with next file with hits */
1600 AdjustPositionValues(file, 0, -undisItemCnt, True);
1602 XmListSetPos(hw->help_dialog.srch.resultList, topPos);
1604 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.srchForm));
1605 if (hw->help_dialog.srch.selectionDlg)
1606 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
1608 return undisItemCnt;
1613 /************************************************************************
1614 * Function: VolListFree()
1616 * Releases all memory used by the volume list
1618 ************************************************************************/
1619 static void VolListFree (
1620 _DtHelpGlobSearchStuff * srch)
1622 _DtHelpFileList nextFile;
1624 /* walk all volumes */
1625 nextFile = srch->volListHead;
1626 while ( NULL != nextFile )
1628 _DtHelpGlobSrchVol * vol;
1629 _DtHelpFileList tmpFile;
1632 /* get the volume info */
1633 vol = (_DtHelpGlobSrchVol *) nextFile->clientData;
1635 /** free vol entry contents and container **/
1636 XtFree(vol->stdLocale);
1637 XtFree(vol->iconv3Codeset);
1638 HitListFree(vol,True); /* True: free hits themselves */
1640 /* no need to free indexEntriesList because these aren't owned by vol */
1641 vol->indexEntriesList = NULL;
1643 /* free indexXmStrsList */
1644 /* indexXmStrs are XmStrings and we can't use FreeStringArray() */
1645 for ( nextStr = vol->indexXmStrsList;
1646 NULL != nextStr && NULL != *nextStr;
1648 XmStringFree (*nextStr);
1649 XtFree((char *) vol->indexXmStrsList); /* its a XmString * */
1650 vol->indexXmStrsList = NULL;
1653 nextFile = _DtHelpFileListGetNext(NULL, nextFile);
1654 _DtHelpFileFreeEntry(tmpFile); /* also frees the clientData (vol) */
1655 } /* walk all volumes */
1657 /* reset related values */
1658 srch->volListHead = NULL;
1659 srch->curSrchVol = NULL;
1660 srch->volLeftCnt = 0;
1662 /* delete the results */
1663 DeleteListContents(srch);
1668 /************************************************************************
1669 * Function: ScanStatusCB
1671 * Updates the status display with the number of volumes found
1672 * as the scan progresses
1674 ************************************************************************/
1675 static void ScanStatusCB(
1677 XtPointer clientData)
1679 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
1681 StatusLabelUpdate(hw,SCANNING_STATUS,True,count);
1685 /************************************************************************
1686 * Function: VolListBuild
1688 * Frees the old list and builds a new one by scanning the
1689 * help directories for volumes and adding the associated
1690 * volume information used for searching.
1692 ************************************************************************/
1693 static void VolListBuild(
1694 DtHelpDialogWidget hw,
1695 Boolean searchStatus,
1696 Boolean displayStatus,
1697 Boolean selectedVolumesOnly)
1700 XmFontList origFontList;
1702 /* turn on hour glass */
1703 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.srchForm));
1704 if (hw->help_dialog.srch.selectionDlg)
1705 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
1707 StatusLabelUpdate(hw,SCANNING_STATUS,True,0);
1709 origFontList = hw->help_dialog.srch.volTitlesFontList;
1711 /* and rescan the volumes for the new list */
1712 _DtHelpFileListScanPaths( &hw->help_dialog.srch.volListHead,
1713 &hw->help_dialog.srch.volTitlesFontList,&mod,
1714 DtHelpVOLUME_TYPE, _DtHelpFileSuffixList, False,
1715 GetVolumeInfoCB,hw->help_dialog.help.pDisplayArea,
1716 /* sysPathCompare */ _DtHELP_FILE_NAME,
1717 /*otherPathCompare*/ _DtHELP_FILE_NAME|_DtHELP_FILE_TIME| _DtHELP_FILE_IDSTR,
1718 /* sortBy */ _DtHELP_FILE_TITLE, ScanStatusCB, (XtPointer)hw);
1720 /* if new fonts added to list, add them to the resultList */
1723 MergeFontListIntoWidgetFonts(
1724 hw->help_dialog.srch.resultList,
1725 hw->help_dialog.srch.volTitlesFontList);
1727 if (origFontList) XmFontListFree(origFontList);
1730 /* Add on the Vol info and (T,F) allow search on all volumes */
1731 AddVolInfoToList(hw->help_dialog.srch.volListHead,
1732 searchStatus, displayStatus, selectedVolumesOnly);
1734 hw->help_dialog.srch.volScanDone = True;
1736 StatusLabelUpdate(hw,BLANK_STATUS,True,0);
1738 /* turn off hour glass */
1739 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.srchForm));
1740 if (hw->help_dialog.srch.selectionDlg)
1741 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
1746 #if 0 || defined(DEBUG) /* for debug, set to 1 */
1747 /************************************************************************
1748 * Function: OutputVolInfo()
1750 * Output info on all volumes in the list
1752 ************************************************************************/
1753 static void OutputVolInfo(
1754 _DtHelpFileList listHead)
1758 listHead = _DtHelpFileListGetNext(listHead,listHead) )
1760 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) listHead->clientData;
1761 if (NULL == vol) continue;
1763 /* output the info */
1764 printf("==================\n");
1765 printf("fileName: %s, %s\npathName: %s\n",
1766 listHead->fileName, listHead->fileTitle, listHead->fullFilePath);
1767 printf("searchThisVolume = %d, hitCnt = %d, startPos = %d\n",
1768 (int) listHead->fileSelected,
1770 (int) vol->startPosition);
1776 /************************************************************************
1777 * Function: SearchContinuePossible()
1779 * Test whether the search can be continued from the
1782 ************************************************************************/
1783 static Boolean SearchContinuePossible(
1784 DtHelpDialogWidget hw,
1787 char * normSrchWord;
1788 Boolean possible = False;
1790 normSrchWord = XtNewString(srchWord);
1791 _DtHelpCeCompressSpace(normSrchWord);
1792 _DtHelpCeUpperCase(normSrchWord);
1794 /* are we searching on the same word as previous search ? */
1795 /* comparison with srchNormWordStr is correct, given calls to this fn */
1796 /* FIX: use CheckSearchWord()? */
1797 if ( ( hw->help_dialog.srch.fullIndex
1798 || ( NULL != hw->help_dialog.srch.normWordStr
1799 && NULL != normSrchWord
1800 && strcmp(normSrchWord, hw->help_dialog.srch.normWordStr) == 0) )
1801 && NULL != hw->help_dialog.srch.volListHead
1802 && hw->help_dialog.srch.volLeftCnt > 0 )
1805 XtFree(normSrchWord);
1811 /************************************************************************
1812 * Function: SearchOnSameCriteria()
1814 * Test whether the search criteria have changed
1816 ************************************************************************/
1817 static Boolean SearchOnSameCriteria(
1818 DtHelpDialogWidget hw,
1821 char * normSrchWord;
1822 Boolean sameCrit = False;
1824 normSrchWord = XtNewString(srchWord);
1825 _DtHelpCeCompressSpace(normSrchWord);
1826 _DtHelpCeUpperCase(normSrchWord);
1828 /* are we searching on the same word as previous search ? */
1829 /* comparison with srchNormWordStr is correct, given calls to this fn */
1830 if ( hw->help_dialog.srch.fullIndex
1831 || ( NULL != hw->help_dialog.srch.normWordStr
1832 && NULL != normSrchWord
1833 && strcmp(normSrchWord, hw->help_dialog.srch.normWordStr) == 0) )
1836 XtFree(normSrchWord);
1839 #endif /* not_used */
1844 /************************************************************************
1845 * Function: UpdateActionButtonLabel()
1847 * Sets the start button label properly
1849 ************************************************************************/
1850 static void UpdateActionButtonLabel(
1851 DtHelpDialogWidget hw,
1853 Boolean startContAction)
1856 XmString labelString;
1857 XmString curLabelString;
1859 /* char * mnemonic; */
1861 /* if action label is to start or continue */
1862 _DtHelpProcessLock();
1863 if (startContAction)
1865 if ( SearchContinuePossible(hw,srchWord) )
1866 { /* then continue search */
1867 textString=(char *)_DTGETMESSAGE (GSSET,
1868 CONT_SEARCH_CAT,CONT_SEARCH_STR);
1869 labelString = XmStringCreateLocalized(textString);
1870 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 22,CONT_SEARCH_MNEM));*/
1873 { /* otherwise start it */
1874 textString=(char *)_DTGETMESSAGE (GSSET,
1875 START_SEARCH_CAT,START_SEARCH_STR);
1876 labelString = XmStringCreateLocalized(textString);
1877 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 20,START_SEARCH_MNEM));*/
1880 else /* action label is to stop */
1882 textString = (char *)_DTGETMESSAGE (GSSET,
1883 STOP_SEARCH_CAT,STOP_SEARCH_STR);
1884 labelString = XmStringCreateLocalized(textString);
1885 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, ??,STOP_SEARCH_MNEM));*/
1887 _DtHelpProcessUnlock();
1889 /* get the current state of the button */
1890 XtSetArg(args[0],XmNlabelString,&curLabelString);
1891 XtGetValues (hw->help_dialog.srch.actionBtn, args, 1);
1893 /* update label if it is different; avoid flashing this way */
1894 if ( XmStringCompare(labelString,curLabelString) == False )
1896 XtSetArg(args[0],XmNlabelString,labelString);
1897 XtSetArg(args[1], XmNalignment, XmALIGNMENT_CENTER);
1898 /* XtSetArg(args[2], XmNmnemonic, mnemonic[0]);*/
1899 XtSetValues (hw->help_dialog.srch.actionBtn, args, 2);
1900 XmUpdateDisplay(hw->help_dialog.srch.actionBtn);
1903 /* release the memory */
1904 XmStringFree(labelString);
1905 XmStringFree(curLabelString);
1909 /*****************************************************************************
1910 * Function: CheckSearchWord()
1914 * Return Value: True: word has changed
1915 * False: word is same
1917 * Purpose: Checks whether the search word is a new
1918 * one or the same as before. If the same, it frees
1919 * the word and returns False. If new, it moves the
1920 * previous word to another variable and installs
1921 * the new word in its place, using the srchWord mem.
1922 * ...but only if updateWidgetFields is True
1924 *****************************************************************************/
1925 static Boolean CheckSearchWord(
1926 DtHelpDialogWidget hw,
1928 Boolean updateWidgetFields)
1933 /* avoid a core dump */
1934 if ( NULL == srchWord )
1936 if ( NULL == hw->help_dialog.srch.normWordStr
1937 || hw->help_dialog.srch.normWordStr[0] == 0)
1938 return False; /* word hasn't changed */
1939 return True; /* RETURN: word has changed */
1942 _DtHelpCeCompressSpace(srchWord);
1943 rawSrchWord = XtNewString(srchWord);
1944 _DtHelpCeUpperCase(srchWord);
1945 /* FIX: to support regcomp(3), do that here */
1947 /* are we searching on the same word? */
1948 if ( NULL != hw->help_dialog.srch.normWordStr
1949 && strcmp(srchWord, hw->help_dialog.srch.normWordStr) == 0 )
1952 XtFree(rawSrchWord);
1954 /* output a message */
1955 if ( NULL != hw->help_dialog.srch.normWordStr
1956 && EOS != hw->help_dialog.srch.normWordStr[0])
1957 StatusLabelUpdate(hw,FIRST_PROMPT_STATUS,False,0);
1960 return False; /* RETURN: no change */
1963 if (False == updateWidgetFields) return True; /* RETURN */
1965 /* update search word fields */
1966 XtFree(hw->help_dialog.srch.normWordStr);
1967 XtFree(hw->help_dialog.srch.rawWordStr);
1968 hw->help_dialog.srch.normWordStr = srchWord;
1969 hw->help_dialog.srch.rawWordStr = rawSrchWord;
1970 hw->help_dialog.srch.wordFieldLen = strlen(srchWord); /* note: not nl_strlen
1971 because used on strncmp not nl_strncmp */
1973 /* convert first char to a value for easy access for _DtHelpStrchr() */
1974 if ( mbtowc(&firstChar,srchWord,1) <= 0 ) firstChar = 0;
1975 hw->help_dialog.srch.wordFieldFirstChar = firstChar;
1977 /* output a message */
1978 if ( NULL != hw->help_dialog.srch.normWordStr
1979 && EOS != hw->help_dialog.srch.normWordStr[0])
1980 StatusLabelUpdate(hw,FIRST_PROMPT_STATUS,False,0);
1982 return True; /* word changed */
1987 /*****************************************************************************
1988 * Function: PrepSearchSourceData()
1992 * Return Value: Void.
1994 * Purpose: Based on the current settings of the volume
1995 * selection buttons construct or utilitize an
1996 * existing volume list for processing.
1997 * Determine whether to continue search or
1998 * restart by comparing search words and states.
2000 *****************************************************************************/
2001 static void PrepSearchSourceData(
2002 DtHelpDialogWidget hw,
2005 /* try to install the new word; if returns False, word is same
2006 as before. True = also update widget fields. */
2007 /* This test determines whether we might need to continue. */
2008 if ( hw->help_dialog.srch.fullIndex
2009 || CheckSearchWord(hw,srchWord,True) == False )
2011 /* check to see if CheckSearchWord() was called. If it wasn't
2012 then srchWord has not been freed or saved. We will lose the
2013 memory unless we free it here. */
2014 if (hw->help_dialog.srch.fullIndex)
2017 /* are we continuing an interrupted search? */
2018 if ( hw->help_dialog.srch.volLeftCnt > 0
2019 && NULL != hw->help_dialog.srch.volListHead )
2020 return; /* RETURN: continue with search */
2022 /* if searching full index, False=don't free vol with full index */
2023 if (hw->help_dialog.srch.fullIndex)
2024 HitListFreeAllVolHits(hw,False);
2025 /* else we're searching on the same word, but completed
2026 previous search. So reset the volumes to search/display
2027 according to the current settings of the Volumes radio buttons,
2028 but leave the results intact.
2030 /* fall thru to do prep */
2032 else /* searching for a different word */
2034 /* free all hit-related data and reset flags */
2035 HitListFreeAllVolHits(hw,True); /*True=free everything*/
2038 /*** It's not just a continue. So, we may be beginning a new search
2039 or continuing a search based on new volume selection params ***/
2041 /* update display area */
2042 DeleteListContents(&hw->help_dialog.srch);
2043 StatusLabelUpdate(hw,WORKING_STATUS,False,0);
2045 /*** update the volumes list according to sources selected ***/
2046 if ( _DtHelpGlobSrchSelectedVolumes == hw->help_dialog.srch.srchSources )
2048 /* volume list already built when opening selection dialog */
2049 /* (F,F,F,F): disable search,disable display,no 0 hits,for all vols */
2050 SetVolStatus(hw->help_dialog.srch.volListHead,False,False,False,False);
2051 /* (T,T,T,T): enable search, enable display,
2052 zero hits ok, only for selected volumes */
2053 SetVolStatus(hw->help_dialog.srch.volListHead,True,True,True,True);
2054 } /* if selected volumes button */
2055 else if ( _DtHelpGlobSrchAllVolumes == hw->help_dialog.srch.srchSources )
2057 /* Scan directories for volumes if necessary */
2058 if ( False == hw->help_dialog.srch.volScanDone
2059 || NULL == hw->help_dialog.srch.volListHead)
2061 /* Add on the Vol info; (T,T,F) search, display, all */
2062 VolListBuild(hw,True,True,False);
2065 /* (T,T,F,F): enable search,enable display,no 0 hits,for all vols */
2066 SetVolStatus(hw->help_dialog.srch.volListHead,True,True,False,False);
2067 } /* if all volumes button */
2068 else /*** current volume button ***/
2071 _DtHelpFileEntry cur;
2073 /* (F,F,F,F): disable search,disable display,no 0 hits,for all vols */
2074 SetVolStatus(hw->help_dialog.srch.volListHead,False,False,False,False);
2076 /* try to locate file and its entry, if present */
2077 path = _DtHelpFileLocate(DtHelpVOLUME_TYPE, hw->help_dialog.display.helpVolume,
2078 _DtHelpFileSuffixList,False,R_OK);
2079 cur = _DtHelpFileListGetMatch(hw->help_dialog.srch.volListHead,path,
2080 GetVolumeInfoCB, _DtHELP_FILE_NAME,
2081 hw->help_dialog.help.pDisplayArea);
2083 if (NULL == cur && NULL != path) /*file was located but isn't in list*/
2084 { /* add it to the list */
2086 XmFontList origFontList;
2088 origFontList = hw->help_dialog.srch.volTitlesFontList;
2090 _DtHelpFileListAddFile(&hw->help_dialog.srch.volListHead,
2091 &hw->help_dialog.srch.volTitlesFontList,&mod,path,NULL,
2092 GetVolumeInfoCB, _DtHELP_FILE_NAME, _DtHELP_FILE_TITLE,
2093 hw->help_dialog.help.pDisplayArea);
2096 MergeFontListIntoWidgetFonts(
2097 hw->help_dialog.srch.resultList,
2098 hw->help_dialog.srch.volTitlesFontList);
2100 if (origFontList) XmFontListFree(origFontList);
2103 /* (F,F,F): disable search, disable display, for all volumes */
2104 AddVolInfoToList(hw->help_dialog.srch.volListHead,False,False,False);
2105 cur = _DtHelpFileListGetMatch(hw->help_dialog.srch.volListHead,path,
2106 GetVolumeInfoCB, _DtHELP_FILE_NAME,
2107 hw->help_dialog.help.pDisplayArea);
2110 if (cur) /* file present in list */
2112 /* enable search and display on this volume */
2113 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) cur->clientData;
2115 vol->searchThisVolume = True;
2116 vol->showVolInList = True;
2117 vol->zeroHitsOk = True; /* show zero hits for search of cur vol */
2119 else /* file not found */
2121 /* FIX: put up error dialog and disable the button */
2122 /*printf("Current volume %s not found\n",
2123 hw->help_dialog.display.helpVolume);*/
2124 } /* if file found */
2126 XtFree(path); /* tests for NULL */
2127 } /* if selected/all/cur volumes sources */
2129 #if 0 || defined(DEBUG) /* for debug, set to 1 */
2130 OutputVolInfo(hw->help_dialog.srch.volListHead);
2133 /* get num volumes to process */
2134 hw->help_dialog.srch.volLeftCnt =
2135 CountSelectedVolumes(hw->help_dialog.srch.volListHead,True);
2137 /* empty the results list */
2138 XmUpdateDisplay(hw->help_dialog.srch.resultList);
2142 /************************************************************************
2143 * Function: CloseSearchCB()
2145 * Close the Global Search Dialog
2147 ************************************************************************/
2148 static void CloseSearchCB (
2150 XtPointer clientData,
2153 _DtHelpGlobSearchStuff * srch = (_DtHelpGlobSearchStuff *) clientData;
2155 /* stop any work proc */
2156 if(srch->workProcId)
2158 XtRemoveWorkProc(srch->workProcId);
2159 srch->workProcId = 0;
2162 /* unmanage the srchForm dialog but don't destroy it */
2163 if (NULL != srch->srchForm)
2165 XtUnmanageChild(srch->srchForm);
2166 XtUnmapWidget(srch->srchForm);
2171 /*****************************************************************************
2172 * Function: void DeleteListContents()
2176 * Return Value: Void.
2178 * Purpose: empties list and resets position values
2180 *****************************************************************************/
2181 static void DeleteListContents(
2182 _DtHelpGlobSearchStuff * srch)
2184 _DtHelpFileEntry curFile;
2186 if (NULL != srch->resultList)
2187 XmListDeleteAllItems(srch->resultList);
2189 for ( curFile = srch->volListHead;
2191 curFile = _DtHelpFileListGetNext(NULL,curFile) )
2193 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) curFile->clientData;
2194 if (NULL == vol) continue; /* CONTINUE */
2196 /* if any hits are displayed and any have open topics,
2197 walk through and close them */
2198 if ( vol->hitsDisplayed
2199 && ((vol->nextVolPosition - vol->startPosition) != vol->hitCnt) )
2201 _DtHelpGlobSrchHit * hit;
2202 for ( hit = vol->hitListHead;
2206 hit->topicsDisplayed = False;
2210 vol->startPosition = 1;
2211 vol->nextVolPosition = 1;
2212 vol->hitsDisplayed = False;
2217 /*****************************************************************************
2218 * Function: void StatusLabelUpdate()
2222 * Return Value: Void.
2224 * Purpose: Installs proper label over results list
2226 *****************************************************************************/
2227 static void StatusLabelUpdate(
2228 DtHelpDialogWidget hw,
2229 ResultsStatus status,
2230 Boolean forceUpdate,
2234 XmString labelString;
2235 XmString curLabelString;
2240 /* only update if necessary */
2241 if (status == hw->help_dialog.srch.statusLineUsage && !forceUpdate)
2245 /* order up the right message */
2246 hw->help_dialog.srch.statusLineUsage = status;
2249 case SCANNING_STATUS:
2250 labelMsg = (char *)_DTGETMESSAGE(GSSET, 17,"Scanning for volumes... Found %d");
2251 sprintf(buf,labelMsg,intArg);
2254 case WORKING_STATUS:
2255 labelMsg = (char *)_DTGETMESSAGE(GSSET, 18,
2256 "Searching... Volumes remaining: %d");
2257 /* we need +1 because of when this message is used */
2258 sprintf(buf,labelMsg,hw->help_dialog.srch.volLeftCnt + 1);
2261 case SEARCH_RESULTS_STATUS:
2262 /* if no hits found */
2263 if (hw->help_dialog.srch.hitsFound == False) /*don't use == True*/
2265 if (hw->help_dialog.srch.fullIndex)
2267 if (hw->help_dialog.srch.srchSources == _DtHelpGlobSrchAllVolumes)
2268 labelMsg = (char *)_DTGETMESSAGE (GSSET,19,
2269 "No index entries found.");
2271 labelMsg = (char *)_DTGETMESSAGE (GSSET,50,
2272 "No index entries found. Try All Volumes.");
2274 else /* searched on a pattern */
2276 labelMsg = (char *)_DTGETMESSAGE (GSSET,51,
2277 "No index entries found. Try another word.");
2279 /* change focus to the search word. Traversal is ignored
2280 if srchWord is desensitized (Contains btn not selected) */
2282 if (XtIsSensitive(hw->help_dialog.srch.wordField))
2285 * make sure the text field is editable before sending
2286 * the traversal there.
2288 XtSetArg(args[0],XmNeditable,True);
2289 XtSetValues(hw->help_dialog.srch.wordField, args, 1);
2291 (hw->help_dialog.srch.wordField,XmTRAVERSE_CURRENT);
2295 (hw->help_dialog.srch.allVolRadBtn,XmTRAVERSE_CURRENT);
2298 else /* if hits found */
2300 /* select the appropriate message */
2301 if (hw->help_dialog.srch.fullIndex)
2303 labelMsg = (char *)_DTGETMESSAGE(GSSET, 20,"Complete Index");
2308 labelMsg = (char *)_DTGETMESSAGE(GSSET, 21,"Entries with \"%s\"");
2309 sprintf(buf,labelMsg,hw->help_dialog.srch.rawWordStr);
2313 /* change focus to the results list */
2315 hw->help_dialog.srch.resultList,XmTRAVERSE_CURRENT);
2318 } /* if no hits found else */
2322 labelMsg = (char *)_DTGETMESSAGE (GSSET, 22,"No volumes selected");
2324 case FIRST_PROMPT_STATUS:
2325 labelMsg = (char *)_DTGETMESSAGE(GSSET,23,"Select search options above");
2329 /* DBG: when an empty string, form constraints are wrong; make a space */
2334 /* make a label string */
2335 labelString = XmStringCreateLocalized(labelMsg);
2337 /* get the current string of the label */
2338 curLabelString = NULL;
2339 XtSetArg(args[0],XmNlabelString,&curLabelString);
2340 XtGetValues (hw->help_dialog.srch.statusLabel, args, 1);
2342 /* update label if it is different; avoid flashing this way */
2343 if ( NULL != curLabelString && NULL != labelString
2344 && XmStringCompare(labelString,curLabelString) == False )
2346 /* update msg over results list */
2347 XtSetArg(args[0],XmNlabelString,labelString);
2348 XtSetValues(hw->help_dialog.srch.statusLabel,args,1);
2351 XmStringFree(labelString);
2352 XmStringFree(curLabelString);
2354 XmUpdateDisplay(hw->help_dialog.srch.statusLabel);
2360 /*****************************************************************************
2361 * Function: void ResultsListUpdate()
2365 * Return Value: Void.
2367 * Purpose: empty list and display results status message
2369 *****************************************************************************/
2370 static void ResultsListUpdate(
2371 DtHelpDialogWidget hw,
2372 _DtHelpFileEntry newFile)
2374 _DtHelpFileEntry testFile;
2376 /* check that in fact, there are no results that will be overwritten */
2377 for ( testFile = hw->help_dialog.srch.volListHead;
2379 testFile = _DtHelpFileListGetNext(NULL,testFile) )
2381 _DtHelpGlobSrchVol * vol;
2382 vol = (_DtHelpGlobSrchVol *)testFile->clientData;
2383 if (vol && vol->showVolInList && (vol->hitCnt > 0 || vol->zeroHitsOk))
2387 /* clean the list out if this is the first new result */
2388 /* this presumes that files are processed in order in the list */
2389 if (testFile == newFile)
2391 DeleteListContents(&hw->help_dialog.srch);
2392 AdjustPositionValues(newFile,0,1,True);
2394 /* True: insert new item */
2395 VolNameDisplay(hw,newFile,True);
2397 /* Update status label */
2398 StatusLabelUpdate(hw,SEARCH_RESULTS_STATUS,True,0); /* FIX: False */
2403 /*****************************************************************************
2404 * Function: void SearchForPattern()
2408 * Return Value: True if pattern found, False if not found
2410 * Purpose: Find a pattern in a string
2412 * WARNING: may convert string to uppercase in place
2413 * depending on which code is compiled.
2414 *****************************************************************************/
2415 static Boolean SearchForPattern(
2420 #if defined(NO_REGEX) /* don't support regex in string searches */
2423 _DtHelpCeUpperCase(string);
2424 /* FIX: make this code much faster by using an improved
2425 pattern search algorithm, such as Rabin-Karp. */
2426 /* hit is set to NULL if no matching char is found */
2427 while (_DtHelpCeStrchr(string, pattern, MB_CUR_MAX, &hit) == 0)
2429 if ( strncmp(hit,pattern,patternLen) == 0 )
2432 string = hit + mblen(hit,1);
2434 return (NULL != hit); /* RETURN True or False */
2435 #else /* if NO_REGEX */
2440 /* use regexec to pattern match */
2441 /* a 0 return value indicates success */
2442 if ( regcomp(&re,pattern,REG_NOSUB|REG_ICASE|REG_EXTENDED) == 0 )
2444 /* a 0 return value indicates success */
2445 ret = regexec(&re,string,0,NULL,0);
2448 return (ret == 0); /* RETURN True or False */
2449 # else /* NO_REGCOMP */
2453 /* a non NULL return value indicates success */
2454 compiledRE = (char *)regcmp(pattern, (char *) NULL);
2457 /* a non NULL return value indicates success */
2458 ret = regex(compiledRE, string);
2461 return (ret != NULL); /* RETURN True or False */
2462 # endif /* NO_REGCOMP */
2463 #endif /* if NO_REGEX */
2467 /*****************************************************************************
2468 * Function: void OpenVolForSearch()
2472 * Return Value: False if an error
2475 * Purpose: Opens a volume for searching,
2476 * gets the volume locale, if
2477 * different from system locale,
2478 * saves system locale in vol,
2479 * installs volume locale
2481 * Note that the system locale
2482 *****************************************************************************/
2483 static Boolean OpenVolForSearch(
2484 DtHelpDialogWidget hw,
2485 char * fullFilePath,
2486 _DtHelpGlobSrchVol * curVol)
2488 Boolean openedVolume = False;
2490 /* open the volume if not open */
2491 if ( NULL == curVol->volHandle )
2493 _DtHelpOpenVolume(fullFilePath, &curVol->volHandle);
2494 if (NULL == curVol->volHandle) return False; /* RETURN */
2496 if (curVol->gotLocale == False)
2498 curVol->stdLocale = _DtHelpGetVolumeLocale(curVol->volHandle);
2499 /* get the op-specific locales; the strings are default values */
2500 _DtHelpCeXlateStdToOpLocale(DtLCX_OPER_ICONV3,curVol->stdLocale,
2501 "iso88591",&curVol->iconv3Codeset);
2502 curVol->gotLocale = True;
2504 openedVolume = True;
2506 /* get the codeset of the application's locale, if haven't gotten it */
2507 if ( NULL == hw->help_dialog.srch.iconv3Codeset )
2509 char * locale = NULL;
2510 _DtHelpCeXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,
2511 setlocale(LC_CTYPE,NULL),&locale,NULL,NULL);
2512 /* get the op-specific locales; the strings are default values */
2513 /* impt: XlateStdToOpLocale() call requires a locale, not a codeset */
2514 _DtHelpCeXlateStdToOpLocale(DtLCX_OPER_ICONV3,locale,
2515 "iso88591",&hw->help_dialog.srch.iconv3Codeset);
2519 /** only saves or changes the locale if necessary **/
2520 /* create an iconv3 context to convert codeset of */
2521 /* the volume to the codeset of the application */
2522 if ( _DtHelpCeIconvContextSuitable(hw->help_dialog.srch.iconv3Context,
2523 curVol->iconv3Codeset,hw->help_dialog.srch.iconv3Codeset) == False )
2525 /* close old, open new */
2526 _DtHelpCeIconvClose(&hw->help_dialog.srch.iconv3Context);
2527 _DtHelpCeIconvOpen(&hw->help_dialog.srch.iconv3Context,
2528 curVol->iconv3Codeset,hw->help_dialog.srch.iconv3Codeset,' ',' ');
2531 /* else volume already open */
2533 /* if just opened volume */
2536 /* we just share pointers; when freeing localeWordStr, we need to
2537 test whether they are different before freeing */
2538 hw->help_dialog.srch.localeWordStr = hw->help_dialog.srch.normWordStr;
2541 /* get the str coll function, iff needed */
2542 if (NULL == curVol->strcollProc)
2544 /* get strcollProc for vol locale */
2545 curVol->strcollProc = _DtHelpCeGetStrcollProc();
2552 /*****************************************************************************
2553 * Function: void CloseVolAfterSearch()
2557 * Return Value: Void.
2559 * Purpose: Closes a volume opened for searching,
2560 * installs system locale, if diff from volume.
2562 *****************************************************************************/
2563 static void CloseVolAfterSearch(
2564 DtHelpDialogWidget hw,
2565 _DtHelpGlobSrchVol * curVol)
2567 /* close the volume if open */
2568 if ( NULL != curVol->volHandle )
2570 _DtHelpCloseVolume(curVol->volHandle);
2571 curVol->volHandle = NULL;
2572 /* free the locale word string, if allocated */
2573 if(hw->help_dialog.srch.localeWordStr!=hw->help_dialog.srch.normWordStr)
2575 XtFree(hw->help_dialog.srch.localeWordStr);
2576 hw->help_dialog.srch.localeWordStr = NULL;
2580 /* don't free the iconv context...may apply to the next volume */
2585 /*****************************************************************************
2586 * Function: void SearchTopic()
2590 * Return Value: Void.
2592 * Purpose: Get a single topic and search for the search word in it
2594 *****************************************************************************/
2595 static void SearchTopic(
2596 DtHelpDialogWidget hw,
2597 _DtHelpFileEntry curFile,
2598 _DtHelpGlobSrchVol * curVol,
2606 /* if the volume is not open; don't continue */
2607 if ( NULL == curVol->volHandle )
2608 return; /* RETURN */
2610 if ( NULL == curVol->indexEntriesList )
2611 _CEVolumeTopicList(curVol->volHandle,&curVol->indexEntriesList);
2612 if ( NULL == curVol->volHandle || NULL == curVol->indexEntriesList )
2614 curVol->topicSearchInProgress = False;
2615 curVol->topicSearchDone = True;
2616 curVol->indexSearchInProgress = True;
2617 if ( NULL == curVol->volHandle ) curVol->searchCompleted = True;
2618 return; /* RETURN */
2621 curVol->topicSearchInProgress = True;
2624 /* search the topics */
2625 /* note that indexEntriesList[0] is correct; ptr is incremented */
2626 /* we can increment the pointer because we don't own this memory;
2627 the open volume does. */
2629 i < numSearches && NULL != curVol->indexEntriesList[0];
2630 i++, curVol->indexEntriesList++ )
2632 char * topicTitle = NULL;
2635 validTopic = _DtHelpGetTopicTitle( curVol->volHandle,
2636 curVol->indexEntriesList[0],&topicTitle);
2639 /* look for a hit and process if there was one */
2640 if (SearchForPattern(topicTitle,srchWord,srchWordLen) == True)
2642 HitListAddFound(curFile, curVol->indexEntriesList[0], True, NULL);
2646 /* clean up and advance to next topic */
2648 curVol->searchedCnt++;
2649 } /* for all topics to search */
2652 if ( NULL == curVol->indexEntriesList /* no topics queried */
2653 || NULL == curVol->indexEntriesList[0] ) /* no more topics available */
2655 /* hand off to next stage */
2656 curVol->indexEntriesList = NULL;
2657 curVol->topicSearchInProgress = False;
2658 curVol->topicSearchDone = True;
2659 curVol->indexSearchInProgress = True;
2666 /*****************************************************************************
2667 * Function: void SearchIndex()
2671 * Return Value: void
2673 * Purpose: Get a single Index and search for the search word in it
2675 * Commentary: There are two strings for each index entry.
2676 * One string is the straight text in
2677 * the codeset of the volume. The
2678 * other string is a XmString that
2679 * has a font tag that will allow
2680 * it to be displayed in the
2683 * Preconditions: This code requires that the volume to be search
2684 * has already been opened [OpenVolForSearch()],
2685 * that the locale of the volume has been installed,
2686 * and that the search word is in the same code
2687 * set as the volume and has been converted to
2690 *****************************************************************************/
2691 static void SearchIndex(
2692 DtHelpDialogWidget hw,
2693 _DtHelpFileEntry curFile,
2694 _DtHelpGlobSrchVol * curVol,
2695 _DtHelpCeIconvContext iconvContext,
2701 char * indexEntry = NULL;
2702 size_t entryLen = 100; /* starting size */
2705 /* if the volume is not open; don't continue */
2706 if ( NULL == curVol->volHandle )
2707 return; /* RETURN */
2709 /* get the XmStrings of the entries */
2710 if ( NULL == curVol->indexXmStrsList )
2712 XmFontList fontList = NULL;
2713 Boolean mod = False;
2716 /* get results font list */
2717 XtSetArg(args[0], XmNfontList, &fontList);
2718 XtGetValues(hw->help_dialog.srch.resultList,args,1);
2721 /* Don't need to copy, _DtHelpFormatVolumeTitle copies
2725 /* work with copy, because FontListAppendEntry() destroys input FL */
2726 fontList = XmFontListCopy(fontList);
2729 /* get the entries */
2730 _DtHelpFormatIndexEntries(hw->help_dialog.help.pDisplayArea,
2731 curVol->volHandle,&numEntries, &curVol->indexXmStrsList,
2734 /* install the changed list */
2737 XtSetArg(args[0], XmNfontList, fontList);
2738 XtSetValues(hw->help_dialog.srch.resultList,args,1);
2739 if (fontList) XmFontListFree(fontList);
2743 /* get the pure strings for searching */
2744 if ( NULL == curVol->indexEntriesList )
2746 /* recall that the array and strings pointed to by
2747 the indexEntriesList is owned by the open volume */
2748 _DtHelpCeGetKeywordList(curVol->volHandle,&curVol->indexEntriesList);
2750 /* and re-init curIndexXmStr */
2751 curVol->curIndexXmStr = curVol->indexXmStrsList;
2754 if ( NULL == curVol->volHandle
2755 || NULL == curVol->indexEntriesList
2756 || NULL == curVol->indexXmStrsList )
2758 curVol->indexSearchInProgress = False;
2759 curVol->indexSearchDone = True;
2760 curVol->searchCompleted = True;
2761 if ( NULL == curVol->volHandle ) curVol->searchCompleted = True;
2762 return; /* RETURN */
2765 curVol->indexSearchInProgress = True;
2767 /* alloc memory for index processing */
2768 indexEntry = XtMalloc(sizeof(char)*(entryLen+1));
2769 if (NULL == indexEntry) return; /* RETURN */
2771 /* get a index entry */
2773 i < numSearches && NULL != curVol->indexEntriesList[0];
2774 i++, curVol->indexEntriesList++, curVol->curIndexXmStr++ )
2776 /* prevent overflow of buffer */
2777 if (strlen(curVol->indexEntriesList[0]) > entryLen)
2779 entryLen = strlen(curVol->indexEntriesList[0]) + 50;
2780 indexEntry = XtRealloc(indexEntry,entryLen+1);
2781 if (NULL == indexEntry) break; /* BREAK */
2783 indexEntry[0] = EOS; /* init to empty string */
2785 /* look for a hit and process if there was one */
2786 /* if srchWord is NULL, all entries are hits */
2787 /* copy, and possible iconv, the index string into the */
2788 /* the codeset of srchWord (the application) */
2789 if ( NULL == srchWord
2790 || ( _DtHelpCeIconvStr(iconvContext,curVol->indexEntriesList[0],
2791 &indexEntry, &entryLen,indexEntry,entryLen) == 0
2792 && SearchForPattern(indexEntry, srchWord, srchWordLen) == True ) )
2794 _DtHelpGlobSrchHit * hit;
2795 char * * topicIdList;
2797 HitListAddFound ( curFile, curVol->curIndexXmStr[0],
2798 curVol->indexEntriesList[0], True, &hit);
2800 /* topicIdList is set but not allocated & need not be freed */
2801 hit->topicCnt = _DtHelpCeFindKeyword(curVol->volHandle,
2802 hit->indexEntry,&topicIdList);
2805 /* clean up and advance to next topic */
2806 curVol->searchedCnt++;
2809 if ( NULL == curVol->indexEntriesList /*no topics queried*/
2810 || NULL == curVol->indexEntriesList[0] )/*no more index entries avail*/
2812 /* hand off to next stage */
2813 curVol->indexEntriesList = NULL; /* init */
2814 curVol->curIndexXmStr = curVol->indexXmStrsList; /* re-init */
2815 curVol->indexSearchInProgress = False;
2816 curVol->indexSearchDone = True;
2817 curVol->searchCompleted = True;
2824 /*****************************************************************************
2825 * Function: void SearchVolume()
2829 * Return Value: Void.
2831 * Purpose: do the search operation
2832 * This routine does incremental search--it searchs
2833 * a little, then returns to allow further processing.
2834 * It is called whenever Xt detects no other events.
2836 *****************************************************************************/
2837 static void SearchVolume(
2838 DtHelpDialogWidget hw,
2839 _DtHelpFileEntry curFile,
2840 _DtHelpGlobSrchVol * curVol,
2843 XmString labelString;
2847 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.srchForm));
2848 if (hw->help_dialog.srch.selectionDlg)
2849 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
2851 /* Process according to state */
2852 if ( curVol->nothingDone )
2854 curVol->nothingDone = False;
2855 curVol->topicSearchInProgress = True;
2857 /* Update the search status string */
2858 sprintf(buf,(char *)_DTGETMESSAGE(GSSET,18,
2859 "Searching... Volumes remaining: %d"),
2860 hw->help_dialog.srch.volLeftCnt);
2861 labelString = XmStringCreateLocalized(buf);
2862 XtSetArg(args[0],XmNlabelString,labelString);
2863 XtSetValues (hw->help_dialog.srch.statusLabel, args, 1);
2864 XmStringFree(labelString);
2866 XmUpdateDisplay((Widget) hw->help_dialog.srch.statusLabel);
2869 OpenVolForSearch(hw,curFile->fullFilePath,curVol);
2871 if ( curVol->topicSearchInProgress )
2873 SearchTopic(hw, curFile,curVol,hw->help_dialog.srch.localeWordStr,
2874 hw->help_dialog.srch.wordFieldLen, numSearches);
2877 /* NOTE: because this isn't an "else if", we could potentially
2878 search for 2*numSearches; but I know that I've disabled the
2879 topic search. Furthermore, my code depends upon the possibility
2880 of searching an entire volume in one call to the routine, if
2881 desired, and having an else if would break that.
2883 if ( curVol->indexSearchInProgress )
2886 srchWord = hw->help_dialog.srch.localeWordStr;
2887 /* FullIndex search indicated by a null search word string */
2888 if (hw->help_dialog.srch.fullIndex) srchWord = NULL;
2889 SearchIndex(hw, curFile, curVol, hw->help_dialog.srch.iconv3Context,
2890 srchWord, hw->help_dialog.srch.wordFieldLen, numSearches);
2893 /* If search was completed, update dependent stuff */
2894 if (curVol->searchCompleted)
2896 /* handle completion */
2897 CloseVolAfterSearch(hw,curVol);
2898 curVol->indexEntriesList = NULL; /* mem not owned by GlobSrch */
2899 if (hw->help_dialog.srch.fullIndex)
2900 curVol->gatheredFullIndex = True;
2901 hw->help_dialog.srch.volLeftCnt--;
2902 if (hw->help_dialog.srch.volLeftCnt < 0)
2903 hw->help_dialog.srch.volLeftCnt = 0;
2906 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.srchForm));
2907 if (hw->help_dialog.srch.selectionDlg)
2908 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
2913 /*****************************************************************************
2914 * Function: void SearchFile()
2918 * Return Value: Void.
2920 * Purpose: do the search operation on an entire file
2921 * It searches the entire file at once
2922 * and displays the results in the list.
2924 *****************************************************************************/
2925 static void SearchFile(
2926 DtHelpDialogWidget hw,
2927 _DtHelpFileEntry file)
2929 _DtHelpGlobSrchVol * vol;
2931 /* get volume info, adding if necessary */
2932 vol = (_DtHelpGlobSrchVol *) file->clientData;
2933 /* (T,T,F): enable search, enable display, any volume */
2934 if (NULL == vol) AddVolInfoToFile(file, True, True, False);
2935 vol = (_DtHelpGlobSrchVol *) file->clientData;
2936 if (NULL == vol) return;
2938 /* conduct search of entire volume in one call */
2939 hw->help_dialog.srch.volLeftCnt = 1;
2940 vol->searchThisVolume = True;
2941 vol->showVolInList = True;
2942 vol->zeroHitsOk = True;
2943 SearchVolume(hw,file,vol,INT_MAX);
2946 StatusLabelUpdate(hw,SEARCH_RESULTS_STATUS,True,0);/*FIX: False*/
2948 /* update the list to show the volume */
2949 AdjustPositionValues(file,0,1,True);
2950 /* True: do insert new item */
2951 VolNameDisplay(hw,file,True);
2953 if (vol->showHitsWithVol)
2955 VolHitsDisplay(hw,file);
2956 /* False: don't insert new item */
2957 VolNameDisplay(hw,file,False);
2964 /*****************************************************************************
2965 * Function: void DoBackgroundSearchWP(
2966 * XtPointer clientData)
2972 * Return Value: Void.
2974 * Purpose: do the search operation in the background
2975 * This routine does incremental search--it searchs
2976 * a little, then returns to allow further processing.
2977 * It is called whenever Xt detects no other events.
2979 *****************************************************************************/
2980 static Boolean DoBackgroundSearchWP(
2981 XtPointer clientData)
2983 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
2984 _DtHelpFileEntry curFile;
2985 _DtHelpGlobSrchVol * curVol = NULL;
2987 if ( 0 == hw->help_dialog.srch.volLeftCnt )
2988 goto searchComplete; /* GOTO: done! */
2990 /* get file to work on */
2991 curFile = hw->help_dialog.srch.curSrchVol;
2992 if ( NULL == curFile )
2994 curFile = GetNextSearchFileAndDisplayCompleted(
2995 hw, hw->help_dialog.srch.volListHead, NULL);
2996 if ( NULL == curFile ) goto searchComplete; /* GOTO: done */
2997 hw->help_dialog.srch.curSrchVol = curFile;
2998 } /* if no current file */
3000 /* get volume info */
3001 curVol = (_DtHelpGlobSrchVol *) curFile->clientData;
3003 #define NUM_SEARCHES_PER_CALL 30
3004 SearchVolume(hw,curFile,curVol,NUM_SEARCHES_PER_CALL);
3006 /* If search was completed, update dependent stuff */
3007 if (curVol->searchCompleted)
3009 /* update the search results list */
3010 /* True: adjust count beginning with this file */
3011 if (curVol->hitCnt > 0 || curVol->zeroHitsOk)
3013 /* record that a hit found */
3014 if ( curVol->hitCnt > 0
3015 || ( curVol->zeroHitsOk
3016 && _DtHelpGlobSrchSelectedVolumes == hw->help_dialog.srch.srchSources))
3017 hw->help_dialog.srch.hitsFound = True;
3019 /* update the list to show the volume */
3020 AdjustPositionValues(curFile,0,1,True);
3021 ResultsListUpdate(hw,curFile);
3023 /* update the list to show the hits? */
3024 if (hw->help_dialog.srch.srchSources == _DtHelpGlobSrchCurVolume)
3026 VolHitsDisplay(hw,curFile);
3027 /* False: don't insert new item */
3028 VolNameDisplay(hw,curFile,False);
3030 XmUpdateDisplay((Widget) hw->help_dialog.srch.resultList);
3033 /* prepare for next search */
3034 hw->help_dialog.srch.curSrchVol =
3035 GetNextSearchFileAndDisplayCompleted(hw,NULL,curFile);
3037 } /* if search completed */
3040 if ( hw->help_dialog.srch.volLeftCnt > 0
3041 || False == curVol->searchCompleted )
3042 return False; /* RETURN: False ==> continue processing */
3044 /* Do this when no more files are left to search */
3047 XmPushButtonCallbackStruct status;
3049 /* zero search data before stopping */
3050 hw->help_dialog.srch.volLeftCnt = 0; /* just in case */
3051 hw->help_dialog.srch.curSrchVol = NULL; /* just in case */
3053 /* generate a fake event to reset the dialog */
3054 status.reason = XmCR_ACTIVATE;
3055 status.event = NULL;
3056 status.click_count = 1;
3057 StopSearchCB(hw->help_dialog.srch.actionBtn,
3058 (XtPointer)hw,(XtPointer)&status);
3060 return True; /* RETURN: True ==> stop processing */
3066 /*****************************************************************************
3067 * Function: void StartSearchCB(Widget w,
3068 * XtPointer clientData,
3069 * XtPointer callData);
3075 * Return Value: Void.
3077 * Purpose: Create a new user bookmark
3079 * Warning: This CB is also used by the volume selection buttons
3080 * to activate a search when they are selected. The routine
3081 * cannot rely upon the w or callData params. The clientData
3082 * will always be the help widget.
3083 *****************************************************************************/
3084 static void StartSearchCB(
3085 Widget w, /* don't use */
3086 XtPointer clientData,
3087 XtPointer callData) /* don't use */
3089 char *srchWord = NULL;
3090 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3091 XtAppContext appCntx;
3095 /* set state of start button correctly */
3096 UpdateSearchStartStatusCB(NULL, (XtPointer) hw, NULL);
3098 /* if help content isn't a volume, it has no index */
3099 if ( _DtHelpGlobSrchCurVolume == hw->help_dialog.srch.srchSources
3100 && hw->help_dialog.display.helpType != DtHELP_TYPE_TOPIC )
3101 return; /* RETURN */
3103 /* retrieve the name */
3104 srchWord = XmTextFieldGetString(hw->help_dialog.srch.wordField);
3106 /* test for empty (also emtpy spaces) and only process if not emtpy */
3107 _DtHelpCeCompressSpace(srchWord);
3108 if ( (strlen(srchWord) > (size_t) 0 || hw->help_dialog.srch.fullIndex)
3109 && hw->help_dialog.srch.workProcId == 0)
3110 /* test on workProcId prevents multiple activations due to
3111 race condition on desensitizing the start button */
3113 _DtHelpTurnOnHourGlass(XtParent(hw));
3114 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.srchForm));
3115 if (hw->help_dialog.srch.selectionDlg)
3116 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
3118 /*XtSetSensitive (hw->help_dialog.srch.actionBtn,False);*/
3119 XtSetSensitive (hw->help_dialog.srch.curVolRadBtn,False);
3120 XtSetSensitive (hw->help_dialog.srch.allVolRadBtn,False);
3121 XtSetSensitive (hw->help_dialog.srch.selVolRadBtn,False);
3122 XtSetSensitive (hw->help_dialog.srch.selectBtn,False);
3124 /* 9/26/94: these two XtSetArgs (and following SetValues) cause a core dump
3125 for the SunOS 5.3 optimized executable. It isn't a problem for the
3126 non-optimized or debuggable versions or any versions on AIX 3.2 or
3130 XtSetArg(args[n],XmNeditable,False); n++;
3131 XtSetArg(args[n],XmNcursorPositionVisible,False); n++;
3132 XtSetValues (hw->help_dialog.srch.wordField, args, n);
3134 XmUpdateDisplay(hw->help_dialog.srch.srchForm);
3136 /* process the source selection and retain in widget srchWord memory */
3137 PrepSearchSourceData(hw, srchWord);
3139 /* activate search thread; do it even with a 0 count, because the
3140 process reactivates the dialog after search is completed */
3141 appCntx = XtWidgetToApplicationContext((Widget) hw);
3142 hw->help_dialog.srch.workProcId =
3143 XtAppAddWorkProc(appCntx,DoBackgroundSearchWP, (XtPointer) hw);
3145 hw->help_dialog.srch.searchInProgress = True;
3147 /* don't free srchWord */
3149 /* turn on "Stop" label */
3150 UpdateActionButtonLabel(hw,NULL,False);
3152 _DtHelpTurnOffHourGlass(XtParent(hw));
3153 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.srchForm));
3154 if (hw->help_dialog.srch.selectionDlg)
3155 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
3159 if ( strlen(srchWord) == 0 )
3160 StatusLabelUpdate(hw,FIRST_PROMPT_STATUS,False,0);
3168 /*****************************************************************************
3169 * Function: void StartSelectedVolumeSearchCB(Widget w,
3170 * XtPointer clientData,
3171 * XtPointer callData);
3177 * Return Value: Void.
3179 * Purpose: Begin a search on the selected volume
3181 *****************************************************************************/
3182 static void StartSelectedVolumeSearchCB(
3184 XtPointer clientData,
3187 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3188 _DtHelpFileEntry file;
3190 Boolean noSelectedFiles = True;
3192 /* if not full index search */
3193 if (hw->help_dialog.srch.fullIndex == False)
3195 /* get the current contents of the search word field */
3196 srchWord = XmTextFieldGetString(hw->help_dialog.srch.wordField);
3198 /* test the word ; False=dontUpdate--do this in PrepSearchSourceData() */
3199 if ( CheckSearchWord(hw,srchWord,False) == True )
3200 { /* word has changed since last search; do a whole new search */
3201 StartSearchCB(NULL,(XtPointer) hw, NULL);
3202 return; /* RETURN */
3205 /* if the text field is empty, do nothing */
3206 if ( strlen(hw->help_dialog.srch.normWordStr) == 0 )
3207 return; /* RETURN */
3210 /* set this to true to counteract False if no hits */
3211 hw->help_dialog.srch.hitsFound = True;
3213 /* Word is the same, just the selection has changed. */
3214 /* Determine which one was selected or deselected */
3215 for ( file = hw->help_dialog.srch.volListHead;
3217 file = _DtHelpFileListGetNext(NULL,file) )
3219 _DtHelpGlobSrchVol * vol;
3220 vol = (_DtHelpGlobSrchVol *) file->clientData;
3221 if (NULL == vol) continue;
3224 if (file->fileSelected) noSelectedFiles = False;
3226 /* test for contradictory flags; fileSelected reflects dialog list */
3227 if (file->fileSelected != vol->showVolInList)
3229 /* file has been deselected */
3230 if (False == file->fileSelected)
3232 if (vol->showVolInList)
3234 /* update list: delete hits, topics, and volume title */
3235 if (vol->hitsDisplayed) VolHitsUndisplay(hw,file);
3237 /* delete hits first, then volume */
3239 hw->help_dialog.srch.resultList,vol->startPosition);
3240 AdjustPositionValues(file, 0, -1, True);
3241 vol->showVolInList = False;
3242 vol->searchThisVolume = False;
3245 else /* file has been selected */
3247 SearchFile(hw,file);
3248 } /* if file de/selected */
3249 } /* if contradictory flags */
3250 } /* for all volumes */
3253 if (noSelectedFiles) StatusLabelUpdate(hw,NO_VOL_STATUS,True,0);
3258 /*****************************************************************************
3259 * Function: void UpdateSearchStartStatusCB(Widget w,
3260 * XtPointer clientData,
3261 * XtPointer callData);
3267 * Return Value: Void.
3269 * Purpose: update the status of the search status button
3270 * Routine is called whenever text is changed in the search
3273 *****************************************************************************/
3274 static void UpdateSearchStartStatusCB(
3276 XtPointer clientData,
3279 char *srchWord = NULL;
3280 /*XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) callData;*/
3281 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3284 /* retrieve the name */
3285 srchWord = XmTextFieldGetString(hw->help_dialog.srch.wordField);
3287 /* test for empty (also emtpy spaces) */
3288 _DtHelpCeCompressSpace(srchWord);
3290 /* FIX: change the locale from the volume locale back to the system
3291 locale temporarily (if not already in that locale) */
3292 _DtHelpCeUpperCase(srchWord);
3294 /* only sensitize if working on a help volume and word is not emtpy
3297 if ( ( _DtHelpGlobSrchCurVolume == hw->help_dialog.srch.srchSources
3298 && hw->help_dialog.display.helpType != DtHELP_TYPE_TOPIC)
3299 || ( strlen(srchWord) == (size_t) 0
3300 && hw->help_dialog.srch.fullIndex == False))
3302 XtSetSensitive (hw->help_dialog.srch.actionBtn,newState);
3304 /* if word has changed from word of previous search, change to Start */
3305 UpdateActionButtonLabel(hw,srchWord,True);
3311 /*****************************************************************************
3312 * Function: void StopSearchCB(Widget w,
3313 * XtPointer clientData,
3314 * XtPointer callData);
3320 * Return Value: Void.
3322 * Purpose: Stop the search
3324 *****************************************************************************/
3325 static void StopSearchCB(
3327 XtPointer clientData,
3330 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3335 /* stop the search thread */
3336 if(hw->help_dialog.srch.workProcId != 0)
3337 XtRemoveWorkProc(hw->help_dialog.srch.workProcId);
3338 hw->help_dialog.srch.workProcId = 0;
3340 hw->help_dialog.srch.searchInProgress = False;
3342 /* update statuses */
3344 XtSetSensitive (hw->help_dialog.srch.curVolRadBtn,
3345 hw->help_dialog.srch.curVolRadBtnSens);
3347 XtSetSensitive (hw->help_dialog.srch.curVolRadBtn, TRUE);
3350 XtSetSensitive (hw->help_dialog.srch.allVolRadBtn,True);
3351 XtSetSensitive (hw->help_dialog.srch.selVolRadBtn,True);
3353 XtSetArg(args[n],XmNeditable,True); n++;
3354 XtSetArg(args[n],XmNcursorPositionVisible,True); n++;
3355 XtSetValues (hw->help_dialog.srch.wordField, args, n);
3357 /* update select btn status; only when selected and dialog closed */
3358 XtSetArg(args[0],XmNset,&cur);
3359 XtGetValues(hw->help_dialog.srch.selVolRadBtn,args,1);
3360 XtSetSensitive(hw->help_dialog.srch.selectBtn,
3361 cur && ( NULL == hw->help_dialog.srch.selectionDlg
3362 || !XtIsManaged(hw->help_dialog.srch.selectionDlg) ) );
3364 /* set the action button label appropriately */
3365 UpdateActionButtonLabel(hw,hw->help_dialog.srch.normWordStr,True);
3367 /* post message of results */
3368 StatusLabelUpdate(hw,SEARCH_RESULTS_STATUS,True,0);
3374 /*****************************************************************************
3375 * Function: void ActionButtonCB(Widget w,
3376 * XtPointer clientData,
3377 * XtPointer callData);
3383 * Return Value: Void.
3385 * Purpose: Act upon the action
3387 *****************************************************************************/
3388 static void ActionButtonCB(
3390 XtPointer clientData,
3393 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3395 if ( hw->help_dialog.srch.searchInProgress == False )
3396 StartSearchCB(w,clientData,callData);
3398 StopSearchCB(w,clientData,callData);
3404 /*****************************************************************************
3405 * Function: void GotoResultCB(Widget w,
3406 * XtPointer clientData,
3407 * XtPointer callData);
3413 * Return Value: Void.
3415 * Purpose: Goto a result topic
3417 *****************************************************************************/
3418 static void GotoResultCB(
3420 XtPointer clientData,
3423 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3424 char * helpFile = NULL;
3425 int * topicPosList=NULL;
3430 /* Determine the item selected and find that item in our list */
3431 status = XmListGetSelectedPos(hw->help_dialog.srch.resultList, &topicPosList,&i);
3433 /* if true, an item selected */
3434 if (status && topicPosList)
3436 _DtHelpGlobSrchHit * entry = NULL;
3437 _DtHelpFileEntry file = NULL;
3438 char * locationId = NULL;
3439 topicPosition = topicPosList[0] - 1; /* convert to 0 based */
3440 XtFree((String)topicPosList);
3443 HitListGetNth(hw->help_dialog.srch.volListHead,
3444 topicPosition,&file,&entry,&locationId,&helpFile);
3446 /* jump to selected location */
3447 XtFree(hw->help_dialog.display.locationId);
3448 hw->help_dialog.display.locationId = XtNewString(locationId);
3449 XtFree(hw->help_dialog.display.helpVolume);
3450 hw->help_dialog.display.helpVolume = XtNewString(helpFile);
3451 hw->help_dialog.ghelp.volumeFlag = False; /* force search for volume */
3452 hw->help_dialog.display.helpType = DtHELP_TYPE_TOPIC;
3454 _DtHelpSetupDisplayType(hw, TRUE, DtHISTORY_AND_JUMP);
3458 if (topicPosList) XtFree((String)topicPosList);
3460 /* FIX: Put up a message to suggest selecting an item first */
3461 /* Don't close the dialog */
3464 #endif /* not_used */
3466 #if 0 /* save--used in code commented out elsewhere in this file */
3468 /*****************************************************************************
3469 * Function: void CloseHelpCB()
3473 * Return Value: Void.
3475 * Purpose: Close and destroy the help widget
3477 *****************************************************************************/
3478 static void CloseHelpCB(
3480 XtPointer clientData,
3486 #endif /* save--used in code commented out elsewhere in this file */
3489 /*****************************************************************************
3490 * Function: void GotoLocation(hw,helpVolume,location)
3494 * Return Value: Void.
3496 * Purpose: Goto a topic by opening a new help dialog window
3498 *****************************************************************************/
3499 static void GotoLocation(
3500 DtHelpDialogWidget hw,
3504 #if 0 /* don't delete...useful as reference */
3510 /* This opens a new help window on the topic */
3512 XtSetArg( args[n], XmNtitle, "Help" ); n++;
3513 XtSetArg( args[n], DtNhelpType, DtHELP_TYPE_TOPIC ); n++;
3514 XtSetArg( args[n], DtNlocationId, locationId ); n++;
3515 XtSetArg( args[n], DtNhelpVolume, helpVolume ); n++;
3516 helpDlg = DtCreateHelpDialog(XtParent(hw),"mainHelpDialog",args,n);
3517 XtAddCallback(helpDlg,DtNcloseCallback,CloseHelpCB,helpDlg);
3518 XtManageChild(helpDlg);
3522 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.srchForm));
3523 if (hw->help_dialog.srch.selectionDlg)
3524 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
3526 /* jump to selected location in same window */
3527 XtFree(hw->help_dialog.display.locationId);
3528 hw->help_dialog.display.locationId = XtNewString(locationId);
3529 XtFree(hw->help_dialog.display.helpVolume);
3530 hw->help_dialog.display.helpVolume = XtNewString(helpVolume);
3531 hw->help_dialog.ghelp.volumeFlag = False; /* force search for volume */
3532 hw->help_dialog.display.helpType = DtHELP_TYPE_TOPIC;
3534 _DtHelpSetupDisplayType(hw, TRUE, DtHISTORY_AND_JUMP);
3536 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.srchForm));
3537 if (hw->help_dialog.srch.selectionDlg)
3538 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.selectionDlg));
3545 /*****************************************************************************
3546 * Function: void ProcessResultSelectionCB(Widget w,
3547 * XtPointer clientData,
3548 * XtPointer callData);
3554 * Return Value: Void.
3556 * Purpose: Process user selection of an item in the result List.
3558 *****************************************************************************/
3559 static void ProcessResultSelectionCB(
3561 XtPointer clientData,
3564 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3565 int * topicPosList = NULL;
3570 /* Determine the item selected and find that item in our list */
3571 status = XmListGetSelectedPos(
3572 hw->help_dialog.srch.resultList, &topicPosList,&n);
3574 /* if true, an item selected */
3575 if (status && topicPosList)
3577 _DtHelpFileEntry file = NULL;
3578 _DtHelpGlobSrchHit * hit = NULL;
3579 char * locationId = NULL;
3580 char * helpFile = NULL;
3582 topicPosition = topicPosList[0]; /* 1 based */
3583 XtFree((String)topicPosList);
3586 if ( HitListGetNth(hw->help_dialog.srch.volListHead,
3587 topicPosition,&file,&hit,&locationId,&helpFile) == 0 )
3589 _DtHelpTurnOnHourGlass(XtParent(hw->help_dialog.srch.srchForm));
3592 XmListDeselectPos(hw->help_dialog.srch.resultList,topicPosition);
3594 /* was a volume item selected? */
3597 _DtHelpGlobSrchVol * vol = (_DtHelpGlobSrchVol *) file->clientData;
3598 if (vol->hitCnt > 0)
3600 if (False == vol->hitsDisplayed)
3602 VolHitsDisplay(hw,file); /* toggle state */
3606 VolHitsUndisplay(hw,file);
3607 vol->showHitsWithVol = False;
3609 /* update the volume label to show the state */
3610 /* False: don't insert hw item */
3611 VolNameDisplay(hw,file,False);
3613 /* else don't otherwise handle a 0-hits volume */
3615 /* was an expandable index selected */
3616 else if (NULL == locationId && hit->topicCnt > 1)
3620 /* if we're turning them on, build a list */
3621 if (False == hit->topicsDisplayed)
3623 topicCnt = HitTopicsDisplay(hw,file,hit,topicPosition+1);
3627 topicCnt = - HitTopicsUndisplay(hw,file,hit,topicPosition+1);
3628 hit->showTopicsWithHit = False;
3630 /* update the hit label to show the state; False--don't insert */
3631 HitNameDisplay(hw,file,hit,topicPosition,False);
3633 /* add to all the following */
3636 /* adjust count beginning with next file with hits */
3637 AdjustPositionValues(file, 0, topicCnt, True);
3640 /* a location or index with one topic was selected */
3643 /* if a single click, goto the location */
3644 if (hit->topicCnt == 1)
3646 if ( HitLoadTopics(hw,file,hit) == 0 )
3648 GotoLocation(hw, file->fullFilePath, hit->topicIdList[0]);
3649 HitFree(hit,False); /*release what was loaded 3 lines up*/
3652 { /* volume couldn't be opened or some other error */
3653 /* FIX: error message */
3655 } /* if an index with a single topic */
3657 { /* a location from an open multi-topic index entry */
3658 GotoLocation(hw, file->fullFilePath, locationId);
3660 } /* else index with one topic or topic was selected */
3662 /* finish up processing a selection */
3663 _DtHelpTurnOffHourGlass(XtParent(hw->help_dialog.srch.srchForm));
3665 } /* got the nth item */
3667 else /* could not find the nth hit */
3669 if (topicPosList) XtFree((String)topicPosList);
3676 /*****************************************************************************
3677 * Function: void CloseVolSelDialogCB(Widget w,
3678 * XtPointer clientData,
3679 * XtPointer callData);
3683 * Return Value: Void.
3685 * Purpose: Resets the selection dialog variable to NULL
3687 *****************************************************************************/
3688 static void CloseVolSelDialogCB(
3690 XtPointer clientData,
3693 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3695 /* unmanage & destroy the dialog zero the variable */
3696 if ( hw->help_dialog.srch.selectionDlg
3697 && XtIsManaged(hw->help_dialog.srch.selectionDlg) )
3698 XtUnmanageChild(hw->help_dialog.srch.selectionDlg);
3700 /* start a search to be sure we got all changes; FIX: need this??? */
3701 /*StartSearchCB(NULL,hw,NULL);*/
3702 XtSetSensitive(hw->help_dialog.srch.selectBtn,True);
3705 if (hw->help_dialog.srch.hitsFound == True)
3706 XmProcessTraversal(hw->help_dialog.srch.resultList,XmTRAVERSE_CURRENT);
3708 XmProcessTraversal(hw->help_dialog.srch.allVolRadBtn,XmTRAVERSE_CURRENT);
3713 /*****************************************************************************
3714 * Function: void CreateVolSelDialog(
3718 * Return Value: Void.
3720 * Purpose: Creates selection dialog to chose volumes
3722 *****************************************************************************/
3723 static void CreateVolSelDialog(
3724 DtHelpDialogWidget hw)
3727 _DtHelpFileDlgChildren dlgChld;
3728 Atom wm_delete_window;
3731 /* desensitize the button */
3732 XtSetSensitive(hw->help_dialog.srch.selectBtn,False);
3734 /* only create one */
3735 if ( NULL != hw->help_dialog.srch.selectionDlg )
3737 XtManageChild(hw->help_dialog.srch.selectionDlg);
3741 /* open the modal dialog and let user select the volumes */
3742 selDlg = _DtHelpFileListCreateSelectionDialog(
3743 hw, hw->help_dialog.srch.srchForm, False,
3744 (char *)_DTGETMESSAGE (GSSET, 40,
3745 "Help - Search Volume Selection"),
3746 &hw->help_dialog.srch.volTitlesFontList,
3747 hw->help_dialog.srch.volListHead, &dlgChld);
3748 hw->help_dialog.srch.selectionDlg = selDlg;
3750 XtAddCallback(dlgChld.closeBtn, XmNactivateCallback,
3751 CloseVolSelDialogCB,(XtPointer)hw);
3752 XtAddCallback(dlgChld.form, XmNunmapCallback,
3753 CloseVolSelDialogCB,(XtPointer)hw);
3755 /* set the default response to a WM_DELETE_WINDOW message
3756 to no response instead of UNMAP. */
3757 XtSetArg(args[0], XmNdeleteResponse, XmDO_NOTHING);
3758 XtSetValues(dlgChld.shell, args, 1);
3759 wm_delete_window = XmInternAtom(XtDisplay(dlgChld.shell),
3760 "WM_DELETE_WINDOW", FALSE);
3761 XmAddWMProtocolCallback(dlgChld.shell,wm_delete_window,
3762 (XtCallbackProc)CloseVolSelDialogCB, (XtPointer)hw);
3764 XtAddCallback(dlgChld.list, XmNsingleSelectionCallback,
3765 StartSelectedVolumeSearchCB, (XtPointer) hw);
3766 XtAddCallback(dlgChld.list, XmNmultipleSelectionCallback,
3767 StartSelectedVolumeSearchCB, (XtPointer) hw);
3768 XtAddCallback(dlgChld.list, XmNextendedSelectionCallback,
3769 StartSelectedVolumeSearchCB, (XtPointer) hw);
3770 XtAddCallback(dlgChld.list, XmNdefaultActionCallback,
3771 StartSelectedVolumeSearchCB, (XtPointer) hw);
3776 /*****************************************************************************
3777 * Function: void OpenSelectDialogCB(Widget w,
3778 * XtPointer clientData,
3779 * XtPointer callData);
3785 * Return Value: Void.
3787 * Purpose: Process user selection of the select button
3789 *****************************************************************************/
3790 static void OpenSelectDialogCB(
3792 XtPointer clientData,
3795 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3797 /* only build the list of files if it hasn't been done */
3798 if ( False == hw->help_dialog.srch.volScanDone
3799 || NULL == hw->help_dialog.srch.volListHead)
3801 /* Add on the Vol info; (T,T,T) search, display, selected only */
3802 VolListBuild(hw,True,True,True);
3805 /* FIX: the modal behaviour doesn't seem to be set; is it desired/needed? */
3806 /* don't need to worry about having open twice, since
3807 the dialog is always opened in modal mode from the search dialog */
3808 /* open the dialog and let user select the volumes */
3809 CreateVolSelDialog(hw);
3813 /*****************************************************************************
3814 * Function: void UpdateSearchVolumesCB(Widget w,
3815 * XtPointer clientData,
3816 * XtPointer callData);
3822 * Return Value: Void.
3824 * Purpose: Process user selection of a button in the Volumes Radio box
3826 *****************************************************************************/
3827 static void UpdateSearchVolumesCB(
3829 XtPointer clientData,
3832 XmToggleButtonCallbackStruct *status = (XmToggleButtonCallbackStruct *) callData;
3833 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3839 if (hw->help_dialog.srch.hitsFound == True)
3840 XmProcessTraversal(hw->help_dialog.srch.resultList,XmTRAVERSE_CURRENT);
3842 XmProcessTraversal(hw->help_dialog.srch.allVolRadBtn,XmTRAVERSE_CURRENT);
3846 /* if turning off the button, just reinforce the current settings.
3847 This message occurs when an on button is hit again. */
3848 if ( False == status->set )
3850 XtSetArg(args[0], XmNset, hw->help_dialog.srch.allVolRadBtn == widget);
3851 XtSetValues(hw->help_dialog.srch.allVolRadBtn,args,1);
3852 XtSetArg(args[0], XmNset, hw->help_dialog.srch.selVolRadBtn == widget);
3853 XtSetValues(hw->help_dialog.srch.selVolRadBtn,args,1);
3854 XtSetArg(args[0], XmNset, hw->help_dialog.srch.curVolRadBtn == widget);
3855 XtSetValues(hw->help_dialog.srch.curVolRadBtn,args,1);
3859 /*** if work when something is turned on; ignore the off messages
3860 except when the button is the selected volumes button; we
3861 want to catch every click on that button */
3862 if ( XmCR_VALUE_CHANGED == status->reason
3863 && True == status->set
3864 && NULL != status->event ) /* event is NULL for 1st of the two calls
3865 to this routine that are made when a
3866 button is pressed. */
3868 /*** now update the sources value according to button selected ***/
3869 hw->help_dialog.srch.volLeftCnt = 0; /* change invalidates prior search */
3870 UpdateActionButtonLabel(hw,NULL,True);
3872 XtSetArg(args[0], XmNset, hw->help_dialog.srch.allVolRadBtn == widget);
3873 XtSetValues(hw->help_dialog.srch.allVolRadBtn,args,1);
3874 XtSetArg(args[0], XmNset, hw->help_dialog.srch.curVolRadBtn == widget);
3875 XtSetValues(hw->help_dialog.srch.curVolRadBtn,args,1);
3876 XtSetArg(args[0], XmNset, hw->help_dialog.srch.selVolRadBtn == widget);
3877 XtSetValues(hw->help_dialog.srch.selVolRadBtn,args,1);
3879 /*** selected volumes button activated ***/
3880 if (hw->help_dialog.srch.selVolRadBtn == widget)
3883 hw->help_dialog.srch.srchSources = _DtHelpGlobSrchSelectedVolumes;
3885 /* only build the list of files if it hasn't been done */
3886 if ( False == hw->help_dialog.srch.volScanDone
3887 || NULL == hw->help_dialog.srch.volListHead)
3889 /* Add on the Vol info; (T,T,T) search, display, selected only */
3890 VolListBuild(hw,True,True,True);
3893 /* (F,F,F,F): disable search,disable display,no 0 hits,for all vols */
3894 SetVolStatus(hw->help_dialog.srch.volListHead,False,False,False,False);
3895 /* (T,T,T,T): enable search, enable display,
3896 zero hits ok, only for selected volumes */
3897 /* Set these here so that the CountSelectedVolumes() works right */
3898 SetVolStatus(hw->help_dialog.srch.volListHead,True,True,True,True);
3900 /* count all volumes selected, including those already searched */
3901 if (CountSelectedVolumes(hw->help_dialog.srch.volListHead,True)==0)
3903 StatusLabelUpdate(hw,NO_VOL_STATUS,False,0);
3904 DeleteListContents(&hw->help_dialog.srch);
3905 CreateVolSelDialog(hw);
3906 /* NOTE: don't start search here, start it from the callback */
3907 /* set state of start button correctly */
3908 UpdateSearchStartStatusCB(NULL, (XtPointer) hw, NULL);
3910 else /* volumes already selected; just display */
3912 hw->help_dialog.srch.hitsFound = False; /*DBG*/
3913 StartSearchCB(NULL,(XtPointer) hw, NULL);
3915 } /* if selected volumes button */
3917 /*** all volumes button ***/
3918 else if (hw->help_dialog.srch.allVolRadBtn == widget)
3920 /* close the selection dialog, if open */
3921 if (hw->help_dialog.srch.selectionDlg)
3922 XtUnmanageChild(hw->help_dialog.srch.selectionDlg);
3924 /* set sources state */
3925 hw->help_dialog.srch.srchSources = _DtHelpGlobSrchAllVolumes;
3926 hw->help_dialog.srch.hitsFound = False; /*DBG*/
3927 StartSearchCB(NULL,(XtPointer) hw, NULL);
3929 /*** current volume button ***/
3932 /* close the selection dialog, if open */
3933 if (hw->help_dialog.srch.selectionDlg)
3934 XtUnmanageChild(hw->help_dialog.srch.selectionDlg);
3936 /* set sources state */
3937 hw->help_dialog.srch.srchSources = _DtHelpGlobSrchCurVolume;
3938 hw->help_dialog.srch.hitsFound = False; /*DBG*/
3939 StartSearchCB(NULL,(XtPointer) hw, NULL);
3942 /* update the Select... button status */
3943 /* do this last, so that while searching for volumes (VolListBuild),
3944 the button is not active. */
3945 XtSetSensitive(hw->help_dialog.srch.selectBtn,
3946 (hw->help_dialog.srch.selVolRadBtn == widget)
3947 && ( NULL == hw->help_dialog.srch.selectionDlg
3948 || !XtIsManaged(hw->help_dialog.srch.selectionDlg) ) );
3950 } /* if value changed */
3955 /*****************************************************************************
3956 * Function: void UpdateIndexSelectionCB(Widget w,
3957 * XtPointer clientData,
3958 * XtPointer callData);
3964 * Return Value: Void.
3966 * Purpose: Process user selection of a button in the Entries Radio box
3968 *****************************************************************************/
3969 static void UpdateIndexSelectionCB(
3971 XtPointer clientData,
3974 XmToggleButtonCallbackStruct *status = (XmToggleButtonCallbackStruct *) callData;
3975 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
3976 Boolean containsState;
3981 if (hw->help_dialog.srch.hitsFound == True)
3982 XmProcessTraversal(hw->help_dialog.srch.resultList,XmTRAVERSE_CURRENT);
3984 XmProcessTraversal(hw->help_dialog.srch.allVolRadBtn,XmTRAVERSE_CURRENT);
3987 /* if turning off the button, just reinforce the current settings.
3988 This message occurs when an on button is hit again. */
3989 if ( False == status->set )
3991 containsState = (hw->help_dialog.srch.containsRadBtn == widget);
3992 XtSetArg(args[0], XmNset, !containsState);
3993 XtSetValues(hw->help_dialog.srch.fullIndexRadBtn,args,1);
3994 XtSetArg(args[0], XmNset, containsState);
3995 XtSetValues(hw->help_dialog.srch.containsRadBtn,args,1);
3999 /*** if work when something is turned on; ignore the off messages
4000 except when the button is the selected volumes button; we
4001 want to catch every click on that button */
4002 if ( XmCR_VALUE_CHANGED == status->reason
4003 && True == status->set
4004 && NULL != status->event ) /* event is NULL for 1st of the two calls
4005 to this routine that are made when a
4006 button is pressed. */
4008 /* if search in progress, stop it */
4009 if(hw->help_dialog.srch.searchInProgress||hw->help_dialog.srch.workProcId)
4011 XmPushButtonCallbackStruct status;
4013 /* generate a fake event to reset the dialog */
4014 status.reason = XmCR_ACTIVATE;
4015 status.event = NULL;
4016 status.click_count = 1;
4017 StopSearchCB(hw->help_dialog.srch.actionBtn,
4018 (XtPointer)hw,(XtPointer)&status);
4021 containsState = (hw->help_dialog.srch.containsRadBtn == widget);
4022 XtSetArg(args[0], XmNset, !containsState);
4023 XtSetValues(hw->help_dialog.srch.fullIndexRadBtn,args,1);
4024 XtSetArg(args[0], XmNset, containsState);
4025 XtSetValues(hw->help_dialog.srch.containsRadBtn,args,1);
4027 /* sensitize/desensitize the Contains text field */
4028 XtSetSensitive(hw->help_dialog.srch.wordField,containsState);
4030 XtSetArg(args[n],XmNeditable,containsState); n++;
4031 XtSetArg(args[n],XmNcursorPositionVisible,containsState); n++;
4032 XtSetValues(hw->help_dialog.srch.wordField,args,n);
4034 /* set widget status here; do this way bec. srchFullIndex is a bit flag */
4035 hw->help_dialog.srch.fullIndex = (containsState ? False : True); /*flag*/
4037 /* set state of start button correctly */
4038 UpdateSearchStartStatusCB(NULL, (XtPointer) hw, NULL);
4041 { /* if changing to "Containing" */
4042 /* change focus to the search word */
4043 XmProcessTraversal(hw->help_dialog.srch.wordField,XmTRAVERSE_CURRENT);
4044 /* user will need to hit CR to initiate search */
4047 { /* if changing to full index */
4048 /* indicate that no contains word is valid by deleting it */
4049 /* FIX: I'm concerned that normWordStr & localeWordStr aren't in synch */
4050 XtFree(hw->help_dialog.srch.normWordStr);
4051 hw->help_dialog.srch.normWordStr = NULL;
4052 /* search full index */
4053 StartSearchCB(NULL,(XtPointer) hw, NULL);
4056 /* and search to update results to the new state */
4057 } /* if value changed */
4062 /*****************************************************************************
4063 * Function: void ContainsDisarmCB(Widget w,
4064 * XtPointer clientData,
4065 * XtPointer callData);
4071 * Return Value: Void.
4073 * Purpose: Process disarm of the contains radio button
4075 *****************************************************************************/
4076 static void ContainsDisarmCB(
4078 XtPointer clientData,
4081 XmToggleButtonCallbackStruct *status = (XmToggleButtonCallbackStruct *) callData;
4082 DtHelpDialogWidget hw = (DtHelpDialogWidget) clientData;
4084 /* Force focus to the word field if set. */
4085 if (True==status->set)
4086 XmProcessTraversal(hw->help_dialog.srch.wordField,XmTRAVERSE_CURRENT);
4091 /*****************************************************************************
4092 * Function: CreateCurVolBtnLabel()
4097 * Return Value: True or False if current vol has an index
4099 * Purpose: Creates the label for the current volume button
4101 *****************************************************************************/
4102 static Boolean CreateCurVolBtnLabel(
4103 DtHelpDialogWidget hw,
4104 Boolean * out_curVolAvailable,
4105 XmString * out_labelString,
4106 char * * out_mnemonic)
4111 XmString volTitleString = NULL;
4112 XmString preTitleString = NULL;
4113 XmString postTitleString = NULL;
4115 XmString labelString;
4117 Boolean curVolAvail;
4122 if (out_curVolAvailable)
4123 *out_curVolAvailable = False;
4124 if (out_labelString)
4125 *out_labelString = XmStringCreateLocalized("dum");
4131 /* if help content is a volume, get the title */
4132 if ( hw->help_dialog.display.helpType == DtHELP_TYPE_TOPIC )
4134 /* determine whether a current volume index is available */
4135 curVolAvail = VolumeHasIndexP(
4136 hw->help_dialog.srch.srchSources,
4137 hw->help_dialog.display.helpType,
4138 hw->help_dialog.display.helpVolume);
4140 /* change False to True to search home dir; may want this */
4141 path = _DtHelpFileLocate(DtHelpVOLUME_TYPE, hw->help_dialog.display.helpVolume,
4142 _DtHelpFileSuffixList,False,R_OK);
4144 /* title needs to be an XmString to use volume's font */
4147 XmFontList fontList = NULL;
4148 Boolean mod = False;
4150 /* get the font list of the btn */
4152 XtSetArg (args[n], XmNfontList, &fontList); n++;
4153 XtGetValues (hw->help_dialog.srch.curVolRadBtn, args, n);
4155 #if defined(DONT_USE_CDExc22774)
4156 /* copy the list before passing it in for modification */
4157 fontList = XmFontListCopy (fontList);
4160 GetVolumeInfoCB(hw->help_dialog.help.pDisplayArea,path,
4161 NULL,&volTitleString,NULL,NULL,NULL,&fontList,&mod);
4163 /* if font list was changed, install it */
4166 /* set the font list of the btn */
4168 XtSetArg (args[n], XmNfontList, fontList); n++;
4169 XtSetValues (hw->help_dialog.srch.curVolRadBtn, args, n);
4170 if (fontList) XmFontListFree (fontList);
4175 if (NULL == volTitleString)
4176 volTitleString = XmStringCreateLocalized(
4177 hw->help_dialog.display.helpVolume);
4178 } /* if helpType == TOPIC */
4180 { /* if helpType != TOPIC */
4181 curVolAvail = False;
4182 switch (hw->help_dialog.display.helpType)
4184 case DtHELP_TYPE_STRING:
4185 case DtHELP_TYPE_DYNAMIC_STRING:
4186 volTitleString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4187 (GSSET, 32,"Help Message")));
4189 case DtHELP_TYPE_FILE:
4190 volTitleString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4191 (GSSET, 33,"Help File")));
4193 case DtHELP_TYPE_MAN_PAGE:
4194 volTitleString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4195 (GSSET, 34,"Manual Page")));
4198 volTitleString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4199 (GSSET, 35,"Unknown Format")));
4201 } /* switch on helpType */
4202 } /* if helpType != TOPIC */
4204 /* record path in the widget */
4205 XtFree(hw->help_dialog.srch.curVolPath);
4206 hw->help_dialog.srch.curVolPath = path;
4209 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4210 (GSSET, 3,"Current")));
4211 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 4,"r"));*/
4214 /* append volume name to title */
4215 preTitle = (char *)_DTGETMESSAGE(GSSET, 60," (");
4216 preTitleString = XmStringCreateLocalized(preTitle);
4217 postTitle = (char *)_DTGETMESSAGE(GSSET, 61,")");
4218 postTitleString = XmStringCreateLocalized(postTitle);
4220 newTitle = XmStringConcat(labelString,preTitleString);
4221 XmStringFree(labelString);
4222 XmStringFree(preTitleString);
4223 labelString = newTitle;
4225 newTitle = XmStringConcat(labelString,volTitleString);
4226 XmStringFree(labelString);
4227 XmStringFree(volTitleString);
4228 labelString = newTitle;
4230 newTitle = XmStringConcat(labelString,postTitleString);
4231 XmStringFree(labelString);
4232 XmStringFree(postTitleString);
4233 labelString = newTitle;
4235 /* set the out values */
4236 if (out_curVolAvailable) *out_curVolAvailable = curVolAvail;
4237 if (out_mnemonic) *out_mnemonic = mnemonic;
4238 if (out_labelString) *out_labelString = labelString;
4239 else XmStringFree(labelString);
4247 /*****************************************************************************
4248 * Function: void CreateGlobSrchDialog()
4255 * Purpose: Creates and displays an instance of the search dialog.
4257 *****************************************************************************/
4258 static void CreateGlobSrchDialog(
4265 /* Widget topWidget; */
4266 Widget volumesFrame;
4271 XmString labelString;
4272 /* char * mnemonic; */
4273 Dimension widgetHeight;
4274 Dimension widgetBorderHeight;
4276 DtHelpListStruct *pHelpInfo;
4277 Atom wm_delete_window;
4278 DtHelpDialogWidget hw = (DtHelpDialogWidget) nw ;
4279 XtTranslations btnTransTable;
4280 /* XtTranslations listTransTable; */
4281 /* XtTranslations mgrTransTable; */
4282 Boolean curVolAvailable;
4286 /* get state of the volume */
4287 curVolAvailable = VolumeHasIndexP (
4288 hw->help_dialog.srch.srchSources,
4289 hw->help_dialog.display.helpType,
4290 hw->help_dialog.display.helpVolume);
4292 /* Set up the translations table stuff */
4293 btnTransTable = XtParseTranslationTable(defaultBtnTranslations);
4294 /* listTransTable = XtParseTranslationTable(defaultListTranslations); */
4295 /* mgrTransTable = XtParseTranslationTable(defaultMgrTranslations); */
4297 /* Create the shell used for the dialog. */
4298 title = XtNewString(((char *)_DTGETMESSAGE(GSSET,1,"Help - Index Search")));
4300 XtSetArg (args[n], XmNtitle, title); n++;
4301 XtSetArg (args[n], XmNallowShellResize, True); n++;
4302 srchShell = XmCreateDialogShell((Widget) hw, "searchShell", args, n);
4305 /* Set the useAsyncGeo on the shell */
4307 XtSetArg (args[n], XmNuseAsyncGeometry, True); n++;
4308 XtSetValues (XtParent(srchShell), args, n); /* parent is new's shell */
4310 /* Adjust the decorations for the dialog shell of the dialog */
4312 XtSetArg(args[n], XmNmwmFunctions, 0); n++;
4313 XtSetArg (args[n], XmNmwmDecorations,
4314 MWM_DECOR_BORDER | MWM_DECOR_TITLE); n++;
4315 XtSetValues (srchShell, args, n);
4318 /* Grab the window mgr close and install a close dialog
4319 callback when closed from dialog WM menu; this prevents
4320 the dialog from closing the host application. */
4321 wm_delete_window = XmInternAtom(XtDisplay(srchShell),
4322 "WM_DELETE_WINDOW", FALSE);
4323 XtSetArg(args[0], XmNdeleteResponse, XmDO_NOTHING);
4324 XmAddWMProtocolCallback(srchShell,wm_delete_window,
4325 CloseSearchCB, (XtPointer)&hw->help_dialog.srch);
4326 XtSetValues(srchShell, args, 1);
4328 /* set the callback that positions the dialog when popped up */
4329 XtAddCallback (srchShell, XmNpopupCallback,
4330 (XtCallbackProc)_DtHelpMapCB, (XtPointer) XtParent(hw));
4332 /*** Create the form used for the dialog. ***/
4333 /* setting RESIZE_NONE is important to prevent the resultList from
4334 dynamically resizing as items with various fonts are added and
4337 XtSetArg (args[n], XmNmarginWidth, 1); n++;
4338 XtSetArg (args[n], XmNmarginHeight, 1); n++;
4339 XtSetArg (args[n], XmNshadowThickness, 1); n++;
4340 XtSetArg (args[n], XmNshadowType, XmSHADOW_OUT); n++;
4341 XtSetArg (args[n], XmNautoUnmanage, False); n++;
4342 XtSetArg (args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
4343 parentForm = XmCreateForm (srchShell, "parentForm", args, n);
4344 hw->help_dialog.srch.srchForm = parentForm;
4346 /*==============================================================*/
4347 /****** Create the volumes region ******/
4349 XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
4350 XtSetArg (args[n], XmNtopOffset, 5); n++;
4351 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4352 XtSetArg (args[n], XmNrightOffset, 5); n++;
4353 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4354 XtSetArg (args[n], XmNleftOffset, 5); n++;
4355 XtSetArg (args[n], XmNmarginWidth, 5); n++;
4356 XtSetArg (args[n], XmNmarginHeight, 2); n++;
4357 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;/*EXP*/
4358 volumesFrame = XmCreateFrame(parentForm, "volFrame", args, n);
4359 XtManageChild (volumesFrame);
4361 /* put form inside frame */
4362 volumesForm = XmCreateForm (volumesFrame, "volumesForm", args, 0);
4363 XtManageChild (volumesForm);
4365 /* create the frame title */
4366 labelString = XmStringCreateLocalized ((_DTGETMESSAGE(GSSET,2, "Search")));
4368 XtSetArg (args[n], XmNlabelString, labelString); n++;
4369 XtSetArg (args[n], XmNchildType, XmFRAME_TITLE_CHILD); n++;
4370 XtSetArg (args[n], XmNtraversalOn, False); n++;
4371 frameTitle = XmCreateLabelGadget(volumesFrame, "volFrameTitle", args, n);
4372 XtManageChild (frameTitle);
4373 XmStringFree (labelString);
4375 /* create Current Volume radio button */
4376 /* Use a dummy label until CreateCurVolBtnLabel can be used.
4377 It refs the srchCurVolRadBtn widget and other things that need
4380 labelString = XmStringCreateLocalized (" ");
4382 XtSetArg (args[n], XmNindicatorType, XmONE_OF_MANY); n++;
4383 XtSetArg (args[n], XmNset, TRUE); n++;
4385 XtSetArg(args[n], XmNlabelString, labelString); n++;
4386 XtSetArg (args[n], XmNmarginHeight, 0); n++;
4387 XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
4388 XtSetArg (args[n], XmNtopOffset, 0); n++;
4389 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4390 XtSetArg (args[n], XmNleftOffset, 5); n++;
4391 /* Attaching to form causes the hilite outline of the button to
4392 stretch to the form edge when selected. But it also forces
4393 the form to resize when the current volume title is too big
4394 for the available space. */
4395 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4396 XtSetArg (args[n], XmNrightOffset, 10); n++;
4397 XtSetArg (args[n], XmNbottomOffset, 0); n++;
4398 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
4399 XtSetArg (args[n], XmNhighlightOnEnter, True); n++;
4400 hw->help_dialog.srch.curVolRadBtn =
4401 XmCreateToggleButtonGadget(volumesForm,"srchCurVolRadBtn",args,n);
4402 XtAddCallback(hw->help_dialog.srch.curVolRadBtn,XmNvalueChangedCallback,
4403 UpdateSearchVolumesCB, (XtPointer) hw);
4404 /* ??? XtSetSensitive (hw->help_dialog.srch.curVolRadBtn,False); */
4405 XtManageChild (hw->help_dialog.srch.curVolRadBtn);
4406 XmStringFree (labelString);
4408 /* create All Volumes radio button */
4409 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4410 (GSSET, 5,"All Volumes")));
4411 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 7,"A"));*/
4414 XtSetArg (args[n], XmNindicatorType, XmONE_OF_MANY); n++;
4415 XtSetArg (args[n], XmNset, FALSE); n++;
4416 XtSetArg (args[n], XmNlabelString, labelString); n++;
4417 XtSetArg (args[n], XmNmarginHeight, 0); n++;
4418 XtSetArg (args[n], XmNmarginWidth, 2); n++;
4419 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4420 XtSetArg (args[n], XmNtopWidget, hw->help_dialog.srch.curVolRadBtn); n++;
4421 XtSetArg (args[n], XmNtopOffset, 1); n++;
4422 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4423 XtSetArg (args[n], XmNleftOffset, 5); n++;
4424 XtSetArg(args[n], XmNhighlightOnEnter, True); n++;
4425 hw->help_dialog.srch.allVolRadBtn =
4426 XmCreateToggleButtonGadget(volumesForm,"srchAllVolRadBtn",args, n);
4427 XtAddCallback(hw->help_dialog.srch.allVolRadBtn,XmNvalueChangedCallback,
4428 UpdateSearchVolumesCB, (XtPointer) hw);
4429 XtManageChild (hw->help_dialog.srch.allVolRadBtn);
4430 XmStringFree (labelString);
4432 /* create Selected Volumes radio button */
4433 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4434 (GSSET, 6,"Selected")));
4435 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 9,"d"));*/
4438 XtSetArg (args[n], XmNindicatorType, XmONE_OF_MANY); n++;
4439 XtSetArg (args[n], XmNlabelString, labelString); n++;
4440 XtSetArg (args[n], XmNmarginHeight, 0); n++;
4441 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4442 XtSetArg (args[n], XmNtopWidget, hw->help_dialog.srch.allVolRadBtn); n++;
4443 XtSetArg (args[n], XmNtopOffset, 1); n++;
4444 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4445 XtSetArg (args[n], XmNleftOffset, 5); n++;
4446 XtSetArg (args[n], XmNbottomOffset, 2); n++;
4447 XtSetArg(args[n], XmNhighlightOnEnter, True); n++;
4448 hw->help_dialog.srch.selVolRadBtn =
4449 XmCreateToggleButtonGadget(volumesForm,"srchSelVolRadBtn", args, n);
4450 XtAddCallback(hw->help_dialog.srch.selVolRadBtn,XmNvalueChangedCallback,
4451 UpdateSearchVolumesCB, (XtPointer) hw);
4452 XtManageChild (hw->help_dialog.srch.selVolRadBtn);
4453 XmStringFree (labelString);
4456 /* Create Selected... button */
4457 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4458 (GSSET, 7,"Select Volumes...")));
4461 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4462 XtSetArg (args[n], XmNtopOffset, 0); n++;
4463 XtSetArg (args[n], XmNtopWidget, hw->help_dialog.srch.allVolRadBtn); n++;
4464 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4465 XtSetArg (args[n], XmNrightOffset, 10); n++;
4466 XtSetArg (args[n], XmNbottomOffset, 2); n++;
4467 XtSetArg (args[n], XmNmarginTop, 0); n++;
4468 XtSetArg (args[n], XmNmarginHeight, 3); n++;
4469 XtSetArg (args[n], XmNlabelString, labelString); n++;
4470 hw->help_dialog.srch.selectBtn =
4471 XmCreatePushButtonGadget(volumesForm,"selectBtn", args, n);
4472 XtAddCallback (hw->help_dialog.srch.selectBtn, XmNactivateCallback,
4473 OpenSelectDialogCB, (XtPointer) hw);
4474 XtManageChild (hw->help_dialog.srch.selectBtn);
4475 XtSetSensitive (hw->help_dialog.srch.selectBtn,False);
4476 XmStringFree (labelString);
4478 /****** Create the show selection region ******/
4480 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4481 XtSetArg (args[n], XmNtopWidget, volumesFrame); n++;
4482 XtSetArg (args[n], XmNtopOffset, 5); n++;
4483 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4484 XtSetArg (args[n], XmNrightOffset, 5); n++;
4485 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4486 XtSetArg (args[n], XmNleftOffset, 5); n++;
4487 XtSetArg (args[n], XmNmarginWidth, 5); n++;
4488 XtSetArg (args[n], XmNmarginHeight, 2); n++;
4489 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;/*EXP*/
4490 showFrame = XmCreateFrame(parentForm, "showFrame", args, n);
4491 XtManageChild (showFrame);
4493 /* FIX: is this doing enough? Goal: CR activation of FullIndex */
4494 /* Setup the proper translation on the title box widget */
4495 /* XtAugmentTranslations(showFrame, mgrTransTable); */
4497 /* put form inside frame */
4498 showForm = XmCreateForm (showFrame, "showForm", args, 0);
4499 XtManageChild (showForm);
4501 /* create the frame title */
4502 labelString = XmStringCreateLocalized ((_DTGETMESSAGE(GSSET,8, "Show")));
4504 XtSetArg (args[n], XmNlabelString, labelString); n++;
4505 XtSetArg (args[n], XmNtraversalOn, False); n++;
4506 XtSetArg (args[n], XmNchildType, XmFRAME_TITLE_CHILD); n++;
4507 frameTitle = XmCreateLabelGadget(showFrame, "showFrameTitle", args, n);
4508 XtManageChild (frameTitle);
4509 XmStringFree (labelString);
4511 /* create the All Entries button */
4512 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4513 (GSSET, 9,"Complete Index")));
4516 XtSetArg (args[n], XmNindicatorType, XmONE_OF_MANY); n++;
4517 XtSetArg (args[n], XmNset, True); n++;
4518 XtSetArg (args[n], XmNlabelString, labelString); n++;
4519 XtSetArg (args[n], XmNmarginHeight, 1); n++;
4520 XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
4521 XtSetArg (args[n], XmNtopOffset, 0); n++;
4522 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4523 XtSetArg (args[n], XmNleftOffset, 5); n++;
4524 XtSetArg (args[n], XmNbottomOffset, 0); n++;
4525 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
4526 XtSetArg (args[n], XmNhighlightOnEnter, True); n++;
4527 hw->help_dialog.srch.fullIndexRadBtn =
4528 XmCreateToggleButtonGadget(showForm,"srchFullIndexRadBtn",args,n);
4529 XtAddCallback(hw->help_dialog.srch.fullIndexRadBtn,XmNvalueChangedCallback,
4530 UpdateIndexSelectionCB, (XtPointer) hw);
4531 XtManageChild (hw->help_dialog.srch.fullIndexRadBtn);
4532 XmStringFree (labelString);
4534 /* create Contains radio button */
4535 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4536 (GSSET, 10,"Entries with:")));
4537 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 16,"n"));*/
4540 XtSetArg (args[n], XmNindicatorType, XmONE_OF_MANY); n++;
4541 XtSetArg (args[n], XmNset, False); n++;
4542 XtSetArg (args[n], XmNlabelString, labelString); n++;
4543 XtSetArg (args[n], XmNmarginHeight, 1); n++;
4544 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4545 XtSetArg (args[n], XmNtopWidget,hw->help_dialog.srch.fullIndexRadBtn);n++;
4546 XtSetArg (args[n], XmNtopOffset, 1); n++;
4547 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4548 XtSetArg (args[n], XmNleftOffset, 5); n++;
4549 XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
4550 XtSetArg (args[n], XmNbottomOffset, 4); n++;
4551 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
4552 XtSetArg (args[n], XmNhighlightOnEnter, True); n++;
4553 hw->help_dialog.srch.containsRadBtn =
4554 XmCreateToggleButtonGadget(showForm,"srchContainsRadBtn",args,n);
4555 XtAddCallback(hw->help_dialog.srch.containsRadBtn,XmNvalueChangedCallback,
4556 UpdateIndexSelectionCB, (XtPointer) hw);
4557 XtAddCallback(hw->help_dialog.srch.containsRadBtn,XmNdisarmCallback,
4558 ContainsDisarmCB, (XtPointer) hw);
4559 XtManageChild (hw->help_dialog.srch.containsRadBtn);
4560 XmStringFree (labelString);
4562 /* create the search name text field */
4564 XtSetArg (args[n], XmNvalue, ""); n++;
4565 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4566 XtSetArg (args[n], XmNtopWidget,hw->help_dialog.srch.fullIndexRadBtn); n++;
4567 XtSetArg (args[n], XmNtopOffset, 0); n++;
4568 XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
4569 XtSetArg (args[n], XmNleftWidget,hw->help_dialog.srch.containsRadBtn); n++;
4570 XtSetArg (args[n], XmNleftOffset, 5); n++;
4571 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4572 XtSetArg (args[n], XmNrightOffset, 10); n++;
4573 XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
4574 XtSetArg (args[n], XmNbottomOffset, 3); n++;
4575 XtSetArg (args[n], XmNhighlightOnEnter, True); n++;
4576 XtSetArg (args[n], XmNcursorPositionVisible, False); n++;
4577 hw->help_dialog.srch.wordField =
4578 XmCreateTextField (showForm,"srchWord",args, n);
4579 XtSetSensitive(hw->help_dialog.srch.wordField,False);
4580 XtManageChild (hw->help_dialog.srch.wordField);
4581 /* Because the actionBtn is the default button on the form,
4582 and it activates a search, we do not need to (nor do we want
4583 to, since ActionButtonCB toggles between states) make it
4584 a callback on activation of the text field */
4585 XtAddCallback (hw->help_dialog.srch.wordField, XmNvalueChangedCallback,
4586 UpdateSearchStartStatusCB, (XtPointer) hw);
4588 /* Setup the proper translation on the text field widget */
4589 XtAugmentTranslations(hw->help_dialog.srch.wordField, btnTransTable);
4592 /* Create a separator search specs and result area */
4594 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4595 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4596 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4597 XtSetArg (args[n], XmNtopWidget, showFrame); n++;
4598 XtSetArg (args[n], XmNtopOffset, 10); n++;
4599 separator = XmCreateSeparatorGadget (parentForm, "separator", args, n);
4600 XtManageChild (separator);
4602 /*==============================================================*/
4603 /****** result related stuff *******/
4604 /* Create result List Label */
4606 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4607 XtSetArg (args[n], XmNtopWidget, separator); n++;
4608 XtSetArg (args[n], XmNtopOffset, 10); n++;
4609 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4610 XtSetArg (args[n], XmNleftOffset, 10); n++;
4611 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4612 XtSetArg (args[n], XmNrightOffset, 10); n++;
4613 XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
4614 hw->help_dialog.srch.statusLabel =
4615 XmCreateLabelGadget (parentForm, "resultListLabel", args, n);
4616 StatusLabelUpdate(hw,FIRST_PROMPT_STATUS,True,0); /* installs a label */
4617 XtManageChild (hw->help_dialog.srch.statusLabel);
4619 /* Create our result topics scrolled list (not placed on form) */
4621 XtSetArg (args[n], XmNlistSizePolicy, XmCONSTANT); n++;
4622 XtSetArg (args[n], XmNselectionPolicy, XmSINGLE_SELECT); n++;
4623 XtSetArg (args[n], XmNhighlightOnEnter, True); n++;
4624 XtSetArg (args[n], XmNscrollBarDisplayPolicy, XmSTATIC); n++;
4625 hw->help_dialog.srch.resultList =
4626 XmCreateScrolledList (parentForm, "resultList", args, n);
4627 XtManageChild (hw->help_dialog.srch.resultList);
4629 XtAddCallback (hw->help_dialog.srch.resultList, XmNsingleSelectionCallback,
4630 ProcessResultSelectionCB, (XtPointer) hw);
4631 XtAddCallback (hw->help_dialog.srch.resultList, XmNdefaultActionCallback,
4632 ProcessResultSelectionCB, (XtPointer) hw);
4634 /* Set the constraints on our scrolled list (place on form) */
4636 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4637 XtSetArg (args[n], XmNtopWidget, hw->help_dialog.srch.statusLabel); n++;
4638 XtSetArg (args[n], XmNtopOffset, 5); n++;
4639 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4640 XtSetArg (args[n], XmNleftOffset, 10); n++;
4641 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4642 XtSetArg (args[n], XmNrightOffset, 10); n++;
4643 XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
4644 XtSetArg (args[n], XmNbottomOffset, 70); n++;
4645 /* 70 is just a rough value that will be updated with a calculated
4646 value below, after we know the height of the buttons */
4647 XtSetValues (XtParent (hw->help_dialog.srch.resultList), args, n);
4649 /* Create a separator between the buttons */
4651 XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
4652 XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
4653 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4654 XtSetArg (args[n], XmNtopWidget,
4655 XtParent (hw->help_dialog.srch.resultList)); n++;
4656 XtSetArg (args[n], XmNtopOffset, 5); n++;
4657 separator = XmCreateSeparatorGadget (parentForm, "separator", args, n);
4658 XtManageChild (separator);
4660 /***** search spec-related stuff *****/
4661 /* Create start button (left of stop button)*/
4662 _DtHelpProcessLock();
4663 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4664 (GSSET, START_SEARCH_CAT,START_SEARCH_STR)));
4665 _DtHelpProcessUnlock();
4666 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 20,START_SEARCH_MNEM));*/
4669 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4670 XtSetArg (args[n], XmNtopWidget, separator); n++;
4671 XtSetArg (args[n], XmNtopOffset, 5); n++;
4672 /* L & R position set below */
4673 XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
4674 XtSetArg (args[n], XmNbottomOffset, 5); n++;
4675 /*XtSetArg (args[n], XmNmarginHeight, 3); n++;*/
4676 XtSetArg (args[n], XmNlabelString, labelString); n++;
4677 XtSetArg(args[n], XmNhighlightOnEnter, True); n++;
4678 hw->help_dialog.srch.actionBtn =
4679 XmCreatePushButtonGadget(parentForm,"actionBtn", args, n);
4680 XtAddCallback (hw->help_dialog.srch.actionBtn, XmNactivateCallback,
4681 ActionButtonCB, (XtPointer) hw);
4682 XtSetSensitive (hw->help_dialog.srch.actionBtn,False);
4683 XtManageChild (hw->help_dialog.srch.actionBtn);
4684 XmStringFree (labelString);
4686 XtSetArg (args[0], XmNdefaultButton, hw->help_dialog.srch.actionBtn);
4687 XtSetValues (parentForm, args, 1);
4689 /* Build the Cancel Button */
4690 _DtHelpProcessLock();
4691 labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
4692 (GSSET, CLOSE_BTN_CAT,CLOSE_BTN_STR)));
4693 _DtHelpProcessUnlock();
4694 /*mnemonic = ((char *)_DTGETMESSAGE(GSSET, 25,CLOSE_BTN_MNEM));*/
4696 XtSetArg (args[n], XmNlabelString, labelString); n++;
4697 /* L & R position set below */
4698 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4699 XtSetArg (args[n], XmNtopWidget, separator); n++;
4700 XtSetArg (args[n], XmNtopOffset, 5); n++;
4701 XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
4702 XtSetArg (args[n], XmNbottomOffset, 5); n++;
4703 XtSetArg (args[n], XmNmarginHeight, 3); n++;
4704 XtSetArg(args[n], XmNhighlightOnEnter, True); n++;
4705 hw->help_dialog.srch.closeBtn =
4706 XmCreatePushButtonGadget (parentForm, "srchCloseBtn", args, n);
4708 XtAddCallback(hw->help_dialog.srch.closeBtn,
4709 XmNactivateCallback, CloseSearchCB,(XtPointer) &hw->help_dialog.srch);
4711 XtManageChild (hw->help_dialog.srch.closeBtn);
4712 XmStringFree (labelString);
4714 /* Build the Help button */
4715 _DtHelpProcessLock();
4716 labelString = XmStringCreateLocalized((char *)_DTGETMESSAGE
4717 (GSSET, HELP_BTN_CAT,HELP_BTN_STR));
4718 _DtHelpProcessUnlock();
4719 /*mnemonic = (char *)_DTGETMESSAGE(GSSET, 27,HELP_BTN_MNEM);*/
4722 XtSetArg (args[n], XmNlabelString, labelString); n++;
4723 /* L & R position set below */
4724 XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
4725 XtSetArg (args[n], XmNtopWidget, separator); n++;
4726 XtSetArg (args[n], XmNtopOffset, 5); n++;
4727 XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
4728 XtSetArg (args[n], XmNbottomOffset, 5); n++;
4729 XtSetArg (args[n], XmNmarginHeight, 3); n++;
4730 XtSetArg(args[n], XmNhighlightOnEnter, True); n++;
4731 hw->help_dialog.srch.helpBtn =
4732 XmCreatePushButtonGadget (parentForm, "srchHelpBtn", args, n);
4733 XtManageChild (hw->help_dialog.srch.helpBtn);
4734 XmStringFree (labelString);
4736 pHelpInfo = _DtHelpListAdd(DtHELP_srchIndexHelpBtn_STR,
4737 (Widget) hw, &hw->help_dialog.help,
4738 &hw->help_dialog.help.pHelpListHead);
4739 XtAddCallback(hw->help_dialog.srch.helpBtn, XmNactivateCallback,
4740 _DtHelpCB, (XtPointer) pHelpInfo);
4742 /*==============================================================*/
4743 /****** finishing touches *******/
4744 /* set the Form cancel button (for KCancel) */
4746 XtSetArg (args[n], XmNcancelButton, hw->help_dialog.srch.closeBtn); n++;
4747 XtSetValues (parentForm, args, n);
4749 { /* position buttons */
4750 /* This code adds up the sizes of the buttons to go into
4751 the bottom row and calculates the form position percentages.
4752 All buttons are the same size, and are able to hold all
4753 the strings that may be dynamically placed in them.
4754 All buttons are 5% apart. */
4755 /* This code is specifically written to handle 3 buttons
4756 and assumes that the first 3 strings are to the ActionBtn */
4758 Dimension maxWidth = 0;
4759 Dimension borderWidth = 0;
4760 Dimension sumWidth = 0;
4762 float posList[11]; /* need 11 due to algorithm, which uses index 10 */
4763 XmFontList fontList = NULL;
4766 /* get the fontList for the button */
4767 XtSetArg (args[0], XmNborderWidth, &borderWidth);
4768 XtSetArg (args[1], XmNfontList, &fontList);
4769 XtGetValues (hw->help_dialog.srch.actionBtn, args, 2);
4771 #define BETBUTSPACE 5 /* pixels */
4772 sumWidth = BETBUTSPACE; /* left side space */
4773 posList[0] = (float) sumWidth;
4774 for (i=0; i<NUMSTRS; i++)
4776 XmString labelString;
4778 _DtHelpProcessLock();
4779 s_GlobSrchDlgBtnStrs[i] = (char *) _DTGETMESSAGE(GSSET,
4780 s_GlobSrchDlgBtnCatNum[i],s_GlobSrchDlgBtnStrs[i]);
4781 labelString = XmStringCreateLocalized(s_GlobSrchDlgBtnStrs[i]);
4782 _DtHelpProcessUnlock();
4783 #define MARGINS 4 /* pixel margins: 2=L, 2=R */
4784 width = XmStringWidth(fontList,labelString) + borderWidth + MARGINS;
4785 if (i<=2) maxWidth = max(width,maxWidth);
4786 if (i==2) width = maxWidth; /* 1st three labels go in 1st button */
4787 if (i>=2) /* after scanning just labels, do buttons */
4790 posList[i*2+1] = (float) sumWidth;
4791 sumWidth += BETBUTSPACE;
4792 posList[i*2+2] = (float) sumWidth;
4794 XmStringFree(labelString);
4795 } /* for calcing widths */
4797 /* scale pixels to percent */
4798 scale = 100.0 / (float) sumWidth;
4801 XtSetArg (args[n], XmNwidth, maxWidth); n++;
4802 XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
4803 XtSetArg (args[n], XmNleftPosition, (Dimension) (posList[0]*scale)); n++;
4804 XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
4805 XtSetArg (args[n], XmNrightPosition,(Dimension) (posList[5]*scale)); n++;
4806 XtSetValues (hw->help_dialog.srch.actionBtn, args, n);
4809 XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
4810 XtSetArg (args[n], XmNleftPosition, (Dimension) (posList[6]*scale)); n++;
4811 XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
4812 XtSetArg (args[n], XmNrightPosition,(Dimension) (posList[7]*scale)); n++;
4813 XtSetValues (hw->help_dialog.srch.closeBtn, args, n);
4816 XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
4817 XtSetArg (args[n], XmNleftPosition, (Dimension) (posList[8]*scale)); n++;
4818 XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
4819 XtSetArg (args[n], XmNrightPosition,(Dimension) (posList[9]*scale)); n++;
4820 XtSetValues (hw->help_dialog.srch.helpBtn, args, n);
4823 { /* set the proper offset between the bottom of the results list
4824 and the bottom of the form to maintain a constant sized
4828 /* first calc offset of list to form bottom based on earlier sizes */
4829 #define KNOWN_OFFSETS_BELOW_LIST 20 /* actually only 15, but 15 fails */
4831 XtSetArg(args[n], XmNborderWidth, &widgetBorderHeight); n++;
4832 XtSetArg(args[n], XmNheight, &widgetHeight); n++;
4833 XtGetValues(hw->help_dialog.srch.actionBtn, args, n);
4834 offset = widgetHeight + 2 * widgetBorderHeight;
4835 XtGetValues(separator, args, n);
4836 offset += widgetHeight + 2 * widgetBorderHeight;
4837 XtGetValues(XtParent(hw->help_dialog.srch.resultList), args, 1);
4838 offset += widgetBorderHeight;
4839 offset += KNOWN_OFFSETS_BELOW_LIST;
4841 /* then set the offset */
4843 XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
4844 XtSetArg (args[n], XmNbottomOffset, offset); n++;
4845 XtSetValues (XtParent (hw->help_dialog.srch.resultList), args, n);
4848 /** force tabs to go to each widget and in right order **/
4849 XtSetArg (args[0], XmNnavigationType, XmSTICKY_TAB_GROUP);
4850 XtSetValues (hw->help_dialog.srch.curVolRadBtn,args,1);
4851 XtSetValues (hw->help_dialog.srch.allVolRadBtn,args,1);
4852 XtSetValues (hw->help_dialog.srch.selVolRadBtn,args,1);
4853 XtSetValues (hw->help_dialog.srch.selectBtn,args,1);
4854 XtSetValues (hw->help_dialog.srch.fullIndexRadBtn,args,1);
4855 XtSetValues (hw->help_dialog.srch.containsRadBtn,args,1);
4856 XtSetValues (hw->help_dialog.srch.wordField,args,1);
4857 XtSetValues (hw->help_dialog.srch.resultList,args,1);
4858 XtSetValues (hw->help_dialog.srch.actionBtn,args,1);
4859 XtSetValues (hw->help_dialog.srch.closeBtn,args,1);
4860 XtSetValues (hw->help_dialog.srch.helpBtn,args,1);
4862 /** put focus on the text field **/
4863 XtSetArg (args[0], XmNinitialFocus, hw->help_dialog.srch.wordField);
4864 XtSetValues (parentForm,args,1);
4866 /* Add the proper help callback to the print dialog shell "F1" support */
4867 pHelpInfo = _DtHelpListAdd(DtHELP_srchIndexShell_STR,
4868 (Widget) hw, &hw->help_dialog.help,
4869 &hw->help_dialog.help.pHelpListHead);
4870 XtAddCallback(parentForm, XmNhelpCallback,
4871 _DtHelpCB, (XtPointer) pHelpInfo);
4875 /*****************************************************************************
4876 * Function: updateDisplay()
4879 * Parameters: hw: the help widget
4883 * Purpose: forces an update on index search dialog widgets
4885 *****************************************************************************/
4886 static int updateDisplay(
4887 DtHelpDialogWidget hw)
4889 XmUpdateDisplay((Widget)hw->help_dialog.srch.actionBtn);/*DBG*/
4890 XmUpdateDisplay((Widget)hw->help_dialog.srch.curVolRadBtn);/*DBG*/
4891 XmUpdateDisplay((Widget)hw->help_dialog.srch.allVolRadBtn);/*DBG*/
4892 XmUpdateDisplay((Widget)hw->help_dialog.srch.selVolRadBtn);/*DBG*/
4893 XmUpdateDisplay((Widget)hw->help_dialog.srch.selectBtn);/*DBG*/
4894 XmUpdateDisplay((Widget)hw->help_dialog.srch.fullIndexRadBtn);/*DBG*/
4895 XmUpdateDisplay((Widget)hw->help_dialog.srch.containsRadBtn);/*DBG*/
4896 XmUpdateDisplay((Widget)hw->help_dialog.srch.wordField);/*DBG*/
4897 XmUpdateDisplay((Widget)hw->help_dialog.srch.statusLabel);/*DBG*/
4898 XmUpdateDisplay((Widget)hw->help_dialog.srch.resultList);/*DBG*/
4899 XmUpdateDisplay((Widget)hw->help_dialog.srch.closeBtn);/*DBG*/
4900 XmUpdateDisplay((Widget)hw->help_dialog.srch.helpBtn);/*DBG*/
4901 XmUpdateDisplay(XtParent((Widget)hw->help_dialog.srch.srchForm));/*DBG*/
4907 /*****************************************************************************
4908 * Function: void _DtHelpGlobSrchDisplayDialog()
4911 * Parameters: parent Specifies the parent widget
4912 * searchWord word to put into searchWord field
4913 * remove this when integrated into DtHelp:
4914 * curVolume volume considered the current volume
4918 * Purpose: Setsup the proper data in the search dialog and
4919 * displays an instance of the search dialog.
4921 *****************************************************************************/
4922 void _DtHelpGlobSrchDisplayDialog(
4927 DtHelpDialogWidget hw = (DtHelpDialogWidget) w;
4928 XmToggleButtonCallbackStruct status; /* the call data */
4929 Widget sourceBtn; /* widget owning event */
4935 XmString labelString = NULL;
4938 /* make the dialog itself */
4939 if (NULL == hw->help_dialog.srch.srchForm)
4941 CreateGlobSrchDialog((Widget) hw,searchWord);
4943 /* create the button label */
4944 CreateCurVolBtnLabel(hw, NULL, &labelString, NULL);
4945 XtSetArg (args[0], XmNlabelString, labelString);
4946 XtSetValues (hw->help_dialog.srch.curVolRadBtn, args, 1);
4947 XmStringFree (labelString);
4949 /*** map widget and update display before doing any searching ***/
4950 /* Make sure the Search Dialog is managed */
4951 XtManageChild(hw->help_dialog.srch.srchForm);
4952 XtMapWidget(hw->help_dialog.srch.srchForm);
4954 /* set focus to contains word */
4955 XmProcessTraversal(hw->help_dialog.srch.wordField,XmTRAVERSE_CURRENT);
4957 /* force several updates to make sure it is fully displayed and
4958 that height/width are correctly inited */
4959 XmUpdateDisplay(XtParent((Widget)hw->help_dialog.srch.srchForm));
4960 XmUpdateDisplay(XtParent((Widget)hw->help_dialog.srch.srchForm));
4961 XmUpdateDisplay(XtParent((Widget)hw->help_dialog.srch.srchForm));
4963 /*** now update settings, which may also invoke a search ***/
4964 /* set the cur vol btn sensitivity */
4965 UpdateCurVolBtnSens(hw,True);
4967 /* set default show index state */
4968 /* set full index if current vol has an index, contains word if not */
4969 if (hw->help_dialog.srch.curVolRadBtnSens) /* set in UpdateCurVolBtnSens*/
4970 sourceBtn = hw->help_dialog.srch.fullIndexRadBtn;
4972 sourceBtn = hw->help_dialog.srch.containsRadBtn;
4974 /* set the show index state */
4975 status.reason = XmCR_VALUE_CHANGED;
4977 status.event = (XEvent *) 1; /* thwart == NULL test in Update...() */
4978 UpdateIndexSelectionCB(sourceBtn,(XtPointer)hw,(XtPointer)&status);
4979 StatusLabelUpdate(hw,FIRST_PROMPT_STATUS,False,0);
4981 updateDisplay(hw); /* DBG */
4983 #if 0 /* 11/23/94 */
4984 /** Set min size for the dialog **/
4986 XtSetArg(args[n], XmNheight, &height); ++n;
4987 XtSetArg(args[n], XmNwidth, &width); ++n;
4988 XtGetValues(XtParent((Widget)hw->help_dialog.srch.srchForm), args, n);
4990 XtSetArg(args[n], XmNminHeight, height - 200); ++n; /* 200: arbitrary */
4991 XtSetArg(args[n], XmNminWidth, width); ++n;
4992 XtSetValues(XtParent((Widget)hw->help_dialog.srch.srchForm), args, n);
4995 else /* properly update dialog to support new word and cur vol */
4997 /* fixup current volume, if need be */
4998 _DtHelpGlobSrchUpdateCurVol((Widget)hw);
5000 /* fixup search word, if need be */
5001 if (NULL != searchWord)
5003 String srchWord = XtNewString(searchWord);
5004 /* srchWord is freed or used in CheckSearchWord() */
5005 if (CheckSearchWord(hw,srchWord,True) == True)
5006 { /* words are different */
5007 /* free all hit-related data and reset flags */
5008 HitListFreeAllVolHits(hw,True); /*True=free everything*/
5012 /* if its not managed, manage it */
5013 if ( XtIsManaged(hw->help_dialog.srch.srchForm) == False )
5015 /* manage and map the Search Dialog */
5016 XtManageChild(hw->help_dialog.srch.srchForm);
5017 XtMapWidget((Widget)hw->help_dialog.srch.srchForm);
5019 /* see if the selection dialog was already open */
5020 if ( hw->help_dialog.srch.selectionDlg
5021 && XtIsManaged(hw->help_dialog.srch.selectionDlg) )
5023 XtManageChild(hw->help_dialog.srch.selectionDlg);
5024 XtMapWidget(hw->help_dialog.srch.selectionDlg);
5027 else /* if it is managed, bring it forward */
5029 Widget parent = XtParent(hw->help_dialog.srch.srchForm);
5030 XRaiseWindow ( XtDisplay(parent), XtWindow(parent) );
5035 if (hw->help_dialog.srch.hitsFound == True)
5036 XmProcessTraversal(hw->help_dialog.srch.resultList,XmTRAVERSE_CURRENT);
5038 XmProcessTraversal(hw->help_dialog.srch.allVolRadBtn,XmTRAVERSE_CURRENT);
5042 } /* end if create a new dialog */
5047 /*****************************************************************************
5048 * Function: void _DtHelpGlobSrchUpdateCurVol()
5050 * Parameters: new the help widget
5054 * Purpose: Adjusts the current volume of the dialog
5056 *****************************************************************************/
5057 void _DtHelpGlobSrchUpdateCurVol(
5061 DtHelpDialogWidget hw = (DtHelpDialogWidget) w;
5064 if ( NULL == hw->help_dialog.srch.srchForm )
5066 if ( NULL == hw->help_dialog.srch.srchForm
5067 || XtIsManaged(hw->help_dialog.srch.srchForm) == False )
5069 return; /* RETURN */
5071 /* get full pathname for the volume */
5073 if (hw->help_dialog.display.helpVolume)
5074 path = _DtHelpFileLocate(DtHelpVOLUME_TYPE,
5075 /* FIX: will helpVolume have matching path? */
5076 hw->help_dialog.display.helpVolume,
5077 _DtHelpFileSuffixList,False,R_OK);
5079 if ( _DtHelpGlobSrchCurVolume == hw->help_dialog.srch.srchSources
5080 && hw->help_dialog.display.helpType == DtHELP_TYPE_TOPIC
5082 && NULL != hw->help_dialog.srch.curVolPath
5083 && _DtHelpFileIsSameP(path,hw->help_dialog.srch.curVolPath,
5084 GetVolumeInfoCB, _DtHELP_FILE_NAME,
5085 hw->help_dialog.help.pDisplayArea) )
5087 /* leave current status as is */
5089 return; /* RETURN */
5093 /* a different current volume or change of topic */
5095 XmString labelString;
5098 /* if still searching previous cur volume, stop any search in progress */
5099 if ( _DtHelpGlobSrchCurVolume == hw->help_dialog.srch.srchSources
5100 && hw->help_dialog.srch.workProcId)
5102 /* cancel the search */
5103 StopSearchCB(NULL,(XtPointer) hw, NULL);
5105 /* (F,F,F,F): disable search,disable display,no 0 hits,for all vols */
5106 SetVolStatus(hw->help_dialog.srch.volListHead,False,False,False,False);
5108 /* zero search data */
5109 hw->help_dialog.srch.volLeftCnt = 0;
5110 hw->help_dialog.srch.curSrchVol = NULL;
5112 /* assumption is, that even though the search was incomplete,
5113 nothing bad will happen if we don't free the hit data,
5114 and the search could resume where left off, if necessary. */
5117 CreateCurVolBtnLabel(hw, NULL, &labelString, NULL);
5118 XtSetArg(args[0],XmNlabelString,labelString);
5119 XtSetValues(hw->help_dialog.srch.curVolRadBtn,args,1);
5120 XmStringFree(labelString);
5122 /* set the cur vol btn sensitivity */
5123 UpdateCurVolBtnSens(hw,False);
5125 /* set state of start button correctly */
5126 UpdateSearchStartStatusCB(NULL, (XtPointer) hw, NULL);
5128 /* and search if needed */
5129 if ( _DtHelpGlobSrchCurVolume == hw->help_dialog.srch.srchSources )
5131 /* if to search a volume, start the search */
5132 if (hw->help_dialog.display.helpType == DtHELP_TYPE_TOPIC)
5133 StartSearchCB(NULL,(XtPointer) hw, NULL);
5134 else /* if current isn't a volume, clear the display & update status */
5136 DeleteListContents(&hw->help_dialog.srch);
5137 StatusLabelUpdate(hw,NO_VOL_STATUS,False,0);
5145 /*****************************************************************************
5146 * Function: void _DtHelpGlobSrchInitVars()
5148 * Parameters: srch search main data structure
5152 * Purpose: Init the contents of the control data structure
5154 *****************************************************************************/
5155 void _DtHelpGlobSrchInitVars(
5156 _DtHelpGlobSearchStuff * srch)
5158 /* set the font resource */
5159 if (srch->hitPrefixFont != _DtHelpDefaultSrchHitPrefixFont)
5160 srch->hitPrefixFont = XtNewString(srch->hitPrefixFont);
5162 /* File Selection Dialog font list */
5163 srch->volTitlesFontList = NULL;
5165 /* Set our search dialog widgets to NULL */
5166 srch->srchForm = NULL;
5167 srch->actionBtn = NULL;
5168 srch->curVolRadBtn = NULL;
5169 srch->allVolRadBtn = NULL;
5170 srch->selVolRadBtn = NULL;
5171 srch->selectBtn = NULL;
5172 srch->fullIndexRadBtn = NULL;
5173 srch->containsRadBtn = NULL;
5174 srch->wordField = NULL;
5175 srch->statusLabel = NULL;
5176 srch->resultList = NULL;
5177 srch->gotoBtn = NULL;
5178 srch->closeBtn = NULL;
5179 srch->helpBtn = NULL;
5180 srch->selectionDlg = NULL;
5182 /* init dialog content variables */
5183 srch->curVolPath = NULL;
5184 srch->rawWordStr = NULL;
5185 srch->normWordStr = NULL;
5186 srch->localeWordStr = NULL;
5187 srch->wordFieldFirstChar = 0;
5188 srch->wordFieldLen = 0;
5189 srch->statusLineUsage = 0; /* empty */
5191 /* init srch processing variables */
5192 srch->iconv3Codeset = NULL; /* iconv(3)-compatible code set of current locale */
5193 srch->iconv3Context = NULL;
5194 srch->srchSources = _DtHelpGlobSrchVolumeUndef; /* radio btn usage */
5195 srch->curSrchVol = NULL; /* volume currently in search */
5196 srch->hitsFontLoaded= False; /* is font loaded? */
5197 srch->volScanDone = False; /* is the volume list complete? */
5198 srch->fullIndex = False;
5199 srch->hitsFound = False; /* state of search */
5200 srch->readyToStart = False; /* state of search */
5201 srch->searchInProgress= False; /* state of search */
5202 srch->curVolRadBtnSens = False;
5203 srch->volLeftCnt = 0;
5204 srch->volListHead = NULL; /* info on search topics found */
5205 srch->workProcId = 0;
5209 /*****************************************************************************
5210 * Function: void _DtHelpGlobSrchCleanAndClose()
5212 * Parameters: srch search main data structure
5213 * destroy flag to signal srch dialog should be destroyed
5217 * Purpose: Free the contents of the control data structure
5219 *****************************************************************************/
5220 void _DtHelpGlobSrchCleanAndClose(
5221 _DtHelpGlobSearchStuff * srch,
5224 /* close conversion context */
5225 _DtHelpCeIconvClose(&srch->iconv3Context);
5227 /* free the font list */
5228 if(srch->volTitlesFontList)
5230 XmFontListFree(srch->volTitlesFontList);
5231 srch->volTitlesFontList = NULL;
5235 * Make sure CloseSearchCB does not try using an invalid
5236 * widget id in its XtUnmanageChild and XtUnmapWidget calls.
5239 srch->srchForm = NULL;
5241 /* make dialog invisible; update sensitivities */
5242 CloseSearchCB(NULL,(XtPointer)srch, NULL);
5244 /* Destroy our index search dialog? */
5247 /* set the font resource */
5248 if (srch->hitPrefixFont != _DtHelpDefaultSrchHitPrefixFont)
5249 XtFree(srch->hitPrefixFont);
5252 * mark widgets as destroyed.
5253 * The XtDestroyWidget that called me will have called the destroy
5254 * callback of the widgets. So I don't have to do anything except
5255 * make sure I know they are destroyed.
5257 srch->selectionDlg = NULL;
5258 srch->srchForm = NULL;
5259 srch->resultList = NULL;
5261 /* free other data released to search dialog */
5264 /* free the locale word string, if allocated
5265 * (i.e. diff from normWordStr) */
5266 if(srch->localeWordStr!=srch->normWordStr)
5268 XtFree(srch->localeWordStr);
5269 srch->localeWordStr=NULL;
5271 XtFree(srch->normWordStr);
5272 srch->normWordStr=NULL;
5273 XtFree(srch->rawWordStr);
5274 srch->rawWordStr=NULL;
5275 XtFree(srch->curVolPath);
5276 srch->curVolPath=NULL;
5277 XtFree(srch->iconv3Codeset);
5278 srch->iconv3Codeset = NULL;