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>
78 #include <sys/param.h>
81 #define DEBUGF(X) printf X
87 # define RCS_DEBUG(statement) cerr << statement << endl
89 # define RCS_DEBUG(statement)
92 extern "C" { void _Xm_dump_external(XmString); }
95 XmStringCreateComponent (XmStringComponentType tag, void *data, u_int length);
96 static void register_actions();
98 enum { XmSTRING_COMPONENT_POINTER = XmSTRING_COMPONENT_USER_BEGIN };
101 // /////////////////////////////////////////////////////////////////
103 // /////////////////////////////////////////////////////////////////
105 OutlineListView::OutlineListView (const WComposite &parent, const char *name,
107 bool enable_activate)
108 : WXmList ((Widget) NULL), f_list (NULL), f_max_level (LEVEL_UNLIMITED),
109 f_current_selection (NULL), f_selected_item_count(0),
110 f_tracking_position (0),
111 f_tracking_element (NULL),
112 f_library_agent (NULL)
114 static int serial_number = 1;
116 // Assign a unique serial number to this outline list.
117 f_serial_number = serial_number++;
119 // Non-scrolled list is useless so make it a scrolled list.
120 widget = XmCreateScrolledList (parent, (char *) name, NULL, 0);
123 // if dtinfo_font is defined then get the fontlist for the widget
124 // and append thte dtinfo_font
126 if (window_system().dtinfo_font()) {
127 XmFontList tempFontList, defaultList;
129 // get the current font list and make a copy
130 XtVaGetValues(widget, XmNfontList, &tempFontList, NULL);
131 defaultList = XmFontListCopy(tempFontList);
133 // append the dtinfo font. XmFontListAppendEntry deallocates the original font list after
134 // extracting the required information.
136 defaultList = XmFontListAppendEntry(defaultList, window_system().dtinfo_font());
138 // set the new new font list back
139 XtVaSetValues(widget, XmNfontList, defaultList, NULL);
143 // Save this pointer in user data of widget so that actions can
148 printf (">>> *** shadow %d, margin %d, highlight %d\n",
149 ShadowThickness(), ListMarginWidth(), HighlightThickness());
151 f_margin = ShadowThickness() + ListMarginWidth() + HighlightThickness();
152 f_selection_policy = SelectionPolicy();
156 SetSingleSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
157 SetBrowseSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
158 SetExtendedSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
159 SetMultipleSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
161 SetConvertCallback (this, (WWL_FUN) &OutlineListView::printConvertCallback);
165 SetDefaultActionCallback (this, (WWL_FUN) &OutlineListView::activate);
166 f_tracking_possible = 1;
170 f_tracking_possible = 0;
180 XmFontList defaultList;
181 XtVaGetValues(w, XmNfontList, &defaultList, NULL);
183 // Setup parameters for calculating click position.
185 if (window_system().nofonts())
188 string[0] = OLIAS_PLACEHOLDER_ICON;
190 XmString thing = XmStringCreate (string, (char*)OLIAS_FONT);
192 Dimension rval = XmStringWidth(defaultList, thing);
193 XmStringFree (thing);
198 // /////////////////////////////////////////////////////////////////
200 // /////////////////////////////////////////////////////////////////
202 OutlineListView::~OutlineListView()
206 f_data_handle = library_mgr().library().get_data_handle();
211 // /////////////////////////////////////////////////////////////////
212 // xmstring - return the xm string given an outline element
213 // /////////////////////////////////////////////////////////////////
216 OutlineListView::xmstring (OutlineElement *oe, unsigned force, char icon)
218 if (force || (oe->string_creator() != f_serial_number))
220 if (oe->xm_string() != NULL)
221 XmStringFree ((XmString) oe->xm_string());
222 oe->set_xm_string ((void *) create_xm_string (oe, f_base_level,
223 f_tracking_possible, icon));
224 oe->string_creator (f_serial_number);
226 return ((XmString) oe->xm_string());
230 // /////////////////////////////////////////////////////////////////
231 // set_list - set the list
232 // /////////////////////////////////////////////////////////////////
235 OutlineListView::set_list (OutlineList *list, BitHandle handle)
237 // NOTE: Eventually it should be possible to set the list to NULL.
238 if (f_list != NULL && f_list != list )
239 list->free_data_handle (f_data_handle);
243 f_data_handle = handle ;
245 f_data_handle = list->get_data_handle();
246 // Determine the base level.
248 if (list->length() > 0) {
249 // SWM -- need to change this so that when determining
250 // the base level, we check all of the roots...
251 f_base_level = ((OutlineElement *)(*list)[0])->level();
253 ON_DEBUG(printf (">> OutlineList base level = %d\n", f_base_level));
258 // /////////////////////////////////////////////////////////////////
259 // regen_list - regenerate list based on internal list
260 // /////////////////////////////////////////////////////////////////
262 static u_int g_table_index;
265 OutlineListView::regen_list()
267 Xassert (f_list != NULL);
268 // if list is null we should just empty the list.
270 u_int visible_count = f_list->count_expanded (f_data_handle);
272 XmStringTable table = new XmString[visible_count];
273 bool *selected_list = new bool[visible_count];
276 generate_table (f_list, table, selected_list, 0);
280 ItemCount (visible_count, args);
284 delete [] selected_list;
287 // reset tracking position to let dtinfo determine
288 // the new position in track_to()
289 f_tracking_element = NULL;
290 f_tracking_position = 0;
293 // /////////////////////////////////////////////////////////////////
294 // create_outline_string - create the XmString to display
295 // /////////////////////////////////////////////////////////////////
298 OutlineListView::create_xm_string (OutlineElement *oe, int base_level,
299 unsigned char track_on, char icon)
301 XmString string, tmp, next;
303 unsigned char track = track_on ? 1 : 0; // normalize track_on into 1 or 0
305 // First component is pointer to original element. Motif 1.2
306 // will ignore this component.
308 string = XmStringCreateComponent (XmSTRING_COMPONENT_POINTER,
311 // Next component is expand/contract icon, if any.
312 // 1 for tracker, 1 for arrow, 3 for icon and spacing, 1 for terminator
315 assert ((oe->level() - base_level + 6) * sizeof(char) < 64);
316 // Spaces before and including arrow, if any
317 if (window_system().nofonts())
319 memset (s, ' ', oe->level() - base_level + 1 + track);
331 s[0] = OLIAS_PLACEHOLDER_ICON ;
335 memset (p, OLIAS_PLACEHOLDER_ICON, oe->level() - base_level);
337 unsigned int pos = oe->level() - base_level + track;
339 // Only show the icon if this entry has children and
340 // the max level is unlimited or max level is higher than this level.
342 if (oe->has_children() &&
343 (f_max_level == LEVEL_UNLIMITED || f_max_level > oe->level())) {
344 if (oe->is_expanded (f_data_handle))
345 s[pos] = OLIAS_EXPANDED_ICON;
347 s[pos] = OLIAS_CONTRACTED_ICON;
350 s[pos] = OLIAS_NO_CHILDREN_ICON;
352 // Slot for icon -- plug in icon based on element type.
353 char entry_icon = '\0';
355 if (oe->type() == TOC_Element::TOC_ElementClass)
357 UAS_ObjectType type = ((TOC_Element *) oe)->toc()->type();
361 entry_icon = OLIAS_INFOLIB_ICON;
364 entry_icon = OLIAS_INFOBASE_ICON;
367 entry_icon = OLIAS_BOOK_ICON;
374 if (entry_icon != '\0' && !window_system().nofonts())
376 s[oe->level() - base_level + 1 + track] = OLIAS_SPACE04;
377 s[oe->level() - base_level + 2 + track] = entry_icon;
378 s[oe->level() - base_level + 3 + track] = OLIAS_SPACE04;
379 s[oe->level() - base_level + 4 + track] = '\0';
381 else if (window_system().nofonts())
383 s[oe->level() - base_level + 1 + track] = ' ';
384 s[oe->level() - base_level + 2 + track] = '\0';
387 s[oe->level() - base_level + 1 + track] = '\0';
389 next = XmStringCreate (s, (char*)OLIAS_FONT);
394 string = XmStringConcat (tmp, next);
401 // Final component is text of item
402 next = XmStringCreateLocalized ((String) oe->display_as());
404 string = XmStringConcat (tmp, next);
407 // _Xm_dump_external (string);
413 // /////////////////////////////////////////////////////////////////
414 // set_icon - set the icon in the xm string (the quick way)
415 // /////////////////////////////////////////////////////////////////
417 // Warning: This routine depends heavily upon the format of the XmString
418 // generated above. Any changes in that string WILL break this routine.
421 OutlineListView::set_icon (OutlineElement *oe)
423 xmstring (oe, 1); // force creation of string
427 // /////////////////////////////////////////////////////////////////
428 // generate_table - generate XmStringTable starting at list
429 // /////////////////////////////////////////////////////////////////
431 // NOTE: Can probably (and should) change g_element to f_element
432 static OutlineElement *g_element;
435 OutlineListView::generate_table (OutlineList *list, XmStringTable &table,
436 bool *selected_list, u_int level, unsigned force)
441 printf ("In generate_table, list = %p, level = %d\n", list, level);
443 for (i = 0; i < list->length(); i++)
445 g_element = ((OutlineElement *)(*list)[i]);
446 // NOTE: temporary for now - calc level in outline list code - DJB
447 // The level can be stored in the list, instead of the element.
448 // Store pointer to list in each element to back tracing.
450 // Level is initialized on first display.
451 // NOTE: This is a temporary hack. 15:59 01/13/93 DJB
452 if (g_element->string_creator() == 0)
453 g_element->level (level);
455 xmstring (g_element, force); // create the string
457 selected_list[g_table_index] = g_element->is_selected (f_data_handle);
458 table[g_table_index++] = (XmString) g_element->xm_string();
460 // g_element->print();
461 if ((g_element->has_children()) &&
462 g_element->is_expanded (f_data_handle))
463 generate_table (g_element->children(), table, selected_list, level+1, force);
468 // /////////////////////////////////////////////////////////////////
469 // XmStringCreateComponent
470 // /////////////////////////////////////////////////////////////////
473 XmStringCreateComponent (XmStringComponentType tag,
474 void *data, u_int length)
476 // NOTE: Possible improvement is to handle greater lengths, but this
477 // is easiest for now. DJB 8-8-92
478 assert (length <= 124);
480 // Length = ASN header + Component header + data
481 unsigned char total_length = 2 + length;
483 XmString string = (XmString) XtMalloc (total_length + 4);
484 unsigned char *p = (unsigned char*) string;
486 // Write the ASN.1 header (values from XmString.c)
492 // Write the component header
496 memcpy (p, data, length);
498 printf ("data = %p\n", data);
501 printf ("XmStringComponent = ");
502 for (i = 0; i < total_length + 4; i++)
503 printf ("%02x ", string[i]);
510 // /////////////////////////////////////////////////////////////////
511 // y_to_outline_element
512 // /////////////////////////////////////////////////////////////////
515 OutlineListView::y_to_outline_element (Position y)
518 // NOTE: if having problems with list expansion items, check here
520 // NOTE: Motif 1.2 bug alert: YToPos returns zero based, instead of 1 based
523 // NOTE: seems to be fixed returning 1 based
525 f_item_pos = YToPos (y) - 1;
528 printf ("Click in item %d, item count = %d\n", f_item_pos, ItemCount());
530 // Another Motif 1.2 bug. YToPos should return 0 for bogus position,
531 // but it doesn't check the range.
532 if (f_item_pos < 0 || f_item_pos >= ItemCount())
535 oe = item_at (f_item_pos);
538 ON_DEBUG(printf ("Found element %p (%s) at pos %d, level %d\n",
539 oe, oe->display_as(), f_item_pos, oe->level()));
542 f_item_pos++; // Adjust for Motif bug here.
547 // /////////////////////////////////////////////////////////////////
549 // /////////////////////////////////////////////////////////////////
552 OutlineListView::icon_extent(OutlineElement *oe) const
554 ON_DEBUG (printf ("horiz sbar value = %d\n",
555 WXmScrollBar(HorizontalScrollBar()).Value()));
556 ON_DEBUG (printf (" extent = %d\n",
557 f_margin - WXmScrollBar(HorizontalScrollBar()).Value() +
558 icon_width(*this) * (oe->level() - f_base_level + 1 + f_tracking_possible)));
560 return (f_margin - WXmScrollBar(HorizontalScrollBar()).Value() +
561 icon_width(*this) * (oe->level() - f_base_level + 1 + f_tracking_possible));
565 // /////////////////////////////////////////////////////////////////
566 // select_start - mouse button pressed (action proc)
567 // /////////////////////////////////////////////////////////////////
570 OutlineListView::_select_start (Widget w, XEvent *event,
571 String *params, Cardinal *num_params)
574 OutlineListView *lv = (OutlineListView *) W.UserData();
577 lv->select_start (w, event, params, num_params);
581 OutlineListView::select_start (Widget w, XEvent *event,
582 String *params, Cardinal *num_params)
584 if (event->type != ButtonPress)
587 ON_DEBUG(printf ("Select start at (%d, %d)\n",
588 event->xbutton.x, event->xbutton.y));
590 f_outline_element = y_to_outline_element (event->xbutton.y);
593 if (f_outline_element)
595 printf (">>> *** shadow %d, margin %d, highlight %d\n",
596 ShadowThickness(), ListMarginWidth(), HighlightThickness());
598 printf ("margin = %d, icon width = %d, level = %d\n",
599 f_margin, icon_width(*this), f_outline_element->level());
602 printf ("No element found at this location\n");
604 // See if item valid and icon was clicked in.
605 ON_DEBUG (printf ("X pos = %d\n", event->xbutton.x));
606 if (f_outline_element && event->xbutton.x < icon_extent (f_outline_element)
607 && f_outline_element->has_children())
609 ON_DEBUG (puts ("Clicked in an icon #1"));
613 // Set variable to signal that icon was not clicked on. This is
614 // checked in the select_end method.
615 f_outline_element = NULL;
617 ON_DEBUG (puts ("Passing through start"));
618 XtCallActionProc (w, "ListBeginSelect", event, params, *num_params);
622 // /////////////////////////////////////////////////////////////////
623 // select_end - mouse button released (action_proc)
624 // /////////////////////////////////////////////////////////////////
627 OutlineListView::_select_end (Widget w, XEvent *event, String *params,
628 Cardinal *num_params)
631 OutlineListView *lv = (OutlineListView *) W.UserData();
634 lv->select_end (w, event, params, num_params);
638 OutlineListView::select_end (Widget w, XEvent *event,
639 String *params, Cardinal *num_params)
641 if (event->type != ButtonRelease)
644 ON_DEBUG (printf ("Select end at (%d, %d)\n",
645 event->xbutton.x, event->xbutton.y));
647 // See if selection ended on the same item and in range.
648 if (f_outline_element != NULL &&
649 (y_to_outline_element (event->xbutton.y) == f_outline_element) &&
650 f_outline_element && event->xbutton.x < icon_extent (f_outline_element)
651 && f_outline_element->has_children() &&
652 (f_max_level == LEVEL_UNLIMITED ||
653 f_max_level > f_outline_element->level()))
655 ON_DEBUG (puts ("Clicked in an icon #2"));
656 unsigned char current_policy = f_selection_policy;
659 // Remove previous tracking, if any.
660 // Must happen before any expand/contract takes place
661 // or either the position will be wrong, or item hidden.
662 if (f_tracking_position > 0)
664 if (window_system().nofonts())
665 set_track_icon (f_tracking_element, f_tracking_position, ' ');
667 set_track_icon (f_tracking_element, f_tracking_position,
668 OLIAS_PLACEHOLDER_ICON);
669 f_tracking_position = 0;
672 if (f_outline_element->is_expanded (f_data_handle))
674 /* -------- Toggle current state to contracted -------- */
675 f_outline_element->set_contracted (f_data_handle);
677 f_outline_element->children()->count_expanded (f_data_handle);
678 DeleteItemsPos (subcount, f_item_pos + 1);
682 /* -------- Toggle current state to expanded -------- */
683 // Turn on the wait cursor if database access to occur.
684 bool wait_state = FALSE;
685 if (!f_outline_element->children_cached())
687 window_system().set_wait_state (WS_ON);
691 f_outline_element->set_expanded (f_data_handle);
693 f_outline_element->children()->count_expanded (f_data_handle);
694 XmStringTable table = new XmString[subcount];
695 bool *selected_list = new bool[subcount];
697 generate_table (f_outline_element->children(),
698 table, selected_list,
699 f_outline_element->level() + 1);
700 AddItemsUnselected (table, subcount, f_item_pos + 1);
701 // Must be in multiple select mode to add selected items
702 if (f_selection_policy != XmMULTIPLE_SELECT)
704 SelectionPolicy (XmMULTIPLE_SELECT);
705 current_policy = XmMULTIPLE_SELECT;
707 // Bogus Motif should have a routine to select multiple items.
709 if (selected_list[--subcount])
710 SelectPos (f_item_pos + subcount + 1, False);
712 delete selected_list;
714 // Turn the wait cursor off if it was on.
716 window_system().set_wait_state (WS_OFF);
719 // Update the icon for new mode
720 set_icon (f_outline_element);
722 // Tell the list about the change
723 XmString item = (XmString) f_outline_element->xm_string();
724 bool selected = PosSelected (f_item_pos);
725 ReplaceItemsPosUnselected (&item, 1, f_item_pos);
727 // YAMB (Yet Another Motif Bug): Cannot call ReplaceItemsPos
728 // because if the item matches another item in the list that
729 // happens to be selected, the item replaced will be selected.
730 // So, do selection here, if needed.
733 // Bugs Galore!! Motif will automatically (gee thanks)
734 // deselect all other selections on a select call, even
735 // if this list is in extended select mode. Work around
736 // by switching to multiple select mode which allows it.
737 if (current_policy != XmMULTIPLE_SELECT)
739 SelectionPolicy (XmMULTIPLE_SELECT);
740 current_policy = XmMULTIPLE_SELECT;
743 // Select it, do not call the select callback.
744 SelectPos (f_item_pos, False);
747 // Update the tracking if activated.
748 // Must happen after the expand/contract so that the track
749 // location is correctly computed.
750 bool scroll = (f_tracking_element == f_outline_element);
751 if (f_tracking_possible && f_library_agent)
752 f_library_agent->track (scroll);
754 // Switch the policy back, if it had been changed.
755 if (f_selection_policy != current_policy)
756 SelectionPolicy (f_selection_policy);
758 // f_outline_element can only be NULL if the click down wasn't in the icon.
759 else if (f_outline_element == NULL)
761 ON_DEBUG (("Passing through end"));
762 XtCallActionProc (w, "ListEndSelect", event, params, *num_params);
766 ON_DEBUG(puts ("Click down in icon, but click up wasn't"));
771 OutlineListView::update_list(OutlineList *list, BitHandle handle)
773 u_int visible_count = list->count_expanded (handle);
775 XmStringTable table = new XmString[visible_count];
776 bool *selected_list = new bool[visible_count];
778 generate_table (list, table, selected_list, 0, 1);
782 ItemCount (visible_count, args);
786 delete selected_list;
789 // /////////////////////////////////////////////////////////////////
791 // /////////////////////////////////////////////////////////////////
794 OutlineListView::register_actions()
796 static bool registered = FALSE;
800 static XtActionsRec actions_list[] =
802 {(char*)"OutlineListBeginSelect", OutlineListView::_select_start},
803 {(char*)"OutlineListEndSelect", OutlineListView::_select_end},
807 XtAppAddActions (AppContext(), actions_list, XtNumber (actions_list));
810 /**********************************************************************
811 OutputAnAtomName: Translates a target from its internal atom format into
812 a human readable character string.
813 **********************************************************************/
815 OutputAnAtomName(Widget w, Atom target)
817 char *AtomName = (char *)malloc(sizeof(char *) * 34);
819 AtomName = XGetAtomName(XtDisplay(w), target);
820 printf("\t%s\n", AtomName);
823 // /////////////////////////////////////////////////////////////////
824 // /////////////////////////////////////////////////////////////////
827 OutlineListView::printConvertCallback(WCallback *wcb)
829 XmConvertCallbackStruct *ccs = (XmConvertCallbackStruct *)wcb->CallData();
830 Widget w = wcb->GetWidget();
831 unsigned int * selectedPositions;
832 int selectedItemCount;
833 char filepath[MAXPATHLEN];
834 OutlineElement *oe = NULL;
838 Atom FILE_NAME = XInternAtom(XtDisplay(w), XmSFILE_NAME, False);
839 Atom TARGETS = XInternAtom(XtDisplay(w), XmSTARGETS, False);
840 Atom MOTIF_EXPORT_TARGETS = XInternAtom(XtDisplay(w), XmS_MOTIF_EXPORT_TARGETS, False);
842 RCS_DEBUG("printConvertCallback: called.\n");
848 RCS_DEBUG("\nNow in ConvertCallback.\n");
849 RCS_DEBUG("\tSelection: ");
850 OutputAnAtomName((Widget)w, ccs->selection);
851 RCS_DEBUG("\tTarget: ");
852 OutputAnAtomName((Widget)w, ccs->target);
855 * XmeDragSource is going to call ConvertCallback and ask
856 * it to convert MOTIF_EXPORT_TARGETS.
858 if ( (ccs->target == MOTIF_EXPORT_TARGETS) ||
859 (ccs->target == TARGETS))
863 * this callback must support the FILE_NAME transfer
864 * as this is the mechanism the Printer Icon on the
865 * front panel uses to transfer data.
867 Atom *targs = (Atom *) XtMalloc(sizeof(Atom) * 1);
869 ccs->status = XmCONVERT_REFUSE;
874 targs[n] = FILE_NAME; n++;
876 ccs->value = (XtPointer) targs;
880 ccs->status = XmCONVERT_DONE; /* Yes, we converted the target. */
884 * As the drop site supports FILE_NAME as an import target, then
885 * the drop site will ask ConvertCallback to convert the
886 * value to FILE_NAME format.
888 else if (ccs->target == FILE_NAME) {
891 * Get the text from the container
894 XmNselectedPositions, &selectedPositions,
895 XmNselectedItemCount, &selectedItemCount,
898 f_selected_item_count = selectedItemCount;
900 // This is commented out for now until i go and make this function private
902 tmpfile = _DtActGenerateTmpFile(NULL,
904 ( S_IRUSR|S_IRGRP|S_IWUSR|S_IWGRP),
907 strcpy(filepath, getenv("HOME"));
908 strcat(filepath, "/.dt/tmp/file.itp");
912 fprintf(stderr, "printConvertCallback: temp file = %s.\n", filepath);
914 // open the temporary file for writing
916 if ((fp = fopen(filepath, "w")) == NULL) {
917 fprintf(stderr, "Cannot open file %s.\n", filepath);
920 // write out each element in the list
922 for (int i = 0; i < f_selected_item_count; i++) {
923 oe = item_at(selectedPositions[i] - 1) ;
924 TOC_Element *te = (TOC_Element *)oe;
926 // write out the locator
927 if (fputs(((TOC_Element *)te)->toc()->locator(), fp) == EOF) {
928 fprintf(stderr, "Cannot write file %s in current directory.\n", filepath);
933 if (fputs("\n", fp) == EOF) {
934 fprintf(stderr, "Cannot write file %s in current directory.\n", filepath);
943 AppPrintData* p = window_system().GetAppPrintData();
944 p->f_pshell_parent = w;
946 // Assign file name to XmConvertCallbackStruct.
948 ccs->value = (XtPointer)filepath;
949 ccs->type = XA_STRING;
950 ccs->length = strlen(filepath);
952 ccs->status = XmCONVERT_DONE;
956 /* Unexpected target. */
957 ccs->status = XmCONVERT_REFUSE;
961 // /////////////////////////////////////////////////////////////////
962 // select - selection callback
963 // /////////////////////////////////////////////////////////////////
966 OutlineListView::select (WCallback *wcb)
968 XmListCallbackStruct *lcs = (XmListCallbackStruct *) wcb->CallData();
969 XmStringTable items = Items();
970 OutlineElement *oe = NULL;
972 DEBUGF (("**** select: item count = %d, pos = %d, selected = %s\n",
973 lcs->selected_item_count, lcs->item_position,
974 (PosSelected (lcs->item_position) ? "true" : "false")));
976 // DEBUGF ((">>>> SELECTION TYPE <<< %d\n", lcs->selection_type));
978 /* Fix for DTS #6303 -- Removed "if" statement. Always deselect all. */
979 deselect (f_list, DESELECT_ALL);
981 if (f_selection_policy == XmMULTIPLE_SELECT ||
982 f_selection_policy == XmEXTENDED_SELECT)
984 f_selected_item_count = lcs->selected_item_count;
986 printf ("selected # = %d\n", f_selected_item_count);
987 printf (" # = %d\n", SelectedItemCount());
989 for (int i = 0; i < f_selected_item_count; i++)
991 DEBUGF (("M-> extracting at %d\n", lcs->selected_item_positions[i]));
992 oe = item_at(lcs->selected_item_positions[i] - 1) ;
993 oe->set_selected (f_data_handle);
995 // Make the current selection the last item selected. This is
996 // (unfortunately) used by the LibraryAgent for the detach feature.
997 // The reason is that the Document List didn't support these selection
998 // modes until printing was added and could only have one selection.
999 // If there's more than one selection it won't matter because the
1000 // Detach button will be insensitive.
1001 f_current_selection = oe;
1005 if (PosSelected (lcs->item_position))
1007 DEBUGF (("--> extracting pointer @ %d\n", lcs->item_position));
1008 oe = item_at(lcs->item_position - 1) ;
1009 oe->set_selected (f_data_handle);
1010 // Save the selection:
1011 f_current_selection = oe;
1012 f_selected_item_count = 1;
1015 if (f_selected_item_count != 1) // 94/10/28 haya
1016 f_item_pos = 0; // modify to change sensitive of detach
1017 else // button by cursol key.
1018 f_item_pos = *lcs->selected_item_positions; //
1020 notify (ENTRY_SELECTED);
1022 // DISCOURSE: If the list is in extended selection mode it is possible
1023 // for the user to toggle in and out of add mode (cf. Motif Style Guide
1024 // 1.2 pg. 4-6). Unfortunately there's no way for us to know if he is
1025 // in add mode, but that's ok for now, since there's a bug in Motif 1.2
1026 // which deselects the previous selection, even when add mode is on and
1027 // the selection policy is extended select.
1031 // /////////////////////////////////////////////////////////////////
1032 // deselect - turn off select bit in in-memory elements in list
1033 // /////////////////////////////////////////////////////////////////
1035 #define OUTLINE_ELEMENT(I) ((OutlineElement *)(*list)[I])
1038 OutlineListView::deselect (OutlineList *list, deselect_mode_t mode)
1042 for (i = 0; i < list->length(); i++)
1044 OUTLINE_ELEMENT(i)->unset_selected (f_data_handle);
1045 if (OUTLINE_ELEMENT(i)->children_cached() &&
1046 OUTLINE_ELEMENT(i)->has_children() &&
1047 (mode == DESELECT_ALL ||
1048 OUTLINE_ELEMENT(i)->is_expanded (f_data_handle)))
1049 deselect (OUTLINE_ELEMENT(i)->children(), mode);
1054 // /////////////////////////////////////////////////////////////////
1055 // activate - activate callback
1057 // Here's the deal: to get a consistent result for "activate" on any
1058 // entry in the booklist, such expert activation will always** do at
1059 // least an open of the object in the/a reading window. If the item
1060 // also is the parent of a sub-hierarchy of more nodes, the first
1061 // level beneath this object will be expanded [or contracted] in the
1062 // booklist. No expansion will occur, of course, if it is the lowest
1063 // leaf in the tree. A TOC (== a "Book" level) will display its TOC
1064 // page per its OutlineElement type; all other entries will display
1065 // the document or the top-most document in the sub-hierarchy. -jcb
1067 // ** Only if an entry has children and is initially expanded,
1068 // double-click contracts it, but does Not [re-]display its topmost
1069 // document. The assumption is being made that user Contract of a
1070 // hierarchical level is more often than not an expression of lesser
1071 // interest in its content. In many cases, the topmost doc will have
1072 // been previously displayed by a double-click on the entry while
1073 // contracted, anyway.
1075 // Also, the double-click action "selects" only the activated entry.
1076 // /////////////////////////////////////////////////////////////////
1079 OutlineListView::activate (WCallback *wcb)
1081 XmListCallbackStruct *lcs = (XmListCallbackStruct *) wcb->CallData();
1082 XmStringTable items = Items();
1084 int expanded = False;
1086 oe = item_at(lcs->item_position - 1) ;
1089 if( oe == NULL ) printf( "OLV::activate: NULL outline element pointer\n" ) ;
1092 if ( oe->has_children() )
1096 // Remove previous tracking, if any.
1097 // Must happen before any expand/contract takes place
1098 // or either the position will be wrong, or item hidden.
1099 if (f_tracking_position > 0)
1101 if (window_system().nofonts())
1102 set_track_icon (f_tracking_element, f_tracking_position, ' ');
1104 set_track_icon (f_tracking_element, f_tracking_position,
1105 OLIAS_PLACEHOLDER_ICON);
1106 f_tracking_position = 0;
1109 if (oe->is_expanded (f_data_handle))
1113 printf( "OLV::activate: entry is Expanded\n" ) ;
1115 /* -------- Toggle current state to contracted -------- */
1116 oe->set_contracted (f_data_handle);
1118 oe->children()->count_expanded (f_data_handle);
1119 DeleteItemsPos (subcount, lcs->item_position + 1);
1124 printf( "OLV::activate: entry is Not expanded\n" ) ;
1126 /* -------- Toggle current state to expanded -------- */
1127 // Turn on the wait cursor if database access to occur.
1128 bool wait_state = FALSE;
1129 if (!oe->children_cached())
1131 window_system().set_wait_state (WS_ON);
1135 oe->set_expanded (f_data_handle);
1137 oe->children()->count_expanded (f_data_handle);
1138 XmStringTable table = new XmString[subcount];
1139 bool *sel_list = new bool[subcount];
1141 generate_table (oe->children(),
1144 AddItemsUnselected (table, subcount, lcs->item_position + 1);
1148 // Turn the wait cursor off if it was on.
1150 window_system().set_wait_state (WS_OFF);
1153 // Update the icon for new mode
1155 // Tell the list about the change
1156 XmString item = (XmString) oe->xm_string();
1157 ReplaceItemsPosUnselected (&item, 1, lcs->item_position);
1159 // Update the tracking if activated.
1160 // Must happen after the expand/contract so that the track
1161 // location is correctly computed.
1162 bool scroll = (f_tracking_element == oe);
1163 if (f_tracking_possible && f_library_agent)
1164 f_library_agent->track (scroll);
1168 // seems to occur ok for has_children case, above...
1169 deselect (f_list, DESELECT_ALL);
1172 // Select it as the only selection; do not call the select callback.
1173 // Need to reset all class pointers to elements or item pos, regardless
1174 // of traversal method paths in which used by class.
1175 SelectPos (lcs->item_position, True);
1176 oe->set_selected (f_data_handle);
1177 f_current_selection = oe;
1178 f_selected_item_count = 1;
1179 f_item_pos = lcs->item_position;
1181 f_outline_element = NULL; // because it should be with this path
1184 ON_DEBUG(cout << ">>>>>> CALLING DISPLAY ON ELEMENT <<<<<<" << endl);
1186 if ((oe->type() == TOC_Element::TOC_ElementClass) && !expanded)
1189 UAS_ObjectType type = ((TOC_Element *) oe)->toc()->type();
1194 UAS_List<UAS_Common> kids =
1195 ((TOC_Element *)oe)->toc()->children();
1196 if ( (kids != (const int)NULL)
1197 && (kids[0] != (const int)NULL)
1198 && (kids[0]->type() == UAS_BOOKCASE))
1200 UAS_List<UAS_Common> bckids = kids[0]->children();
1201 if (! (bckids[0] == (const int)NULL))
1203 bckids[0]->retrieve();
1211 UAS_List<UAS_Common> kids =
1212 ((TOC_Element *)oe)->toc()->children();
1213 if (! (kids[0] == (const int)NULL))
1215 kids[0]->retrieve();
1222 // let the OutlineElement "display" method handle it.
1229 message_mgr().error_dialog( (char*)UAS_String(CATGETS(
1230 Set_UrlAgent, 5, "Document not found." )) ) ;
1234 else if (oe->type() != TOC_Element::TOC_ElementClass) oe->display();
1238 // /////////////////////////////////////////////////////////////////
1239 // data_handle - return a new data handle
1240 // /////////////////////////////////////////////////////////////////
1244 OutlineListView::data_handle (BitHandle new_handle)
1246 f_data_handle = new_handle;
1247 // Need a variable since routine modifies it.
1249 update_highlighting (f_list, item_pos);
1254 // NOTE: is the calling objects responsibility to make sure that expanded
1255 // flag is correct with the current visual representation
1257 // /////////////////////////////////////////////////////////////////
1258 // update_highlighting
1259 // /////////////////////////////////////////////////////////////////
1263 OutlineListView::update_highlighting_recursive (OutlineList *list,
1266 for (int i = 0; i < list->length(); i++)
1268 // Select it, do not call the select callback.
1269 if (OUTLINE_ELEMENT(i)->is_selected (f_data_handle))
1271 if (!PosSelected(item_pos))
1273 SelectPos (item_pos, False);
1276 DeselectPos(item_pos);
1280 if (OUTLINE_ELEMENT(i)->is_expanded (f_data_handle) &&
1281 OUTLINE_ELEMENT(i)->has_children())
1282 update_highlighting (OUTLINE_ELEMENT(i)->children(), item_pos);
1288 OutlineListView::update_highlighting (OutlineList *list, u_int &item_pos)
1297 // Motif bug - see above.
1298 unsigned char current_policy = f_selection_policy;
1300 if (f_selection_policy != XmMULTIPLE_SELECT)
1302 current_policy = f_selection_policy;
1303 f_selection_policy = XmMULTIPLE_SELECT;
1304 SelectionPolicy (f_selection_policy);
1307 update_highlighting_recursive (list, item_pos);
1309 // Switch the policy back, if it was changed.
1310 if (f_selection_policy != current_policy)
1312 f_selection_policy = current_policy;
1313 SelectionPolicy (f_selection_policy);
1318 // /////////////////////////////////////////////////////////////////
1319 // selected_item_list
1320 // /////////////////////////////////////////////////////////////////
1323 OutlineListView::selected_item_list()
1325 return (f_list->selected_items (f_data_handle));
1329 // /////////////////////////////////////////////////////////////////
1331 // /////////////////////////////////////////////////////////////////
1334 OutlineListView::clear()
1337 deselect(f_list, DESELECT_ALL);
1338 f_selected_item_count = 0;
1341 // /////////////////////////////////////////////////////////////////
1342 // track_to - display tracking icon at specified position
1343 // /////////////////////////////////////////////////////////////////
1346 OutlineListView::track_to (OutlineElement *oe, u_int position, char icon)
1348 // Remove the old tracking icon, if any set.
1349 if (f_tracking_position > 0)
1350 if (window_system().nofonts())
1351 set_track_icon (f_tracking_element, f_tracking_position, ' ');
1353 set_track_icon (f_tracking_element, f_tracking_position,
1354 OLIAS_PLACEHOLDER_ICON);
1356 // Set the new tracking icon.
1357 set_track_icon (oe, position, icon);
1358 f_tracking_position = position;
1359 f_tracking_element = oe;
1364 OutlineListView::untrack()
1366 if (f_tracking_position > 0)
1367 if (window_system().nofonts())
1368 set_track_icon (f_tracking_element, f_tracking_position, ' ');
1370 set_track_icon (f_tracking_element, f_tracking_position,
1371 OLIAS_PLACEHOLDER_ICON);
1373 f_tracking_position = 0;
1377 // Warning: This routine depends heavily upon the format of the XmString
1378 // generated earlier. Any changes in that string WILL break this routine.
1381 OutlineListView::set_track_icon (OutlineElement *oe, u_int position, char icon)
1383 xmstring (oe, 1, icon);
1385 XmStringTable items = Items();
1387 // Tell the list about the change
1388 XmString item = (XmString) oe->xm_string();
1389 bool selected = PosSelected (position);
1390 ReplaceItemsPosUnselected (&item, 1, position);
1393 unsigned char current_policy = f_selection_policy;
1394 if (current_policy != XmMULTIPLE_SELECT)
1396 SelectionPolicy (XmMULTIPLE_SELECT);
1397 current_policy = XmMULTIPLE_SELECT;
1400 // Select it, do not call the select callback.
1401 SelectPos (position, False);
1402 // Switch the policy back, if it had been changed.
1403 if (f_selection_policy != current_policy)
1404 SelectionPolicy (f_selection_policy);
1408 // OutlineListView::item_at(position)
1410 // return the OutlineElement that is visible at 'position' in
1415 OutlineListView::item_at(unsigned int position)
1417 OutlineList *lptr = f_list ;
1418 unsigned int count = 0 ;
1419 unsigned int offset = 0 ;
1421 ON_DEBUG(cerr << "item_at: " << position << endl);
1423 // start at the beginning and descend the nested lists until we
1424 // reach the desired position, and return the element there
1426 OutlineElement *element = (OutlineElement *) (*lptr)[offset] ;
1427 while (count < position)
1429 if (element->is_expanded(f_data_handle) && element->has_children())
1431 if (count + element->children()->count_expanded(f_data_handle) >= position)
1433 ON_DEBUG(cerr << "descend: " << element->display_as() << endl);
1434 lptr = element->children();
1439 count += element->children()->count_expanded(f_data_handle) ;
1445 offset++ ; // go to the next one
1447 element = (OutlineElement*) (*lptr)[offset] ;
1450 ON_DEBUG(cerr << "item_at ==> " << element->display_as() << endl);