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