Remove redundant motif widgets
[oweals/cde.git] / cde / programs / dtcm / dtcm / misc.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 /* $TOG: misc.c /main/14 1999/07/01 09:51:24 mgreess $ */
24 /*
25  *  (c) Copyright 1993, 1994 Hewlett-Packard Company
26  *  (c) Copyright 1993, 1994 International Business Machines Corp.
27  *  (c) Copyright 1993, 1994 Novell, Inc.
28  *  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
29  */
30
31 #include <EUSCompat.h>
32 #include <stdarg.h>
33 #include <stdlib.h>
34 #include <stdint.h>
35 #include <unistd.h>
36 #include <stdio.h>
37 #include <ctype.h>
38 #include <string.h>
39 #include <time.h>
40 #include <limits.h>
41 #include <sys/stat.h>
42 #include <sys/param.h>
43 #include <Xm/PushBG.h>
44 #include <Xm/DialogS.h>
45 #include <Xm/Form.h>
46 #include <Xm/LabelG.h>
47 #include <Xm/SeparatoG.h>
48 #include <Xm/Protocols.h>
49 #include <Xm/AtomMgr.h>
50 #include <Xm/RowColumn.h>
51 #include <Xm/TextF.h>
52 #include <Xm/MwmUtil.h>
53 #include <Xm/ComboBox.h>
54 #include <Dt/Help.h>
55 #include "misc.h"
56 #include "help.h"
57 #include "datefield.h"
58 #include "util.h"
59 #include "calendar.h"
60 #include "props_pu.h"
61 #include "timeops.h"
62 #include "contract_xbm"
63 #include "expand_xbm"
64 #include "postup_xbm"
65 #include <X11/bitmaps/xm_error>
66 #include <X11/bitmaps/xm_information>
67 #include <X11/bitmaps/xm_question>
68 #include <X11/bitmaps/xm_warning>
69
70 /*******************************************************************************
71 **
72 **  External functions
73 **
74 *******************************************************************************/
75 /*
76 **  Widget building functions
77 */
78 extern Widget
79 create_repeat_menu(Widget parent, XtCallbackProc cb_func, XtPointer data) {
80         int                     ac;
81         Arg                     args[5];
82         Widget                  cb;
83         XmString                xmstr;
84         Repeat_menu_op          i;
85         extern                  Calendar *calendar;
86
87         ac = 0;
88         XtSetArg(args[ac], XmNcomboBoxType, XmDROP_DOWN_LIST); ++ac;
89         XtSetArg(args[ac], XmNpositionMode, XmONE_BASED); ++ac;
90         cb = XmCreateComboBox(parent, "repeat_cb", args, ac);
91
92         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 200, "One Time"));
93         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
94         XmStringFree(xmstr);
95
96         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 853, "Daily"));
97         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
98         XmStringFree(xmstr);
99
100         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 854, "Weekly"));
101         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
102         XmStringFree(xmstr);
103
104         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 855, "Every Two Weeks"));
105         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
106         XmStringFree(xmstr);
107
108         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 856, "Monthly By Date"));
109         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
110         XmStringFree(xmstr);
111
112         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 857, "Monthly By Weekday"));
113         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
114         XmStringFree(xmstr);
115
116         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 858, "Yearly"));
117         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
118         XmStringFree(xmstr);
119
120         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 859, "Monday Thru Friday"));
121         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
122         XmStringFree(xmstr);
123
124         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 860, "Mon, Wed, Fri"));
125         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
126         XmStringFree(xmstr);
127
128         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 861, "Tuesday, Thursday"));
129         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
130         XmStringFree(xmstr);
131
132         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 862, "Repeat Every..."));
133         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
134         XmStringFree(xmstr);
135
136         if (cb_func) 
137                 XtAddCallback(cb, XmNselectionCallback, cb_func, data);
138
139         return cb;
140 }
141
142 extern Widget
143 create_for_menu(Widget parent) {
144         int                     ac;
145         Arg                     args[5];
146         Widget                  cb, list, text;
147         XmString                xmstr;
148         For_menu_op             i;
149         extern                  Calendar *calendar;
150
151         ac = 0;
152         XtSetArg(args[ac], XmNcomboBoxType, XmDROP_DOWN_COMBO_BOX); ++ac;
153         XtSetArg(args[ac], XmNpositionMode, XmONE_BASED); ++ac;
154         cb = XmCreateComboBox(parent, "for_cb", args, ac);
155
156         /*
157          * This is a hack until the sizing bug in the combo box is fixed.
158          * To get it to size correctly, you must managed it and then reset
159          * the width.
160          */
161         XtVaSetValues(cb, XmNwidth, 80, NULL);
162
163         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 863, "2"));
164         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
165         XmStringFree(xmstr);
166
167         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 864, "3"));
168         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
169         XmStringFree(xmstr);
170
171         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 865, "4"));
172         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
173         XmStringFree(xmstr);
174
175         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 866, "5"));
176         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
177         XmStringFree(xmstr);
178
179         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 867, "6"));
180         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
181         XmStringFree(xmstr);
182
183         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 868, "7"));
184         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
185         XmStringFree(xmstr);
186
187         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 869, "8"));
188         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
189         XmStringFree(xmstr);
190
191         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 870, "9"));
192         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
193         XmStringFree(xmstr);
194
195         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 871, "10"));
196         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
197         XmStringFree(xmstr);
198
199         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 872, "11"));
200         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
201         XmStringFree(xmstr);
202
203         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 873, "12"));
204         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
205         XmStringFree(xmstr);
206
207         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 874, "13"));
208         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
209         XmStringFree(xmstr);
210
211         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 875, "14"));
212         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
213         XmStringFree(xmstr);
214
215         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 876, "forever"));
216         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
217         XmStringFree(xmstr);
218
219         XtVaGetValues(cb, XmNlist, &list, XmNtextField, &text, NULL);
220         XtVaSetValues(list, XmNsensitive, False, NULL);
221         XtVaSetValues(text, XmNsensitive, False, NULL);
222
223         return cb;
224 }
225
226 extern Widget
227 create_privacy_menu(Widget parent) {
228         int                     ac, i;
229         Arg                     args[5];
230         Widget                  cb;
231         XmString                xmstr;
232         extern                  Calendar *calendar;
233
234         ac = 0;
235         XtSetArg(args[ac], XmNcomboBoxType, XmDROP_DOWN_LIST); ++ac;
236         XtSetArg(args[ac], XmNvisibleItemCount, 3); ++ac;
237         XtSetArg(args[ac], XmNpositionMode, XmONE_BASED); ++ac;
238         cb = XmCreateComboBox(parent, "privacy_cb", args, ac);
239
240         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 721, "Others See Time And Text"));
241         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
242         XmStringFree(xmstr);
243
244         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 722, "Others See Time Only"));
245         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
246         XmStringFree(xmstr);
247
248         xmstr = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 723, "Others See Nothing"));
249         XmComboBoxAddItem((Widget)cb, xmstr, 0, False);
250         XmStringFree(xmstr);
251
252         return cb;
253 }
254
255
256 extern void
257 set_time_submenu(Widget parent, 
258         Widget option_menu, 
259         Props *p,
260         XtCallbackProc callback, 
261         XtPointer client_data, 
262         Boolean nt, 
263         Boolean ad, 
264         Widget **widget_list, 
265         int *widget_count) {
266
267         XmString        xmstr;
268         int             i, j, allocation_counter = 0;
269         char            buf[4], buf2[10];
270         Widget          menu, menuitem;
271         DisplayType     dt = get_int_prop(p, CP_DEFAULTDISP);
272         int             beg = get_int_prop(p, CP_DAYBEGIN);
273         int             end = get_int_prop(p, CP_DAYEND);
274         Calendar        *c = calendar;
275
276         XtVaGetValues(option_menu, XmNsubMenuId, &menu, NULL);
277
278         for (i = 0; i < *widget_count; i++)
279                 XtDestroyWidget((*widget_list)[i]);
280
281         if (*widget_list)
282                 free(*widget_list);
283
284
285         *widget_count = ((end - beg) * 4);
286
287         if (nt == True)
288                 (*widget_count)++;
289
290         if (ad == True)
291                 (*widget_count)++;
292
293         *widget_list = calloc(sizeof(Widget), *widget_count);
294
295         /*
296         **  Loop through and create the time menu using the starting and
297         **  ending times from the properties.
298         */
299         for (i = beg; i < end; i++) {
300                 if (dt == HOUR12) {
301                         if (i > 12)
302                                  sprintf(buf, "%2d:", i-12);
303                         else
304                                 if (i == 0)
305                                         cm_strcpy(buf, "12:");
306                         else
307                                  sprintf(buf, "%2d:", i);       
308                 }
309                 else
310                         sprintf(buf, "%02d", i);
311
312                 for (j = 0; j <= 45; j += 15) {
313                         sprintf(buf2, "%s%02d", buf, j);
314                         (*widget_list)[allocation_counter++] =
315                                 menuitem = XtVaCreateWidget(buf2,
316                                 xmPushButtonGadgetClass, menu,
317                                 XmNuserData, (i * hrsec) + (j * minsec),
318                                 NULL);
319                         if (callback)
320                                 XtAddCallback(menuitem, XmNactivateCallback,
321                                         callback, client_data);
322                 }
323         }
324
325         if (nt) {
326                 xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 353, 
327                                                         "No Time"));
328                 (*widget_list)[allocation_counter++] =
329                 menuitem = XtVaCreateWidget("noTime",
330                         xmPushButtonGadgetClass, menu,
331                         XmNlabelString, xmstr,
332                         XmNuserData, NO_TIME,
333                         NULL);
334                 XmStringFree(xmstr);
335                 if (callback)
336                         XtAddCallback(menuitem, XmNactivateCallback,
337                                 callback, client_data);
338         }
339
340         if (ad) {
341                 xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 354,
342                                                         "All Day"));
343                 (*widget_list)[allocation_counter++] =
344                 menuitem = XtVaCreateWidget("allDay",
345                         xmPushButtonGadgetClass, menu,
346                         XmNlabelString, xmstr,
347                         XmNuserData, ALL_DAY,
348                         NULL);
349                 XmStringFree(xmstr);
350                 if (callback)
351                         XtAddCallback(menuitem, XmNactivateCallback,
352                                 callback, client_data);
353         }
354
355         XtManageChildren(*widget_list, allocation_counter);
356 }
357
358 extern Widget
359 create_start_stop_time_menu(Widget parent, 
360         XmString label,
361         XtCallbackProc callback, 
362         XtPointer client_data, 
363         Props *p, 
364         Boolean nt, 
365         Boolean ad, 
366         Widget **widget_list, 
367         int *widget_count) {
368
369         int             ac;
370         Arg             args[5];
371         Widget          menu, option_m;
372         int             beg = get_int_prop(p, CP_DAYBEGIN);
373         int             end = get_int_prop(p, CP_DAYEND);
374
375         menu = XmCreatePulldownMenu(parent, "pulldown", NULL, 0);
376         XtVaSetValues(menu,
377                 XmNpacking, XmPACK_COLUMN,
378                 XmNorientation, XmHORIZONTAL,
379                 XmNnumColumns, (end - beg) + 1,
380                 NULL); 
381         ac = 0;
382         XtSetArg(args[ac], XmNsubMenuId, menu); ++ac;
383         XtSetArg(args[ac], XmNlabelString, label); ++ac;
384         option_m = XmCreateOptionMenu(parent, "option_m", args, ac);
385
386         set_time_submenu(parent, option_m, p, callback, 
387                          client_data, nt, ad, widget_list, widget_count);
388
389         return option_m;
390 }
391
392 extern Widget
393 create_time_scope_menu(Widget parent, 
394         XmString label, 
395         XtCallbackProc callback, 
396         XtPointer client_data) {
397         int                     ac;
398         Arg                     args[5];
399         Widget                  menu, option_m, menuitems[3];
400         XmString                xmstr;
401         Calendar                *c = calendar;
402
403         menu = XmCreatePulldownMenu(parent, "pulldown", NULL, 0);
404         XtVaSetValues(menu,
405                 XmNpacking, XmPACK_COLUMN,
406                 XmNorientation, XmHORIZONTAL,
407                 XmNnumColumns, TIME_DAYS + 1,
408                 NULL);
409
410         ac = 0;
411         XtSetArg(args[ac], XmNsubMenuId, menu); ++ac;
412         XtSetArg(args[ac], XmNlabelString, label); ++ac;
413         option_m = XmCreateOptionMenu(parent, "option_m", args, ac);
414
415
416         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 877, "Mins"));
417         menuitems[0] = XtVaCreateWidget("timescope0",
418                 xmPushButtonGadgetClass, menu,
419                 XmNlabelString, xmstr,
420                 XmNuserData, 0,
421                 NULL);
422         if (callback)
423                 XtAddCallback(menuitems[0], XmNactivateCallback,
424                               callback, client_data);
425         XmStringFree(xmstr);
426
427         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 878, "Hrs"));
428         menuitems[1] = XtVaCreateWidget("timescope1",
429                 xmPushButtonGadgetClass, menu,
430                 XmNlabelString, xmstr,
431                 XmNuserData, 1,
432                 NULL);
433         if (callback)
434                 XtAddCallback(menuitems[1], XmNactivateCallback,
435                               callback, client_data);
436         XmStringFree(xmstr);
437
438         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 879, "Days"));
439         menuitems[2] = XtVaCreateWidget("timescope2",
440                 xmPushButtonGadgetClass, menu,
441                 XmNlabelString, xmstr,
442                 XmNuserData, 2,
443                 NULL);
444         if (callback)
445                 XtAddCallback(menuitems[2], XmNactivateCallback,
446                               callback, client_data);
447         XmStringFree(xmstr);
448
449         XtVaSetValues(XmOptionButtonGadget(option_m), XmNsensitive, False,
450                 NULL);
451
452         XtManageChildren((WidgetList)menuitems, 3);
453
454         return option_m;
455 }
456
457 extern Widget
458 create_repeat_scope_menu(Widget parent, XmString label,
459                          XtCallbackProc callback, XtPointer client_data) {
460         int                     ac;
461         Arg                     args[5];
462         char                    buf[MAXNAMELEN];
463         Widget                  menu, option_m, menuitems[3];
464         XmString                xmstr;
465         Repeat_scope_menu_op    i;
466         Calendar                *c = calendar;
467
468         menu = XmCreatePulldownMenu(parent, "pulldown", NULL, 0);
469         XtVaSetValues(menu,
470                 XmNpacking, XmPACK_COLUMN,
471                 XmNorientation, XmHORIZONTAL,
472                 XmNnumColumns, REPEAT_MONTHS + 1,
473                 NULL);
474
475         ac = 0;
476         XtSetArg(args[ac], XmNsubMenuId, menu); ++ac;
477         XtSetArg(args[ac], XmNlabelString, label); ++ac;
478         option_m = XmCreateOptionMenu(parent, "option_m", args, ac);
479
480
481         sprintf(buf, "repeatscope%d", REPEAT_DAYS); 
482         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 816, "Days"));;
483         menuitems[0] = XtVaCreateWidget(buf,
484                 xmPushButtonGadgetClass, menu,
485                 XmNlabelString, xmstr,
486                 XmNuserData, REPEAT_DAYS,
487                 NULL);
488         if (callback)
489                 XtAddCallback(menuitems[0], XmNactivateCallback,
490                               callback, client_data);
491         XmStringFree(xmstr);
492
493         sprintf(buf, "repeatscope%d", REPEAT_WEEKS); 
494         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 817, "Weeks"));;
495         menuitems[1] = XtVaCreateWidget(buf,
496                 xmPushButtonGadgetClass, menu,
497                 XmNlabelString, xmstr,
498                 XmNuserData, REPEAT_WEEKS,
499                 NULL);
500         if (callback)
501                 XtAddCallback(menuitems[1], XmNactivateCallback,
502                               callback, client_data);
503         XmStringFree(xmstr);
504
505         sprintf(buf, "repeatscope%d", REPEAT_MONTHS); 
506         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 818, "Months"));;
507         menuitems[2] = XtVaCreateWidget(buf,
508                 xmPushButtonGadgetClass, menu,
509                 XmNlabelString, xmstr,
510                 XmNuserData, REPEAT_MONTHS,
511                 NULL);
512         if (callback)
513                 XtAddCallback(menuitems[2], XmNactivateCallback,
514                               callback, client_data);
515         XmStringFree(xmstr);
516
517         XtManageChildren((WidgetList)menuitems, 3);
518
519         return option_m;
520 }
521
522 static void
523 fill_pixmap(XImage *xi, int w, int h, unsigned char *data)
524 {
525         xi->width = w;
526         xi->height = h;
527         xi->data = (char *) data;
528         xi->xoffset = 0;
529         xi->format = XYBitmap;
530         xi->byte_order = MSBFirst;
531         xi->bitmap_pad = 8;
532         xi->bitmap_bit_order = LSBFirst;
533         xi->bitmap_unit = 8;
534         xi->depth = 1;
535         xi->bytes_per_line = (int)((w - 1) / 8) + 1;
536         xi->obdata = NULL;
537 }
538
539 extern void
540 create_all_pixmaps(Props_pu *p, Widget w)
541 {
542         Pixel           fg, bg;
543         Screen          *s;
544         static XImage   ic, ei, ci, li, ri, eri, ii, pui, qi, wi;
545
546         s = XtScreen(w);
547         XtVaGetValues(w, XmNforeground, &fg, XmNbackground, &bg,
548                 NULL);
549
550         fill_pixmap(&ei,
551                 expand_xbm_width, expand_xbm_height, expand_xbm_bits);
552         if (XmInstallImage(&ei, "x_pixmap"))
553                 p->expand_pixmap = XmGetPixmap(s, "x_pixmap", fg, bg);
554
555         fill_pixmap(&ci, contract_xbm_width, contract_xbm_height,
556                 contract_xbm_bits);
557         if (XmInstallImage(&ci, "c_pixmap"))
558                 p->contract_pixmap = XmGetPixmap(s, "c_pixmap", fg, bg);
559
560         fill_pixmap(&pui,
561                 postup_xbm_width, postup_xbm_height, postup_xbm_bits);
562         if (XmInstallImage(&pui, "postup_pixmap"))
563                 p->postup_pixmap = XmGetPixmap(s, "postup_pixmap", fg, bg);
564
565         fill_pixmap(&eri, xm_error_width, xm_error_height,
566                 xm_error_bits);
567         if (XmInstallImage(&eri, "err_pixmap"))
568                 p->xm_error_pixmap = XmGetPixmap(s, "err_pixmap", fg, bg);
569
570         fill_pixmap(&ii, xm_information_width, xm_information_height,
571                 xm_information_bits);
572         if (XmInstallImage(&ii, "info_pixmap"))
573                 p->xm_info_pixmap = XmGetPixmap(s, "info_pixmap", fg, bg);
574
575         fill_pixmap(&qi, xm_question_width, xm_question_height,
576                 xm_question_bits);
577         if (XmInstallImage(&qi, "q_pixmap"))
578                 p->xm_question_pixmap = XmGetPixmap(s, "q_pixmap", fg, bg);
579
580         fill_pixmap(&wi, xm_warning_width, xm_warning_height,
581                 xm_warning_bits);
582         if (XmInstallImage(&wi, "w_pixmap"))
583                 p->xm_warning_pixmap = XmGetPixmap(s, "w_pixmap", fg, bg);
584
585         if ((p->drag_icon_xbm = XmGetPixmap(s, "DtCMdnd.m.pm", fg, bg)) ==
586                                                         XmUNSPECIFIED_PIXMAP) {
587                 p->drag_icon_xbm = 0;
588         }
589 }
590
591
592 /*
593 **  I18N related routine
594 **  Parameter:  A pointer to a multibyte string.
595 **  Return Value:  The number of characters in the multibyte string.
596 */
597 extern int
598 cm_mbstrlen(char *s) {
599         int num_byte = 0, num_char = 0;
600
601         while (*s) {
602                 if ( (num_byte = mblen(s, MB_LEN_MAX)) <= 0 )
603                         break;
604                 num_char++;
605                 s += num_byte;
606         }
607         return num_char;
608 }
609
610 /*
611 **  I18N related routine
612 **  Parameter:  A pointer to a multibyte string or a pointer to NULL.
613 **  Return Value:  Returns a pointer to the next multibyte character.
614 **  Usage:  If the actual argument is non NULL then a pointer to the first
615 **          multibyte character is returned.  If the actual argument is NULL
616 **          then a pointer to the next multibyte character is returned.  The
617 **          parameter scheme is very much like strtok();
618 **  CAUTION:  If the calling function uses the return value then it should
619 **            make a copy.  The return value is a static buffer that may
620 **            be overwritten or freed on subsequent calls to this routine.
621 */
622 extern char *
623 cm_mbchar(char *str) {
624      static char *string;
625      static char *string_head;
626      static char *buf;
627      int num_byte = 0;
628  
629      if ( str != NULL ) {
630           if ( string != NULL ) {
631                free(string_head);
632                string_head = NULL;
633                string = NULL;
634           }
635           string = (char *)cm_strdup(str);
636           string_head = string;
637      }
638      if ( buf != NULL ) {
639           free(buf);
640           buf = NULL;
641      }
642      if ( string == '\0' ) {
643           free(string_head);
644           string_head = NULL;
645      } else {
646           num_byte = mblen(string, MB_LEN_MAX);
647           buf = (char *)malloc(num_byte+1);
648           strncpy(buf, string, num_byte);
649           buf[num_byte] = '\0';
650           string += num_byte;
651      }
652  
653      return buf;
654 }
655
656 /*
657 **  Callback for generic dialogs to set the answer so the program can continue
658 **  in a normal flow ...
659 **
660 **  This is really frickin brain dead.
661 **
662 **  Client data will be set to the button id stored as user data in the widget.
663 */
664 static void
665 response(Widget w, XtPointer client_data, XtPointer cbs) {
666         XtPointer userData = (XtPointer)0;
667         int *answerP = (int *) (intptr_t)client_data;
668
669         XtVaGetValues(w, XmNuserData, &userData, NULL);
670         *answerP = (intptr_t)userData;
671 }
672
673 /*
674 **  Generic dialog box creator
675 */
676 extern int
677 dialog_popup(Widget parent, ...) {
678         int                     button_id, t_cnt = 0, b_cnt = 0;
679         char                    *text_str = NULL, *ptr, buf[MAXNAMELEN], *help_str;
680         Pixmap                  px;
681         va_list                 pvar;
682         Widget                  frame, form, image, sep, text, last_text, button;
683         Display                 *dpy = XtDisplayOfObject(parent);
684         XmString                xmstr;
685         Dialog_create_op        op;
686         extern XtAppContext     app;
687         Calendar                *c = calendar;
688
689         int                     answer;
690
691         frame = XtVaCreatePopupShell("generic_dialog",
692                 xmDialogShellWidgetClass, parent,
693                 XmNallowShellResize, True,
694                 XmNmwmFunctions, MWM_FUNC_MOVE | MWM_FUNC_CLOSE,
695                 NULL);
696
697         form = XtVaCreateWidget("form",
698                 xmFormWidgetClass, frame,
699                 XmNhorizontalSpacing, 5,
700                 XmNverticalSpacing, 5,
701                 XmNmarginWidth, 0,
702                 XmNfractionBase, 100,
703                 XmNautoUnmanage, False,
704                 XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
705                 NULL);
706
707         image = XtVaCreateWidget("image",
708                 xmLabelGadgetClass, form,
709                 XmNlabelType, XmPIXMAP,
710                 XmNtopAttachment, XmATTACH_FORM,
711                 XmNleftAttachment, XmATTACH_FORM,
712                 NULL);
713
714         sep = XtVaCreateWidget("sep",
715                 xmSeparatorGadgetClass, form,
716                 XmNtopAttachment, XmATTACH_WIDGET,
717                 XmNleftAttachment, XmATTACH_FORM,
718                 XmNrightAttachment, XmATTACH_FORM,
719                 NULL);
720
721         va_start(pvar, parent);
722         op = va_arg(pvar, Dialog_create_op);
723         while(op) {
724                 switch(op) {
725                 case DIALOG_TITLE:
726                         ptr = va_arg(pvar, char *);
727                         XtVaSetValues(frame, XtNtitle, ptr,
728                                 NULL);
729                         break;
730                 case DIALOG_TEXT:
731                         ptr = va_arg(pvar, char *);
732                         if (text_str)
733                                 free(text_str);
734                         text_str = cm_strdup(ptr);
735                         break;
736                 case BUTTON_IDENT:
737                 case BUTTON_INSENSITIVE:
738                         button_id = va_arg(pvar, int);
739                         ptr = va_arg(pvar, char *);
740                         xmstr = XmStringCreateLocalized(ptr);
741                         sprintf(buf, "button%d", b_cnt);
742                         button = XtVaCreateWidget(buf,
743                                 xmPushButtonGadgetClass, form,
744                                 XmNlabelString, xmstr,
745                                 XmNleftAttachment, XmATTACH_POSITION,
746                                 XmNleftPosition, b_cnt * 2,
747                                 XmNleftOffset,  5,
748                                 XmNrightAttachment, XmATTACH_POSITION,
749                                 XmNrightPosition, (b_cnt+1) * 2,
750                                 XmNrightOffset, 5,
751                                 XmNuserData, button_id,
752                                 XmNtopAttachment, XmATTACH_WIDGET,
753                                 XmNtopWidget, sep,
754                                 XmNtopOffset, 10,
755                                 XmNbottomAttachment, XmATTACH_FORM,
756                                 XmNbottomOffset, 10,
757                                 NULL);
758                         ++b_cnt;
759                         if (op == BUTTON_INSENSITIVE)
760                                 XtSetSensitive(button, False);
761                         XtAddCallback(button, XmNactivateCallback,
762                                       response, (XtPointer)&answer);
763                         XmStringFree(xmstr);
764                         break;
765                 case BUTTON_HELP:
766                         help_str = cm_strdup(va_arg(pvar, char *));
767                         xmstr = XmStringCreateLocalized(
768                                         catgets(c->DT_catd, 1, 77, "Help"));
769                         button = XtVaCreateWidget("help_button",
770                                 xmPushButtonGadgetClass, form,
771                                 XmNlabelString, xmstr,
772                                 XmNleftAttachment, XmATTACH_POSITION,
773                                 XmNleftPosition, b_cnt * 2,
774                                 XmNrightAttachment, XmATTACH_POSITION,
775                                 XmNrightPosition, (b_cnt+1) * 2,
776                                 XmNrightOffset, 5,
777                                 XmNtopAttachment, XmATTACH_WIDGET,
778                                 XmNtopWidget, sep,
779                                 XmNtopOffset, 10,
780                                 XmNbottomAttachment, XmATTACH_FORM,
781                                 XmNbottomOffset, 10,
782                                 NULL);
783                         ++b_cnt;
784                         XtAddCallback(button, XmNactivateCallback,
785                                       help_cb, help_str);
786                         XmStringFree(xmstr);
787                         break;
788                 case DIALOG_IMAGE:
789                         px = va_arg(pvar, Pixmap);
790                         XtVaSetValues(image, XmNlabelPixmap, px,
791                                 NULL);
792                         break;
793                 default:
794                         break;
795                 }
796                 op = va_arg(pvar, Dialog_create_op);
797         }
798         va_end(pvar);
799         XtVaSetValues(form, XmNfractionBase, b_cnt * 2,
800                 NULL);
801
802         ptr = strtok(text_str, "\n");
803         while (ptr) {
804                 ++t_cnt;
805                 sprintf(buf, "text_label%d", t_cnt);
806                 xmstr = XmStringCreateLocalized(ptr);
807                 text = XtVaCreateWidget(buf,
808                         xmLabelGadgetClass, form,
809                         XmNalignment, XmALIGNMENT_BEGINNING,
810                         XmNlabelString, xmstr,
811                         XmNleftAttachment, XmATTACH_WIDGET,
812                         XmNleftWidget, image,
813                         XmNrightAttachment, XmATTACH_FORM,
814                         NULL);
815                 XmStringFree(xmstr);
816
817                 if (t_cnt == 1)
818                         XtVaSetValues(text, XmNtopAttachment, XmATTACH_FORM,
819                                 NULL);
820                 else
821                         XtVaSetValues(text, XmNtopAttachment, XmATTACH_WIDGET,
822                                 XmNtopWidget, last_text,
823                                 NULL);
824                 last_text = text;
825
826                 ptr = strtok(NULL, "\n");
827         }
828         free(text_str);
829
830         XtVaSetValues(sep,
831                       XmNtopWidget, last_text,
832                       XmNtopOffset, 10,
833                       NULL);
834         ManageChildren(form);
835         XtManageChild(form);
836
837         XBell(dpy, 50);
838         answer = 0;
839         while (answer == 0)
840                 XtAppProcessEvent(app, XtIMXEvent | XtIMAll);
841         XtUnmanageChild(form);
842         XtDestroyWidget(frame);
843
844         return answer;
845 }
846
847 /*
848 **  This routine returns the true boundaries of a particular view, i.e,
849 **  12 midnight - 11:59:59 pm.  It does not return the boundaries for doing
850 **  lookups, i.e., 11:59:59 pm - 12 pm (lookup ranges must encompass true range)
851 */
852 extern void
853 get_range(Glance glance, time_t date, time_t *start, time_t *stop) {
854         int day_of_week;
855
856         switch(glance) {
857         case monthGlance:
858                 *start = first_dom(date);
859                 *stop = last_dom(date);
860                 break;
861         case weekGlance:
862                 *start = first_dow(date);
863                 *stop = last_dow(date);
864                 break;
865         case dayGlance:
866                 *start = lowerbound(date);
867                 *stop = upperbound(date);
868                 break;
869         default:
870         case yearGlance:
871                 *start = lowerbound(jan1(date));
872                 *stop = lowerbound(nextjan1(date));
873                 break;
874         }
875 }
876
877 /*
878 **  Standard set of error messages for the editors (errors from data entry
879 **  validation and from the backend).
880 */
881 extern void
882 editor_err_msg(Widget frame, char *name, Validate_op op, Pixmap p) {
883         Calendar        *c = calendar;
884         char            buf[MAXNAMELEN], 
885                         buf2[MAXNAMELEN * 2],
886                         error_buf[64];
887         int             help_button = True;
888
889         switch(op) {
890         case COULD_NOT_OPEN_FILE:
891                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 355, "Unable to open callog file.\nOperation was cancelled.  Calendar"));
892                 sprintf(error_buf, CMSD_ERROR_HELP);
893                 break;
894         case CANCEL_APPT:
895                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 356, "Per user request, Operation was cancelled.\nCalendar"));
896                 help_button = False;
897                 break;
898         case INVALID_DATE:
899                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 357, "Invalid value in DATE field.\nOperation was cancelled.  Calendar"));
900                 sprintf(error_buf, DATE_ERROR_HELP);
901                 break;
902         case INVALID_START:
903                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 358, "Invalid value in START field.\nOperation was cancelled.  Calendar"));
904                 sprintf(error_buf, START_ERROR_HELP);
905                 break;
906         case INVALID_TIME_DUE:
907                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 1011, "Invalid value in the \"Time Due\" field.\nOperation was cancelled.  Calendar"));
908                 sprintf(error_buf, START_ERROR_HELP);
909                 break;
910         case INVALID_STOP:
911                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 359, "Invalid value in END field.\nOperation was cancelled.  Calendar"));
912                 sprintf(error_buf, STOP_ERROR_HELP);
913                 break;
914         case MISSING_DATE:
915                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 360, "You must provide a DATE value.\nOperation was cancelled.  Calendar"));
916                 sprintf(error_buf, MISSING_FIELD_ERROR_HELP);
917                 break;
918         case MISSING_START:
919                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 361, "You must provide a START value.\nOperation was cancelled.  Calendar"));
920                 sprintf(error_buf, MISSING_FIELD_ERROR_HELP);
921                 break;
922         case MISSING_WHAT:
923                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 362, "You must provide a WHAT value.\nOperation was cancelled.  Calendar"));
924                 sprintf(error_buf, MISSING_FIELD_ERROR_HELP);
925                 break;
926         case REPEAT_FOR_MISMATCH:
927                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 363, "Invalid or mismatched REPEAT and FOR values.\nOperation was cancelled.  Calendar"));
928                 sprintf(error_buf, REPEAT_FOR_ERROR_HELP);
929                 break;
930         case INVALID_NOTIME_APPT:
931                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 724, "No Time appointments must have a WHAT value specified.\nOperation was cancelled.  Calendar"));
932                 sprintf(error_buf, NO_TIME_ERROR_HELP);
933                 break;
934         case INVALID_TIME:
935                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 1104, "Invalid value in TIME DUE field.\nOperation was cancelled.  Calendar"));
936                 sprintf(error_buf, START_ERROR_HELP);
937                 break;
938         case MISSING_TIME:
939                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 1105, "You must provide a TIME DUE value.\nOperation was cancelled.  Calendar"));
940                 sprintf(error_buf, MISSING_FIELD_ERROR_HELP);
941                 break;
942         case VALID_APPT:
943         default:
944                 return;
945         }
946
947         sprintf(buf2, "%s %s", buf, name);
948         if (help_button) {
949                 char *title = XtNewString(catgets(c->DT_catd, 1, 914,
950                                         "Calendar : Error - Editor"));
951                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 95, 
952                                                 "Continue"));
953                 dialog_popup(frame, DIALOG_TITLE, title,
954                         DIALOG_TEXT, buf2,
955                         BUTTON_IDENT, 1, ident1,
956                         BUTTON_HELP, error_buf,
957                         DIALOG_IMAGE, p,
958                         NULL);
959                 XtFree(ident1);
960                 XtFree(title);
961         }
962         else {
963                 char *title = XtNewString(catgets(c->DT_catd, 1, 914,
964                                         "Calendar : Error - Editor"));
965                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 95, 
966                                                 "Continue"));
967                 dialog_popup(frame, DIALOG_TITLE, title,
968                         DIALOG_TEXT, buf2,
969                         BUTTON_IDENT, 1, ident1,
970                         DIALOG_IMAGE, p,
971                         NULL);
972                 XtFree(ident1);
973                 XtFree(title);
974         }
975 }
976
977 extern void
978 backend_err_msg(
979         Widget           frame, 
980         char            *name, 
981         CSA_return_code  stat, 
982         Pixmap           p)
983 {
984         char             buf[MAXNAMELEN],
985                          buf2[MAXNAMELEN * 2],
986                          error_buf[64];
987         Calendar        *c = calendar;
988         int              help_button = True;
989
990         sprintf(error_buf, BACK_END_ERROR_HELP);
991
992         switch(stat) {
993         case CSA_E_CALENDAR_EXISTS:
994                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 367, "Calendar already exists.\nOperation was cancelled.  Calendar"));
995                 help_button = False;
996                 break;
997         case CSA_E_CALENDAR_NOT_EXIST:
998                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 368, "Calendar does not exist.\nOperation was cancelled.  Calendar"));
999                 help_button = False;
1000                 break;
1001         case CSA_X_DT_E_ENTRY_NOT_FOUND:
1002                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 725, "Calendar Entry does not exist.\nOperation was cancelled.  Calendar"));
1003                 break;
1004         case CSA_E_INVALID_ENTRY_HANDLE:
1005                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 881, "Internal Error #1: Invalid calendar/entry handle.\nOperation was cancelled.  Calendar"));
1006                 break;
1007         case CSA_E_INVALID_SESSION_HANDLE:
1008                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 882, "Internal Error #2: Invalid session handle.\nOperation was cancelled.  Calendar"));
1009                 break;
1010         case CSA_E_NO_AUTHORITY:
1011                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 370, "Authorization error.  Permission denied.\nOperation was cancelled.  Calendar"));
1012                 help_button = False;
1013                 break;
1014         case CSA_E_INVALID_PARAMETER:
1015                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 883, "Internal Error #3: Invalid data value.\nOperation was cancelled.  Calendar"));
1016                 break;
1017         case CSA_E_READONLY:
1018                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 884, "Internal Error #4: Value specified for a read-only attribute.\nOperation was cancelled.  Calendar"));
1019                 break;
1020         case CSA_E_INVALID_ATTRIBUTE_VALUE:
1021                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 885, "Internal Error #5: Incorrect data type specified for an attribute value.\nOperation was cancelled.  Calendar"));
1022                 break;
1023         case CSA_E_UNSUPPORTED_ATTRIBUTE:
1024                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 886, "Internal Error #6: Specified attribute is not supported on this calendar version.\nOperation was cancelled.  Calendar"));
1025                 break;
1026         case CSA_E_NOT_SUPPORTED:
1027                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 887, "Internal Error #7: Specified function is not supported on this calendar version.\nOperation was cancelled.  Calendar"));
1028                 break;
1029         case CSA_E_INVALID_ENUM:
1030                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 888, "Internal Error #8: Invalid operator specified.\nOperation was cancelled.  Calendar"));
1031                 break;
1032         case CSA_E_INSUFFICIENT_MEMORY:
1033                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 378, "Memory allocation error - not enough memory.\nOperation was cancelled.  Calendar"));
1034                 sprintf(error_buf, MEMORY_ALLOC_ERROR_HELP);
1035                 break;
1036         case CSA_E_DISK_FULL:
1037                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 907, "No space left for calendar file.\nOperation was cancelled.  Calendar"));
1038                 break;
1039         case CSA_E_SERVICE_UNAVAILABLE:
1040                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 921, "Couldn't access calendar: "));
1041                 break;
1042         case CSA_X_DT_E_INVALID_SERVER_LOCATION:
1043                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 641, "Server failed to get network address\nfor the specified location:  invalid hostname."));
1044                 break;
1045         case CSA_X_DT_E_SERVICE_NOT_REGISTERED:
1046                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 642, "rpc.cmsd daemon is not registered.\nPlease verify rpc.cmsd is installed correctly on your system."));
1047                 sprintf(error_buf, CMSD_ERROR_HELP);
1048                 break;
1049         case CSA_X_DT_E_SERVER_TIMEOUT:
1050                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 727, "Your request timed out\nPlease verify rpc.cmsd is installed correctly on your system."));
1051                 sprintf(error_buf, CMSD_ERROR_HELP);
1052                 break;
1053         case CSA_E_FAILURE:
1054                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 643, "Couldn't access calendar. Calendar"));
1055                 break;
1056         case CSA_E_INVALID_RULE:
1057                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 1120, "The event cannot be scheduled in the given time frame.\nThe operation was cancelled."));
1058                 break;
1059         case CSA_SUCCESS:
1060                 return;
1061         default:
1062                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 383, "Unknown error.\nOperation was cancelled.  Calendar"));
1063                 break;
1064         }
1065
1066         sprintf(buf2, "%s %s", buf, name);
1067         if (help_button) {
1068                 char *title = XtNewString(catgets(c->DT_catd, 1, 890,
1069                                                 "Calendar : Error - Services"));
1070                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 95, 
1071                                                 "Continue"));
1072                 dialog_popup(frame, DIALOG_TITLE, title,
1073                         DIALOG_TEXT, buf2,
1074                         BUTTON_IDENT, 1, ident1,
1075                         BUTTON_HELP, error_buf,
1076                         DIALOG_IMAGE, p,
1077                         NULL);
1078                 XtFree(ident1);
1079                 XtFree(title);
1080         }
1081         else {
1082                 char *title = XtNewString(catgets(c->DT_catd, 1, 890,
1083                                                 "Calendar : Error - Services"));
1084                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 95, 
1085                                                 "Continue"));
1086                 dialog_popup(frame, DIALOG_TITLE, title,
1087                         DIALOG_TEXT, buf2,
1088                         BUTTON_IDENT, 1, ident1,
1089                         DIALOG_IMAGE, p,
1090                         NULL);
1091                 XtFree(ident1);
1092                 XtFree(title);
1093         }
1094 }
1095
1096 /*
1097  * This function is called by the parse_appt_from_file routine if the end_date
1098  * was before the start date for the appointment - this queries the user as to
1099  * her intentions
1100  */
1101 extern boolean_t
1102 query_user(void *user_data) {
1103         char            buf[MAXNAMELEN];
1104         Calendar        *c = (Calendar *)user_data;
1105         Props_pu        *p = (Props_pu *)c->properties_pu;
1106         boolean_t       ret = B_FALSE;
1107         char            *title;
1108         char            *ident1;
1109         char            *ident2;
1110         static int      answer;
1111
1112         sprintf(buf, "%s", catgets(c->DT_catd, 1, 386,
1113                 "That appointment has an end time earlier than its begin time.\nDo you want to schedule it into the next day?"));
1114         title = XtNewString(catgets(c->DT_catd, 1, 248, "Calendar : Schedule Appointment"));
1115         ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
1116         ident2 = XtNewString(catgets(c->DT_catd, 1, 389, "Next Day"));
1117         answer = dialog_popup(c->frame,
1118                 DIALOG_TITLE, title,
1119                 DIALOG_TEXT, buf,
1120                 BUTTON_IDENT, 1, ident1,
1121                 BUTTON_IDENT, 2, ident2,
1122                 DIALOG_IMAGE, p->xm_question_pixmap,
1123                 NULL);
1124         XtFree(ident2);
1125         XtFree(ident1);
1126         XtFree(title);
1127         if (answer == 2)
1128                 ret = B_TRUE;
1129
1130         return ret;
1131 }
1132
1133 extern void
1134 set_message(Widget w, char *msg) {
1135         XmString        xmstr;
1136
1137         /*
1138          * If msg is NULL or a null string set it to be a space.  This
1139          * prevents label widgets from shrinking (which they do when they
1140          * have no text
1141          */
1142         if (msg == NULL || *msg == '\0') {
1143                 msg = " ";
1144         }
1145
1146         if (w) {
1147                 xmstr = XmStringCreateLocalized(msg);
1148                 XtVaSetValues(w, XmNlabelString, xmstr, NULL);
1149                 XmStringFree(xmstr);
1150         }
1151
1152
1153 }
1154
1155 extern void
1156 setup_quit_handler(Widget w, XtCallbackProc cb, caddr_t user_data) {
1157         Atom delete_window;
1158
1159         delete_window = XmInternAtom(XtDisplay(w), "WM_DELETE_WINDOW", False);
1160         XmAddWMProtocolCallback(w, delete_window, cb, user_data);
1161 }
1162
1163 int
1164 ds_is_double_click(XEvent *last_event, XEvent *event)
1165 {
1166         static  int             time_threshold;
1167         static  int             dist_threshold;
1168         static  short           first_time      = TRUE;
1169         short                   ret_value       = FALSE;
1170         int                     delta_time;
1171         int                     delta_x, delta_y;
1172
1173         if (last_event == NULL || event == NULL)
1174                 return ret_value;
1175
1176         /* first time this is called init the thresholds */
1177         if( first_time ) {
1178                 /* Get time threshold in miliseconds */
1179                 time_threshold = 800;
1180                 dist_threshold = 4;
1181                 first_time      = FALSE;
1182         }
1183         /* only deal with the down events */
1184         if (event->type == ButtonRelease)
1185                 return ret_value;
1186
1187         if ((event->xbutton.type == ButtonPress) &&
1188             (last_event->xbutton.type == ButtonPress)) {
1189  
1190                 delta_time = event->xbutton.time - last_event->xbutton.time;
1191                 delta_time += event->xbutton.time;
1192                 delta_time -= last_event->xbutton.time;
1193  
1194                 /* is the time within bounds? */
1195                 if( delta_time <= time_threshold ) {
1196  
1197                         /* check to see if the distance is ok */
1198                         delta_x = (last_event->xbutton.x > event->xbutton.x ?
1199                                            last_event->xbutton.x - event->xbutton.x :
1200                                            event->xbutton.x - last_event->xbutton.x);
1201
1202                         delta_y = (last_event->xbutton.y > event->xbutton.y ?
1203                                            last_event->xbutton.y - event->xbutton.y :
1204                                            event->xbutton.y - last_event->xbutton.y);
1205                         if( delta_x <= dist_threshold &&
1206                             delta_y <= dist_threshold )
1207                                 ret_value       = TRUE;
1208                 }
1209         }
1210         return ret_value;
1211 }        
1212
1213
1214 /*
1215  * Select the contents of a text item.
1216  *
1217  */
1218 extern int
1219 cm_select_text(Widget field, Time time) {
1220         XmTextPosition  last;
1221
1222         last = XmTextFieldGetLastPosition(field);
1223
1224         if (last > 0) {
1225                 XmTextFieldSetSelection(field, 0, last, time);
1226         }
1227
1228         return last;
1229 }
1230
1231 extern Dimension
1232 ComputeMaxWidth(
1233         Widget          w1,
1234         Widget          w2,
1235         Widget          w3,
1236         Widget          w4)
1237 {
1238         Dimension       width1,
1239                         width2;
1240         Widget          w[5];
1241         int             i;
1242
1243         if (!w1) return 0;
1244
1245         w[0] = w1;
1246         w[1] = w2;
1247         w[2] = w3;
1248         w[3] = w4;
1249         w[4] = (Widget) NULL;
1250
1251         XtVaGetValues(w1,
1252                 XmNwidth,               &width1,
1253                 NULL);
1254
1255         for (i = 1; w[i]; i++) {
1256
1257                 XtVaGetValues(w[i],
1258                         XmNwidth,       &width2,
1259                         NULL);
1260
1261                 if ((int)width2 > (int)width1) width1 = width2;
1262         }
1263
1264         return width1;
1265 }
1266
1267 extern void
1268 ManageChildren(
1269         Widget          w)
1270 {
1271         WidgetList      children;
1272         int             n;
1273
1274         XtVaGetValues(w,
1275                 XmNchildren,            &children,
1276                 XmNnumChildren,         &n,
1277                 NULL);
1278         XtManageChildren(children, n);
1279 }
1280
1281 #define MAX_NUM 10
1282 /*
1283  * Look for the highest/widest Widget
1284  * num <= MAX_NUM;
1285  */
1286 #include <X11/IntrinsicP.h>
1287 #include <X11/CoreP.h>
1288 #include <Xm/Scale.h>
1289 static Widget    _widget[MAX_NUM];
1290 static Dimension _height[MAX_NUM];
1291 static Dimension _width[MAX_NUM];
1292
1293 extern  void
1294 _i18n_HighestWidget(
1295 int num,
1296 Widget *ret,
1297 Dimension *dim,
1298 ... )
1299 {
1300     va_list   ap;
1301     int       i, _high;
1302     Dimension _max;
1303     Widget    _targetW, _highestW;
1304     Arg       _args[3];
1305     XtWidgetGeometry geo;
1306     unsigned char type;
1307
1308     *ret = (Widget)NULL;
1309     *dim = (Dimension)0;
1310     if ( num > MAX_NUM )
1311         return; /* Do nothing */
1312
1313     va_start( ap, dim );
1314
1315     for ( i = 0, _max = (Dimension)0; i < num; i++ ) {
1316         _widget[i] = (Widget)va_arg( ap, Widget );
1317         /*
1318          * Ugly check. XmScale's XmNheight is determined after being mapped.
1319          * So if WidgeClass == xmScaleWidgetClass, use XtQueryGeometry() !!
1320          * ( It's dangerous ! )
1321          * See p_create_display_pane()'s comment :)
1322          *
1323          * Same for xmRowColumnWidgetClass
1324          *
1325          */
1326         if  (XmIsManager (_widget[i])) {
1327             _targetW =  _widget[i];
1328             XtQueryGeometry( _targetW, NULL, &geo );
1329             _height[i] = geo.height;
1330         } else {
1331             _targetW =  _widget[i];
1332             XtVaGetValues( _targetW, XmNheight, &(_height[i]), NULL );
1333         }
1334         if ( _height[i] >= _max ) {
1335             _max = _height[i];
1336             _high = i;
1337             _highestW = _targetW;
1338         }
1339     }
1340
1341     *ret = _widget[_high];
1342     *dim = _max;
1343
1344     va_end( ap );
1345 }
1346
1347 extern  void
1348 _i18n_WidestWidget(
1349 int num,
1350 Widget *ret,
1351 Dimension *dim,
1352 ... )
1353 {
1354     va_list   ap;
1355     int       i, _wide;
1356     Widget    _targetW, _widestW;
1357     Dimension _max;
1358     XtWidgetGeometry geo;
1359     unsigned char type;
1360
1361     *ret = (Widget)NULL;
1362     *dim = (Dimension)0;
1363     if ( num > MAX_NUM )
1364         return; /* Do nothing */
1365
1366     va_start( ap, dim );
1367
1368     for ( i = 0, _max = (Dimension)0; i < num; i++ ) {
1369         _widget[i] = (Widget)va_arg( ap, Widget );
1370         /*
1371          * Ugly check. XmScale's XmNheight is determined after being mapped.
1372          * So if WidgeClass == xmScaleWidgetClass, use XtQueryGeometry() !!
1373          * ( It's dangerous ! )
1374          * See p_create_display_pane()'s comment :)
1375          *
1376          * Same for xmRowColumnWidgetClass
1377          *
1378          */
1379         if  (XmIsManager (_widget[i])) {
1380             _targetW = _widget[i];
1381             XtQueryGeometry( _targetW, NULL, &geo );
1382             _width[i] = geo.width;
1383         } else {
1384             _targetW = _widget[i];
1385             XtVaGetValues( _targetW, XmNwidth, &(_width[i]), NULL );
1386         } if ( _width[i] >= _max ) {
1387             _max = _width[i];
1388             _wide = i;
1389             _widestW = _targetW;
1390         }
1391     }
1392
1393     *ret = _widget[_wide];
1394     *dim = _max;
1395
1396     va_end( ap );
1397 }
1398
1399 /*
1400  * Look for the highest Widget plus, do layout as,
1401  *
1402  * +-------------------+
1403  * |                   |
1404  * |                   |                +----------------+
1405  * |                   | +------------+ |                |
1406  * | Most Highest      | |            | |                | <--- Center !
1407  * |                   | +------------+ |                |
1408  * |                   |       ^        +----------------+
1409  * |                   |       |                 ^
1410  * +-------------------+ ......|.................|........
1411  * 
1412  * Note : If you are using this function, as for Left/Right Attachment, 
1413  *        don't use these Widget as XmATTACHMENT_WIDGET's XmNwidget !
1414  * 
1415  * num <= MAX_NUM;
1416  */
1417 extern  void
1418 _i18n_HighestWidgetAdjust(
1419 int num,
1420 Widget *ret,
1421 Dimension *dim,
1422 ... )
1423 {
1424     va_list   ap;
1425     int       i, _high;
1426     Dimension _max;
1427     Widget    _targetW, _highestW;
1428     Arg       _args[3];
1429     XtWidgetGeometry geo;
1430     unsigned char type;
1431
1432     *ret = (Widget)NULL;
1433     *dim = (Dimension)0;
1434     if ( num > MAX_NUM )
1435         return; /* Do nothing */
1436
1437     va_start( ap, dim );
1438
1439     for ( i = 0, _max = (Dimension)0; i < num; i++ ) {
1440         _widget[i] = (Widget)va_arg( ap, Widget );
1441         /*
1442          * Ugly check. XmScale's XmNheight is determined after being mapped.
1443          * So if WidgeClass == xmScaleWidgetClass, use XtQueryGeometry() !!
1444          * ( It's dangerous ! )
1445          * See p_create_display_pane()'s comment :)
1446          *
1447          * Same for xmRowColumnWidgetClass
1448          *
1449          */
1450         if  (XmIsManager (_widget[i])) {
1451             _targetW =  _widget[i];
1452             XtQueryGeometry( _targetW, NULL, &geo );
1453             _height[i] = geo.height;
1454         } else {
1455             _targetW =  _widget[i];
1456             XtVaGetValues( _targetW, XmNheight, &(_height[i]), NULL );
1457         }
1458         if ( _height[i] >= _max ) {
1459             _max = _height[i];
1460             _high = i;
1461             _highestW = _targetW;
1462         }
1463     }
1464
1465     /*
1466      *  Do layout by XmNbottomAttachment/XmATTACH_OPPTOSITE_WIDGET
1467      */
1468     for ( i = 0; i < num; i++ ) {
1469         if ( i != _high ) {
1470             XtSetArg(_args[0], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET );
1471             XtSetArg(_args[1], XmNbottomWidget, _highestW );
1472             XtSetArg(_args[2], XmNbottomOffset, (_max - _height[i]) >> 1 );
1473             XtSetValues( _widget[i], _args, 3 );
1474         }
1475     }
1476
1477     *ret = _widget[_high];
1478     *dim = _max;
1479
1480     va_end( ap );
1481 }