Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtinfo / dtinfo / src / Agents / NodeHistoryAgentMotif.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 // $TOG: NodeHistoryAgentMotif.C /main/13 1998/04/17 11:34:27 mgreess $
24 /*      Copyright (c) 1994,1995,1996 FUJITSU LIMITED    */
25 /*      All Rights Reserved                             */
26 /*
27  *
28  * Copyright (c) 1993 HAL Computer Systems International, Ltd.
29  * All rights reserved.  Unpublished -- rights reserved under
30  * the Copyright Laws of the United States.  USE OF A COPYRIGHT
31  * NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
32  * OR DISCLOSURE.
33  * 
34  * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
35  * SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.  USE,
36  * DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
37  * PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
38  * INTERNATIONAL, LTD.
39  * 
40  *                         RESTRICTED RIGHTS LEGEND
41  * Use, duplication, or disclosure by the Government is subject
42  * to the restrictions as set forth in subparagraph (c)(l)(ii)
43  * of the Rights in Technical Data and Computer Software clause
44  * at DFARS 252.227-7013.
45  *
46  *          HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
47  *                  1315 Dell Avenue
48  *                  Campbell, CA  95008
49  * 
50  */
51
52 #include <stream.h>
53
54 #include "UAS.hh"
55
56 #define C_TOC_Element
57 #define L_Basic
58
59 #define C_xList
60 #define L_Support
61
62 #define C_GlobalHistoryMgr
63 #define C_MessageMgr
64 #define C_NodeMgr
65 #define L_Managers
66
67 #define C_HelpAgent
68 #define C_NodeHistoryAgent
69 #define L_Agents
70
71 #define C_WindowSystem
72 #define L_Other
73
74 #include "Other/XmStringLocalized.hh"
75 #include "Managers/CatMgr.hh"
76 #include "Managers/WString.hh"
77
78 #include <Prelude.h>
79
80 #include "Registration.hh"
81
82 #include <WWL/WXmForm.h>
83 #include <WWL/WXmSeparator.h>
84 #include <WWL/WXmLabel.h>
85
86 #define CLASS NodeHistoryAgent
87 #include "create_macros.hh"
88
89
90 NodeHistoryAgent::~NodeHistoryAgent()
91 {
92   if (f_shell != NULL)
93     f_shell.Destroy();
94 }
95
96
97 // /////////////////////////////////////////////////////////////////
98 // display
99 // /////////////////////////////////////////////////////////////////
100
101 void
102 NodeHistoryAgent::display()
103 {
104   if (f_shell == NULL)
105     create_ui();
106
107   refresh_list();
108   ON_DEBUG (puts ("Popping up the node hist list"));
109   f_shell.Popup();
110   f_shell.DeIconify();
111   f_popped_up = TRUE;
112 }
113
114
115 // /////////////////////////////////////////////////////////////////
116 // create_ui
117 // /////////////////////////////////////////////////////////////////
118
119 #define SECTION_OFFSET 150
120
121 void
122 NodeHistoryAgent::create_ui()
123 {
124   XmStringLocalized mtfstring;
125   String            string;
126
127   f_shell = WTopLevelShell (window_system().toplevel(), WPopup, "node_hist");
128   window_system().register_shell (&f_shell);
129
130   string = CATGETS(Set_NodeHistoryAgent, 1, "Dtinfo: Section History");
131   XtVaSetValues((Widget)f_shell, XmNtitle, string, NULL);
132
133   DECL  (WXmForm,         form,       f_shell,   "form");
134   ASSNM (WXmPushButton,   f_display,  form,      "display");
135   DECLM (WXmPushButton,   close,      form,      "close");
136   DECLM (WXmPushButton,   help,       form,      "help");
137   DECLM (WXmSeparator,    sep,        form,      "separator");
138
139   mtfstring = CATGETS(Set_AgentLabel, 165, "Display");
140   XtVaSetValues(f_display, XmNlabelString, (XmString)mtfstring, NULL);
141   mtfstring = CATGETS(Set_AgentLabel, 12, "Close");
142   XtVaSetValues(close, XmNlabelString, (XmString)mtfstring, NULL);
143   mtfstring = CATGETS(Set_AgentLabel, 48, "Help");
144   XtVaSetValues(help, XmNlabelString, (XmString)mtfstring, NULL);
145
146   // set up column labels (Book, Section) 
147   WXmLabel booklabel    (form, "book", WAutoManage);
148   WXmLabel sectionlabel (form, "section", WAutoManage);
149
150   mtfstring = CATGETS(Set_AgentLabel, 184, "Book");
151   XtVaSetValues(booklabel, XmNlabelString, (XmString)mtfstring, NULL);
152   mtfstring = CATGETS(Set_AgentLabel, 185, "Section");
153   XtVaSetValues(sectionlabel, XmNlabelString, (XmString)mtfstring, NULL);
154
155   Widget scrolled_list =  XmCreateScrolledList (form, "list", NULL, 0);
156   f_list = WXmList (scrolled_list);
157   f_list.Manage();
158
159   XmFontList defaultList;
160   {
161     XmFontList font;
162     XtVaGetValues(scrolled_list, XmNfontList, &font, NULL);
163     defaultList = XmFontListCopy(font);
164   }
165
166   if (window_system().dtinfo_space_font())
167     defaultList = XmFontListAppendEntry(defaultList,
168                                         window_system().dtinfo_space_font());
169   XtVaSetValues(scrolled_list, XmNfontList, defaultList, NULL);
170
171   SET_CALLBACK (f_shell,Popdown,popdown);
172   SET_CALLBACK (f_list,SingleSelection,select);
173   SET_CALLBACK (f_list,BrowseSelection,select);
174   SET_CALLBACK (f_list,DefaultAction,view);
175   ON_ACTIVATE (f_display,view);
176   ON_ACTIVATE (close,close);
177   help_agent().add_activate_help (help, "node_hist_help");
178
179   global_history_mgr().UAS_Sender<HistoryAdd>::request (this);
180   global_history_mgr().UAS_Sender<HistoryDelete>::request (this);
181
182   form.DefaultButton (f_display);
183   form.ShadowThickness(0);
184   form.Manage();
185
186   // Set the min size based on the current size.
187   f_shell.Realize();
188   f_shell.MinWidth (f_shell.Width());
189   f_shell.MinHeight (f_shell.Height());
190
191 // account for list offset in its frame 
192 #define MARGIN_FACTOR 3
193   int offset = 0 ;
194   booklabel.LeftOffset(MARGIN_FACTOR + offset); 
195
196   sectionlabel.LeftPosition(0);
197   sectionlabel.LeftAttachment(XmATTACH_POSITION);
198   sectionlabel.LeftOffset(SECTION_OFFSET + MARGIN_FACTOR + offset);
199 #undef MARGIN_FACTOR
200
201   WXmPrimitive prim(XtParent(f_list));
202   prim.TopWidget(booklabel);
203   prim.TopAttachment(XmATTACH_WIDGET);
204 }
205
206
207 // /////////////////////////////////////////////////////////////////
208 // refresh_list - get all history list items and display them
209 // /////////////////////////////////////////////////////////////////
210
211 void
212 NodeHistoryAgent::refresh_list()
213 {
214   Xassert (f_list != NULL);
215
216   xList<UAS_Pointer<UAS_Common> > &hist_list = global_history_mgr().history_list();
217   XmStringTable table = new XmString [hist_list.length()];
218   List_Iterator<UAS_Pointer<UAS_Common> > hl (hist_list);
219
220   // Create the XmString values for the list.
221   // Stick the items in the list in reverse order. 
222   int i = hist_list.length() - 1;
223   while (hl)
224     {
225       UAS_String bn = hl.item()->book_name(UAS_SHORT_TITLE);
226       UAS_String tt = hl.item()->title();
227
228       table[i--] = compose_entry(bn, tt);
229       hl++;
230     }
231
232   // Set the items in the list. 
233   f_list.DeselectAllItems();
234   f_display.SetSensitive (False);
235   f_list.Set (WArgList (XmNitems, (XtArgVal) table,
236                         XmNitemCount, hist_list.length(),
237                         NULL));
238
239   // Free up memory used to make the list.
240   for (i = hist_list.length() - 1; i >= 0; i--)
241     XmStringFree (table[i]);
242   delete table;
243 }
244
245
246 // /////////////////////////////////////////////////////////////////
247 // select - handle item selection
248 // /////////////////////////////////////////////////////////////////
249
250 void
251 NodeHistoryAgent::select (WCallback *wcb)
252 {
253   CALL_DATA (XmListCallbackStruct,lcs);
254
255   f_selected_item = lcs->item_position;
256
257   ON_DEBUG (printf ("Selected item #%d\n", f_selected_item);)
258
259   f_display.SetSensitive (True);
260 }
261
262
263 // /////////////////////////////////////////////////////////////////
264 // display
265 // /////////////////////////////////////////////////////////////////
266
267 void
268 NodeHistoryAgent::view()
269 {
270   Xassert (f_list.SelectedItemCount() == 1);
271   Xassert (f_selected_item != 0);
272
273   xList<UAS_Pointer<UAS_Common> > &hist_list = global_history_mgr().history_list();
274   List_Iterator<UAS_Pointer<UAS_Common> > n (hist_list);
275   int i = hist_list.length();
276
277   // Skip ahead to the selected item in the list. 
278   while (i > f_selected_item)
279     i--, n++;
280
281   // Now `n' points to the selected Node.
282   n.item()->retrieve();
283 }
284
285 // /////////////////////////////////////////////////////////////////
286 // close
287 // /////////////////////////////////////////////////////////////////
288
289 void
290 NodeHistoryAgent::close()
291 {
292   f_shell.Popdown();
293 }
294
295
296 void
297 NodeHistoryAgent::popdown()
298 {
299   f_popped_up = FALSE;
300   f_list.DeleteAllItems();
301   f_selected_item = 0;
302   f_display.SetSensitive (False);
303 }
304
305
306 // /////////////////////////////////////////////////////////////////
307 // receive
308 // /////////////////////////////////////////////////////////////////
309
310 void
311 NodeHistoryAgent::receive (HistoryAdd &message, void* /*client_data*/)
312 {
313   if (!f_popped_up)
314     return;
315   // Add new item to the beginning (index 1) of the list.
316   UAS_String bn = message.f_new_entry->book_name(UAS_SHORT_TITLE);
317   UAS_String tt = message.f_new_entry->title();
318
319   f_list.AddItemUnselected (compose_entry(bn, tt), 1);
320   f_list.SetPos (1);
321   if (message.f_moving)
322     f_list.SelectPos (1, True);
323 }
324
325 XmString
326 NodeHistoryAgent::compose_entry(UAS_String book, UAS_String section)
327 {
328   WXmString bookString((char*)book);
329   WXmString sectString((char*)section);
330
331   if (bookString.Width(f_list.FontList()) >= SECTION_OFFSET)
332   {
333     char* dots = "...";
334
335     char* ungenerated = (char*)(bookString + WXmString(dots));
336
337     WString anonym_wstring = ungenerated;
338     wchar_t* buf = (wchar_t*)anonym_wstring;
339     wchar_t* ptr = buf + wcslen(buf) - (strlen(dots)+1);
340
341     XtFree(ungenerated);
342
343     WXmString stake;
344     WString wdots(dots);
345
346     int allowance;
347     do
348     {
349       char* str;
350       memcpy(ptr--, (wchar_t*)wdots, (strlen(dots)+1) * sizeof(wchar_t));
351
352       stake = str = WString(buf).get_mbstr();
353
354       allowance = SECTION_OFFSET - stake.Width(f_list.FontList());
355
356       delete[] str;
357     }
358     while (allowance <= 0 && ptr >= buf);
359
360     while (*ptr <= (wchar_t)' ' && ptr >= buf)
361     {
362       char* str;
363       memcpy(ptr--, (wchar_t*)wdots, (strlen(dots)+1) * sizeof(wchar_t));
364
365       stake = str = WString(buf).get_mbstr();
366       allowance = SECTION_OFFSET - stake.Width(f_list.FontList());
367
368       delete[] str;
369     }
370
371     bookString = stake;
372   }
373
374   WXmString space(window_system().
375                   make_space(SECTION_OFFSET -
376                              bookString.Width(f_list.FontList()), f_list),
377                   False);
378
379   WXmString entry = bookString + space + sectString;
380
381   return entry.disown();
382 }
383
384 void
385 NodeHistoryAgent::receive (HistoryDelete &message, void* /*client_data*/)
386 {
387   if (!f_popped_up)
388     return;
389   // Remove old items from the list.
390   int length = f_list.ItemCount();
391   ON_DEBUG (printf ("----- history list delete: count %d, index %d, len %d\n",
392                     message.f_count,
393                     length - message.f_index - message.f_count + 1, length));
394   // The list is stored in inverted form, ie: new items on top.
395   int item = length - message.f_index - message.f_count + 1;
396   if (f_selected_item == item && message.f_moving == TRUE)
397     f_display.SetSensitive (False);
398   f_list.DeleteItemsPos (message.f_count, item);
399 }