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