History.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: History.c /main/10 1996/11/22 12:25:49 cde-hp $ */
  24. /************************************<+>*************************************
  25. ****************************************************************************
  26. **
  27. ** File: History.c
  28. **
  29. ** Project: Cache Creek (Rivers) Project
  30. **
  31. ** Description: Creates an instance of a Cache Creek History Dialog.
  32. **
  33. **
  34. ** (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 Hewlett-Packard Company
  35. **
  36. ** (c) Copyright 1993, 1994 Hewlett-Packard Company
  37. ** (c) Copyright 1993, 1994 International Business Machines Corp.
  38. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  39. ** (c) Copyright 1993, 1994 Novell, Inc.
  40. **
  41. **
  42. ****************************************************************************
  43. ************************************<+>*************************************/
  44. #include <sys/param.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <X11/Intrinsic.h>
  49. #include <X11/Shell.h>
  50. #include <X11/Xutil.h>
  51. #include <X11/keysymdef.h>
  52. /* These includes work in R4 and R5 */
  53. #include <Xm/MwmUtil.h>
  54. #include <Xm/Protocols.h>
  55. #include <Xm/Xm.h>
  56. #include <Xm/XmP.h>
  57. #include <Xm/TextF.h>
  58. #include <Xm/Form.h>
  59. #include <Xm/LabelG.h>
  60. #include <Xm/ScrolledW.h>
  61. #include <Xm/SeparatoG.h>
  62. #include <Xm/PushBG.h>
  63. #include <Xm/List.h>
  64. #include <Xm/DialogS.h>
  65. /* Dt Includes */
  66. #include "Access.h"
  67. #include "bufioI.h"
  68. #include <Dt/Help.h>
  69. #include "DisplayAreaI.h"
  70. #include "DisplayAreaP.h"
  71. #include "StringFuncsI.h"
  72. #include "HelposI.h"
  73. #include "HistoryI.h"
  74. #include "HelpDialogI.h"
  75. #include "HelpDialogP.h"
  76. #include "HelpUtilI.h"
  77. #include "HelpAccessI.h"
  78. #include "FormatI.h"
  79. /*
  80. * Local Includes
  81. */
  82. static void CloseHistoryCB (
  83. Widget w,
  84. XtPointer client_data,
  85. XtPointer call_data);
  86. static void ProcessTopicSelectionCB(
  87. Widget w,
  88. XtPointer client_data,
  89. XtPointer call_data);
  90. static void ProcessVolumeSelectionCB(
  91. Widget w,
  92. XtPointer client_data,
  93. XtPointer call_data);
  94. static void CreateHistoryDialog(
  95. Widget nw);
  96. static DtHistoryListStruct *AddItemToHistoryList(
  97. DtHistoryListStruct **pHead,
  98. XmString title,
  99. int topicType,
  100. Boolean *duplicateItem);
  101. static DtTopicListStruct *PullTopicListFromSelVolumeList(
  102. Widget nw);
  103. static void UpdateTopicList(
  104. DtHistoryListStruct *pHistoryList,
  105. Widget nw,
  106. int topicType);
  107. static Boolean IsTopicInHistoryList(
  108. DtTopicListStruct *pTopicList,
  109. XmString topicTitle);
  110. /************************************************************************
  111. * Function: CloseHistoryCB()
  112. *
  113. * Close the History Dialog
  114. *
  115. ************************************************************************/
  116. static void CloseHistoryCB (
  117. Widget w,
  118. XtPointer client_data,
  119. XtPointer call_data)
  120. {
  121. DtHelpDialogWidget hw = (DtHelpDialogWidget) client_data;
  122. /* We unmap the history dialog */
  123. XtUnmanageChild(hw->help_dialog.history.historyWidget);
  124. /* Re-sensatize the search button so the user can select it agan */
  125. XtSetSensitive(hw->help_dialog.menu.historyBtn, TRUE);
  126. XtSetSensitive(hw->help_dialog.browser.btnBoxHistoryBtn, TRUE);
  127. }
  128. /*****************************************************************************
  129. * Function: Boolean _DtHelpDisplayHistoryInfo(Widget nw);
  130. *
  131. *
  132. * Parameters: nw Specifies the name of the current help dialog
  133. * widget.
  134. *
  135. * Return Value:
  136. *
  137. * Purpose: Displays the pre-created history dialog.
  138. *
  139. *****************************************************************************/
  140. void _DtHelpDisplayHistoryInfo(
  141. Widget nw)
  142. {
  143. DtHelpDialogWidget hw = (DtHelpDialogWidget) nw;
  144. if (hw->help_dialog.history.historyWidget == NULL)
  145. CreateHistoryDialog((Widget) hw);
  146. /* if its not managed, manage it */
  147. if ( XtIsManaged(hw->help_dialog.history.historyWidget) == False )
  148. {
  149. /* manage and map the History Dialog */
  150. XtManageChild(hw->help_dialog.history.historyWidget);
  151. XtMapWidget(XtParent((Widget)hw->help_dialog.history.historyWidget));
  152. }
  153. else /* if it is managed, bring it forward */
  154. {
  155. Widget parent = XtParent(hw->help_dialog.history.historyWidget);
  156. XRaiseWindow ( XtDisplay(parent), XtWindow(parent) );
  157. }
  158. }
  159. /*****************************************************************************
  160. * Function: Boolean IsTopicInHistoryList(nw)
  161. *
  162. *
  163. * Parameters: nw Specifies the name of the current help dialog
  164. * widget.
  165. *
  166. * Return Value:
  167. *
  168. * Purpose: checks the current topic list for a matching value, and
  169. * returns true if found, false if not.
  170. *
  171. *****************************************************************************/
  172. static Boolean IsTopicInHistoryList(
  173. DtTopicListStruct *pTopicList,
  174. XmString topicTitle)
  175. {
  176. Boolean done=FALSE;
  177. while (!done && (pTopicList != NULL))
  178. {
  179. if (XmStringCompare (topicTitle, pTopicList->topicTitleLbl) == True)
  180. done= TRUE;
  181. pTopicList = pTopicList->pNext;
  182. }
  183. return(done);
  184. }
  185. /*****************************************************************************
  186. * Function: void UpdateTopicList(
  187. * DtHistoryListStruct *pTopics,
  188. * Widget topicList
  189. *
  190. *
  191. *
  192. * Parameters:
  193. *
  194. * Return Value: Void.
  195. *
  196. * Purpose: Cleans and recreates a new topic list
  197. *
  198. *****************************************************************************/
  199. static void UpdateTopicList(
  200. DtHistoryListStruct *pHistoryList,
  201. Widget nw,
  202. int topicType)
  203. {
  204. int i;
  205. int n;
  206. Arg args[5];
  207. XmString labelString;
  208. XmString *items;
  209. DtTopicListStruct *pTopicList=NULL;
  210. DtHelpDialogWidget hw = (DtHelpDialogWidget) nw;
  211. /* Flush the current history topic list */
  212. XmListDeselectAllItems(hw->help_dialog.history.topicList);
  213. XmListDeleteAllItems(hw->help_dialog.history.topicList);
  214. /* Grab the top of our current topic list from our history list struct */
  215. pTopicList = pHistoryList->pTopicHead;
  216. /* Loop through and build up a new visible topics list */
  217. items = (XmString *) XtMalloc(sizeof(XmString) * pHistoryList->totalNodes);
  218. for (i = 0; i < pHistoryList->totalNodes; i++)
  219. {
  220. items[i] = pTopicList->topicTitleLbl;
  221. pTopicList = pTopicList->pNext;
  222. }
  223. XtSetArg(args[0], XmNitems,items);
  224. XtSetArg(args[1], XmNitemCount, pHistoryList->totalNodes);
  225. XtSetValues(hw->help_dialog.history.topicList, args, 2);
  226. XtFree((char *)items);
  227. /* Now, modify the label if we need to */
  228. switch (topicType)
  229. {
  230. case DtHELP_TYPE_TOPIC:
  231. labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
  232. (3, 8,"Help Topics Visited:")));
  233. break;
  234. case DtHELP_TYPE_FILE:
  235. labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
  236. (3, 9,"Help Files Visited:")));
  237. break;
  238. case DtHELP_TYPE_MAN_PAGE:
  239. labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
  240. (3, 10,"Man Pages Visited:")));
  241. break;
  242. case DtHELP_TYPE_STRING:
  243. case DtHELP_TYPE_DYNAMIC_STRING:
  244. labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
  245. (3, 11,"Help Messages Visited:")));
  246. break;
  247. default:
  248. /* Bogus type, how did we ever get here ??? */
  249. break;
  250. } /* End Switch Statement */
  251. n = 0;
  252. XtSetArg (args[n], XmNlabelString, labelString); n++;
  253. XtSetValues (hw->help_dialog.history.topicsListLabel, args, n);
  254. XmStringFree(labelString);
  255. }
  256. /*****************************************************************************
  257. * Function: void ProcessVolumeSelectionCB(Widget w,
  258. * XtPointer client_data,
  259. * XtPointer call_data);
  260. *
  261. *
  262. *
  263. * Parameters:
  264. *
  265. * Return Value: Void.
  266. *
  267. * Purpose: Process user selection of an item in the Volume List
  268. * of the history dialo.
  269. *
  270. *****************************************************************************/
  271. static void ProcessVolumeSelectionCB(
  272. Widget w,
  273. XtPointer client_data,
  274. XtPointer call_data)
  275. {
  276. XmListCallbackStruct *selectedItem = (XmListCallbackStruct *) call_data;
  277. DtHelpDialogWidget hw = (DtHelpDialogWidget) client_data;
  278. DtHistoryListStruct *pTemp= NULL;
  279. int topicPosition=0;
  280. int i;
  281. XmString labelString;
  282. int * topicPosList = NULL;
  283. int topicCnt = 0;
  284. Boolean mod = False;
  285. Arg args[2];
  286. XmFontList fontList;
  287. /* Determin the item selected in the volume list */
  288. topicPosition = selectedItem->item_position;
  289. /* To fix the bug of having no volume selected, check
  290. whether user clicked again on the currently selected item,
  291. deselecting it and leaving no other selected, and just
  292. reselect that item and do nothing else */
  293. /* for reasons unknown, selectedItem->selected_item_positions
  294. doesnt seem properly initialized and leads to a core dump;
  295. so use XmListGetSelectedPos() instead */
  296. if ( False == XmListGetSelectedPos(w, &topicPosList, &topicCnt)
  297. && NULL == topicPosList )
  298. {
  299. XmListSelectPos(w,topicPosition,False); /* False=dont notify */
  300. return; /* RETURN */
  301. }
  302. XtFree((char *)topicPosList);
  303. /* and find that item in our list */
  304. pTemp = hw->help_dialog.history.pHistoryListHead;
  305. for (i=1;i < topicPosition; i++)
  306. pTemp = pTemp->pNext;
  307. UpdateTopicList(pTemp, (Widget)hw, pTemp->topicType);
  308. /* Look to see if we have the current visible topic matches something in
  309. * in the topic list. If so, highlight the item in the topic list
  310. */
  311. XtSetArg(args[0], XmNfontList, &fontList);
  312. XtGetValues(hw->help_dialog.history.topicList, args, 1);
  313. if ( _DtHelpFormatTopicTitle (hw->help_dialog.help.pDisplayArea,
  314. hw->help_dialog.display.volumeHandle,
  315. hw->help_dialog.display.locationId,
  316. &labelString, &fontList, &mod) != 0
  317. || NULL == labelString)
  318. {
  319. labelString = XmStringCreateLocalized(hw->help_dialog.display.locationId);
  320. }
  321. if (True == mod)
  322. {
  323. /* must set the fontlist, otherwise this will cause a dangle later. */
  324. XtSetArg(args[0], XmNfontList, fontList);
  325. XtSetValues(hw->help_dialog.history.topicList, args, 1);
  326. XmFontListFree(fontList);
  327. }
  328. XmListSelectItem(hw->help_dialog.history.topicList,labelString, FALSE);
  329. XmListSetBottomItem(hw->help_dialog.history.topicList,labelString);
  330. XmStringFree(labelString);
  331. }
  332. /*****************************************************************************
  333. * Function: void ProcessTopicSelectionCB(Widget w,
  334. * XtPointer client_data,
  335. * XtPointer call_data);
  336. *
  337. *
  338. *
  339. * Parameters:
  340. *
  341. * Return Value: Void.
  342. *
  343. * Purpose: Process user selection of an item in the History List.
  344. *
  345. *****************************************************************************/
  346. static void ProcessTopicSelectionCB(
  347. Widget w,
  348. XtPointer client_data,
  349. XtPointer call_data)
  350. {
  351. XmListCallbackStruct *selectedItem = (XmListCallbackStruct *) call_data;
  352. DtHelpDialogWidget hw = (DtHelpDialogWidget) client_data;
  353. DtTopicListStruct *pTemp= NULL;
  354. int topicPosition=0;
  355. int i;
  356. /* First, find out what item is currently selected in our
  357. * volume list. From this, we can get the proper topic list to
  358. * travers.
  359. */
  360. pTemp = PullTopicListFromSelVolumeList((Widget)hw);
  361. if (pTemp == NULL)
  362. {
  363. /*FIX: We have a problem, this should never happen; decide what to do*/
  364. return;
  365. }
  366. /* Determin the item selected and find that item in our list */
  367. topicPosition = selectedItem->item_position;
  368. for (i=1;i < topicPosition; i++)
  369. pTemp = pTemp->pNext;
  370. hw->help_dialog.display.helpType = pTemp->topicType;
  371. if (hw->help_dialog.display.helpType != DtHELP_TYPE_TOPIC)
  372. {
  373. if (hw->help_dialog.display.topicTitleLbl != NULL)
  374. XmStringFree(hw->help_dialog.display.topicTitleLbl);
  375. hw->help_dialog.display.topicTitleLbl =
  376. XmStringCopy(pTemp->topicTitleLbl);
  377. }
  378. switch (pTemp->topicType)
  379. {
  380. case DtHELP_TYPE_TOPIC:
  381. /* Look and see if we need to update our helpVolue to a new value */
  382. if ( pTemp->helpVolume != NULL
  383. && ( hw->help_dialog.display.helpVolume == NULL
  384. || strcmp(hw->help_dialog.display.helpVolume,pTemp->helpVolume) != 0))
  385. {
  386. XtFree(hw->help_dialog.display.helpVolume);
  387. hw->help_dialog.display.helpVolume = XtNewString(pTemp->helpVolume);
  388. /* Set our help volume flag so we open the proper volume */
  389. hw->help_dialog.ghelp.volumeFlag = FALSE;
  390. }
  391. XtFree(hw->help_dialog.display.locationId);
  392. hw->help_dialog.display.locationId = XtNewString(pTemp->locationId);
  393. /* set the topicType flag to process correctly */
  394. hw->help_dialog.display.helpType = DtHELP_TYPE_TOPIC;
  395. break;
  396. case DtHELP_TYPE_STRING:
  397. XtFree(hw->help_dialog.display.stringData);
  398. hw->help_dialog.display.stringData = XtNewString(pTemp->locationId);
  399. /* set the topicType flag to process correctly */
  400. hw->help_dialog.display.helpType = DtHELP_TYPE_STRING;
  401. break;
  402. case DtHELP_TYPE_DYNAMIC_STRING:
  403. XtFree(hw->help_dialog.display.stringData);
  404. hw->help_dialog.display.stringData = XtNewString(pTemp->locationId);
  405. /* set the topicType flag to process correctly */
  406. hw->help_dialog.display.helpType = DtHELP_TYPE_DYNAMIC_STRING;
  407. break;
  408. case DtHELP_TYPE_MAN_PAGE:
  409. XtFree(hw->help_dialog.display.manPage);
  410. hw->help_dialog.display.manPage = XtNewString(pTemp->locationId);
  411. /* set the topicType flag to process correctly */
  412. hw->help_dialog.display.helpType = DtHELP_TYPE_MAN_PAGE;
  413. break;
  414. case DtHELP_TYPE_FILE:
  415. XtFree(hw->help_dialog.display.helpFile);
  416. hw->help_dialog.display.helpFile = XtNewString(pTemp->locationId);
  417. /* set the topicType flag to process correctly */
  418. hw->help_dialog.display.helpType = DtHELP_TYPE_FILE;
  419. break;
  420. default:
  421. /* ERROR-MESSAGE */
  422. /* We should never get here, because we using the proper types */
  423. return;
  424. } /* End Switch Statement */
  425. _DtHelpSetupDisplayType(hw, FALSE, DtHISTORY_AND_JUMP);
  426. }
  427. /*****************************************************************************
  428. * Function: void CreateHistoryDialog(
  429. * Widget nw);
  430. *
  431. *
  432. * Parameters: helpDialogWidget Specifies the current Help Dialog to
  433. * create the history dialog for.
  434. *
  435. *
  436. * Return Value:
  437. *
  438. * Purpose: Create and display an instance of a history dialog.
  439. *
  440. *****************************************************************************/
  441. static void CreateHistoryDialog(
  442. Widget nw)
  443. {
  444. Widget historyForm;
  445. Widget volumeListLabel;
  446. Widget separator;
  447. Widget cancelBtn, helpBtn;
  448. Widget historyShell;
  449. XmString labelString;
  450. Arg args[20];
  451. int n;
  452. char * title;
  453. DtHelpListStruct *pHelpInfo;
  454. int offset=0;
  455. Dimension btnHeight=0;
  456. Dimension widgetBorderHeight=0;
  457. DtHelpDialogWidget hw = (DtHelpDialogWidget) nw ;
  458. /* Create the shell and form used for the dialog. */
  459. title = XtNewString(((char *)_DTGETMESSAGE(3, 1,"Help - History Browser")));
  460. n = 0;
  461. XtSetArg (args[n], XmNtitle, title); n++;
  462. XtSetArg (args[n], XmNallowShellResize, TRUE); n++;
  463. historyShell = XmCreateDialogShell((Widget) hw, "historyShell", args, n);
  464. XtFree(title);
  465. /* Set the useAsyncGeo on the shell */
  466. n = 0;
  467. XtSetArg (args[n], XmNuseAsyncGeometry, True); n++;
  468. XtSetValues (XtParent(historyShell), args, n);
  469. n = 0;
  470. XtSetArg (args[n], XmNmarginWidth, 1); n++;
  471. XtSetArg (args[n], XmNmarginHeight, 1); n++;
  472. XtSetArg (args[n], XmNshadowThickness, 1); n++;
  473. XtSetArg (args[n], XmNshadowType, XmSHADOW_OUT); n++;
  474. XtSetArg (args[n], XmNautoUnmanage, False); n++;
  475. historyForm = XmCreateForm (historyShell, "historyForm", args, n);
  476. labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
  477. (3, 2,"Help Volumes Visited:")));
  478. n = 0;
  479. XtSetArg (args[n], XmNlabelString, labelString); n++;
  480. XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  481. XtSetArg (args[n], XmNleftOffset, 5); n++;
  482. XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  483. XtSetArg (args[n], XmNtopOffset, 10); n++;
  484. volumeListLabel =
  485. XmCreateLabelGadget (historyForm, "volumeListLabel", args, n);
  486. XtManageChild (volumeListLabel);
  487. XmStringFree (labelString);
  488. /* Create our history scrolled list */
  489. n = 0;
  490. XtSetArg (args[n], XmNlistSizePolicy, XmCONSTANT); n++;
  491. XtSetArg (args[n], XmNselectionPolicy, XmSINGLE_SELECT); n++;
  492. XtSetArg (args[n], XmNresizable, FALSE); n++;
  493. hw->help_dialog.history.volumeList =
  494. XmCreateScrolledList (historyForm, "historyVolumeList", args, n);
  495. XtManageChild (hw->help_dialog.history.volumeList);
  496. XtAddCallback (hw->help_dialog.history.volumeList,
  497. XmNsingleSelectionCallback,
  498. (XtCallbackProc)ProcessVolumeSelectionCB, (XtPointer) hw);
  499. /* Set the constraints on our scrolled list */
  500. n = 0;
  501. XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  502. XtSetArg (args[n], XmNtopWidget, volumeListLabel); n++;
  503. XtSetArg (args[n], XmNtopOffset, 5); n++;
  504. XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  505. XtSetArg (args[n], XmNleftOffset, 10); n++;
  506. XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  507. XtSetArg (args[n], XmNrightOffset, 10); n++;
  508. XtSetValues (XtParent (hw->help_dialog.history.volumeList), args, n);
  509. /* Create the Result Label and scrolled list */
  510. /* Create Result List Label */
  511. labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
  512. (3, 8,"Help Topics Visited:")));
  513. n = 0;
  514. XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  515. XtSetArg (args[n], XmNtopWidget,
  516. XtParent(hw->help_dialog.history.volumeList)); n++;
  517. XtSetArg (args[n], XmNtopOffset, 10); n++;
  518. XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  519. XtSetArg (args[n], XmNleftOffset, 10); n++;
  520. XtSetArg (args[n], XmNlabelString, labelString); n++;
  521. hw->help_dialog.history.topicsListLabel =
  522. XmCreateLabelGadget (historyForm, "topicsListLabel", args, n);
  523. XtManageChild (hw->help_dialog.history.topicsListLabel);
  524. XmStringFree (labelString);
  525. /* Create our volume topics list */
  526. n = 0;
  527. XtSetArg (args[n], XmNlistSizePolicy, XmCONSTANT); n++;
  528. XtSetArg (args[n], XmNselectionPolicy, XmSINGLE_SELECT); n++;
  529. XtSetArg (args[n], XmNresizable, FALSE); n++;
  530. hw->help_dialog.history.topicList =
  531. XmCreateScrolledList (historyForm, "historyTopicList", args, n);
  532. XtManageChild (hw->help_dialog.history.topicList);
  533. XtAddCallback (hw->help_dialog.history.topicList,
  534. XmNsingleSelectionCallback,
  535. (XtCallbackProc)ProcessTopicSelectionCB,
  536. (XtPointer) hw);
  537. XtAddCallback (hw->help_dialog.history.topicList,
  538. XmNdefaultActionCallback,
  539. (XtCallbackProc)ProcessTopicSelectionCB,
  540. (XtPointer) hw);
  541. /* Set the constraints on our scrolled list */
  542. n = 0;
  543. XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  544. XtSetArg (args[n], XmNtopWidget, hw->help_dialog.history.topicsListLabel); n++;
  545. XtSetArg (args[n], XmNtopOffset, 5); n++;
  546. XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  547. XtSetArg (args[n], XmNleftOffset, 10); n++;
  548. XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  549. XtSetArg (args[n], XmNrightOffset, 10); n++;
  550. XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  551. XtSetArg (args[n], XmNbottomOffset, 70); n++;
  552. XtSetValues (XtParent (hw->help_dialog.history.topicList), args, n);
  553. /* Create a separator between the buttons */
  554. n = 0;
  555. XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  556. XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  557. XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  558. XtSetArg (args[n], XmNtopWidget,
  559. XtParent(hw->help_dialog.history.topicList)); n++;
  560. XtSetArg (args[n], XmNtopOffset, 8); n++;
  561. separator = XmCreateSeparatorGadget (historyForm, "separator", args, n);
  562. XtManageChild (separator);
  563. /* Create the action buttons along the bottom */
  564. labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
  565. (3, 3,"Close")));
  566. n = 0;
  567. XtSetArg (args[n], XmNlabelString, labelString); n++;
  568. XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  569. XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
  570. XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  571. XtSetArg (args[n], XmNtopWidget, separator); n++;
  572. XtSetArg (args[n], XmNtopOffset, 5); n++;
  573. XtSetArg (args[n], XmNmarginHeight, 4); n++;
  574. XtSetArg (args[n], XmNmarginWidth, 6); n++;
  575. /*XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  576. *XtSetArg (args[n], XmNbottomOffset, 3); n++;
  577. */
  578. cancelBtn = XmCreatePushButtonGadget (historyForm, "cancelBtn", args, n);
  579. XtAddCallback(cancelBtn, XmNactivateCallback,
  580. (XtCallbackProc)CloseHistoryCB, (XtPointer) hw);
  581. XtManageChild (cancelBtn);
  582. XmStringFree (labelString);
  583. XtSetArg (args[0], XmNdefaultButton, cancelBtn);
  584. XtSetValues (historyForm, args, 1);
  585. /* set the cancel button (for KCancel) */
  586. n = 0;
  587. XtSetArg (args[n], XmNcancelButton, cancelBtn); n++;
  588. XtSetValues (historyForm, args, n);
  589. /* Build the Help button */
  590. labelString = XmStringCreateLocalized(((char *)_DTGETMESSAGE
  591. (3, 4,"Help")));
  592. n = 0;
  593. XtSetArg (args[n], XmNlabelString, labelString); n++;
  594. XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  595. XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
  596. XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  597. XtSetArg (args[n], XmNtopWidget, separator); n++;
  598. XtSetArg (args[n], XmNtopOffset, 5); n++;
  599. XtSetArg (args[n], XmNmarginHeight, 4); n++;
  600. XtSetArg (args[n], XmNmarginWidth, 6); n++;
  601. helpBtn = XmCreatePushButtonGadget (historyForm, "helpBtn", args, n);
  602. XtManageChild (helpBtn);
  603. /* Setup and add our help callback for this button */
  604. pHelpInfo = _DtHelpListAdd(DtHELP_historyHelpBtn_STR,
  605. (Widget) hw, &hw->help_dialog.help,
  606. &hw->help_dialog.help.pHelpListHead);
  607. XtAddCallback (helpBtn, XmNactivateCallback,
  608. _DtHelpCB, (XtPointer) pHelpInfo);
  609. XmStringFree (labelString);
  610. /* Adjust the decorations for the dialog shell of the dialog */
  611. n = 0;
  612. XtSetArg(args[n], XmNmwmFunctions,
  613. MWM_FUNC_MOVE |MWM_FUNC_RESIZE); n++;
  614. XtSetArg (args[n], XmNmwmDecorations,
  615. MWM_DECOR_BORDER | MWM_DECOR_TITLE | MWM_DECOR_RESIZEH); n++;
  616. XtSetValues (historyShell, args, n);
  617. /* calculate and set the buttons' positions on the form */
  618. {
  619. Widget btnList[2];
  620. unsigned long avgWidth = 73; /* default size, in 10ths of pixel */
  621. Dimension formWidth;
  622. XmFontList fontList = NULL;
  623. Atom xa_ave_width;
  624. #define BTN_MARGINS 4
  625. #define BETW_BTN_SPC 5
  626. XtSetArg(args[0], XmNfontList, &fontList);
  627. XtGetValues(hw->help_dialog.history.topicList, args, 1);
  628. btnList[0] = cancelBtn;
  629. btnList[1] = helpBtn;
  630. /* get the average width of the topic list's font */
  631. xa_ave_width = XmInternAtom(XtDisplay(cancelBtn), "AVERAGE_WIDTH", False);
  632. _DtHelpXmFontListGetPropertyMax(fontList, xa_ave_width, &avgWidth);
  633. /* xa_ave_width is given in 10ths of a pixel; convert to pixels by div thru 10 */
  634. /* we want a 25 column minimum width */
  635. formWidth = avgWidth * 25 / 10;
  636. _DtHelpSetButtonPositions(btnList, 2, formWidth, BTN_MARGINS, BETW_BTN_SPC);
  637. }
  638. /* Perform the final form layout so our dialog resizes correctly. */
  639. /* Get height of: bottom buttons and separator */
  640. n = 0;
  641. XtSetArg(args[n], XmNheight, &btnHeight); n++;
  642. XtSetArg(args[n], XmNborderWidth, &widgetBorderHeight); n++;
  643. XtGetValues(cancelBtn, args, n);
  644. offset = btnHeight + widgetBorderHeight + 15;
  645. /* 20 =='s fudge factor */
  646. n = 0;
  647. XtSetArg(args[n], XmNborderWidth, &widgetBorderHeight); n++;
  648. XtSetArg(args[n], XmNheight, &btnHeight); n++;
  649. XtGetValues(separator, args, n);
  650. offset += btnHeight + widgetBorderHeight;
  651. /* make the bottom attachment for the seporator such that things will fit,
  652. * and the dialog will size properly.
  653. */
  654. n = 0;
  655. XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  656. XtSetArg (args[n], XmNbottomOffset, offset); n++;
  657. XtSetValues (XtParent (hw->help_dialog.history.topicList), args, n);
  658. /* We may have some history values already, so update our newlly
  659. * created scrolled list widget.
  660. */
  661. /* Add the popup position callback to our history dialog */
  662. XtAddCallback (historyShell, XmNpopupCallback, (XtCallbackProc)_DtHelpMapCB,
  663. (XtPointer) XtParent(hw));
  664. /* Add our help callback to the shell of the dialog */
  665. pHelpInfo = _DtHelpListAdd(DtHELP_historyShell_STR,
  666. (Widget) hw, &hw->help_dialog.help,
  667. &hw->help_dialog.help.pHelpListHead);
  668. XtAddCallback(historyForm, XmNhelpCallback,
  669. _DtHelpCB, (XtPointer) pHelpInfo);
  670. /* Assign our new search dialog to our widget instance */
  671. hw->help_dialog.history.historyWidget = historyForm;
  672. }
  673. /*****************************************************************************
  674. * Function: void _DtHelpUpdateHistoryList(char *locationId,
  675. * int topicType,
  676. * Widget nw);
  677. *
  678. *
  679. * Parameters: parent Specifies the ID string for the new topic we
  680. * are going to display in the HelpDialog widget.
  681. *
  682. * helpDialogWidget Specifies the current help dialog widget.
  683. *
  684. * Return Value: Void.
  685. *
  686. * Purpose: Updates the Path Display area on top of the help
  687. * dialog.
  688. *
  689. *****************************************************************************/
  690. void _DtHelpUpdateHistoryList(
  691. char *locationId,
  692. int topicType,
  693. Boolean vol_changed,
  694. Widget nw)
  695. {
  696. DtHistoryListStruct *pCurrentHistoryList=NULL;
  697. XmString topicTitle = NULL;
  698. XmString currentItemTitle = NULL;
  699. Boolean allocTopic=FALSE;
  700. Boolean dupItem=FALSE;
  701. Boolean changedSelectedVolume=FALSE;
  702. Boolean mod=FALSE;
  703. XmFontList fontList;
  704. Arg args[2];
  705. DtHelpDialogWidget hw = (DtHelpDialogWidget) nw;
  706. /* Lets just build a history dialog so we can start populating it.
  707. * We won't manage it tell we need it
  708. */
  709. if (hw->help_dialog.history.historyWidget == NULL)
  710. CreateHistoryDialog((Widget) hw);
  711. /* Find out what type of topic we are currently processing */
  712. switch (topicType)
  713. {
  714. case DtHELP_TYPE_TOPIC:
  715. /*
  716. * get the font list for the volume list.
  717. */
  718. XtSetArg(args[0], XmNfontList, &fontList);
  719. XtGetValues(hw->help_dialog.history.topicList, args, 1);
  720. /* First we get the current topics Title */
  721. allocTopic = True;
  722. mod = False;
  723. if (_DtHelpFormatTopicTitle (hw->help_dialog.help.pDisplayArea,
  724. hw->help_dialog.display.volumeHandle,
  725. locationId, &topicTitle,
  726. &fontList, &mod) != 0
  727. || NULL == topicTitle)
  728. topicTitle = XmStringCreateLocalized(locationId);
  729. if (mod == True)
  730. {
  731. XtSetArg(args[0], XmNfontList, fontList);
  732. XtSetValues(hw->help_dialog.history.topicList, args, 1);
  733. XmFontListFree(fontList);
  734. }
  735. /*
  736. * get the font list for the volume list.
  737. */
  738. XtSetArg(args[0], XmNfontList, &fontList);
  739. XtGetValues(hw->help_dialog.history.volumeList, args, 1);
  740. /* Second, we get the current volume title */
  741. mod = False;
  742. _DtHelpFormatVolumeTitle (hw->help_dialog.help.pDisplayArea,
  743. hw->help_dialog.display.volumeHandle,
  744. &currentItemTitle, &fontList, &mod);
  745. if(currentItemTitle == NULL &&
  746. NULL != hw->help_dialog.display.helpVolume)
  747. currentItemTitle = XmStringCreateLocalized(
  748. hw->help_dialog.display.helpVolume);
  749. if (mod == True)
  750. {
  751. XtSetArg(args[0], XmNfontList, fontList);
  752. XtSetValues(hw->help_dialog.history.volumeList, args, 1);
  753. XmFontListFree(fontList);
  754. }
  755. break;
  756. case DtHELP_TYPE_FILE:
  757. currentItemTitle = XmStringCreateLocalized(
  758. ((char *)_DTGETMESSAGE(3, 5, "Help Files")));
  759. topicTitle = hw->help_dialog.display.topicTitleLbl;
  760. break;
  761. case DtHELP_TYPE_MAN_PAGE:
  762. currentItemTitle = XmStringCreateLocalized(
  763. ((char *)_DTGETMESSAGE(3, 6, "Man Pages")));
  764. topicTitle = hw->help_dialog.display.topicTitleLbl;
  765. break;
  766. case DtHELP_TYPE_STRING:
  767. case DtHELP_TYPE_DYNAMIC_STRING:
  768. currentItemTitle = XmStringCreateLocalized(
  769. ((char *)_DTGETMESSAGE(3, 7, "Help Messages")));
  770. topicTitle = hw->help_dialog.display.topicTitleLbl;
  771. break;
  772. default:
  773. /* Bogus type, how did we ever get here ??? */
  774. break;
  775. } /* End Switch Statement */
  776. /* Now add this item to the history list if necessary. This fuction
  777. * will return a pointer to the current working history list item.
  778. */
  779. pCurrentHistoryList = AddItemToHistoryList(
  780. &(hw->help_dialog.history.pHistoryListHead),
  781. currentItemTitle, topicType, &dupItem);
  782. if (dupItem != TRUE)
  783. {
  784. /* We can skip this if it already exists in our history list,else
  785. * we add the new history item to the top of the scrolled window
  786. */
  787. XmListAddItem(hw->help_dialog.history.volumeList,currentItemTitle, 1);
  788. XmListSelectPos(hw->help_dialog.history.volumeList,1, FALSE);
  789. }
  790. else /* dupItem == True */
  791. {
  792. /* We changed to a diferent volume or help type so force it selected */
  793. XmListSelectItem(hw->help_dialog.history.volumeList,
  794. currentItemTitle, FALSE);
  795. changedSelectedVolume = TRUE;
  796. if (NULL != currentItemTitle)
  797. XmStringFree(currentItemTitle);
  798. }
  799. /* Now add this item to the proper Topic List. */
  800. if (pCurrentHistoryList != NULL)
  801. {
  802. if (!IsTopicInHistoryList(pCurrentHistoryList->pTopicHead, topicTitle))
  803. {
  804. /* Add the new topic to the history top of the history list */
  805. _DtHelpTopicListAddToHead(locationId, topicTitle,topicType,
  806. DtHISTORY_LIST_MAX,
  807. hw->help_dialog.display.helpVolume,
  808. &(pCurrentHistoryList->pTopicHead),
  809. &(pCurrentHistoryList->pTopicTale),
  810. &(pCurrentHistoryList->totalNodes),
  811. hw->help_dialog.backtr.scrollPosition);
  812. XmUpdateDisplay((Widget) hw);
  813. UpdateTopicList(pCurrentHistoryList, (Widget)hw, topicType);
  814. /* Force the top item to be selected */
  815. XmListSelectPos(hw->help_dialog.history.topicList,1, FALSE);
  816. }
  817. else
  818. {
  819. if (changedSelectedVolume)
  820. {
  821. if (TRUE == vol_changed)
  822. UpdateTopicList(pCurrentHistoryList, (Widget)hw, topicType);
  823. XmListSelectItem(hw->help_dialog.history.topicList,topicTitle,
  824. FALSE);
  825. /* Make sure the item is visible */
  826. }
  827. }
  828. }
  829. if (allocTopic == True)
  830. XmStringFree(topicTitle);
  831. }
  832. /*****************************************************************************
  833. * Function: static DtHistoryListStruct *AddItemToHistoryList(
  834. *
  835. * Parameters:
  836. * title Specifies the XmString of the title. If
  837. * 'duplicateItem' returns False, the caller
  838. * must not modify or free this parameter.
  839. *
  840. *
  841. * Return Value: Pointer to the current history list node that we are going
  842. * to add the item.
  843. *
  844. * Purpose: Add or update our history list with a new item
  845. *
  846. *****************************************************************************/
  847. static DtHistoryListStruct *AddItemToHistoryList(
  848. DtHistoryListStruct **pHead,
  849. XmString title,
  850. int topicType,
  851. Boolean *duplicateItem)
  852. {
  853. DtHistoryListStruct *pTemp=NULL;
  854. Boolean done=FALSE;
  855. /*
  856. * Walk the list.
  857. */
  858. pTemp = (*pHead);
  859. *duplicateItem = False;
  860. while (!done && (pTemp != NULL))
  861. {
  862. if (XmStringCompare (title, pTemp->itemTitle) == True)
  863. {
  864. /* We have a match, so lets use it */
  865. *duplicateItem = TRUE;
  866. done = TRUE;
  867. }
  868. else
  869. pTemp = pTemp->pNext;
  870. }
  871. if (pTemp == NULL)
  872. {
  873. /* We did not find a match, so lets add one to the top of
  874. * our current list.
  875. */
  876. pTemp =(DtHistoryListStruct *) XtMalloc((sizeof(DtHistoryListStruct)));
  877. pTemp->itemTitle = title;
  878. pTemp->totalNodes = 0;
  879. pTemp->topicType = topicType;
  880. pTemp->pNext = (*pHead);
  881. pTemp->pTopicHead = NULL;
  882. pTemp->pTopicTale = NULL;
  883. /* Re-Assign our head pointer to point to the new
  884. * head of the list
  885. */
  886. (*pHead) = pTemp;
  887. }
  888. return (pTemp);
  889. }
  890. /*****************************************************************************
  891. * Function: static DtHistoryListStruct PullTopicListFromSelVolumeList
  892. *
  893. *
  894. *
  895. *
  896. * Return Value: Pointer to the current history list node that we are going
  897. * to add the item.
  898. *
  899. * Purpose: Add or update our history list with a new item
  900. *
  901. *****************************************************************************/
  902. static DtTopicListStruct *PullTopicListFromSelVolumeList(
  903. Widget nw)
  904. {
  905. DtHelpDialogWidget hw = (DtHelpDialogWidget) nw;
  906. DtHistoryListStruct *pTemp=NULL;
  907. Boolean itemsSelected=FALSE;
  908. int positionCount;
  909. int *positionList; /* Should always be only one item */
  910. int i;
  911. pTemp = hw->help_dialog.history.pHistoryListHead;
  912. /* Find out what item is currently selected in our visited volumes list */
  913. itemsSelected = XmListGetSelectedPos(hw->help_dialog.history.volumeList,
  914. &positionList, &positionCount);
  915. if (itemsSelected)
  916. {
  917. /* We should get in here every time */
  918. for (i=1;i < positionList[0]; i++)
  919. pTemp = pTemp->pNext;
  920. free(positionList);
  921. return (pTemp->pTopicHead);
  922. }
  923. else
  924. {
  925. free(positionList);
  926. return (NULL);
  927. /* error condition we must account for */
  928. }
  929. }