1b8b18a8e071e516146736a71d2d1dffaf06c450
[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 = NULL;
625      static char *string_head = NULL;
626      static char *buf = NULL;
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           if(num_byte > 0) {
648                buf = (char *)malloc(num_byte+1);
649                strncpy(buf, string, num_byte);
650                buf[num_byte] = '\0';
651                string += num_byte;
652           }
653      }
654  
655      return buf;
656 }
657
658 /*
659 **  Callback for generic dialogs to set the answer so the program can continue
660 **  in a normal flow ...
661 **
662 **  This is really frickin brain dead.
663 **
664 **  Client data will be set to the button id stored as user data in the widget.
665 */
666 static void
667 response(Widget w, XtPointer client_data, XtPointer cbs) {
668         XtPointer userData = (XtPointer)0;
669         int *answerP = (int *) (intptr_t)client_data;
670
671         XtVaGetValues(w, XmNuserData, &userData, NULL);
672         *answerP = (intptr_t)userData;
673 }
674
675 /*
676 **  Generic dialog box creator
677 */
678 extern int
679 dialog_popup(Widget parent, ...) {
680         int                     button_id, t_cnt = 0, b_cnt = 0;
681         char                    *text_str = NULL, *ptr, buf[MAXNAMELEN], *help_str;
682         Pixmap                  px;
683         va_list                 pvar;
684         Widget                  frame, form, image, sep, text, last_text, button;
685         Display                 *dpy = XtDisplayOfObject(parent);
686         XmString                xmstr;
687         Dialog_create_op        op;
688         extern XtAppContext     app;
689         Calendar                *c = calendar;
690
691         int                     answer;
692
693         frame = XtVaCreatePopupShell("generic_dialog",
694                 xmDialogShellWidgetClass, parent,
695                 XmNallowShellResize, True,
696                 XmNmwmFunctions, MWM_FUNC_MOVE | MWM_FUNC_CLOSE,
697                 NULL);
698
699         form = XtVaCreateWidget("form",
700                 xmFormWidgetClass, frame,
701                 XmNhorizontalSpacing, 5,
702                 XmNverticalSpacing, 5,
703                 XmNmarginWidth, 0,
704                 XmNfractionBase, 100,
705                 XmNautoUnmanage, False,
706                 XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
707                 NULL);
708
709         image = XtVaCreateWidget("image",
710                 xmLabelGadgetClass, form,
711                 XmNlabelType, XmPIXMAP,
712                 XmNtopAttachment, XmATTACH_FORM,
713                 XmNleftAttachment, XmATTACH_FORM,
714                 NULL);
715
716         sep = XtVaCreateWidget("sep",
717                 xmSeparatorGadgetClass, form,
718                 XmNtopAttachment, XmATTACH_WIDGET,
719                 XmNleftAttachment, XmATTACH_FORM,
720                 XmNrightAttachment, XmATTACH_FORM,
721                 NULL);
722
723         va_start(pvar, parent);
724         op = va_arg(pvar, Dialog_create_op);
725         while(op) {
726                 switch(op) {
727                 case DIALOG_TITLE:
728                         ptr = va_arg(pvar, char *);
729                         XtVaSetValues(frame, XtNtitle, ptr,
730                                 NULL);
731                         break;
732                 case DIALOG_TEXT:
733                         ptr = va_arg(pvar, char *);
734                         if (text_str)
735                                 free(text_str);
736                         text_str = cm_strdup(ptr);
737                         break;
738                 case BUTTON_IDENT:
739                 case BUTTON_INSENSITIVE:
740                         button_id = va_arg(pvar, int);
741                         ptr = va_arg(pvar, char *);
742                         xmstr = XmStringCreateLocalized(ptr);
743                         sprintf(buf, "button%d", b_cnt);
744                         button = XtVaCreateWidget(buf,
745                                 xmPushButtonGadgetClass, form,
746                                 XmNlabelString, xmstr,
747                                 XmNleftAttachment, XmATTACH_POSITION,
748                                 XmNleftPosition, b_cnt * 2,
749                                 XmNleftOffset,  5,
750                                 XmNrightAttachment, XmATTACH_POSITION,
751                                 XmNrightPosition, (b_cnt+1) * 2,
752                                 XmNrightOffset, 5,
753                                 XmNuserData, button_id,
754                                 XmNtopAttachment, XmATTACH_WIDGET,
755                                 XmNtopWidget, sep,
756                                 XmNtopOffset, 10,
757                                 XmNbottomAttachment, XmATTACH_FORM,
758                                 XmNbottomOffset, 10,
759                                 NULL);
760                         ++b_cnt;
761                         if (op == BUTTON_INSENSITIVE)
762                                 XtSetSensitive(button, False);
763                         XtAddCallback(button, XmNactivateCallback,
764                                       response, (XtPointer)&answer);
765                         XmStringFree(xmstr);
766                         break;
767                 case BUTTON_HELP:
768                         help_str = cm_strdup(va_arg(pvar, char *));
769                         xmstr = XmStringCreateLocalized(
770                                         catgets(c->DT_catd, 1, 77, "Help"));
771                         button = XtVaCreateWidget("help_button",
772                                 xmPushButtonGadgetClass, form,
773                                 XmNlabelString, xmstr,
774                                 XmNleftAttachment, XmATTACH_POSITION,
775                                 XmNleftPosition, b_cnt * 2,
776                                 XmNrightAttachment, XmATTACH_POSITION,
777                                 XmNrightPosition, (b_cnt+1) * 2,
778                                 XmNrightOffset, 5,
779                                 XmNtopAttachment, XmATTACH_WIDGET,
780                                 XmNtopWidget, sep,
781                                 XmNtopOffset, 10,
782                                 XmNbottomAttachment, XmATTACH_FORM,
783                                 XmNbottomOffset, 10,
784                                 NULL);
785                         ++b_cnt;
786                         XtAddCallback(button, XmNactivateCallback,
787                                       help_cb, help_str);
788                         XmStringFree(xmstr);
789                         break;
790                 case DIALOG_IMAGE:
791                         px = va_arg(pvar, Pixmap);
792                         XtVaSetValues(image, XmNlabelPixmap, px,
793                                 NULL);
794                         break;
795                 default:
796                         break;
797                 }
798                 op = va_arg(pvar, Dialog_create_op);
799         }
800         va_end(pvar);
801         XtVaSetValues(form, XmNfractionBase, b_cnt * 2,
802                 NULL);
803
804         ptr = strtok(text_str, "\n");
805         while (ptr) {
806                 ++t_cnt;
807                 sprintf(buf, "text_label%d", t_cnt);
808                 xmstr = XmStringCreateLocalized(ptr);
809                 text = XtVaCreateWidget(buf,
810                         xmLabelGadgetClass, form,
811                         XmNalignment, XmALIGNMENT_BEGINNING,
812                         XmNlabelString, xmstr,
813                         XmNleftAttachment, XmATTACH_WIDGET,
814                         XmNleftWidget, image,
815                         XmNrightAttachment, XmATTACH_FORM,
816                         NULL);
817                 XmStringFree(xmstr);
818
819                 if (t_cnt == 1)
820                         XtVaSetValues(text, XmNtopAttachment, XmATTACH_FORM,
821                                 NULL);
822                 else
823                         XtVaSetValues(text, XmNtopAttachment, XmATTACH_WIDGET,
824                                 XmNtopWidget, last_text,
825                                 NULL);
826                 last_text = text;
827
828                 ptr = strtok(NULL, "\n");
829         }
830         free(text_str);
831
832         XtVaSetValues(sep,
833                       XmNtopWidget, last_text,
834                       XmNtopOffset, 10,
835                       NULL);
836         ManageChildren(form);
837         XtManageChild(form);
838
839         XBell(dpy, 50);
840         answer = 0;
841         while (answer == 0)
842                 XtAppProcessEvent(app, XtIMXEvent | XtIMAll);
843         XtUnmanageChild(form);
844         XtDestroyWidget(frame);
845
846         return answer;
847 }
848
849 /*
850 **  This routine returns the true boundaries of a particular view, i.e,
851 **  12 midnight - 11:59:59 pm.  It does not return the boundaries for doing
852 **  lookups, i.e., 11:59:59 pm - 12 pm (lookup ranges must encompass true range)
853 */
854 extern void
855 get_range(Glance glance, time_t date, time_t *start, time_t *stop) {
856         int day_of_week;
857
858         switch(glance) {
859         case monthGlance:
860                 *start = first_dom(date);
861                 *stop = last_dom(date);
862                 break;
863         case weekGlance:
864                 *start = first_dow(date);
865                 *stop = last_dow(date);
866                 break;
867         case dayGlance:
868                 *start = lowerbound(date);
869                 *stop = upperbound(date);
870                 break;
871         default:
872         case yearGlance:
873                 *start = lowerbound(jan1(date));
874                 *stop = lowerbound(nextjan1(date));
875                 break;
876         }
877 }
878
879 /*
880 **  Standard set of error messages for the editors (errors from data entry
881 **  validation and from the backend).
882 */
883 extern void
884 editor_err_msg(Widget frame, char *name, Validate_op op, Pixmap p) {
885         Calendar        *c = calendar;
886         char            buf[MAXNAMELEN], 
887                         buf2[MAXNAMELEN * 2],
888                         error_buf[64];
889         int             help_button = True;
890
891         switch(op) {
892         case COULD_NOT_OPEN_FILE:
893                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 355, "Unable to open callog file.\nOperation was cancelled.  Calendar"));
894                 sprintf(error_buf, CMSD_ERROR_HELP);
895                 break;
896         case CANCEL_APPT:
897                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 356, "Per user request, Operation was cancelled.\nCalendar"));
898                 help_button = False;
899                 break;
900         case INVALID_DATE:
901                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 357, "Invalid value in DATE field.\nOperation was cancelled.  Calendar"));
902                 sprintf(error_buf, DATE_ERROR_HELP);
903                 break;
904         case INVALID_START:
905                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 358, "Invalid value in START field.\nOperation was cancelled.  Calendar"));
906                 sprintf(error_buf, START_ERROR_HELP);
907                 break;
908         case INVALID_TIME_DUE:
909                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 1011, "Invalid value in the \"Time Due\" field.\nOperation was cancelled.  Calendar"));
910                 sprintf(error_buf, START_ERROR_HELP);
911                 break;
912         case INVALID_STOP:
913                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 359, "Invalid value in END field.\nOperation was cancelled.  Calendar"));
914                 sprintf(error_buf, STOP_ERROR_HELP);
915                 break;
916         case MISSING_DATE:
917                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 360, "You must provide a DATE value.\nOperation was cancelled.  Calendar"));
918                 sprintf(error_buf, MISSING_FIELD_ERROR_HELP);
919                 break;
920         case MISSING_START:
921                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 361, "You must provide a START value.\nOperation was cancelled.  Calendar"));
922                 sprintf(error_buf, MISSING_FIELD_ERROR_HELP);
923                 break;
924         case MISSING_WHAT:
925                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 362, "You must provide a WHAT value.\nOperation was cancelled.  Calendar"));
926                 sprintf(error_buf, MISSING_FIELD_ERROR_HELP);
927                 break;
928         case REPEAT_FOR_MISMATCH:
929                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 363, "Invalid or mismatched REPEAT and FOR values.\nOperation was cancelled.  Calendar"));
930                 sprintf(error_buf, REPEAT_FOR_ERROR_HELP);
931                 break;
932         case INVALID_NOTIME_APPT:
933                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 724, "No Time appointments must have a WHAT value specified.\nOperation was cancelled.  Calendar"));
934                 sprintf(error_buf, NO_TIME_ERROR_HELP);
935                 break;
936         case INVALID_TIME:
937                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 1104, "Invalid value in TIME DUE field.\nOperation was cancelled.  Calendar"));
938                 sprintf(error_buf, START_ERROR_HELP);
939                 break;
940         case MISSING_TIME:
941                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 1105, "You must provide a TIME DUE value.\nOperation was cancelled.  Calendar"));
942                 sprintf(error_buf, MISSING_FIELD_ERROR_HELP);
943                 break;
944         case VALID_APPT:
945         default:
946                 return;
947         }
948
949         sprintf(buf2, "%s %s", buf, name);
950         if (help_button) {
951                 char *title = XtNewString(catgets(c->DT_catd, 1, 914,
952                                         "Calendar : Error - Editor"));
953                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 95, 
954                                                 "Continue"));
955                 dialog_popup(frame, DIALOG_TITLE, title,
956                         DIALOG_TEXT, buf2,
957                         BUTTON_IDENT, 1, ident1,
958                         BUTTON_HELP, error_buf,
959                         DIALOG_IMAGE, p,
960                         NULL);
961                 XtFree(ident1);
962                 XtFree(title);
963         }
964         else {
965                 char *title = XtNewString(catgets(c->DT_catd, 1, 914,
966                                         "Calendar : Error - Editor"));
967                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 95, 
968                                                 "Continue"));
969                 dialog_popup(frame, DIALOG_TITLE, title,
970                         DIALOG_TEXT, buf2,
971                         BUTTON_IDENT, 1, ident1,
972                         DIALOG_IMAGE, p,
973                         NULL);
974                 XtFree(ident1);
975                 XtFree(title);
976         }
977 }
978
979 extern void
980 backend_err_msg(
981         Widget           frame, 
982         char            *name, 
983         CSA_return_code  stat, 
984         Pixmap           p)
985 {
986         char             buf[MAXNAMELEN],
987                          buf2[MAXNAMELEN * 2],
988                          error_buf[64];
989         Calendar        *c = calendar;
990         int              help_button = True;
991
992         sprintf(error_buf, BACK_END_ERROR_HELP);
993
994         switch(stat) {
995         case CSA_E_CALENDAR_EXISTS:
996                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 367, "Calendar already exists.\nOperation was cancelled.  Calendar"));
997                 help_button = False;
998                 break;
999         case CSA_E_CALENDAR_NOT_EXIST:
1000                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 368, "Calendar does not exist.\nOperation was cancelled.  Calendar"));
1001                 help_button = False;
1002                 break;
1003         case CSA_X_DT_E_ENTRY_NOT_FOUND:
1004                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 725, "Calendar Entry does not exist.\nOperation was cancelled.  Calendar"));
1005                 break;
1006         case CSA_E_INVALID_ENTRY_HANDLE:
1007                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 881, "Internal Error #1: Invalid calendar/entry handle.\nOperation was cancelled.  Calendar"));
1008                 break;
1009         case CSA_E_INVALID_SESSION_HANDLE:
1010                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 882, "Internal Error #2: Invalid session handle.\nOperation was cancelled.  Calendar"));
1011                 break;
1012         case CSA_E_NO_AUTHORITY:
1013                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 370, "Authorization error.  Permission denied.\nOperation was cancelled.  Calendar"));
1014                 help_button = False;
1015                 break;
1016         case CSA_E_INVALID_PARAMETER:
1017                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 883, "Internal Error #3: Invalid data value.\nOperation was cancelled.  Calendar"));
1018                 break;
1019         case CSA_E_READONLY:
1020                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 884, "Internal Error #4: Value specified for a read-only attribute.\nOperation was cancelled.  Calendar"));
1021                 break;
1022         case CSA_E_INVALID_ATTRIBUTE_VALUE:
1023                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 885, "Internal Error #5: Incorrect data type specified for an attribute value.\nOperation was cancelled.  Calendar"));
1024                 break;
1025         case CSA_E_UNSUPPORTED_ATTRIBUTE:
1026                 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"));
1027                 break;
1028         case CSA_E_NOT_SUPPORTED:
1029                 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"));
1030                 break;
1031         case CSA_E_INVALID_ENUM:
1032                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 888, "Internal Error #8: Invalid operator specified.\nOperation was cancelled.  Calendar"));
1033                 break;
1034         case CSA_E_INSUFFICIENT_MEMORY:
1035                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 378, "Memory allocation error - not enough memory.\nOperation was cancelled.  Calendar"));
1036                 sprintf(error_buf, MEMORY_ALLOC_ERROR_HELP);
1037                 break;
1038         case CSA_E_DISK_FULL:
1039                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 907, "No space left for calendar file.\nOperation was cancelled.  Calendar"));
1040                 break;
1041         case CSA_E_SERVICE_UNAVAILABLE:
1042                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 921, "Couldn't access calendar: "));
1043                 break;
1044         case CSA_X_DT_E_INVALID_SERVER_LOCATION:
1045                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 641, "Server failed to get network address\nfor the specified location:  invalid hostname."));
1046                 break;
1047         case CSA_X_DT_E_SERVICE_NOT_REGISTERED:
1048                 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."));
1049                 sprintf(error_buf, CMSD_ERROR_HELP);
1050                 break;
1051         case CSA_X_DT_E_SERVER_TIMEOUT:
1052                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 727, "Your request timed out\nPlease verify rpc.cmsd is installed correctly on your system."));
1053                 sprintf(error_buf, CMSD_ERROR_HELP);
1054                 break;
1055         case CSA_E_FAILURE:
1056                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 643, "Couldn't access calendar. Calendar"));
1057                 break;
1058         case CSA_E_INVALID_RULE:
1059                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 1120, "The event cannot be scheduled in the given time frame.\nThe operation was cancelled."));
1060                 break;
1061         case CSA_SUCCESS:
1062                 return;
1063         default:
1064                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 383, "Unknown error.\nOperation was cancelled.  Calendar"));
1065                 break;
1066         }
1067
1068         sprintf(buf2, "%s %s", buf, name);
1069         if (help_button) {
1070                 char *title = XtNewString(catgets(c->DT_catd, 1, 890,
1071                                                 "Calendar : Error - Services"));
1072                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 95, 
1073                                                 "Continue"));
1074                 dialog_popup(frame, DIALOG_TITLE, title,
1075                         DIALOG_TEXT, buf2,
1076                         BUTTON_IDENT, 1, ident1,
1077                         BUTTON_HELP, error_buf,
1078                         DIALOG_IMAGE, p,
1079                         NULL);
1080                 XtFree(ident1);
1081                 XtFree(title);
1082         }
1083         else {
1084                 char *title = XtNewString(catgets(c->DT_catd, 1, 890,
1085                                                 "Calendar : Error - Services"));
1086                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 95, 
1087                                                 "Continue"));
1088                 dialog_popup(frame, DIALOG_TITLE, title,
1089                         DIALOG_TEXT, buf2,
1090                         BUTTON_IDENT, 1, ident1,
1091                         DIALOG_IMAGE, p,
1092                         NULL);
1093                 XtFree(ident1);
1094                 XtFree(title);
1095         }
1096 }
1097
1098 /*
1099  * This function is called by the parse_appt_from_file routine if the end_date
1100  * was before the start date for the appointment - this queries the user as to
1101  * her intentions
1102  */
1103 extern boolean_t
1104 query_user(void *user_data) {
1105         char            buf[MAXNAMELEN];
1106         Calendar        *c = (Calendar *)user_data;
1107         Props_pu        *p = (Props_pu *)c->properties_pu;
1108         boolean_t       ret = B_FALSE;
1109         char            *title;
1110         char            *ident1;
1111         char            *ident2;
1112         static int      answer;
1113
1114         sprintf(buf, "%s", catgets(c->DT_catd, 1, 386,
1115                 "That appointment has an end time earlier than its begin time.\nDo you want to schedule it into the next day?"));
1116         title = XtNewString(catgets(c->DT_catd, 1, 248, "Calendar : Schedule Appointment"));
1117         ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
1118         ident2 = XtNewString(catgets(c->DT_catd, 1, 389, "Next Day"));
1119         answer = dialog_popup(c->frame,
1120                 DIALOG_TITLE, title,
1121                 DIALOG_TEXT, buf,
1122                 BUTTON_IDENT, 1, ident1,
1123                 BUTTON_IDENT, 2, ident2,
1124                 DIALOG_IMAGE, p->xm_question_pixmap,
1125                 NULL);
1126         XtFree(ident2);
1127         XtFree(ident1);
1128         XtFree(title);
1129         if (answer == 2)
1130                 ret = B_TRUE;
1131
1132         return ret;
1133 }
1134
1135 extern void
1136 set_message(Widget w, char *msg) {
1137         XmString        xmstr;
1138
1139         /*
1140          * If msg is NULL or a null string set it to be a space.  This
1141          * prevents label widgets from shrinking (which they do when they
1142          * have no text
1143          */
1144         if (msg == NULL || *msg == '\0') {
1145                 msg = " ";
1146         }
1147
1148         if (w) {
1149                 xmstr = XmStringCreateLocalized(msg);
1150                 XtVaSetValues(w, XmNlabelString, xmstr, NULL);
1151                 XmStringFree(xmstr);
1152         }
1153
1154
1155 }
1156
1157 extern void
1158 setup_quit_handler(Widget w, XtCallbackProc cb, caddr_t user_data) {
1159         Atom delete_window;
1160
1161         delete_window = XmInternAtom(XtDisplay(w), "WM_DELETE_WINDOW", False);
1162         XmAddWMProtocolCallback(w, delete_window, cb, user_data);
1163 }
1164
1165 int
1166 ds_is_double_click(XEvent *last_event, XEvent *event)
1167 {
1168         static  int             time_threshold;
1169         static  int             dist_threshold;
1170         static  short           first_time      = TRUE;
1171         short                   ret_value       = FALSE;
1172         int                     delta_time;
1173         int                     delta_x, delta_y;
1174
1175         if (last_event == NULL || event == NULL)
1176                 return ret_value;
1177
1178         /* first time this is called init the thresholds */
1179         if( first_time ) {
1180                 /* Get time threshold in miliseconds */
1181                 time_threshold = 800;
1182                 dist_threshold = 4;
1183                 first_time      = FALSE;
1184         }
1185         /* only deal with the down events */
1186         if (event->type == ButtonRelease)
1187                 return ret_value;
1188
1189         if ((event->xbutton.type == ButtonPress) &&
1190             (last_event->xbutton.type == ButtonPress)) {
1191  
1192                 delta_time = event->xbutton.time - last_event->xbutton.time;
1193                 delta_time += event->xbutton.time;
1194                 delta_time -= last_event->xbutton.time;
1195  
1196                 /* is the time within bounds? */
1197                 if( delta_time <= time_threshold ) {
1198  
1199                         /* check to see if the distance is ok */
1200                         delta_x = (last_event->xbutton.x > event->xbutton.x ?
1201                                            last_event->xbutton.x - event->xbutton.x :
1202                                            event->xbutton.x - last_event->xbutton.x);
1203
1204                         delta_y = (last_event->xbutton.y > event->xbutton.y ?
1205                                            last_event->xbutton.y - event->xbutton.y :
1206                                            event->xbutton.y - last_event->xbutton.y);
1207                         if( delta_x <= dist_threshold &&
1208                             delta_y <= dist_threshold )
1209                                 ret_value       = TRUE;
1210                 }
1211         }
1212         return ret_value;
1213 }        
1214
1215
1216 /*
1217  * Select the contents of a text item.
1218  *
1219  */
1220 extern int
1221 cm_select_text(Widget field, Time time) {
1222         XmTextPosition  last;
1223
1224         last = XmTextFieldGetLastPosition(field);
1225
1226         if (last > 0) {
1227                 XmTextFieldSetSelection(field, 0, last, time);
1228         }
1229
1230         return last;
1231 }
1232
1233 extern Dimension
1234 ComputeMaxWidth(
1235         Widget          w1,
1236         Widget          w2,
1237         Widget          w3,
1238         Widget          w4)
1239 {
1240         Dimension       width1,
1241                         width2;
1242         Widget          w[5];
1243         int             i;
1244
1245         if (!w1) return 0;
1246
1247         w[0] = w1;
1248         w[1] = w2;
1249         w[2] = w3;
1250         w[3] = w4;
1251         w[4] = (Widget) NULL;
1252
1253         XtVaGetValues(w1,
1254                 XmNwidth,               &width1,
1255                 NULL);
1256
1257         for (i = 1; w[i]; i++) {
1258
1259                 XtVaGetValues(w[i],
1260                         XmNwidth,       &width2,
1261                         NULL);
1262
1263                 if ((int)width2 > (int)width1) width1 = width2;
1264         }
1265
1266         return width1;
1267 }
1268
1269 extern void
1270 ManageChildren(
1271         Widget          w)
1272 {
1273         WidgetList      children;
1274         int             n;
1275
1276         XtVaGetValues(w,
1277                 XmNchildren,            &children,
1278                 XmNnumChildren,         &n,
1279                 NULL);
1280         XtManageChildren(children, n);
1281 }
1282
1283 #define MAX_NUM 10
1284 /*
1285  * Look for the highest/widest Widget
1286  * num <= MAX_NUM;
1287  */
1288 #include <X11/IntrinsicP.h>
1289 #include <X11/CoreP.h>
1290 #include <Xm/Scale.h>
1291 static Widget    _widget[MAX_NUM];
1292 static Dimension _height[MAX_NUM];
1293 static Dimension _width[MAX_NUM];
1294
1295 extern  void
1296 _i18n_HighestWidget(
1297 int num,
1298 Widget *ret,
1299 Dimension *dim,
1300 ... )
1301 {
1302     va_list   ap;
1303     int       i, _high;
1304     Dimension _max;
1305     Widget    _targetW, _highestW;
1306     Arg       _args[3];
1307     XtWidgetGeometry geo;
1308     unsigned char type;
1309
1310     *ret = (Widget)NULL;
1311     *dim = (Dimension)0;
1312     if ( num > MAX_NUM )
1313         return; /* Do nothing */
1314
1315     va_start( ap, dim );
1316
1317     for ( i = 0, _max = (Dimension)0; i < num; i++ ) {
1318         _widget[i] = (Widget)va_arg( ap, Widget );
1319         /*
1320          * Ugly check. XmScale's XmNheight is determined after being mapped.
1321          * So if WidgeClass == xmScaleWidgetClass, use XtQueryGeometry() !!
1322          * ( It's dangerous ! )
1323          * See p_create_display_pane()'s comment :)
1324          *
1325          * Same for xmRowColumnWidgetClass
1326          *
1327          */
1328         if  (XmIsManager (_widget[i])) {
1329             _targetW =  _widget[i];
1330             XtQueryGeometry( _targetW, NULL, &geo );
1331             _height[i] = geo.height;
1332         } else {
1333             _targetW =  _widget[i];
1334             XtVaGetValues( _targetW, XmNheight, &(_height[i]), NULL );
1335         }
1336         if ( _height[i] >= _max ) {
1337             _max = _height[i];
1338             _high = i;
1339             _highestW = _targetW;
1340         }
1341     }
1342
1343     *ret = _widget[_high];
1344     *dim = _max;
1345
1346     va_end( ap );
1347 }
1348
1349 extern  void
1350 _i18n_WidestWidget(
1351 int num,
1352 Widget *ret,
1353 Dimension *dim,
1354 ... )
1355 {
1356     va_list   ap;
1357     int       i, _wide;
1358     Widget    _targetW, _widestW;
1359     Dimension _max;
1360     XtWidgetGeometry geo;
1361     unsigned char type;
1362
1363     *ret = (Widget)NULL;
1364     *dim = (Dimension)0;
1365     if ( num > MAX_NUM )
1366         return; /* Do nothing */
1367
1368     va_start( ap, dim );
1369
1370     for ( i = 0, _max = (Dimension)0; i < num; i++ ) {
1371         _widget[i] = (Widget)va_arg( ap, Widget );
1372         /*
1373          * Ugly check. XmScale's XmNheight is determined after being mapped.
1374          * So if WidgeClass == xmScaleWidgetClass, use XtQueryGeometry() !!
1375          * ( It's dangerous ! )
1376          * See p_create_display_pane()'s comment :)
1377          *
1378          * Same for xmRowColumnWidgetClass
1379          *
1380          */
1381         if  (XmIsManager (_widget[i])) {
1382             _targetW = _widget[i];
1383             XtQueryGeometry( _targetW, NULL, &geo );
1384             _width[i] = geo.width;
1385         } else {
1386             _targetW = _widget[i];
1387             XtVaGetValues( _targetW, XmNwidth, &(_width[i]), NULL );
1388         } if ( _width[i] >= _max ) {
1389             _max = _width[i];
1390             _wide = i;
1391             _widestW = _targetW;
1392         }
1393     }
1394
1395     *ret = _widget[_wide];
1396     *dim = _max;
1397
1398     va_end( ap );
1399 }
1400
1401 /*
1402  * Look for the highest Widget plus, do layout as,
1403  *
1404  * +-------------------+
1405  * |                   |
1406  * |                   |                +----------------+
1407  * |                   | +------------+ |                |
1408  * | Most Highest      | |            | |                | <--- Center !
1409  * |                   | +------------+ |                |
1410  * |                   |       ^        +----------------+
1411  * |                   |       |                 ^
1412  * +-------------------+ ......|.................|........
1413  * 
1414  * Note : If you are using this function, as for Left/Right Attachment, 
1415  *        don't use these Widget as XmATTACHMENT_WIDGET's XmNwidget !
1416  * 
1417  * num <= MAX_NUM;
1418  */
1419 extern  void
1420 _i18n_HighestWidgetAdjust(
1421 int num,
1422 Widget *ret,
1423 Dimension *dim,
1424 ... )
1425 {
1426     va_list   ap;
1427     int       i, _high;
1428     Dimension _max;
1429     Widget    _targetW, _highestW;
1430     Arg       _args[3];
1431     XtWidgetGeometry geo;
1432     unsigned char type;
1433
1434     *ret = (Widget)NULL;
1435     *dim = (Dimension)0;
1436     if ( num > MAX_NUM )
1437         return; /* Do nothing */
1438
1439     va_start( ap, dim );
1440
1441     for ( i = 0, _max = (Dimension)0; i < num; i++ ) {
1442         _widget[i] = (Widget)va_arg( ap, Widget );
1443         /*
1444          * Ugly check. XmScale's XmNheight is determined after being mapped.
1445          * So if WidgeClass == xmScaleWidgetClass, use XtQueryGeometry() !!
1446          * ( It's dangerous ! )
1447          * See p_create_display_pane()'s comment :)
1448          *
1449          * Same for xmRowColumnWidgetClass
1450          *
1451          */
1452         if  (XmIsManager (_widget[i])) {
1453             _targetW =  _widget[i];
1454             XtQueryGeometry( _targetW, NULL, &geo );
1455             _height[i] = geo.height;
1456         } else {
1457             _targetW =  _widget[i];
1458             XtVaGetValues( _targetW, XmNheight, &(_height[i]), NULL );
1459         }
1460         if ( _height[i] >= _max ) {
1461             _max = _height[i];
1462             _high = i;
1463             _highestW = _targetW;
1464         }
1465     }
1466
1467     /*
1468      *  Do layout by XmNbottomAttachment/XmATTACH_OPPTOSITE_WIDGET
1469      */
1470     for ( i = 0; i < num; i++ ) {
1471         if ( i != _high ) {
1472             XtSetArg(_args[0], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET );
1473             XtSetArg(_args[1], XmNbottomWidget, _highestW );
1474             XtSetArg(_args[2], XmNbottomOffset, (_max - _height[i]) >> 1 );
1475             XtSetValues( _widget[i], _args, 3 );
1476         }
1477     }
1478
1479     *ret = _widget[_high];
1480     *dim = _max;
1481
1482     va_end( ap );
1483 }