2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* 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); }
96 XmStringCreateComponent (XmStringComponentType tag, void *data, u_int length);
99 enum { XmSTRING_COMPONENT_POINTER = XmSTRING_COMPONENT_USER_BEGIN };
102 // /////////////////////////////////////////////////////////////////
104 // /////////////////////////////////////////////////////////////////
106 OutlineListView::OutlineListView (const WComposite &parent, const char *name,
108 bool enable_activate)
109 : WXmList ((Widget) NULL), f_list (NULL), f_max_level (LEVEL_UNLIMITED),
110 f_current_selection (NULL), f_selected_item_count(0),
111 f_tracking_position (0),
112 f_tracking_element (NULL),
113 f_library_agent (NULL)
115 static int serial_number = 1;
117 // Assign a unique serial number to this outline list.
118 f_serial_number = serial_number++;
120 // Non-scrolled list is useless so make it a scrolled list.
121 widget = XmCreateScrolledList (parent, (char *) name, NULL, 0);
124 // if dtinfo_font is defined then get the fontlist for the widget
125 // and append thte dtinfo_font
127 if (window_system().dtinfo_font()) {
128 XmFontList tempFontList, defaultList;
130 // get the current font list and make a copy
131 XtVaGetValues(widget, XmNfontList, &tempFontList, NULL);
132 defaultList = XmFontListCopy(tempFontList);
134 // append the dtinfo font. XmFontListAppendEntry deallocates the original font list after
135 // extracting the required information.
137 defaultList = XmFontListAppendEntry(defaultList, window_system().dtinfo_font());
139 // set the new new font list back
140 XtVaSetValues(widget, XmNfontList, defaultList, NULL);
144 // Save this pointer in user data of widget so that actions can
149 printf (">>> *** shadow %d, margin %d, highlight %d\n",
150 ShadowThickness(), ListMarginWidth(), HighlightThickness());
152 f_margin = ShadowThickness() + ListMarginWidth() + HighlightThickness();
153 f_selection_policy = SelectionPolicy();
157 SetSingleSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
158 SetBrowseSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
159 SetExtendedSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
160 SetMultipleSelectionCallback (this, (WWL_FUN) &OutlineListView::select);
162 SetConvertCallback (this, (WWL_FUN) &OutlineListView::printConvertCallback);
166 SetDefaultActionCallback (this, (WWL_FUN) &OutlineListView::activate);
167 f_tracking_possible = 1;
171 f_tracking_possible = 0;
181 XmFontList defaultList;
182 XtVaGetValues(w, XmNfontList, &defaultList, NULL);
184 // Setup parameters for calculating click position.
186 if (window_system().nofonts())
189 string[0] = OLIAS_PLACEHOLDER_ICON;
191 XmString thing = XmStringCreate (string, (char*)OLIAS_FONT);
193 Dimension rval = XmStringWidth(defaultList, thing);
194 XmStringFree (thing);
199 // /////////////////////////////////////////////////////////////////
201 // /////////////////////////////////////////////////////////////////
203 OutlineListView::~OutlineListView()
207 f_data_handle = library_mgr().library().get_data_handle();
212 // /////////////////////////////////////////////////////////////////
213 // xmstring - return the xm string given an outline element
214 // /////////////////////////////////////////////////////////////////
217 OutlineListView::xmstring (OutlineElement *oe, unsigned force, char icon)
219 if (force || (oe->string_creator() != f_serial_number))
221 if (oe->xm_string() != NULL)
222 XmStringFree ((XmString) oe->xm_string());
223 oe->set_xm_string ((void *) create_xm_string (oe, f_base_level,
224 f_tracking_possible, icon));
225 oe->string_creator (f_serial_number);
227 return ((XmString) oe->xm_string());
231 // /////////////////////////////////////////////////////////////////
232 // set_list - set the list
233 // /////////////////////////////////////////////////////////////////
236 OutlineListView::set_list (OutlineList *list, BitHandle handle)
238 // NOTE: Eventually it should be possible to set the list to NULL.
239 if (f_list != NULL && f_list != list )
240 list->free_data_handle (f_data_handle);
244 f_data_handle = handle ;
246 f_data_handle = list->get_data_handle();
248 // Determine the base level.
250 if (list->length() > 0) {
251 // SWM -- need to change this so that when determining
252 // the base level, we check all of the roots...
253 f_base_level = ((OutlineElement *)(*list)[0])->level();
255 ON_DEBUG(printf (">> OutlineList base level = %d\n", f_base_level));
260 // /////////////////////////////////////////////////////////////////
261 // regen_list - regenerate list based on internal list
262 // /////////////////////////////////////////////////////////////////
264 static u_int g_table_index;
267 OutlineListView::regen_list()
269 Xassert (f_list != NULL);
270 // if list is null we should just empty the list.
272 u_int visible_count = f_list->count_expanded (f_data_handle);
274 XmStringTable table = new XmString[visible_count];
275 bool *selected_list = new bool[visible_count];
278 generate_table (f_list, table, selected_list, 0);
282 ItemCount (visible_count, args);
286 delete [] selected_list;
289 // reset tracking position to let dtinfo determine
290 // the new position in track_to()
291 f_tracking_element = NULL;
292 f_tracking_position = 0;
295 // /////////////////////////////////////////////////////////////////
296 // create_outline_string - create the XmString to display
297 // /////////////////////////////////////////////////////////////////
300 OutlineListView::create_xm_string (OutlineElement *oe, int base_level,
301 unsigned char track_on, char icon)
303 XmString string, tmp, next;
305 unsigned char track = track_on ? 1 : 0; // normalize track_on into 1 or 0
307 // First component is pointer to original element. Motif 1.2
308 // will ignore this component.
310 string = XmStringCreateComponent (XmSTRING_COMPONENT_POINTER,
313 // Next component is expand/contract icon, if any.
314 // 1 for tracker, 1 for arrow, 3 for icon and spacing, 1 for terminator
317 assert ((oe->level() - base_level + 6) * sizeof(char) < 64);
318 // Spaces before and including arrow, if any
319 if (window_system().nofonts())
321 memset (s, ' ', oe->level() - base_level + 1 + track);
333 s[0] = OLIAS_PLACEHOLDER_ICON ;
337 memset (p, (unsigned char)OLIAS_PLACEHOLDER_ICON, oe->level() - base_level);
339 unsigned int pos = oe->level() - base_level + track;
341 // Only show the icon if this entry has children and
342 // the max level is unlimited or max level is higher than this level.
344 if (oe->has_children() &&
345 (f_max_level == LEVEL_UNLIMITED || f_max_level > oe->level())) {
346 if (oe->is_expanded (f_data_handle))
347 s[pos] = OLIAS_EXPANDED_ICON;
349 s[pos] = OLIAS_CONTRACTED_ICON;
352 s[pos] = OLIAS_NO_CHILDREN_ICON;
354 // Slot for icon -- plug in icon based on element type.
355 char entry_icon = '\0';
357 if (oe->type() == TOC_Element::TOC_ElementClass)
359 UAS_ObjectType type = ((TOC_Element *) oe)->toc()->type();
363 entry_icon = OLIAS_INFOLIB_ICON;
366 entry_icon = OLIAS_INFOBASE_ICON;
369 entry_icon = OLIAS_BOOK_ICON;
376 if (entry_icon != '\0' && !window_system().nofonts())
378 s[oe->level() - base_level + 1 + track] = OLIAS_SPACE04;
379 s[oe->level() - base_level + 2 + track] = entry_icon;
380 s[oe->level() - base_level + 3 + track] = OLIAS_SPACE04;
381 s[oe->level() - base_level + 4 + track] = '\0';
383 else if (window_system().nofonts())
385 s[oe->level() - base_level + 1 + track] = ' ';
386 s[oe->level() - base_level + 2 + track] = '\0';
389 s[oe->level() - base_level + 1 + track] = '\0';
391 next = XmStringCreate (s, (char*)OLIAS_FONT);
396 string = XmStringConcat (tmp, next);
403 // Final component is text of item
404 next = XmStringCreateLocalized ((String) oe->display_as());
406 string = XmStringConcat (tmp, next);
409 // _Xm_dump_external (string);
415 // /////////////////////////////////////////////////////////////////
416 // set_icon - set the icon in the xm string (the quick way)
417 // /////////////////////////////////////////////////////////////////
419 // Warning: This routine depends heavily upon the format of the XmString
420 // generated above. Any changes in that string WILL break this routine.
423 OutlineListView::set_icon (OutlineElement *oe)
425 xmstring (oe, 1); // force creation of string
429 // /////////////////////////////////////////////////////////////////
430 // generate_table - generate XmStringTable starting at list
431 // /////////////////////////////////////////////////////////////////
433 // NOTE: Can probably (and should) change g_element to f_element
434 static OutlineElement *g_element;
437 OutlineListView::generate_table (OutlineList *list, XmStringTable &table,
438 bool *selected_list, u_int level, unsigned force)
443 printf ("In generate_table, list = %p, level = %d\n", list, level);
445 for (i = 0; i < list->length(); i++)
447 g_element = ((OutlineElement *)(*list)[i]);
448 // NOTE: temporary for now - calc level in outline list code - DJB
449 // The level can be stored in the list, instead of the element.
450 // Store pointer to list in each element to back tracing.
452 // Level is initialized on first display.
453 // NOTE: This is a temporary hack. 15:59 01/13/93 DJB
454 if (g_element->string_creator() == 0)
455 g_element->level (level);
457 xmstring (g_element, force); // create the string
459 selected_list[g_table_index] = g_element->is_selected (f_data_handle);
460 table[g_table_index++] = (XmString) g_element->xm_string();
462 // g_element->print();
463 if ((g_element->has_children()) &&
464 g_element->is_expanded (f_data_handle))
465 generate_table (g_element->children(), table, selected_list, level+1, force);
471 // /////////////////////////////////////////////////////////////////
472 // XmStringCreateComponent
473 // /////////////////////////////////////////////////////////////////
476 XmStringCreateComponent (XmStringComponentType tag,
477 void *data, u_int length)
479 // NOTE: Possible improvement is to handle greater lengths, but this
480 // is easiest for now. DJB 8-8-92
481 assert (length <= 124);
483 // Length = ASN header + Component header + data
484 unsigned char total_length = 2 + length;
486 XmString string = (XmString) XtMalloc (total_length + 4);
487 unsigned char *p = (unsigned char*) string;
489 // Write the ASN.1 header (values from XmString.c)
495 // Write the component header
499 memcpy (p, data, length);
501 printf ("data = %p\n", data);
504 printf ("XmStringComponent = ");
505 for (i = 0; i < total_length + 4; i++)
506 printf ("%02x ", string[i]);
514 // /////////////////////////////////////////////////////////////////
515 // y_to_outline_element
516 // /////////////////////////////////////////////////////////////////
519 OutlineListView::y_to_outline_element (Position y)
522 // NOTE: if having problems with list expansion items, check here
524 // NOTE: Motif 1.2 bug alert: YToPos returns zero based, instead of 1 based
527 // NOTE: seems to be fixed returning 1 based
529 f_item_pos = YToPos (y) - 1;
532 printf ("Click in item %d, item count = %d\n", f_item_pos, ItemCount());
534 // Another Motif 1.2 bug. YToPos should return 0 for bogus position,
535 // but it doesn't check the range.
536 if ((int) f_item_pos < 0 || (int) f_item_pos >= ItemCount())
539 oe = item_at (f_item_pos);
542 ON_DEBUG(printf ("Found element %p (%s) at pos %d, level %d\n",
543 oe, oe->display_as(), f_item_pos, oe->level()));
546 f_item_pos++; // Adjust for Motif bug here.
551 // /////////////////////////////////////////////////////////////////
553 // /////////////////////////////////////////////////////////////////
556 OutlineListView::icon_extent(OutlineElement *oe) const
558 ON_DEBUG (printf ("horiz sbar value = %d\n",
559 WXmScrollBar(HorizontalScrollBar()).Value()));
560 ON_DEBUG (printf (" extent = %d\n",
561 f_margin - WXmScrollBar(HorizontalScrollBar()).Value() +
562 icon_width(*this) * (oe->level() - f_base_level + 1 + f_tracking_possible)));
564 return (f_margin - WXmScrollBar(HorizontalScrollBar()).Value() +
565 icon_width(*this) * (oe->level() - f_base_level + 1 + f_tracking_possible));
569 // /////////////////////////////////////////////////////////////////
570 // select_start - mouse button pressed (action proc)
571 // /////////////////////////////////////////////////////////////////
574 OutlineListView::_select_start (Widget w, XEvent *event,
575 String *params, Cardinal *num_params)
578 OutlineListView *lv = (OutlineListView *) W.UserData();
581 lv->select_start (w, event, params, num_params);
585 OutlineListView::select_start (Widget w, XEvent *event,
586 String *params, Cardinal *num_params)
588 if (event->type != ButtonPress)
591 ON_DEBUG(printf ("Select start at (%d, %d)\n",
592 event->xbutton.x, event->xbutton.y));
594 f_outline_element = y_to_outline_element (event->xbutton.y);
597 if (f_outline_element)
599 printf (">>> *** shadow %d, margin %d, highlight %d\n",
600 ShadowThickness(), ListMarginWidth(), HighlightThickness());
602 printf ("margin = %d, icon width = %d, level = %d\n",
603 f_margin, icon_width(*this), f_outline_element->level());
606 printf ("No element found at this location\n");
608 // See if item valid and icon was clicked in.
609 ON_DEBUG (printf ("X pos = %d\n", event->xbutton.x));
610 if (f_outline_element && event->xbutton.x < icon_extent (f_outline_element)
611 && f_outline_element->has_children())
613 ON_DEBUG (puts ("Clicked in an icon #1"));
617 // Set variable to signal that icon was not clicked on. This is
618 // checked in the select_end method.
619 f_outline_element = NULL;
621 ON_DEBUG (puts ("Passing through start"));
622 XtCallActionProc (w, "ListBeginSelect", event, params, *num_params);
626 // /////////////////////////////////////////////////////////////////
627 // select_end - mouse button released (action_proc)
628 // /////////////////////////////////////////////////////////////////
631 OutlineListView::_select_end (Widget w, XEvent *event, String *params,
632 Cardinal *num_params)
635 OutlineListView *lv = (OutlineListView *) W.UserData();
638 lv->select_end (w, event, params, num_params);
642 OutlineListView::select_end (Widget w, XEvent *event,
643 String *params, Cardinal *num_params)
645 if (event->type != ButtonRelease)
648 ON_DEBUG (printf ("Select end at (%d, %d)\n",
649 event->xbutton.x, event->xbutton.y));
651 // See if selection ended on the same item and in range.
652 if (f_outline_element != NULL &&
653 (y_to_outline_element (event->xbutton.y) == f_outline_element) &&
654 f_outline_element && event->xbutton.x < icon_extent (f_outline_element)
655 && f_outline_element->has_children() &&
656 (f_max_level == LEVEL_UNLIMITED ||
657 f_max_level > f_outline_element->level()))
659 ON_DEBUG (puts ("Clicked in an icon #2"));
660 unsigned char current_policy = f_selection_policy;
663 // Remove previous tracking, if any.
664 // Must happen before any expand/contract takes place
665 // or either the position will be wrong, or item hidden.
666 if (f_tracking_position > 0)
668 if (window_system().nofonts())
669 set_track_icon (f_tracking_element, f_tracking_position, ' ');
671 set_track_icon (f_tracking_element, f_tracking_position,
672 OLIAS_PLACEHOLDER_ICON);
673 f_tracking_position = 0;
676 if (f_outline_element->is_expanded (f_data_handle))
678 /* -------- Toggle current state to contracted -------- */
679 f_outline_element->set_contracted (f_data_handle);
681 f_outline_element->children()->count_expanded (f_data_handle);
682 DeleteItemsPos (subcount, f_item_pos + 1);
686 /* -------- Toggle current state to expanded -------- */
687 // Turn on the wait cursor if database access to occur.
688 bool wait_state = FALSE;
689 if (!f_outline_element->children_cached())
691 window_system().set_wait_state (WS_ON);
695 f_outline_element->set_expanded (f_data_handle);
697 f_outline_element->children()->count_expanded (f_data_handle);
698 XmStringTable table = new XmString[subcount];
699 bool *selected_list = new bool[subcount];
701 generate_table (f_outline_element->children(),
702 table, selected_list,
703 f_outline_element->level() + 1);
704 AddItemsUnselected (table, subcount, f_item_pos + 1);
705 // Must be in multiple select mode to add selected items
706 if (f_selection_policy != XmMULTIPLE_SELECT)
708 SelectionPolicy (XmMULTIPLE_SELECT);
709 current_policy = XmMULTIPLE_SELECT;
711 // Bogus Motif should have a routine to select multiple items.
713 if (selected_list[--subcount])
714 SelectPos (f_item_pos + subcount + 1, False);
716 delete [] selected_list;
718 // Turn the wait cursor off if it was on.
720 window_system().set_wait_state (WS_OFF);
723 // Update the icon for new mode
724 set_icon (f_outline_element);
726 // Tell the list about the change
727 XmString item = (XmString) f_outline_element->xm_string();
728 bool selected = PosSelected (f_item_pos);
729 ReplaceItemsPosUnselected (&item, 1, f_item_pos);
731 // YAMB (Yet Another Motif Bug): Cannot call ReplaceItemsPos
732 // because if the item matches another item in the list that
733 // happens to be selected, the item replaced will be selected.
734 // So, do selection here, if needed.
737 // Bugs Galore!! Motif will automatically (gee thanks)
738 // deselect all other selections on a select call, even
739 // if this list is in extended select mode. Work around
740 // by switching to multiple select mode which allows it.
741 if (current_policy != XmMULTIPLE_SELECT)
743 SelectionPolicy (XmMULTIPLE_SELECT);
744 current_policy = XmMULTIPLE_SELECT;
747 // Select it, do not call the select callback.
748 SelectPos (f_item_pos, False);
751 // Update the tracking if activated.
752 // Must happen after the expand/contract so that the track
753 // location is correctly computed.
754 bool scroll = (f_tracking_element == f_outline_element);
755 if (f_tracking_possible && f_library_agent)
756 f_library_agent->track (scroll);
758 // Switch the policy back, if it had been changed.
759 if (f_selection_policy != current_policy)
760 SelectionPolicy (f_selection_policy);
762 // f_outline_element can only be NULL if the click down wasn't in the icon.
763 else if (f_outline_element == NULL)
765 ON_DEBUG (("Passing through end"));
766 XtCallActionProc (w, "ListEndSelect", event, params, *num_params);
770 ON_DEBUG(puts ("Click down in icon, but click up wasn't"));
775 OutlineListView::update_list(OutlineList *list, BitHandle handle)
777 u_int visible_count = list->count_expanded (handle);
779 XmStringTable table = new XmString[visible_count];
780 bool *selected_list = new bool[visible_count];
782 generate_table (list, table, selected_list, 0, 1);
786 ItemCount (visible_count, args);
790 delete [] selected_list;
793 // /////////////////////////////////////////////////////////////////
795 // /////////////////////////////////////////////////////////////////
798 OutlineListView::register_actions()
800 static bool registered = FALSE;
804 static XtActionsRec actions_list[] =
806 {(char*)"OutlineListBeginSelect", OutlineListView::_select_start},
807 {(char*)"OutlineListEndSelect", OutlineListView::_select_end},
811 XtAppAddActions (AppContext(), actions_list, XtNumber (actions_list));
814 /**********************************************************************
815 OutputAnAtomName: Translates a target from its internal atom format into
816 a human readable character string.
817 **********************************************************************/
819 OutputAnAtomName(Widget w, Atom target)
821 char *AtomName = NULL;
823 AtomName = XGetAtomName(XtDisplay(w), target);
824 printf("\t%s\n", AtomName);
828 // /////////////////////////////////////////////////////////////////
829 // /////////////////////////////////////////////////////////////////
832 OutlineListView::printConvertCallback(WCallback *wcb)
834 XmConvertCallbackStruct *ccs = (XmConvertCallbackStruct *)wcb->CallData();
835 Widget w = wcb->GetWidget();
836 unsigned int * selectedPositions;
837 int selectedItemCount;
838 char filepath[MAXPATHLEN];
839 OutlineElement *oe = NULL;
843 Atom FILE_NAME = XInternAtom(XtDisplay(w), XmSFILE_NAME, False);
844 Atom TARGETS = XInternAtom(XtDisplay(w), XmSTARGETS, False);
845 Atom MOTIF_EXPORT_TARGETS = XInternAtom(XtDisplay(w), XmS_MOTIF_EXPORT_TARGETS, False);
847 RCS_DEBUG("printConvertCallback: called.\n");
853 RCS_DEBUG("\nNow in ConvertCallback.\n");
854 RCS_DEBUG("\tSelection: ");
855 OutputAnAtomName((Widget)w, ccs->selection);
856 RCS_DEBUG("\tTarget: ");
857 OutputAnAtomName((Widget)w, ccs->target);
860 * XmeDragSource is going to call ConvertCallback and ask
861 * it to convert MOTIF_EXPORT_TARGETS.
863 if ( (ccs->target == MOTIF_EXPORT_TARGETS) ||
864 (ccs->target == TARGETS))
868 * this callback must support the FILE_NAME transfer
869 * as this is the mechanism the Printer Icon on the
870 * front panel uses to transfer data.
872 Atom *targs = (Atom *) XtMalloc(sizeof(Atom) * 1);
874 ccs->status = XmCONVERT_REFUSE;
879 targs[n] = FILE_NAME; n++;
881 ccs->value = (XtPointer) targs;
885 ccs->status = XmCONVERT_DONE; /* Yes, we converted the target. */
889 * As the drop site supports FILE_NAME as an import target, then
890 * the drop site will ask ConvertCallback to convert the
891 * value to FILE_NAME format.
893 else if (ccs->target == FILE_NAME) {
896 * Get the text from the container
899 XmNselectedPositions, &selectedPositions,
900 XmNselectedItemCount, &selectedItemCount,
903 f_selected_item_count = selectedItemCount;
905 // This is commented out for now until i go and make this function private
907 tmpfile = _DtActGenerateTmpFile(NULL,
909 ( S_IRUSR|S_IRGRP|S_IWUSR|S_IWGRP),
912 len = MIN(strlen(getenv("HOME")), MAXPATHLEN - 1);
913 *((char *) memcpy(filepath, getenv("HOME"), len) + len) = '\0';
915 len = MIN(strlen("/.dt/tmp/file.itp"), MAXPATHLEN - 1);
916 *((char *) memcpy(filepath + slen,
917 "/.dt/tmp/file.itp", len) + len) = '\0';
921 fprintf(stderr, "printConvertCallback: temp file = %s.\n", filepath);
923 // open the temporary file for writing
925 if ((fp = fopen(filepath, "w")) == NULL) {
926 fprintf(stderr, "Cannot open file %s.\n", filepath);
929 // write out each element in the list
931 for (unsigned int i = 0; i < f_selected_item_count; i++) {
932 oe = item_at(selectedPositions[i] - 1) ;
933 TOC_Element *te = (TOC_Element *)oe;
935 // write out the locator
936 if (fputs(((TOC_Element *)te)->toc()->locator(), fp) == EOF) {
937 fprintf(stderr, "Cannot write file %s in current directory.\n", filepath);
943 if (fputs("\n", fp) == EOF) {
944 fprintf(stderr, "Cannot write file %s in current directory.\n", filepath);
954 AppPrintData* p = window_system().GetAppPrintData();
955 p->f_pshell_parent = w;
957 // Assign file name to XmConvertCallbackStruct.
959 ccs->value = (XtPointer)filepath;
960 ccs->type = XA_STRING;
961 ccs->length = strlen(filepath);
963 ccs->status = XmCONVERT_DONE;
967 /* Unexpected target. */
968 ccs->status = XmCONVERT_REFUSE;
972 // /////////////////////////////////////////////////////////////////
973 // select - selection callback
974 // /////////////////////////////////////////////////////////////////
977 OutlineListView::select (WCallback *wcb)
979 XmListCallbackStruct *lcs = (XmListCallbackStruct *) wcb->CallData();
980 OutlineElement *oe = NULL;
982 DEBUGF (("**** select: item count = %d, pos = %d, selected = %s\n",
983 lcs->selected_item_count, lcs->item_position,
984 (PosSelected (lcs->item_position) ? "true" : "false")));
986 // DEBUGF ((">>>> SELECTION TYPE <<< %d\n", lcs->selection_type));
988 /* Fix for DTS #6303 -- Removed "if" statement. Always deselect all. */
989 deselect (f_list, DESELECT_ALL);
991 if (f_selection_policy == XmMULTIPLE_SELECT ||
992 f_selection_policy == XmEXTENDED_SELECT)
994 f_selected_item_count = lcs->selected_item_count;
996 printf ("selected # = %d\n", f_selected_item_count);
997 printf (" # = %d\n", SelectedItemCount());
999 for (unsigned int i = 0; i < f_selected_item_count; i++)
1001 DEBUGF (("M-> extracting at %d\n", lcs->selected_item_positions[i]));
1002 oe = item_at(lcs->selected_item_positions[i] - 1) ;
1003 oe->set_selected (f_data_handle);
1005 // Make the current selection the last item selected. This is
1006 // (unfortunately) used by the LibraryAgent for the detach feature.
1007 // The reason is that the Document List didn't support these selection
1008 // modes until printing was added and could only have one selection.
1009 // If there's more than one selection it won't matter because the
1010 // Detach button will be insensitive.
1011 f_current_selection = oe;
1015 if (PosSelected (lcs->item_position))
1017 DEBUGF (("--> extracting pointer @ %d\n", lcs->item_position));
1018 oe = item_at(lcs->item_position - 1) ;
1019 oe->set_selected (f_data_handle);
1020 // Save the selection:
1021 f_current_selection = oe;
1022 f_selected_item_count = 1;
1025 if (f_selected_item_count != 1) // 94/10/28 haya
1026 f_item_pos = 0; // modify to change sensitive of detach
1027 else // button by cursol key.
1028 f_item_pos = *lcs->selected_item_positions; //
1030 notify (ENTRY_SELECTED);
1032 // DISCOURSE: If the list is in extended selection mode it is possible
1033 // for the user to toggle in and out of add mode (cf. Motif Style Guide
1034 // 1.2 pg. 4-6). Unfortunately there's no way for us to know if he is
1035 // in add mode, but that's ok for now, since there's a bug in Motif 1.2
1036 // which deselects the previous selection, even when add mode is on and
1037 // the selection policy is extended select.
1041 // /////////////////////////////////////////////////////////////////
1042 // deselect - turn off select bit in in-memory elements in list
1043 // /////////////////////////////////////////////////////////////////
1045 #define OUTLINE_ELEMENT(I) ((OutlineElement *)(*list)[I])
1048 OutlineListView::deselect (OutlineList *list, deselect_mode_t mode)
1052 for (i = 0; i < list->length(); i++)
1054 OUTLINE_ELEMENT(i)->unset_selected (f_data_handle);
1055 if (OUTLINE_ELEMENT(i)->children_cached() &&
1056 OUTLINE_ELEMENT(i)->has_children() &&
1057 (mode == DESELECT_ALL ||
1058 OUTLINE_ELEMENT(i)->is_expanded (f_data_handle)))
1059 deselect (OUTLINE_ELEMENT(i)->children(), mode);
1064 // /////////////////////////////////////////////////////////////////
1065 // activate - activate callback
1067 // Here's the deal: to get a consistent result for "activate" on any
1068 // entry in the booklist, such expert activation will always** do at
1069 // least an open of the object in the/a reading window. If the item
1070 // also is the parent of a sub-hierarchy of more nodes, the first
1071 // level beneath this object will be expanded [or contracted] in the
1072 // booklist. No expansion will occur, of course, if it is the lowest
1073 // leaf in the tree. A TOC (== a "Book" level) will display its TOC
1074 // page per its OutlineElement type; all other entries will display
1075 // the document or the top-most document in the sub-hierarchy. -jcb
1077 // ** Only if an entry has children and is initially expanded,
1078 // double-click contracts it, but does Not [re-]display its topmost
1079 // document. The assumption is being made that user Contract of a
1080 // hierarchical level is more often than not an expression of lesser
1081 // interest in its content. In many cases, the topmost doc will have
1082 // been previously displayed by a double-click on the entry while
1083 // contracted, anyway.
1085 // Also, the double-click action "selects" only the activated entry.
1086 // /////////////////////////////////////////////////////////////////
1089 OutlineListView::activate (WCallback *wcb)
1091 XmListCallbackStruct *lcs = (XmListCallbackStruct *) wcb->CallData();
1093 int expanded = False;
1095 oe = item_at(lcs->item_position - 1) ;
1098 if( oe == NULL ) printf( "OLV::activate: NULL outline element pointer\n" ) ;
1101 if ( oe->has_children() )
1105 // Remove previous tracking, if any.
1106 // Must happen before any expand/contract takes place
1107 // or either the position will be wrong, or item hidden.
1108 if (f_tracking_position > 0)
1110 if (window_system().nofonts())
1111 set_track_icon (f_tracking_element, f_tracking_position, ' ');
1113 set_track_icon (f_tracking_element, f_tracking_position,
1114 OLIAS_PLACEHOLDER_ICON);
1115 f_tracking_position = 0;
1118 if (oe->is_expanded (f_data_handle))
1122 printf( "OLV::activate: entry is Expanded\n" ) ;
1124 /* -------- Toggle current state to contracted -------- */
1125 oe->set_contracted (f_data_handle);
1127 oe->children()->count_expanded (f_data_handle);
1128 DeleteItemsPos (subcount, lcs->item_position + 1);
1133 printf( "OLV::activate: entry is Not expanded\n" ) ;
1135 /* -------- Toggle current state to expanded -------- */
1136 // Turn on the wait cursor if database access to occur.
1137 bool wait_state = FALSE;
1138 if (!oe->children_cached())
1140 window_system().set_wait_state (WS_ON);
1144 oe->set_expanded (f_data_handle);
1146 oe->children()->count_expanded (f_data_handle);
1147 XmStringTable table = new XmString[subcount];
1148 bool *sel_list = new bool[subcount];
1150 generate_table (oe->children(),
1153 AddItemsUnselected (table, subcount, lcs->item_position + 1);
1157 // Turn the wait cursor off if it was on.
1159 window_system().set_wait_state (WS_OFF);
1162 // Update the icon for new mode
1164 // Tell the list about the change
1165 XmString item = (XmString) oe->xm_string();
1166 ReplaceItemsPosUnselected (&item, 1, lcs->item_position);
1168 // Update the tracking if activated.
1169 // Must happen after the expand/contract so that the track
1170 // location is correctly computed.
1171 bool scroll = (f_tracking_element == oe);
1172 if (f_tracking_possible && f_library_agent)
1173 f_library_agent->track (scroll);
1177 // seems to occur ok for has_children case, above...
1178 deselect (f_list, DESELECT_ALL);
1181 // Select it as the only selection; do not call the select callback.
1182 // Need to reset all class pointers to elements or item pos, regardless
1183 // of traversal method paths in which used by class.
1184 SelectPos (lcs->item_position, True);
1185 oe->set_selected (f_data_handle);
1186 f_current_selection = oe;
1187 f_selected_item_count = 1;
1188 f_item_pos = lcs->item_position;
1190 f_outline_element = NULL; // because it should be with this path
1193 ON_DEBUG(cout << ">>>>>> CALLING DISPLAY ON ELEMENT <<<<<<" << endl);
1195 if ((oe->type() == TOC_Element::TOC_ElementClass) && !expanded)
1198 UAS_ObjectType type = ((TOC_Element *) oe)->toc()->type();
1203 UAS_List<UAS_Common> kids =
1204 ((TOC_Element *)oe)->toc()->children();
1205 if ( (kids != (const int)0)
1206 && (kids[0] != (const int)0)
1207 && (kids[0]->type() == UAS_BOOKCASE))
1209 UAS_List<UAS_Common> bckids = kids[0]->children();
1210 if (! (bckids[0] == (const int)0))
1212 bckids[0]->retrieve();
1220 UAS_List<UAS_Common> kids =
1221 ((TOC_Element *)oe)->toc()->children();
1222 if (! (kids[0] == (const int)0))
1224 kids[0]->retrieve();
1231 // let the OutlineElement "display" method handle it.
1238 message_mgr().error_dialog( (char*)UAS_String(CATGETS(
1239 Set_UrlAgent, 5, "Document not found." )) ) ;
1243 else if (oe->type() != TOC_Element::TOC_ElementClass) oe->display();
1247 // /////////////////////////////////////////////////////////////////
1248 // data_handle - return a new data handle
1249 // /////////////////////////////////////////////////////////////////
1253 OutlineListView::data_handle (BitHandle new_handle)
1255 f_data_handle = new_handle;
1256 // Need a variable since routine modifies it.
1258 update_highlighting (f_list, item_pos);
1263 // NOTE: is the calling objects responsibility to make sure that expanded
1264 // flag is correct with the current visual representation
1266 // /////////////////////////////////////////////////////////////////
1267 // update_highlighting
1268 // /////////////////////////////////////////////////////////////////
1272 OutlineListView::update_highlighting_recursive (OutlineList *list,
1275 for (unsigned int i = 0; i < list->length(); i++)
1277 // Select it, do not call the select callback.
1278 if (OUTLINE_ELEMENT(i)->is_selected (f_data_handle))
1280 if (!PosSelected(item_pos))
1282 SelectPos (item_pos, False);
1285 DeselectPos(item_pos);
1289 if (OUTLINE_ELEMENT(i)->is_expanded (f_data_handle) &&
1290 OUTLINE_ELEMENT(i)->has_children())
1291 update_highlighting (OUTLINE_ELEMENT(i)->children(), item_pos);
1297 OutlineListView::update_highlighting (OutlineList *list, u_int &item_pos)
1306 // Motif bug - see above.
1307 unsigned char current_policy = f_selection_policy;
1309 if (f_selection_policy != XmMULTIPLE_SELECT)
1311 current_policy = f_selection_policy;
1312 f_selection_policy = XmMULTIPLE_SELECT;
1313 SelectionPolicy (f_selection_policy);
1316 update_highlighting_recursive (list, item_pos);
1318 // Switch the policy back, if it was changed.
1319 if (f_selection_policy != current_policy)
1321 f_selection_policy = current_policy;
1322 SelectionPolicy (f_selection_policy);
1327 // /////////////////////////////////////////////////////////////////
1328 // selected_item_list
1329 // /////////////////////////////////////////////////////////////////
1332 OutlineListView::selected_item_list()
1334 return (f_list->selected_items (f_data_handle));
1338 // /////////////////////////////////////////////////////////////////
1340 // /////////////////////////////////////////////////////////////////
1343 OutlineListView::clear()
1346 deselect(f_list, DESELECT_ALL);
1347 f_selected_item_count = 0;
1350 // /////////////////////////////////////////////////////////////////
1351 // track_to - display tracking icon at specified position
1352 // /////////////////////////////////////////////////////////////////
1355 OutlineListView::track_to (OutlineElement *oe, u_int position, char icon)
1357 // Remove the old tracking icon, if any set.
1358 if (f_tracking_position > 0) {
1359 if (window_system().nofonts())
1360 set_track_icon (f_tracking_element, f_tracking_position, ' ');
1362 set_track_icon (f_tracking_element, f_tracking_position,
1363 OLIAS_PLACEHOLDER_ICON);
1366 // Set the new tracking icon.
1367 set_track_icon (oe, position, icon);
1368 f_tracking_position = position;
1369 f_tracking_element = oe;
1374 OutlineListView::untrack()
1376 if (f_tracking_position > 0) {
1377 if (window_system().nofonts())
1378 set_track_icon (f_tracking_element, f_tracking_position, ' ');
1380 set_track_icon (f_tracking_element, f_tracking_position,
1381 OLIAS_PLACEHOLDER_ICON);
1384 f_tracking_position = 0;
1388 // Warning: This routine depends heavily upon the format of the XmString
1389 // generated earlier. Any changes in that string WILL break this routine.
1392 OutlineListView::set_track_icon (OutlineElement *oe, u_int position, char icon)
1394 xmstring (oe, 1, icon);
1396 // Tell the list about the change
1397 XmString item = (XmString) oe->xm_string();
1398 bool selected = PosSelected (position);
1399 ReplaceItemsPosUnselected (&item, 1, position);
1402 unsigned char current_policy = f_selection_policy;
1403 if (current_policy != XmMULTIPLE_SELECT)
1405 SelectionPolicy (XmMULTIPLE_SELECT);
1406 current_policy = XmMULTIPLE_SELECT;
1409 // Select it, do not call the select callback.
1410 SelectPos (position, False);
1411 // Switch the policy back, if it had been changed.
1412 if (f_selection_policy != current_policy)
1413 SelectionPolicy (f_selection_policy);
1417 // OutlineListView::item_at(position)
1419 // return the OutlineElement that is visible at 'position' in
1424 OutlineListView::item_at(unsigned int position)
1426 OutlineList *lptr = f_list ;
1427 unsigned int count = 0 ;
1428 unsigned int offset = 0 ;
1430 ON_DEBUG(cerr << "item_at: " << position << endl);
1432 // start at the beginning and descend the nested lists until we
1433 // reach the desired position, and return the element there
1435 OutlineElement *element = (OutlineElement *) (*lptr)[offset] ;
1436 while (count < position)
1438 if (element->is_expanded(f_data_handle) && element->has_children())
1440 if (count + element->children()->count_expanded(f_data_handle) >= position)
1442 ON_DEBUG(cerr << "descend: " << element->display_as() << endl);
1443 lptr = element->children();
1448 count += element->children()->count_expanded(f_data_handle) ;
1454 offset++ ; // go to the next one
1456 element = (OutlineElement*) (*lptr)[offset] ;
1459 ON_DEBUG(cerr << "item_at ==> " << element->display_as() << endl);