2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* Copyright (c) 1994 FUJITSU LIMITED */
24 /* All Rights Reserved */
27 * $TOG: OutlineListViewMotif.C /main/15 1997/06/18 17:31:56 samborn $
29 * Copyright (c) 1992 HaL Computer Systems, Inc. All rights reserved.
30 * UNPUBLISHED -- rights reserved under the Copyright Laws of the United
31 * States. Use of a copyright notice is precautionary only and does not
32 * imply publication or disclosure.
34 * This software contains confidential information and trade secrets of HaL
35 * Computer Systems, Inc. Use, disclosure, or reproduction is prohibited
36 * withuot the prior express written permission of HaL Computer Systems, Inc.
38 * RESTRICTED RIGHTS LEGEND
39 * Use, duplication, or disclosure by the Government is subject to
40 * restrictions as set forth in subparagraph (c)(l)(ii) of the Rights in
41 * Technical Data and Computer Software clause at DFARS 252.227-7013.
42 * HaL Computer Systems, Inc.
43 * 1315 Dell Avenue, Campbell, CA 95008
49 #define C_WindowSystem
53 #define C_OutlineElement
57 #define C_OutlineListView
58 #define C_LibraryAgent
65 #define USES_OLIAS_FONT
69 #include "Managers/CatMgr.hh"
70 #include "Registration.hh"
72 #include <WWL/WComposite.h>
73 #include <WWL/WXmScrollBar.h>
77 #include <sys/param.h>
80 #define DEBUGF(X) printf X
86 # define RCS_DEBUG(statement) cerr << statement << endl
88 # define RCS_DEBUG(statement)
91 extern "C" { void _Xm_dump_external(XmString); }
94 XmStringCreateComponent (XmStringComponentType tag, void *data, u_int length);
95 static void register_actions();
97 enum { XmSTRING_COMPONENT_POINTER = XmSTRING_COMPONENT_USER_BEGIN };
100 // /////////////////////////////////////////////////////////////////
102 // /////////////////////////////////////////////////////////////////
104 OutlineListView::OutlineListView (const WComposite &parent, const char *name,
106 bool enable_activate)
107 : WXmList ((Widget) NULL), f_list (NULL), f_max_level (LEVEL_UNLIMITED),
108 f_current_selection (NULL), f_selected_item_count(0),
109 f_tracking_position (0),
110 f_tracking_element (NULL),
111 f_library_agent (NULL)
113 static serial_number = 1;
115 // Assign a unique serial number to this outline list.
116 f_serial_number = serial_number++;
118 // Non-scrolled list is useless so make it a scrolled list.
119 widget = XmCreateScrolledList (parent, (char *) name, NULL, 0);
122 // if dtinfo_font is defined then get the fontlist for the widget
123 // and append thte dtinfo_font
125 if (window_system().dtinfo_font()) {
126 XmFontList tempFontList, defaultList;
128 // get the current font list and make a copy
129 XtVaGetValues(widget, XmNfontList, &tempFontList, NULL);
130 defaultList = XmFontListCopy(tempFontList);
132 // append the dtinfo font. XmFontListAppendEntry deallocates the original font list after
133 // extracting the required information.
135 defaultList = XmFontListAppendEntry(defaultList, window_system().dtinfo_font());
137 // set the new new font list back
138 XtVaSetValues(widget, XmNfontList, defaultList, NULL);
142 // Save this pointer in user data of widget so that actions can
147 printf (">>> *** shadow %d, margin %d, highlight %d\n",
148 ShadowThickness(), ListMarginWidth(), HighlightThickness());
150 f_margin = ShadowThickness() + ListMarginWidth() + HighlightThickness();
151 f_selection_policy = SelectionPolicy();
155 SetSingleSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
156 SetBrowseSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
157 SetExtendedSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
158 SetMultipleSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
160 SetConvertCallback (this, (WWL_FUN) &OutlineListView::printConvertCallback);
164 SetDefaultActionCallback (this, (WWL_FUN) &OutlineListView::activate);
165 f_tracking_possible = 1;
169 f_tracking_possible = 0;
179 XmFontList defaultList;
180 XtVaGetValues(w, XmNfontList, &defaultList, NULL);
182 // Setup parameters for calculating click position.
184 if (window_system().nofonts())
187 string[0] = OLIAS_PLACEHOLDER_ICON;
189 XmString thing = XmStringCreate (string, OLIAS_FONT);
191 Dimension rval = XmStringWidth(defaultList, thing);
192 XmStringFree (thing);
197 // /////////////////////////////////////////////////////////////////
199 // /////////////////////////////////////////////////////////////////
201 OutlineListView::~OutlineListView()
205 f_data_handle = library_mgr().library().get_data_handle();
210 // /////////////////////////////////////////////////////////////////
211 // xmstring - return the xm string given an outline element
212 // /////////////////////////////////////////////////////////////////
215 OutlineListView::xmstring (OutlineElement *oe, unsigned force, char icon)
217 if (force || (oe->string_creator() != f_serial_number))
219 if (oe->xm_string() != NULL)
220 XmStringFree ((XmString) oe->xm_string());
221 oe->set_xm_string ((void *) create_xm_string (oe, f_base_level,
222 f_tracking_possible, icon));
223 oe->string_creator (f_serial_number);
225 return ((XmString) oe->xm_string());
229 // /////////////////////////////////////////////////////////////////
230 // set_list - set the list
231 // /////////////////////////////////////////////////////////////////
234 OutlineListView::set_list (OutlineList *list, BitHandle handle)
236 // NOTE: Eventually it should be possible to set the list to NULL.
237 if (f_list != NULL && f_list != list )
238 list->free_data_handle (f_data_handle);
242 f_data_handle = handle ;
244 f_data_handle = list->get_data_handle();
245 // Determine the base level.
247 if (list->length() > 0) {
248 // SWM -- need to change this so that when determining
249 // the base level, we check all of the roots...
250 f_base_level = ((OutlineElement *)(*list)[0])->level();
252 ON_DEBUG(printf (">> OutlineList base level = %d\n", f_base_level));
257 // /////////////////////////////////////////////////////////////////
258 // regen_list - regenerate list based on internal list
259 // /////////////////////////////////////////////////////////////////
261 static u_int g_table_index;
264 OutlineListView::regen_list()
266 Xassert (f_list != NULL);
267 // if list is null we should just empty the list.
269 u_int visible_count = f_list->count_expanded (f_data_handle);
271 XmStringTable table = new XmString[visible_count];
272 bool *selected_list = new bool[visible_count];
275 generate_table (f_list, table, selected_list, 0);
279 ItemCount (visible_count, args);
283 delete [] selected_list;
286 // reset tracking position to let dtinfo determine
287 // the new position in track_to()
288 f_tracking_element = NULL;
289 f_tracking_position = 0;
292 // /////////////////////////////////////////////////////////////////
293 // create_outline_string - create the XmString to display
294 // /////////////////////////////////////////////////////////////////
297 OutlineListView::create_xm_string (OutlineElement *oe, int base_level,
298 unsigned char track_on, char icon)
300 XmString string, tmp, next;
302 unsigned char track = track_on ? 1 : 0; // normalize track_on into 1 or 0
304 // First component is pointer to original element. Motif 1.2
305 // will ignore this component.
307 string = XmStringCreateComponent (XmSTRING_COMPONENT_POINTER,
310 // Next component is expand/contract icon, if any.
311 // 1 for tracker, 1 for arrow, 3 for icon and spacing, 1 for terminator
314 assert ((oe->level() - base_level + 6) * sizeof(char) < 64);
315 // Spaces before and including arrow, if any
316 if (window_system().nofonts())
318 memset (s, ' ', oe->level() - base_level + 1 + track);
330 s[0] = OLIAS_PLACEHOLDER_ICON ;
334 memset (p, OLIAS_PLACEHOLDER_ICON, oe->level() - base_level);
336 unsigned int pos = oe->level() - base_level + track;
338 // Only show the icon if this entry has children and
339 // the max level is unlimited or max level is higher than this level.
341 if (oe->has_children() &&
342 (f_max_level == LEVEL_UNLIMITED || f_max_level > oe->level())) {
343 if (oe->is_expanded (f_data_handle))
344 s[pos] = OLIAS_EXPANDED_ICON;
346 s[pos] = OLIAS_CONTRACTED_ICON;
349 s[pos] = OLIAS_NO_CHILDREN_ICON;
351 // Slot for icon -- plug in icon based on element type.
352 char entry_icon = '\0';
354 if (oe->type() == TOC_Element::TOC_ElementClass)
356 UAS_ObjectType type = ((TOC_Element *) oe)->toc()->type();
360 entry_icon = OLIAS_INFOLIB_ICON;
363 entry_icon = OLIAS_INFOBASE_ICON;
366 entry_icon = OLIAS_BOOK_ICON;
373 if (entry_icon != '\0' && !window_system().nofonts())
375 s[oe->level() - base_level + 1 + track] = OLIAS_SPACE04;
376 s[oe->level() - base_level + 2 + track] = entry_icon;
377 s[oe->level() - base_level + 3 + track] = OLIAS_SPACE04;
378 s[oe->level() - base_level + 4 + track] = '\0';
380 else if (window_system().nofonts())
382 s[oe->level() - base_level + 1 + track] = ' ';
383 s[oe->level() - base_level + 2 + track] = '\0';
386 s[oe->level() - base_level + 1 + track] = '\0';
388 next = XmStringCreate (s, OLIAS_FONT);
393 string = XmStringConcat (tmp, next);
400 // Final component is text of item
401 next = XmStringCreateLocalized ((String) oe->display_as());
403 string = XmStringConcat (tmp, next);
406 // _Xm_dump_external (string);
412 // /////////////////////////////////////////////////////////////////
413 // set_icon - set the icon in the xm string (the quick way)
414 // /////////////////////////////////////////////////////////////////
416 // Warning: This routine depends heavily upon the format of the XmString
417 // generated above. Any changes in that string WILL break this routine.
420 OutlineListView::set_icon (OutlineElement *oe)
422 xmstring (oe, 1); // force creation of string
426 // /////////////////////////////////////////////////////////////////
427 // generate_table - generate XmStringTable starting at list
428 // /////////////////////////////////////////////////////////////////
430 // NOTE: Can probably (and should) change g_element to f_element
431 static OutlineElement *g_element;
434 OutlineListView::generate_table (OutlineList *list, XmStringTable &table,
435 bool *selected_list, u_int level, unsigned force)
440 printf ("In generate_table, list = %p, level = %d\n", list, level);
442 for (i = 0; i < list->length(); i++)
444 g_element = ((OutlineElement *)(*list)[i]);
445 // NOTE: temporary for now - calc level in outline list code - DJB
446 // The level can be stored in the list, instead of the element.
447 // Store pointer to list in each element to back tracing.
449 // Level is initialized on first display.
450 // NOTE: This is a temporary hack. 15:59 01/13/93 DJB
451 if (g_element->string_creator() == 0)
452 g_element->level (level);
454 xmstring (g_element, force); // create the string
456 selected_list[g_table_index] = g_element->is_selected (f_data_handle);
457 table[g_table_index++] = (XmString) g_element->xm_string();
459 // g_element->print();
460 if ((g_element->has_children()) &&
461 g_element->is_expanded (f_data_handle))
462 generate_table (g_element->children(), table, selected_list, level+1, force);
467 // /////////////////////////////////////////////////////////////////
468 // XmStringCreateComponent
469 // /////////////////////////////////////////////////////////////////
472 XmStringCreateComponent (XmStringComponentType tag,
473 void *data, u_int length)
475 // NOTE: Possible improvement is to handle greater lengths, but this
476 // is easiest for now. DJB 8-8-92
477 assert (length <= 124);
479 // Length = ASN header + Component header + data
480 unsigned char total_length = 2 + length;
482 XmString string = (XmString) XtMalloc (total_length + 4);
483 unsigned char *p = (unsigned char*) string;
485 // Write the ASN.1 header (values from XmString.c)
491 // Write the component header
495 memcpy (p, data, length);
497 printf ("data = %p\n", data);
500 printf ("XmStringComponent = ");
501 for (i = 0; i < total_length + 4; i++)
502 printf ("%02x ", string[i]);
509 // /////////////////////////////////////////////////////////////////
510 // y_to_outline_element
511 // /////////////////////////////////////////////////////////////////
514 OutlineListView::y_to_outline_element (Position y)
517 // NOTE: if having problems with list expansion items, check here
519 // NOTE: Motif 1.2 bug alert: YToPos returns zero based, instead of 1 based
522 // NOTE: seems to be fixed returning 1 based
524 f_item_pos = YToPos (y) - 1;
527 printf ("Click in item %d, item count = %d\n", f_item_pos, ItemCount());
529 // Another Motif 1.2 bug. YToPos should return 0 for bogus position,
530 // but it doesn't check the range.
531 if (f_item_pos < 0 || f_item_pos >= ItemCount())
534 oe = item_at (f_item_pos);
537 ON_DEBUG(printf ("Found element %p (%s) at pos %d, level %d\n",
538 oe, oe->display_as(), f_item_pos, oe->level()));
541 f_item_pos++; // Adjust for Motif bug here.
546 // /////////////////////////////////////////////////////////////////
548 // /////////////////////////////////////////////////////////////////
551 OutlineListView::icon_extent(OutlineElement *oe) const
553 ON_DEBUG (printf ("horiz sbar value = %d\n",
554 WXmScrollBar(HorizontalScrollBar()).Value()));
555 ON_DEBUG (printf (" extent = %d\n",
556 f_margin - WXmScrollBar(HorizontalScrollBar()).Value() +
557 icon_width(*this) * (oe->level() - f_base_level + 1 + f_tracking_possible)));
559 return (f_margin - WXmScrollBar(HorizontalScrollBar()).Value() +
560 icon_width(*this) * (oe->level() - f_base_level + 1 + f_tracking_possible));
564 // /////////////////////////////////////////////////////////////////
565 // select_start - mouse button pressed (action proc)
566 // /////////////////////////////////////////////////////////////////
569 OutlineListView::_select_start (Widget w, XEvent *event,
570 String *params, Cardinal *num_params)
573 OutlineListView *lv = (OutlineListView *) W.UserData();
576 lv->select_start (w, event, params, num_params);
580 OutlineListView::select_start (Widget w, XEvent *event,
581 String *params, Cardinal *num_params)
583 if (event->type != ButtonPress)
586 ON_DEBUG(printf ("Select start at (%d, %d)\n",
587 event->xbutton.x, event->xbutton.y));
589 f_outline_element = y_to_outline_element (event->xbutton.y);
592 if (f_outline_element)
594 printf (">>> *** shadow %d, margin %d, highlight %d\n",
595 ShadowThickness(), ListMarginWidth(), HighlightThickness());
597 printf ("margin = %d, icon width = %d, level = %d\n",
598 f_margin, icon_width(*this), f_outline_element->level());
601 printf ("No element found at this location\n");
603 // See if item valid and icon was clicked in.
604 ON_DEBUG (printf ("X pos = %d\n", event->xbutton.x));
605 if (f_outline_element && event->xbutton.x < icon_extent (f_outline_element)
606 && f_outline_element->has_children())
608 ON_DEBUG (puts ("Clicked in an icon #1"));
612 // Set variable to signal that icon was not clicked on. This is
613 // checked in the select_end method.
614 f_outline_element = NULL;
616 ON_DEBUG (puts ("Passing through start"));
617 XtCallActionProc (w, "ListBeginSelect", event, params, *num_params);
621 // /////////////////////////////////////////////////////////////////
622 // select_end - mouse button released (action_proc)
623 // /////////////////////////////////////////////////////////////////
626 OutlineListView::_select_end (Widget w, XEvent *event, String *params,
627 Cardinal *num_params)
630 OutlineListView *lv = (OutlineListView *) W.UserData();
633 lv->select_end (w, event, params, num_params);
637 OutlineListView::select_end (Widget w, XEvent *event,
638 String *params, Cardinal *num_params)
640 if (event->type != ButtonRelease)
643 ON_DEBUG (printf ("Select end at (%d, %d)\n",
644 event->xbutton.x, event->xbutton.y));
646 // See if selection ended on the same item and in range.
647 if (f_outline_element != NULL &&
648 (y_to_outline_element (event->xbutton.y) == f_outline_element) &&
649 f_outline_element && event->xbutton.x < icon_extent (f_outline_element)
650 && f_outline_element->has_children() &&
651 (f_max_level == LEVEL_UNLIMITED ||
652 f_max_level > f_outline_element->level()))
654 ON_DEBUG (puts ("Clicked in an icon #2"));
655 unsigned char current_policy = f_selection_policy;
658 // Remove previous tracking, if any.
659 // Must happen before any expand/contract takes place
660 // or either the position will be wrong, or item hidden.
661 if (f_tracking_position > 0)
663 if (window_system().nofonts())
664 set_track_icon (f_tracking_element, f_tracking_position, ' ');
666 set_track_icon (f_tracking_element, f_tracking_position,
667 OLIAS_PLACEHOLDER_ICON);
668 f_tracking_position = 0;
671 if (f_outline_element->is_expanded (f_data_handle))
673 /* -------- Toggle current state to contracted -------- */
674 f_outline_element->set_contracted (f_data_handle);
676 f_outline_element->children()->count_expanded (f_data_handle);
677 DeleteItemsPos (subcount, f_item_pos + 1);
681 /* -------- Toggle current state to expanded -------- */
682 // Turn on the wait cursor if database access to occur.
683 bool wait_state = FALSE;
684 if (!f_outline_element->children_cached())
686 window_system().set_wait_state (WS_ON);
690 f_outline_element->set_expanded (f_data_handle);
692 f_outline_element->children()->count_expanded (f_data_handle);
693 XmStringTable table = new XmString[subcount];
694 bool *selected_list = new bool[subcount];
696 generate_table (f_outline_element->children(),
697 table, selected_list,
698 f_outline_element->level() + 1);
699 AddItemsUnselected (table, subcount, f_item_pos + 1);
700 // Must be in multiple select mode to add selected items
701 if (f_selection_policy != XmMULTIPLE_SELECT)
703 SelectionPolicy (XmMULTIPLE_SELECT);
704 current_policy = XmMULTIPLE_SELECT;
706 // Bogus Motif should have a routine to select multiple items.
708 if (selected_list[--subcount])
709 SelectPos (f_item_pos + subcount + 1, False);
711 delete selected_list;
713 // Turn the wait cursor off if it was on.
715 window_system().set_wait_state (WS_OFF);
718 // Update the icon for new mode
719 set_icon (f_outline_element);
721 // Tell the list about the change
722 XmString item = (XmString) f_outline_element->xm_string();
723 bool selected = PosSelected (f_item_pos);
724 ReplaceItemsPosUnselected (&item, 1, f_item_pos);
726 // YAMB (Yet Another Motif Bug): Cannot call ReplaceItemsPos
727 // because if the item matches another item in the list that
728 // happens to be selected, the item replaced will be selected.
729 // So, do selection here, if needed.
732 // Bugs Galore!! Motif will automatically (gee thanks)
733 // deselect all other selections on a select call, even
734 // if this list is in extended select mode. Work around
735 // by switching to multiple select mode which allows it.
736 if (current_policy != XmMULTIPLE_SELECT)
738 SelectionPolicy (XmMULTIPLE_SELECT);
739 current_policy = XmMULTIPLE_SELECT;
742 // Select it, do not call the select callback.
743 SelectPos (f_item_pos, False);
746 // Update the tracking if activated.
747 // Must happen after the expand/contract so that the track
748 // location is correctly computed.
749 bool scroll = (f_tracking_element == f_outline_element);
750 if (f_tracking_possible && f_library_agent)
751 f_library_agent->track (scroll);
753 // Switch the policy back, if it had been changed.
754 if (f_selection_policy != current_policy)
755 SelectionPolicy (f_selection_policy);
757 // f_outline_element can only be NULL if the click down wasn't in the icon.
758 else if (f_outline_element == NULL)
760 ON_DEBUG (("Passing through end"));
761 XtCallActionProc (w, "ListEndSelect", event, params, *num_params);
765 ON_DEBUG(puts ("Click down in icon, but click up wasn't"));
770 OutlineListView::update_list(OutlineList *list, BitHandle handle)
772 u_int visible_count = list->count_expanded (handle);
774 XmStringTable table = new XmString[visible_count];
775 bool *selected_list = new bool[visible_count];
777 generate_table (list, table, selected_list, 0, 1);
781 ItemCount (visible_count, args);
785 delete selected_list;
788 // /////////////////////////////////////////////////////////////////
790 // /////////////////////////////////////////////////////////////////
793 OutlineListView::register_actions()
795 static bool registered = FALSE;
799 static XtActionsRec actions_list[] =
801 {"OutlineListBeginSelect", OutlineListView::_select_start},
802 {"OutlineListEndSelect", OutlineListView::_select_end},
806 XtAppAddActions (AppContext(), actions_list, XtNumber (actions_list));
809 /**********************************************************************
810 OutputAnAtomName: Translates a target from its internal atom format into
811 a human readable character string.
812 **********************************************************************/
814 OutputAnAtomName(Widget w, Atom target)
816 char *AtomName = (char *)malloc(sizeof(char *) * 34);
818 AtomName = XGetAtomName(XtDisplay(w), target);
819 printf("\t%s\n", AtomName);
822 // /////////////////////////////////////////////////////////////////
823 // /////////////////////////////////////////////////////////////////
826 OutlineListView::printConvertCallback(WCallback *wcb)
828 XmConvertCallbackStruct *ccs = (XmConvertCallbackStruct *)wcb->CallData();
829 Widget w = wcb->GetWidget();
830 unsigned int * selectedPositions;
831 int selectedItemCount;
832 char filepath[MAXPATHLEN];
833 OutlineElement *oe = NULL;
837 Atom FILE_NAME = XInternAtom(XtDisplay(w), XmSFILE_NAME, False);
838 Atom TARGETS = XInternAtom(XtDisplay(w), XmSTARGETS, False);
839 Atom MOTIF_EXPORT_TARGETS = XInternAtom(XtDisplay(w), XmS_MOTIF_EXPORT_TARGETS, False);
841 RCS_DEBUG("printConvertCallback: called.\n");
847 RCS_DEBUG("\nNow in ConvertCallback.\n");
848 RCS_DEBUG("\tSelection: ");
849 OutputAnAtomName((Widget)w, ccs->selection);
850 RCS_DEBUG("\tTarget: ");
851 OutputAnAtomName((Widget)w, ccs->target);
854 * XmeDragSource is going to call ConvertCallback and ask
855 * it to convert MOTIF_EXPORT_TARGETS.
857 if ( (ccs->target == MOTIF_EXPORT_TARGETS) ||
858 (ccs->target == TARGETS))
862 * this callback must support the FILE_NAME transfer
863 * as this is the mechanism the Printer Icon on the
864 * front panel uses to transfer data.
866 Atom *targs = (Atom *) XtMalloc(sizeof(Atom) * 1);
868 ccs->status = XmCONVERT_REFUSE;
873 targs[n] = FILE_NAME; n++;
875 ccs->value = (XtPointer) targs;
879 ccs->status = XmCONVERT_DONE; /* Yes, we converted the target. */
883 * As the drop site supports FILE_NAME as an import target, then
884 * the drop site will ask ConvertCallback to convert the
885 * value to FILE_NAME format.
887 else if (ccs->target == FILE_NAME) {
890 * Get the text from the container
893 XmNselectedPositions, &selectedPositions,
894 XmNselectedItemCount, &selectedItemCount,
897 f_selected_item_count = selectedItemCount;
899 // This is commented out for now until i go and make this function private
901 tmpfile = _DtActGenerateTmpFile(NULL,
903 ( S_IRUSR|S_IRGRP|S_IWUSR|S_IWGRP),
906 strcpy(filepath, getenv("HOME"));
907 strcat(filepath, "/.dt/tmp/file.itp");
911 fprintf(stderr, "printConvertCallback: temp file = %s.\n", filepath);
913 // open the temporary file for writing
915 if ((fp = fopen(filepath, "w")) == NULL) {
916 fprintf(stderr, "Cannot open file %s.\n", filepath);
919 // write out each element in the list
921 for (int i = 0; i < f_selected_item_count; i++) {
922 oe = item_at(selectedPositions[i] - 1) ;
923 TOC_Element *te = (TOC_Element *)oe;
925 // write out the locator
926 if (fputs(((TOC_Element *)te)->toc()->locator(), fp) == EOF) {
927 fprintf(stderr, "Cannot write file %s in current directory.\n", filepath);
932 if (fputs("\n", fp) == EOF) {
933 fprintf(stderr, "Cannot write file %s in current directory.\n", filepath);
942 AppPrintData* p = window_system().GetAppPrintData();
943 p->f_pshell_parent = w;
945 // Assign file name to XmConvertCallbackStruct.
947 ccs->value = (XtPointer)filepath;
948 ccs->type = XA_STRING;
949 ccs->length = strlen(filepath);
951 ccs->status = XmCONVERT_DONE;
955 /* Unexpected target. */
956 ccs->status = XmCONVERT_REFUSE;
960 // /////////////////////////////////////////////////////////////////
961 // select - selection callback
962 // /////////////////////////////////////////////////////////////////
965 OutlineListView::select (WCallback *wcb)
967 XmListCallbackStruct *lcs = (XmListCallbackStruct *) wcb->CallData();
968 XmStringTable items = Items();
969 OutlineElement *oe = NULL;
971 DEBUGF (("**** select: item count = %d, pos = %d, selected = %s\n",
972 lcs->selected_item_count, lcs->item_position,
973 (PosSelected (lcs->item_position) ? "true" : "false")));
975 // DEBUGF ((">>>> SELECTION TYPE <<< %d\n", lcs->selection_type));
977 /* Fix for DTS #6303 -- Removed "if" statement. Always deselect all. */
978 deselect (f_list, DESELECT_ALL);
980 if (f_selection_policy == XmMULTIPLE_SELECT ||
981 f_selection_policy == XmEXTENDED_SELECT)
983 f_selected_item_count = lcs->selected_item_count;
985 printf ("selected # = %d\n", f_selected_item_count);
986 printf (" # = %d\n", SelectedItemCount());
988 for (int i = 0; i < f_selected_item_count; i++)
990 DEBUGF (("M-> extracting at %d\n", lcs->selected_item_positions[i]));
991 oe = item_at(lcs->selected_item_positions[i] - 1) ;
992 oe->set_selected (f_data_handle);
994 // Make the current selection the last item selected. This is
995 // (unfortunately) used by the LibraryAgent for the detach feature.
996 // The reason is that the Document List didn't support these selection
997 // modes until printing was added and could only have one selection.
998 // If there's more than one selection it won't matter because the
999 // Detach button will be insensitive.
1000 f_current_selection = oe;
1004 if (PosSelected (lcs->item_position))
1006 DEBUGF (("--> extracting pointer @ %d\n", lcs->item_position));
1007 oe = item_at(lcs->item_position - 1) ;
1008 oe->set_selected (f_data_handle);
1009 // Save the selection:
1010 f_current_selection = oe;
1011 f_selected_item_count = 1;
1014 if (f_selected_item_count != 1) // 94/10/28 haya
1015 f_item_pos = 0; // modify to change sensitive of detach
1016 else // button by cursol key.
1017 f_item_pos = *lcs->selected_item_positions; //
1019 notify (ENTRY_SELECTED);
1021 // DISCOURSE: If the list is in extended selection mode it is possible
1022 // for the user to toggle in and out of add mode (cf. Motif Style Guide
1023 // 1.2 pg. 4-6). Unfortunately there's no way for us to know if he is
1024 // in add mode, but that's ok for now, since there's a bug in Motif 1.2
1025 // which deselects the previous selection, even when add mode is on and
1026 // the selection policy is extended select.
1030 // /////////////////////////////////////////////////////////////////
1031 // deselect - turn off select bit in in-memory elements in list
1032 // /////////////////////////////////////////////////////////////////
1034 #define OUTLINE_ELEMENT(I) ((OutlineElement *)(*list)[I])
1037 OutlineListView::deselect (OutlineList *list, deselect_mode_t mode)
1041 for (i = 0; i < list->length(); i++)
1043 OUTLINE_ELEMENT(i)->unset_selected (f_data_handle);
1044 if (OUTLINE_ELEMENT(i)->children_cached() &&
1045 OUTLINE_ELEMENT(i)->has_children() &&
1046 (mode == DESELECT_ALL ||
1047 OUTLINE_ELEMENT(i)->is_expanded (f_data_handle)))
1048 deselect (OUTLINE_ELEMENT(i)->children(), mode);
1053 // /////////////////////////////////////////////////////////////////
1054 // activate - activate callback
1056 // Here's the deal: to get a consistent result for "activate" on any
1057 // entry in the booklist, such expert activation will always** do at
1058 // least an open of the object in the/a reading window. If the item
1059 // also is the parent of a sub-hierarchy of more nodes, the first
1060 // level beneath this object will be expanded [or contracted] in the
1061 // booklist. No expansion will occur, of course, if it is the lowest
1062 // leaf in the tree. A TOC (== a "Book" level) will display its TOC
1063 // page per its OutlineElement type; all other entries will display
1064 // the document or the top-most document in the sub-hierarchy. -jcb
1066 // ** Only if an entry has children and is initially expanded,
1067 // double-click contracts it, but does Not [re-]display its topmost
1068 // document. The assumption is being made that user Contract of a
1069 // hierarchical level is more often than not an expression of lesser
1070 // interest in its content. In many cases, the topmost doc will have
1071 // been previously displayed by a double-click on the entry while
1072 // contracted, anyway.
1074 // Also, the double-click action "selects" only the activated entry.
1075 // /////////////////////////////////////////////////////////////////
1078 OutlineListView::activate (WCallback *wcb)
1080 XmListCallbackStruct *lcs = (XmListCallbackStruct *) wcb->CallData();
1081 XmStringTable items = Items();
1083 int expanded = False;
1085 oe = item_at(lcs->item_position - 1) ;
1088 if( oe == NULL ) printf( "OLV::activate: NULL outline element pointer\n" ) ;
1091 if ( oe->has_children() )
1095 // Remove previous tracking, if any.
1096 // Must happen before any expand/contract takes place
1097 // or either the position will be wrong, or item hidden.
1098 if (f_tracking_position > 0)
1100 if (window_system().nofonts())
1101 set_track_icon (f_tracking_element, f_tracking_position, ' ');
1103 set_track_icon (f_tracking_element, f_tracking_position,
1104 OLIAS_PLACEHOLDER_ICON);
1105 f_tracking_position = 0;
1108 if (oe->is_expanded (f_data_handle))
1112 printf( "OLV::activate: entry is Expanded\n" ) ;
1114 /* -------- Toggle current state to contracted -------- */
1115 oe->set_contracted (f_data_handle);
1117 oe->children()->count_expanded (f_data_handle);
1118 DeleteItemsPos (subcount, lcs->item_position + 1);
1123 printf( "OLV::activate: entry is Not expanded\n" ) ;
1125 /* -------- Toggle current state to expanded -------- */
1126 // Turn on the wait cursor if database access to occur.
1127 bool wait_state = FALSE;
1128 if (!oe->children_cached())
1130 window_system().set_wait_state (WS_ON);
1134 oe->set_expanded (f_data_handle);
1136 oe->children()->count_expanded (f_data_handle);
1137 XmStringTable table = new XmString[subcount];
1138 bool *sel_list = new bool[subcount];
1140 generate_table (oe->children(),
1143 AddItemsUnselected (table, subcount, lcs->item_position + 1);
1147 // Turn the wait cursor off if it was on.
1149 window_system().set_wait_state (WS_OFF);
1152 // Update the icon for new mode
1154 // Tell the list about the change
1155 XmString item = (XmString) oe->xm_string();
1156 ReplaceItemsPosUnselected (&item, 1, lcs->item_position);
1158 // Update the tracking if activated.
1159 // Must happen after the expand/contract so that the track
1160 // location is correctly computed.
1161 bool scroll = (f_tracking_element == oe);
1162 if (f_tracking_possible && f_library_agent)
1163 f_library_agent->track (scroll);
1167 // seems to occur ok for has_children case, above...
1168 deselect (f_list, DESELECT_ALL);
1171 // Select it as the only selection; do not call the select callback.
1172 // Need to reset all class pointers to elements or item pos, regardless
1173 // of traversal method paths in which used by class.
1174 SelectPos (lcs->item_position, True);
1175 oe->set_selected (f_data_handle);
1176 f_current_selection = oe;
1177 f_selected_item_count = 1;
1178 f_item_pos = lcs->item_position;
1180 f_outline_element = NULL; // because it should be with this path
1183 ON_DEBUG(cout << ">>>>>> CALLING DISPLAY ON ELEMENT <<<<<<" << endl);
1185 if ((oe->type() == TOC_Element::TOC_ElementClass) && !expanded)
1188 UAS_ObjectType type = ((TOC_Element *) oe)->toc()->type();
1193 UAS_List<UAS_Common> kids =
1194 ((TOC_Element *)oe)->toc()->children();
1195 if ( (kids != (const int)NULL)
1196 && (kids[0] != (const int)NULL)
1197 && (kids[0]->type() == UAS_BOOKCASE))
1199 UAS_List<UAS_Common> bckids = kids[0]->children();
1200 if (! (bckids[0] == (const int)NULL))
1202 bckids[0]->retrieve();
1210 UAS_List<UAS_Common> kids =
1211 ((TOC_Element *)oe)->toc()->children();
1212 if (! (kids[0] == (const int)NULL))
1214 kids[0]->retrieve();
1221 // let the OutlineElement "display" method handle it.
1228 message_mgr().error_dialog( (char*)UAS_String(CATGETS(
1229 Set_UrlAgent, 5, "Document not found." )) ) ;
1233 else if (oe->type() != TOC_Element::TOC_ElementClass) oe->display();
1237 // /////////////////////////////////////////////////////////////////
1238 // data_handle - return a new data handle
1239 // /////////////////////////////////////////////////////////////////
1243 OutlineListView::data_handle (BitHandle new_handle)
1245 f_data_handle = new_handle;
1246 // Need a variable since routine modifies it.
1248 update_highlighting (f_list, item_pos);
1253 // NOTE: is the calling objects responsibility to make sure that expanded
1254 // flag is correct with the current visual representation
1256 // /////////////////////////////////////////////////////////////////
1257 // update_highlighting
1258 // /////////////////////////////////////////////////////////////////
1262 OutlineListView::update_highlighting_recursive (OutlineList *list,
1265 for (int i = 0; i < list->length(); i++)
1267 // Select it, do not call the select callback.
1268 if (OUTLINE_ELEMENT(i)->is_selected (f_data_handle))
1270 if (!PosSelected(item_pos))
1272 SelectPos (item_pos, False);
1275 DeselectPos(item_pos);
1279 if (OUTLINE_ELEMENT(i)->is_expanded (f_data_handle) &&
1280 OUTLINE_ELEMENT(i)->has_children())
1281 update_highlighting (OUTLINE_ELEMENT(i)->children(), item_pos);
1287 OutlineListView::update_highlighting (OutlineList *list, u_int &item_pos)
1296 // Motif bug - see above.
1297 unsigned char current_policy = f_selection_policy;
1299 if (f_selection_policy != XmMULTIPLE_SELECT)
1301 current_policy = f_selection_policy;
1302 f_selection_policy = XmMULTIPLE_SELECT;
1303 SelectionPolicy (f_selection_policy);
1306 update_highlighting_recursive (list, item_pos);
1308 // Switch the policy back, if it was changed.
1309 if (f_selection_policy != current_policy)
1311 f_selection_policy = current_policy;
1312 SelectionPolicy (f_selection_policy);
1317 // /////////////////////////////////////////////////////////////////
1318 // selected_item_list
1319 // /////////////////////////////////////////////////////////////////
1322 OutlineListView::selected_item_list()
1324 return (f_list->selected_items (f_data_handle));
1328 // /////////////////////////////////////////////////////////////////
1330 // /////////////////////////////////////////////////////////////////
1333 OutlineListView::clear()
1336 deselect(f_list, DESELECT_ALL);
1337 f_selected_item_count = 0;
1340 // /////////////////////////////////////////////////////////////////
1341 // track_to - display tracking icon at specified position
1342 // /////////////////////////////////////////////////////////////////
1345 OutlineListView::track_to (OutlineElement *oe, u_int position, char icon)
1347 // Remove the old tracking icon, if any set.
1348 if (f_tracking_position > 0)
1349 if (window_system().nofonts())
1350 set_track_icon (f_tracking_element, f_tracking_position, ' ');
1352 set_track_icon (f_tracking_element, f_tracking_position,
1353 OLIAS_PLACEHOLDER_ICON);
1355 // Set the new tracking icon.
1356 set_track_icon (oe, position, icon);
1357 f_tracking_position = position;
1358 f_tracking_element = oe;
1363 OutlineListView::untrack()
1365 if (f_tracking_position > 0)
1366 if (window_system().nofonts())
1367 set_track_icon (f_tracking_element, f_tracking_position, ' ');
1369 set_track_icon (f_tracking_element, f_tracking_position,
1370 OLIAS_PLACEHOLDER_ICON);
1372 f_tracking_position = 0;
1376 // Warning: This routine depends heavily upon the format of the XmString
1377 // generated earlier. Any changes in that string WILL break this routine.
1380 OutlineListView::set_track_icon (OutlineElement *oe, u_int position, char icon)
1382 xmstring (oe, 1, icon);
1384 XmStringTable items = Items();
1386 // Tell the list about the change
1387 XmString item = (XmString) oe->xm_string();
1388 bool selected = PosSelected (position);
1389 ReplaceItemsPosUnselected (&item, 1, position);
1392 unsigned char current_policy = f_selection_policy;
1393 if (current_policy != XmMULTIPLE_SELECT)
1395 SelectionPolicy (XmMULTIPLE_SELECT);
1396 current_policy = XmMULTIPLE_SELECT;
1399 // Select it, do not call the select callback.
1400 SelectPos (position, False);
1401 // Switch the policy back, if it had been changed.
1402 if (f_selection_policy != current_policy)
1403 SelectionPolicy (f_selection_policy);
1407 // OutlineListView::item_at(position)
1409 // return the OutlineElement that is visible at 'position' in
1414 OutlineListView::item_at(unsigned int position)
1416 OutlineList *lptr = f_list ;
1417 unsigned int count = 0 ;
1418 unsigned int offset = 0 ;
1420 ON_DEBUG(cerr << "item_at: " << position << endl);
1422 // start at the beginning and descend the nested lists until we
1423 // reach the desired position, and return the element there
1425 OutlineElement *element = (OutlineElement *) (*lptr)[offset] ;
1426 while (count < position)
1428 if (element->is_expanded(f_data_handle) && element->has_children())
1430 if (count + element->children()->count_expanded(f_data_handle) >= position)
1432 ON_DEBUG(cerr << "descend: " << element->display_as() << endl);
1433 lptr = element->children();
1438 count += element->children()->count_expanded(f_data_handle) ;
1444 offset++ ; // go to the next one
1446 element = (OutlineElement*) (*lptr)[offset] ;
1449 ON_DEBUG(cerr << "item_at ==> " << element->display_as() << endl);