7c4c83a1b5e8dafb3d25bdf7886aa56894f0469c
[oweals/cde.git] / cde / programs / dtinfo / dtinfo / src / Agents / PrefAgentMotif.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 libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 //      Copyright (c) 1994,1995,1996 FUJITSU LIMITED
24 //      All Rights Reserved
25
26 /*
27  * $XConsortium: PrefAgentMotif.C /main/14 1996/11/23 14:13:16 cde-hal $
28  *
29  * Copyright (c) 1993 HAL Computer Systems International, Ltd.
30  * All rights reserved.  Unpublished -- rights reserved under
31  * the Copyright Laws of the United States.  USE OF A COPYRIGHT
32  * NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
33  * OR DISCLOSURE.
34  * 
35  * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
36  * SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.  USE,
37  * DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
38  * PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
39  * INTERNATIONAL, LTD.
40  * 
41  *                         RESTRICTED RIGHTS LEGEND
42  * Use, duplication, or disclosure by the Government is subject
43  * to the restrictions as set forth in subparagraph (c)(l)(ii)
44  * of the Rights in Technical Data and Computer Software clause
45  * at DFARS 252.227-7013.
46  *
47  *          HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
48  *                  1315 Dell Avenue
49  *                  Campbell, CA  95008
50  * 
51  */
52
53 #define C_TOC_Element
54 #define L_Basic
55
56 #define C_WindowSystem
57 #define L_Other
58
59 #define C_MapMgr
60 #define C_PrefMgr
61 #define C_StyleSheetMgr
62 #define C_NodeWindowMgr
63 #define C_GlobalHistoryMgr
64 #define C_SearchMgr
65
66 #define L_Managers
67
68 #define C_HelpAgent
69 #define C_PrefAgent
70 #define L_Agents
71
72 #include "Other/XmStringLocalized.hh"
73 #include "Managers/CatMgr.hh"
74
75 #include <Prelude.h>
76
77 #include "Registration.hh"
78
79 #include <WWL/WXmForm.h>
80 #include <WWL/WXmMenu.h>
81 #include <WWL/WXmLabel.h>
82 #include <WWL/WXmFrame.h>
83 #include <WWL/WXmSeparator.h>
84 #include <WWL/WXmArrowButton.h>
85 #include <WWL/WXmDialogShell.h>
86 #include <WWL/WXmMessageBox.h>
87
88 #include <X11/cursorfont.h>
89
90 #ifdef SVR4
91 #ifndef USL
92 #include <libintl.h>    // 1/21/94 yuji
93 #endif
94 #endif
95
96 /* Update time in milliseconds when arrow button held down. */
97 #define CHANGE_SPEED 300
98
99 #define CLASS PrefAgent
100 #include "create_macros.hh"
101
102 // All the stuff below is semi-bogus.  There really needs to be classes
103 // for displaying values of certain types, and there needs to be preference
104 // classes which take care of the modified/unmodified BS.
105 // 14:03 11-Apr-93 DJB
106
107 // Modes of operation:
108 // 1) Set field from preference (initialize only!).
109 // 2) Reset field from preference. 
110 // 3) Set preference from field (when field is modified).
111 // 4) Update other UI parts when preference changes.  
112
113   
114 class ChangeData {
115 public:
116   ChangeData (WXmTextField &f, Widget up, Widget dn, int c, int l)
117     : field (f), up_arrow(up), dn_arrow(dn), change(c), limit(l)
118     { }
119
120   WXmTextField field;           // Field to change 
121   Widget       up_arrow;
122   Widget       dn_arrow;
123   int          change;          // Amount of change
124   int          limit;           // Limit of change 
125 };
126
127
128 class Value {
129 public:
130   Value()
131     { modified();  }
132   void modified()
133     { changed = TRUE; num_changed++; }
134   void unmodified()
135     { changed = FALSE; num_changed--; }
136   bool changed;
137   static int num_changed;
138 };
139
140 int Value::num_changed = 0;
141
142 class IntegerValue : public Value {
143 public:
144   IntegerValue (int value)
145     : original (value), current (value) { }
146   void set_value (int value)
147     {
148       if (value == original)  // ie: reset 
149         unmodified();
150       else if (!changed)      // ie: first change
151         modified();
152       current = value;
153     }
154   void apply (PrefSymbol sym)
155     {
156       if (changed) {
157         unmodified(); original = current;
158         pref_mgr().set_int (sym, current);
159       }
160     };
161
162   int original;
163   int current;
164 };
165
166 class BooleanValue : public Value {
167 public:
168   BooleanValue (bool value)
169     : original (value), current (value) { }
170   void set_value (int value)
171     {
172       if (value == original)  // ie: reset 
173         unmodified();
174       else if (!changed)      // ie: first change
175         modified();
176       current = value;
177     }
178   void apply (PrefSymbol sym)
179     {
180       if (changed) {
181         unmodified(); original = current;
182         pref_mgr().set_boolean (sym, current);
183       }
184     };
185
186   bool original;
187   bool current;
188 };
189
190 // NOTE: String currently unused, will probably have to strdup() values. 
191 class StringValue : public Value {
192 public:
193   StringValue (String value)
194     : original (value), current (value) { }
195   void set_value (String value)
196     {
197       if (value == original)  // ie: reset 
198         unmodified();
199       else if (!changed)      // ie: first change
200         modified();
201       current = value;
202     }
203   void apply (PrefSymbol sym)
204     {
205       if (changed) {
206         unmodified(); original = current;
207         pref_mgr().set_string (sym, current);
208       }
209     };
210
211   String original;
212   String current;
213 };
214
215 class WindowGeometryValue : public Value {
216 public:
217   WindowGeometryValue (const WindowGeometry &value)
218     : original (value), current (value) { }
219   void set_value (WindowGeometry &value)
220     {
221       if (value == original)  // ie: reset 
222         unmodified();
223       else if (!changed)      // ie: first change
224         modified();
225       current = value;
226     }
227   void apply (PrefSymbol sym)
228     {
229       if (changed) {
230           unmodified(); original = current;
231           pref_mgr().set_geometry (sym, current);
232         }
233     };
234
235   WindowGeometry original;
236   WindowGeometry current;
237 };
238
239 #define IS_CHANGED(X) (((Value *) (X).UserData())->changed)
240 #define SET_CHANGED(X,V) ((Value *) (X).UserData())->changed = V
241
242 #if defined(__STDC__) || defined(hpux) || defined(__osf__)
243 #define ATTACH_VALUE(X,T,V) (X).UserData ((void *) new T##Value(V))
244 #define SET_VALUE(X,T,V) ((T##Value *) (X).UserData())->set_value(V)
245 #define ORIGINAL_VALUE(X,T) ((T##Value *) (X).UserData())->original
246 #define CURRENT_VALUE(X,T) ((T##Value *) (X).UserData())->current
247 #define APPLY_VALUE(X,T,S) ((T##Value *) (X).UserData())->apply(S)
248 #else
249 #define ATTACH_VALUE(X,T,V) (X).UserData ((void *) new T/**/Value(V))
250 #define SET_VALUE(X,T,V) ((T/**/Value *) (X).UserData())->set_value(V)
251 #define ORIGINAL_VALUE(X,T) ((T/**/Value *) (X).UserData())->original
252 #define CURRENT_VALUE(X,T) ((T/**/Value *) (X).UserData())->current
253 #define APPLY_VALUE(X,T,S) ((T/**/Value *) (X).UserData())->apply(S)
254 #endif
255
256 // /////////////////////////////////////////////////////////////////
257 // Constructor
258 // /////////////////////////////////////////////////////////////////
259
260
261 PrefAgent::PrefAgent()
262 : f_shell(NULL), f_top_panel(NULL), f_timeout(NULL)
263 {
264 }
265
266
267 // /////////////////////////////////////////////////////////////////
268 // Destructor
269 // /////////////////////////////////////////////////////////////////
270
271 PrefAgent::~PrefAgent()
272 {
273   delete f_timeout;
274   f_timeout = NULL;
275   f_shell.Destroy();
276 }
277
278
279 // /////////////////////////////////////////////////////////////////
280 // display
281 // /////////////////////////////////////////////////////////////////
282
283 void
284 PrefAgent::display()
285 {
286   Wait_Cursor bob;
287   if (f_shell == 0)
288     create_ui();
289
290   // Always reset on new popup. 
291   reset();
292
293   f_shell.Popup();
294   f_shell.DeIconify();
295 }
296
297
298 // /////////////////////////////////////////////////////////////////
299 // create_ui
300 // /////////////////////////////////////////////////////////////////
301
302 void
303 PrefAgent::create_ui()
304 {
305   // Create main preferences window.
306
307   XmStringLocalized mtfstring;
308   String            string;
309   int               decorations=MWM_DECOR_BORDER  |
310                                 MWM_DECOR_RESIZEH |
311                                 MWM_DECOR_TITLE   |
312                                 MWM_DECOR_MENU;
313
314   f_shell = WTopLevelShell (window_system().toplevel(), WPopup, "preferences");
315   window_system().register_shell(&f_shell);
316
317   string = CATGETS(Set_PrefAgent, 1, "Dtinfo: Preferences");
318   XtVaSetValues((Widget)f_shell,
319                 XmNtitle, string,
320                 XmNmwmDecorations, decorations,
321                 NULL);
322
323   DECL  (WXmForm,         form,         f_shell,      "form");
324   DECLMC(WXmOptionMenu,   options,      form,         "options");
325   DECLC (WXmPulldownMenu, options_menu, form,         "options_menu");
326
327   mtfstring = CATGETS(Set_AgentLabel, 186, "Preferences for");
328   XtVaSetValues(options, XmNlabelString, (XmString)mtfstring, NULL);
329
330   ASSNM (WXmPushButton,   f_ok,         form,         "ok");
331   ASSNM (WXmPushButton,   f_apply,      form,         "apply");
332   ASSNM (WXmPushButton,   f_reset,      form,         "reset");
333   DECLM (WXmPushButton,   cancel,       form,         "cancel");
334   DECLM (WXmPushButton,   help,         form,         "help");
335
336   mtfstring = CATGETS(Set_AgentLabel, 161, "OK");
337   XtVaSetValues(f_ok, XmNlabelString, (XmString)mtfstring, NULL);
338   mtfstring = CATGETS(Set_AgentLabel, 201, "Apply");
339   XtVaSetValues(f_apply, XmNlabelString, (XmString)mtfstring, NULL);
340   mtfstring = CATGETS(Set_AgentLabel, 202, "Reset");
341   XtVaSetValues(f_reset, XmNlabelString, (XmString)mtfstring, NULL);
342   mtfstring = CATGETS(Set_AgentLabel, 162, "Cancel");
343   XtVaSetValues(cancel, XmNlabelString, (XmString)mtfstring, NULL);
344   mtfstring = CATGETS(Set_AgentLabel, 48, "Help");
345   XtVaSetValues(help, XmNlabelString, (XmString)mtfstring, NULL);
346
347   SET_CALLBACK (f_ok,Activate,ok);
348   SET_CALLBACK (f_apply,Activate,apply);
349   SET_CALLBACK (f_reset,Activate,reset);
350   SET_CALLBACK (cancel,Activate,cancel);
351   help_agent().add_activate_help (help, (char*)"preferences_help");
352
353   DECLM (WXmFrame,        frame,        form,         "frame");
354   DECL  (WXmForm,         container,    frame,        "container");
355
356   // Create browsing preferences.
357   DECLM (WXmPushButton,   browse,          options_menu,  "browse");
358
359   DECL  (WXmForm,         browse_form,     container,     "browse_prefs");
360   DECLM (WXmLabel,        browse_label,    browse_form,   "browse_label");
361   DECLM (WXmPushButton,   get_browse_geo,  browse_form,   "get_browse_geo");
362   ASSNM (WXmTextField,    f_browse_geo,    browse_form,   "browse_geo");
363   DECLM (WXmLabel,        fs_label,        browse_form,   "fs_label");
364   DECL  (WXmForm,         fs_form,         browse_form,   "fs_form");
365   ASSNM (WXmTextField,    f_fs_field,      fs_form,       "scale_field");
366   DECLM (WXmArrowButton,  scale_up,        fs_form,       "scale_up");
367   DECLM (WXmArrowButton,  scale_down,      fs_form,       "scale_down");
368   DECLM (WXmLabel,        lock_label,      browse_form,   "lock_label");
369   ASSNM (WXmToggleButton, f_lock_toggle,   browse_form,   "lock_toggle");
370
371   mtfstring = CATGETS(Set_AgentLabel, 187, "Browsing");
372   XtVaSetValues(browse, XmNlabelString, (XmString)mtfstring, NULL);
373   mtfstring = CATGETS(Set_AgentLabel, 190, "Browser Geometry");
374   XtVaSetValues(browse_label, XmNlabelString, (XmString)mtfstring, NULL);
375   mtfstring = CATGETS(Set_AgentLabel, 270, "...");
376   XtVaSetValues(get_browse_geo, XmNlabelString, (XmString)mtfstring, NULL);
377   mtfstring = CATGETS(Set_AgentLabel, 192, "Font Scale");
378   XtVaSetValues(fs_label, XmNlabelString, (XmString)mtfstring, NULL);
379   mtfstring = CATGETS(Set_AgentLabel, 193, "Pin Window");
380   XtVaSetValues(lock_label, XmNlabelString, (XmString)mtfstring, NULL);
381   mtfstring = CATGETS(Set_AgentLabel, 194, "File a Bug");
382   XtVaSetValues(f_lock_toggle, XmNlabelString, (XmString)mtfstring, NULL);
383
384   Dimension height;
385   ChangeData *inc, *dec;
386
387   // Assume that the fields are taller than the labels.  If the user
388   // changes the font resources and violates this assumtion he's screwed
389   // and that's the way we like it.
390
391   height = f_fs_field.Height();
392
393   browse_label.Height (height);
394   fs_label.Height (height);
395   scale_up.Height (height/2);
396   scale_down.Height (height/2);
397
398   f_lock_toggle.LabelType (XmPIXMAP);
399   lock_label.Height (height);
400
401   fs_form.Manage();
402   browse_form.Manage();
403   f_top_panel = browse_form;
404
405   SET_CALLBACK_D (browse,Activate,switch_to_window,(Widget)browse_form);
406   SET_CALLBACK_D (get_browse_geo,Activate,get_geometry,(Widget)f_browse_geo);
407   SET_CALLBACK (f_browse_geo,ValueChanged,something_changed);
408   SET_CALLBACK (f_fs_field,ValueChanged,something_changed);
409   SET_CALLBACK (f_lock_toggle,ValueChanged,something_changed);
410   SET_CALLBACK (f_lock_toggle,ValueChanged,lock_toggle);
411
412   inc = new ChangeData(f_fs_field, scale_up, scale_down, 1, 5);
413   dec = new ChangeData(f_fs_field, scale_up, scale_down, -1, -2);
414   SET_CALLBACK_D (scale_up,Activate,change_cb,inc);
415   SET_CALLBACK_D (scale_up,Arm,arm_arrow,inc);
416   SET_CALLBACK  (scale_up,Disarm,disarm_arrow);
417   SET_CALLBACK_D (scale_down,Activate,change_cb,dec);
418   SET_CALLBACK_D (scale_down,Arm,arm_arrow,dec);
419   SET_CALLBACK  (scale_down,Disarm,disarm_arrow);
420
421   // Create map window preferences
422   DECLM (WXmPushButton,   map,             options_menu,  "map");
423   DECLM (WXmForm,         map_form,        container,     "map_prefs");
424   DECLM (WXmLabel,        map_label,       map_form,      "map_label");
425   DECLM (WXmPushButton,   get_map_geo,     map_form,      "get_map_geo");
426   ASSNM (WXmTextField,    f_map_geo,       map_form,      "map_geo");
427   DECLM (WXmLabel,        update_label,    map_form,      "update_label");
428   ASSNM (WXmToggleButton, f_update_toggle, map_form,      "update_toggle");
429
430   mtfstring = CATGETS(Set_AgentLabel, 188, "Map");
431   XtVaSetValues(map, XmNlabelString, (XmString)mtfstring, NULL);
432   mtfstring = CATGETS(Set_AgentLabel, 195, "Map Geometry");
433   XtVaSetValues(map_label, XmNlabelString, (XmString)mtfstring, NULL);
434   mtfstring = CATGETS(Set_AgentLabel, 270, "...");
435   XtVaSetValues(get_map_geo, XmNlabelString, (XmString)mtfstring, NULL);
436   mtfstring = CATGETS(Set_AgentLabel, 196, "Auto Update");
437   XtVaSetValues(update_label, XmNlabelString, (XmString)mtfstring, NULL);
438   mtfstring = CATGETS(Set_AgentLabel, 194, "File a Bug");
439   XtVaSetValues(f_update_toggle, XmNlabelString, (XmString)mtfstring, NULL);
440
441   height = f_map_geo.Height();
442   map_label.Height (height);
443   update_label.Height (height);
444   
445   SET_CALLBACK_D (get_map_geo,Activate,get_geometry,(Widget)f_map_geo);
446   SET_CALLBACK_D (map,Activate,switch_to_window,(Widget)map_form);
447   SET_CALLBACK (f_map_geo,ValueChanged,something_changed);
448   SET_CALLBACK (f_update_toggle,ValueChanged,something_changed);
449   SET_CALLBACK (f_update_toggle,ValueChanged,update_toggle);
450
451   map_form.Manage();
452
453   // Create history preferences 
454   DECLM (WXmPushButton,   history,      options_menu, "history");
455
456   mtfstring = CATGETS(Set_AgentLabel, 260, "History");
457   XtVaSetValues(history, XmNlabelString, (XmString)mtfstring, NULL);
458
459   DECL  (WXmForm,         hist_form,     container,     "history_prefs");
460   DECLM (WXmLabel,        nh_label,      hist_form,     "nh_label");
461   DECL  (WXmForm,         nh_form,       hist_form,     "nh_form");
462   ASSNM (WXmTextField,    f_nh_field,    nh_form,       "nh_field");
463   DECLM (WXmArrowButton,  nh_up,         nh_form,       "nh_up");
464   DECLM (WXmArrowButton,  nh_down,       nh_form,       "nh_down");
465   DECLM (WXmLabel,        sh_label,      hist_form,     "sh_label");
466   DECL  (WXmForm,         sh_form,       hist_form,     "sh_form");
467   ASSNM (WXmTextField,    f_sh_field,    sh_form,       "sh_field");
468   DECLM (WXmArrowButton,  sh_up,         sh_form,       "sh_up");
469   DECLM (WXmArrowButton,  sh_down,       sh_form,       "sh_down");
470
471   mtfstring = CATGETS(Set_AgentLabel, 197, "Section History Size");
472   XtVaSetValues(nh_label, XmNlabelString, (XmString)mtfstring, NULL);
473   mtfstring = CATGETS(Set_AgentLabel, 198, "Search History Size");
474   XtVaSetValues(sh_label, XmNlabelString, (XmString)mtfstring, NULL);
475
476   height = f_nh_field.Height();
477   nh_label.Height (height);
478   nh_up.Height (height/2);
479   nh_down.Height (height/2);
480
481   height = f_sh_field.Height();
482   sh_label.Height (height);
483   sh_up.Height (height/2);
484   sh_down.Height (height/2);
485
486   nh_form.Manage();
487   sh_form.Manage();
488   hist_form.Manage();
489   
490   SET_CALLBACK_D (history,Activate,switch_to_window,(Widget)hist_form);
491   SET_CALLBACK (f_nh_field,ValueChanged,something_changed);
492   SET_CALLBACK (f_sh_field,ValueChanged,something_changed);
493
494   inc = new ChangeData (f_nh_field, nh_up, nh_down, 10, 1000);
495   dec = new ChangeData (f_nh_field, nh_up, nh_down, -10, 10);
496   SET_CALLBACK_D (nh_up,Activate,change_cb,inc);
497   SET_CALLBACK_D (nh_up,Arm,arm_arrow,inc);
498   SET_CALLBACK (nh_up,Disarm,disarm_arrow);
499   SET_CALLBACK_D (nh_down,Activate,change_cb,dec);
500   SET_CALLBACK_D (nh_down,Arm,arm_arrow,dec);
501   SET_CALLBACK (nh_down,Disarm,disarm_arrow);
502
503   inc = new ChangeData (f_sh_field, sh_up, sh_down, 10, 1000);
504   dec = new ChangeData (f_sh_field, sh_up, sh_down, -10, 10);
505   SET_CALLBACK_D (sh_up,Activate,change_cb,inc);
506   SET_CALLBACK_D (sh_up,Arm,arm_arrow,inc);
507   SET_CALLBACK (sh_up,Disarm,disarm_arrow);
508   SET_CALLBACK_D (sh_down,Activate,change_cb,dec);
509   SET_CALLBACK_D (sh_down,Arm,arm_arrow,dec);
510   SET_CALLBACK (sh_down,Disarm,disarm_arrow);
511
512   // Create Search preferences.
513
514   DECLM (WXmPushButton,   search,            options_menu,  "search");
515
516   mtfstring = CATGETS(Set_AgentLabel, 189, "Searching");
517   XtVaSetValues(search, XmNlabelString, (XmString)mtfstring, NULL);
518
519   DECL  (WXmForm,         search_form,       container,     "search_prefs");
520   DECLM (WXmLabel,        max_hits_label,    search_form,   "max_hits");
521   DECL  (WXmForm,         hits_form,         search_form,   "hits_form");
522   ASSNM (WXmTextField,    f_max_hits_field,  hits_form,     "hits_field");
523   DECLM (WXmArrowButton,  hits_up,           hits_form,     "hits_up");
524   DECLM (WXmArrowButton,  hits_down,         hits_form,     "hits_down");
525   DECLM (WXmLabel,        adisplay_label,    search_form,   "adisplay_label");
526   ASSNM (WXmToggleButton, f_adisplay_toggle, search_form,   "adisplay_toggle");
527
528   mtfstring = CATGETS(Set_AgentLabel, 199, "Maximum Search Hits");
529   XtVaSetValues(max_hits_label, XmNlabelString, (XmString)mtfstring, NULL);
530   mtfstring = CATGETS(Set_AgentLabel, 200, "Auto Display First Hit");
531   XtVaSetValues(adisplay_label, XmNlabelString, (XmString)mtfstring, NULL);
532   mtfstring = CATGETS(Set_AgentLabel, 194, "File a Bug");
533   XtVaSetValues(f_adisplay_toggle, XmNlabelString, (XmString)mtfstring, NULL);
534
535   height = f_max_hits_field.Height();
536   max_hits_label.Height (height);
537   hits_up.Height (height/2);
538   hits_down.Height (height/2);
539   adisplay_label.Height (height);
540
541   hits_form.Manage();
542   search_form.Manage();
543
544   SET_CALLBACK_D (search,Activate,switch_to_window,(Widget)search_form);
545   SET_CALLBACK (f_max_hits_field,ValueChanged,something_changed);
546
547   inc = new ChangeData (f_max_hits_field, hits_up, hits_down, 10, 500);
548   dec = new ChangeData (f_max_hits_field, hits_up, hits_down, -10, 10);
549   SET_CALLBACK_D (hits_up,Activate,change_cb,inc);
550   SET_CALLBACK_D (hits_up,Arm,arm_arrow,inc);
551   SET_CALLBACK (hits_up,Disarm,disarm_arrow);
552   SET_CALLBACK_D (hits_down,Activate,change_cb,dec);
553   SET_CALLBACK_D (hits_down,Arm,arm_arrow,dec);
554   SET_CALLBACK (hits_down,Disarm,disarm_arrow);
555   SET_CALLBACK (f_adisplay_toggle,ValueChanged,something_changed);
556   SET_CALLBACK (f_adisplay_toggle,ValueChanged,adisplay_toggle);
557
558   /* -------- node history size, search history size -------- */
559
560   options.SubMenuId (options_menu);
561
562   container.Manage();
563   form.DefaultButton (f_ok);
564   form.ShadowThickness (0);
565   form.Manage();
566
567   f_shell.Realize();
568   Dimension width;
569   f_shell.Get (WArgList (XmNheight, (XtArgVal) &height,
570                          XmNwidth, &width,
571                          NULL));
572   f_shell.Set (WArgList (XmNminHeight, height,
573                          XmNmaxHeight, height,
574                          XmNminWidth,  width,
575                          XmNmaxWidth,  width,
576                          NULL));
577
578   map_form.Unmanage();
579   hist_form.Unmanage();
580   search_form.Unmanage();
581
582   // Values get displayed when reset() is called on dialog display. 
583   init_values();
584 }
585
586
587 // /////////////////////////////////////////////////////////////////
588 // apply
589 // /////////////////////////////////////////////////////////////////
590
591 void
592 PrefAgent::ok()
593 {
594   apply();
595   f_shell.Popdown();
596 }
597
598
599 // NOTE:
600 // All the functionaly in the `if' statements below in appy and reset
601 // really should be part of the class.  No time right now, though. 
602
603
604 // /////////////////////////////////////////////////////////////////
605 // apply
606 // /////////////////////////////////////////////////////////////////
607
608 void
609 PrefAgent::apply()
610 {
611   // Save browse preferences.
612   bool update_fs = False;
613   if (IS_CHANGED (f_fs_field))
614     update_fs = True;
615   APPLY_VALUE (f_browse_geo, WindowGeometry, PrefMgr::BrowseGeometry);
616   APPLY_VALUE (f_fs_field, Integer, PrefMgr::FontScale);
617   APPLY_VALUE (f_lock_toggle, Boolean, PrefMgr::BrowseLock);
618
619   // Save map preferences.
620   APPLY_VALUE (f_map_geo, WindowGeometry, PrefMgr::MapGeometry);
621   APPLY_VALUE (f_update_toggle, Boolean, PrefMgr::MapAutoUpdate);
622   map_mgr().set_auto_update(f_update_toggle.Set());
623
624   // Save history preferences.
625   ON_DEBUG (printf ("Section hist changed = %d\n", IS_CHANGED (f_nh_field)));
626   if (IS_CHANGED (f_nh_field))
627     global_history_mgr().set_max_length (CURRENT_VALUE (f_nh_field, Integer));
628   APPLY_VALUE (f_nh_field, Integer, PrefMgr::NodeHistSize);
629   ON_DEBUG (printf ("Search hist changed = %d\n", IS_CHANGED (f_nh_field)));
630   if (IS_CHANGED (f_sh_field))
631     search_mgr().set_history_length (CURRENT_VALUE (f_sh_field, Integer));
632   APPLY_VALUE (f_sh_field, Integer, PrefMgr::SearchHistSize);
633
634   // Save search preferences. 
635   APPLY_VALUE (f_max_hits_field, Integer, PrefMgr::MaxSearchHits);
636   APPLY_VALUE (f_adisplay_toggle, Boolean, PrefMgr::DisplayFirstHit);
637
638   // Desensitize appropriate controls. 
639   f_ok.SetSensitive (False);
640   f_apply.SetSensitive (False);
641   f_reset.SetSensitive (False);
642
643   pref_mgr().sync();
644
645   if (update_fs)
646     {
647       Wait_Cursor bob;
648       style_sheet_mgr().font_preference_modified();
649     }
650 }
651
652
653 // /////////////////////////////////////////////////////////////////
654 // reset
655 // /////////////////////////////////////////////////////////////////
656
657 void
658 PrefAgent::reset()
659 {
660   // Reset browse preferences.
661   if (IS_CHANGED (f_browse_geo))
662     set_geometry (f_browse_geo, ORIGINAL_VALUE (f_browse_geo, WindowGeometry));
663   if (IS_CHANGED (f_fs_field))
664     set_integer (f_fs_field, ORIGINAL_VALUE (f_fs_field, Integer));
665   if (IS_CHANGED (f_lock_toggle)) {
666     set_lock (ORIGINAL_VALUE (f_lock_toggle, Boolean));
667     f_lock_toggle.Unmap();
668     f_lock_toggle.Map();
669   }
670
671   // Reset map preferences.
672   if (IS_CHANGED (f_map_geo))
673     set_geometry (f_map_geo, ORIGINAL_VALUE (f_map_geo, WindowGeometry));
674   if (IS_CHANGED (f_update_toggle))
675     set_update (ORIGINAL_VALUE (f_update_toggle, Boolean));
676
677   // Reset history preferences.
678   if (IS_CHANGED (f_nh_field))
679     set_integer (f_nh_field, ORIGINAL_VALUE (f_nh_field, Integer));
680   if (IS_CHANGED (f_sh_field))
681     set_integer (f_sh_field, ORIGINAL_VALUE (f_sh_field, Integer));
682
683   // Reset Search preferences. 
684   if (IS_CHANGED (f_max_hits_field))
685     set_integer (f_max_hits_field, ORIGINAL_VALUE (f_max_hits_field, Integer));
686   if (IS_CHANGED (f_adisplay_toggle))
687     set_auto_display (ORIGINAL_VALUE (f_adisplay_toggle, Boolean));
688
689   // Desensitize appropriate controls. 
690   f_ok.SetSensitive (False);
691   f_apply.SetSensitive (False);
692   f_reset.SetSensitive (False);
693 }
694
695 // /////////////////////////////////////////////////////////////////
696 // cancel
697 // /////////////////////////////////////////////////////////////////
698
699 void
700 PrefAgent::cancel()
701 {
702   f_shell.Popdown();
703 }
704
705
706 // /////////////////////////////////////////////////////////////////
707 // init_values
708 // /////////////////////////////////////////////////////////////////
709
710 void
711 PrefAgent::init_values()
712 {
713   PrefMgr &m = pref_mgr();
714   
715   ATTACH_VALUE (f_browse_geo, WindowGeometry,
716                 m.get_geometry (PrefMgr::BrowseGeometry));
717   ATTACH_VALUE (f_fs_field, Integer, m.get_int (PrefMgr::FontScale));
718   ATTACH_VALUE (f_lock_toggle, Boolean, m.get_boolean (PrefMgr::BrowseLock));
719   
720   ATTACH_VALUE (f_map_geo, WindowGeometry,
721                 m.get_geometry (PrefMgr::MapGeometry));
722   ATTACH_VALUE (f_update_toggle, Boolean,
723                 m.get_boolean (PrefMgr::MapAutoUpdate));
724
725   ATTACH_VALUE (f_nh_field, Integer, m.get_int (PrefMgr::NodeHistSize));
726   ATTACH_VALUE (f_sh_field, Integer, m.get_int (PrefMgr::SearchHistSize));
727
728   ATTACH_VALUE (f_max_hits_field, Integer, m.get_int (PrefMgr::MaxSearchHits));
729   ATTACH_VALUE (f_adisplay_toggle, Boolean,
730                 m.get_boolean (PrefMgr::DisplayFirstHit));
731 }
732
733
734 // /////////////////////////////////////////////////////////////////
735 // something_changed
736 // /////////////////////////////////////////////////////////////////
737
738 void
739 PrefAgent::something_changed()
740 {
741   f_ok.SetSensitive (True);
742   f_apply.SetSensitive (True);
743   f_reset.SetSensitive (True);
744 }
745
746
747 // /////////////////////////////////////////////////////////////////
748 // switch_to_window
749 // /////////////////////////////////////////////////////////////////
750
751 void
752 PrefAgent::switch_to_window (WCallback *wcb)
753 {
754   Widget w = (Widget) wcb->ClientData();
755   if (w == f_top_panel)
756     return;
757
758   XtManageChild (w);
759   XRaiseWindow (XtDisplay (w), XtWindow (w));
760   XtUnmanageChild (f_top_panel);
761   f_top_panel = w;
762 }
763
764
765 // Keep track if timeout called.  If so, don't change on active callback. 
766 static int timeout_called;
767
768 // /////////////////////////////////////////////////////////////////
769 // change_cb - update callback for field arrow buttons
770 // /////////////////////////////////////////////////////////////////
771
772 void
773 PrefAgent::change_cb (WCallback *wcb)
774 {
775   if (timeout_called == 0)
776     change_field ((ChangeData *) wcb->ClientData());
777   // Get rid of the timeout if it is active. 
778   if (f_timeout)
779     {
780       delete f_timeout;
781       f_timeout = NULL;
782     }
783 }
784
785
786 // /////////////////////////////////////////////////////////////////
787 // arm_arrow - arm callback for field arrow buttons
788 // /////////////////////////////////////////////////////////////////
789
790 void
791 PrefAgent::arm_arrow (WCallback *wcb)
792 {
793   // Add a timeout to keep changing the value.
794   timeout_called = 0;
795   f_timeout =
796     new WTimeOut (window_system().app_context(), CHANGE_SPEED, this,
797                   (WTimeOutFunc) &PrefAgent::change_timeout,
798                   wcb->ClientData());
799 }
800
801
802 // /////////////////////////////////////////////////////////////////
803 // disarm_arrow - arm callback for field arrow buttons
804 // /////////////////////////////////////////////////////////////////
805
806 void
807 PrefAgent::disarm_arrow()
808 {
809   delete f_timeout;
810   f_timeout = NULL;
811 }
812
813
814 // /////////////////////////////////////////////////////////////////
815 // change_timeout
816 // /////////////////////////////////////////////////////////////////
817
818 void
819 PrefAgent::change_timeout (WTimeOut *wto)
820 {
821   timeout_called++;
822   // Change the value.
823   bool changed = change_field ((ChangeData *) wto->ClientData());
824   // Add the callback again if the limit hasn't been reached. 
825   if (changed)
826     {
827       int speed = CHANGE_SPEED;
828       // After three times double the speed. 
829       if (timeout_called > 3)
830         speed /= 2;
831       f_timeout =
832         new WTimeOut (window_system().app_context(), speed, this,
833                       (WTimeOutFunc) &PrefAgent::change_timeout,
834                       wto->ClientData());
835     }
836   else
837     f_timeout = NULL;
838 }
839
840
841 // /////////////////////////////////////////////////////////////////
842 // change_field
843 // /////////////////////////////////////////////////////////////////
844
845 bool
846 PrefAgent::change_field (ChangeData *cd)
847 {
848   // Get the current field value and add the change to it. 
849   char *value = cd->field.Value();
850   int amount = atoi (value);
851   free (value);
852   amount += cd->change;
853
854   // reached the limit, need to make the arrow go insensitive
855   if (amount == cd->limit)
856   {
857      // see if incrementing or decrementing
858      if(cd->change < 0)
859      {
860        // user is decrementing--make down arrow insensitive
861        XtSetSensitive(cd->dn_arrow, False);
862      }
863      else
864      {
865        // user is incrementing--make down arrow insensitive
866        XtSetSensitive(cd->up_arrow, False);
867      }
868   }
869   else
870   {
871      // see if incrementing or decrementing
872      if(cd->change < 0)
873      {
874        // user is decrementing--make up arrow sensitive if it is
875        // insensitive
876        if(!XtIsSensitive(cd->up_arrow))
877          XtSetSensitive(cd->up_arrow, True);
878      }
879      else
880      {
881        // user is incrementing--make down arrow sensitive if it is
882        // insensitive
883        if(!XtIsSensitive(cd->dn_arrow))
884          XtSetSensitive(cd->dn_arrow, True);
885      }
886   }
887
888   // Make sure the change won't exceed any limits.
889   // If change is negative, then limit is a lower limit (and vice-versa).
890   if ((cd->change < 0 && amount < cd->limit) ||
891       (cd->change > 0 && amount > cd->limit))
892     {
893       // Sorry, Charlie. 
894       window_system().beep();
895       return (FALSE);
896     }
897
898   // Update the field to display the new value.
899   set_integer (cd->field, amount);
900
901   return (TRUE);
902 }
903
904
905 // /////////////////////////////////////////////////////////////////
906 // lock_toggle
907 // /////////////////////////////////////////////////////////////////
908
909 void
910 PrefAgent::lock_toggle (WCallback *wcb)
911 {
912   XmToggleButtonCallbackStruct &cbs =
913     *(XmToggleButtonCallbackStruct*) wcb->CallData();
914
915   set_lock (cbs.set);
916 }
917
918
919 // /////////////////////////////////////////////////////////////////
920 // update_toggle
921 // /////////////////////////////////////////////////////////////////
922
923 void
924 PrefAgent::update_toggle (WCallback *wcb)
925 {
926   XmToggleButtonCallbackStruct &cbs =
927     *(XmToggleButtonCallbackStruct*) wcb->CallData();
928
929   set_update (cbs.set);
930 }
931
932
933 // /////////////////////////////////////////////////////////////////
934 // set_lock
935 // /////////////////////////////////////////////////////////////////
936
937 void
938 PrefAgent::set_lock (bool set)
939 {
940     if (set) {
941         f_lock_toggle.WObject::Set(WArgList(XmNselectPixmap,
942                                             window_system().locked_pixmap(f_lock_toggle.Parent()),
943                                             XmNlabelPixmap,
944                                             window_system().semilocked_pixmap(f_lock_toggle.Parent()),
945                                             NULL));
946     }
947     else {
948         f_lock_toggle.WObject::Set(WArgList(XmNselectPixmap,
949                                             window_system().semilocked_pixmap(f_lock_toggle.Parent()),
950                                             XmNlabelPixmap,
951                                             window_system().unlocked_pixmap(f_lock_toggle.Parent()),
952                                             NULL));
953     }
954     
955     f_lock_toggle.Set (set);
956     SET_VALUE (f_lock_toggle, Boolean, set);
957 }  
958
959
960 // /////////////////////////////////////////////////////////////////
961 // set_update
962 // /////////////////////////////////////////////////////////////////
963
964 void
965 PrefAgent::set_update (bool set)
966 {
967   XmStringLocalized mtfstring =
968         CATGETS(Set_AgentLabel, set? 203 : 204, set ? "On" : "Off");
969
970   XtVaSetValues(f_update_toggle, XmNlabelString, (XmString)mtfstring, NULL);
971
972   f_update_toggle.Set (set);
973   SET_VALUE (f_update_toggle, Boolean, set);
974 }
975
976
977 // /////////////////////////////////////////////////////////////////
978 // set_geometry
979 // /////////////////////////////////////////////////////////////////
980
981 void
982 PrefAgent::set_geometry (WXmTextField &field, WindowGeometry &wg)
983 {
984   static char buf[16];
985   snprintf (buf, sizeof(buf), "%dx%d", wg.width, wg.height);
986   field.Value (buf);
987   SET_VALUE (field, WindowGeometry, wg);
988 }
989
990
991 // /////////////////////////////////////////////////////////////////
992 // set_integer
993 // /////////////////////////////////////////////////////////////////
994
995 void
996 PrefAgent::set_integer (WXmTextField &field, int i)
997 {
998   static char buf[16];
999   snprintf (buf, sizeof(buf), "%d", i);
1000   field.Value (buf);
1001   SET_VALUE (field, Integer, i);
1002 }
1003
1004
1005 // /////////////////////////////////////////////////////////////////
1006 // adisplay_toggle
1007 // /////////////////////////////////////////////////////////////////
1008
1009 void
1010 PrefAgent::adisplay_toggle (WCallback *wcb)
1011 {
1012   XmToggleButtonCallbackStruct &cbs =
1013     *(XmToggleButtonCallbackStruct*) wcb->CallData();
1014
1015   set_auto_display (cbs.set);
1016 }
1017
1018
1019 // /////////////////////////////////////////////////////////////////
1020 // set_auto_display
1021 // /////////////////////////////////////////////////////////////////
1022
1023 void
1024 PrefAgent::set_auto_display (bool set)
1025 {
1026   XmStringLocalized mtfstring =
1027         CATGETS(Set_AgentLabel, set? 203 : 204, set ? "On" : "Off");
1028
1029   XtVaSetValues(f_adisplay_toggle, XmNlabelString, (XmString)mtfstring, NULL);
1030
1031   f_adisplay_toggle.Set (set);
1032   SET_VALUE (f_adisplay_toggle, Boolean, set);
1033 }
1034
1035 #ifdef UseWideChars
1036 // /////////////////////////////////////////////////////////////////
1037 // hyphen_toggle - 4/11/94 kamiya
1038 // This will be obsolete because toggle is not adequate for selecting
1039 // hyphenation processing method - 4/11/94 kamiya
1040 // /////////////////////////////////////////////////////////////////
1041 void
1042 PrefAgent::hyphen_toggle (WCallback *)
1043 {
1044 // obsolete, remove this method right away.
1045 }
1046
1047 // /////////////////////////////////////////////////////////////////
1048 // set_hyphen - 4/11/94 kamiya
1049 // /////////////////////////////////////////////////////////////////
1050 void
1051 PrefAgent::set_hyphen (XtPointer)
1052 {
1053 // obsolete, remove this method right away.
1054 }
1055 #endif
1056
1057 // /////////////////////////////////////////////////////////////////
1058 // get_geometry - interactivly get a window geometry
1059 // /////////////////////////////////////////////////////////////////
1060
1061 void
1062 PrefAgent::get_geometry (WCallback *wcb)
1063 {
1064   WXmTextField text_field ((Widget)wcb->ClientData());
1065   char *shell_name = NULL;
1066   if (text_field == f_map_geo)
1067     shell_name = (char*)"map";
1068   else if (text_field == f_browse_geo)
1069     shell_name = (char*)"nodeview";
1070     
1071   // Display an instructional dialog. 
1072   WXmMessageDialog
1073     info_dialog ((Widget)f_shell, (char*)"geometry_msg",
1074                  WArgList (XmNdialogType, XmDIALOG_INFORMATION, NULL));
1075   WXmDialogShell shell (info_dialog.Parent());
1076   // set window title
1077   String string = CATGETS(Set_PrefAgent, 2, "Dtinfo: Get Geometry");
1078   XtVaSetValues((Widget)shell, XmNtitle, string, NULL);
1079   //  window_system().register_full_modal_shell (&shell);
1080   info_dialog.MessageString (
1081         (char*)UAS_String(CATGETS(Set_Messages, 16, "File a Bug")));
1082   XtUnmanageChild (info_dialog.OkPB());
1083   XtUnmanageChild (info_dialog.HelpPB());
1084
1085   XtVaSetValues((Widget)info_dialog, XmNdefaultPosition, False, NULL);
1086
1087   // Wait for the dialog to appear. 
1088   int mapped = FALSE;
1089   info_dialog.Manage();
1090   XtAddEventHandler (info_dialog, ExposureMask, False,
1091                      dialog_mapped, (XtPointer) &mapped);
1092   XtAppContext app_context = window_system().app_context();
1093   XEvent event;
1094   while (!mapped)
1095     {
1096       XtAppNextEvent (app_context, &event);
1097       XtDispatchEvent (&event);
1098     }
1099
1100   // Let the user pick an OLIAS window. 
1101   static Cursor pick_cursor =
1102     XCreateFontCursor (window_system().display(), XC_crosshair);
1103   Widget target;
1104   target = XmTrackingEvent (f_shell, pick_cursor, False, &event);
1105
1106   // Get the geometry of the selected window.
1107   while (target != NULL && !XtIsShell (target))
1108     target = XtParent (target);
1109
1110   if (target != (Widget) info_dialog.Parent())
1111     {
1112       // Make sure the user clicked on the right kind of window.
1113       if (target != NULL && strcmp (XtName(target), shell_name) != 0)
1114         target = NULL;
1115
1116       if (target == NULL)
1117         {
1118           XBell (window_system().display(), 100);
1119         }
1120       else
1121         {
1122           WShell shell (target);
1123           WindowGeometry wg;
1124           wg.width = shell.Width();
1125           wg.height = shell.Height();
1126           set_geometry (text_field, wg);
1127         }
1128     }
1129
1130   // Nuke the dialog.
1131   info_dialog.Unmanage();
1132   XtDestroyWidget (info_dialog.Parent());
1133 }
1134
1135
1136 // /////////////////////////////////////////////////////////////////
1137 // dialog_mapped - wait for dialog to appear on-screen
1138 // /////////////////////////////////////////////////////////////////
1139
1140 void
1141 PrefAgent::dialog_mapped (Widget w, XtPointer client_data,
1142                           XEvent *, Boolean *)
1143 {
1144   XmUpdateDisplay (w);
1145
1146   *((int *) client_data) = TRUE;
1147 }