Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtcm / dtcm / blist.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*******************************************************************************
24 **
25 **  blist.c
26 **
27 **  $TOG: blist.c /main/5 1999/02/08 17:02:59 mgreess $
28 **
29 **  RESTRICTED CONFIDENTIAL INFORMATION:
30 **
31 **  The information in this document is subject to special
32 **  restrictions in a confidential disclosure agreement between
33 **  HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
34 **  document outside HP, IBM, Sun, USL, SCO, or Univel without
35 **  Sun's specific written approval.  This document and all copies
36 **  and derivative works thereof must be returned or destroyed at
37 **  Sun's request.
38 **
39 **  Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
40 **
41 *******************************************************************************/
42
43 /*                                                                      *
44  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
45  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
46  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
47  * (c) Copyright 1993, 1994 Novell, Inc.                                *
48  */
49
50 #ifndef lint
51 static  char sccsid[] = "@(#)blist.c 1.66 95/03/28 Copyr 1994 Sun Microsystems, Inc.";
52 #endif
53
54 #include <EUSCompat.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <sys/param.h>
58 #include <Xm/Xm.h>
59 #include <Xm/Form.h>
60 #include <Xm/Label.h>
61 #include <Xm/LabelG.h>
62 #include <Xm/List.h>
63 #include <Xm/DialogS.h>
64 #include <Xm/PushB.h>
65 #include <Xm/Text.h>
66 #include <Xm/TextF.h>
67 #include <Xm/RowColumn.h>
68 #include <Xm/SeparatoG.h>
69 #include "browser.h"
70 #include "calendar.h"
71 #include "util.h"
72 #include "misc.h"
73 #include "timeops.h"
74 #include "blist.h"
75 #include "props.h"
76 #include "help.h"
77
78
79 static void
80 bl_pending_change(Widget w, XtPointer data, XtPointer cbs) {
81         Calendar *c = (Calendar *) data;
82         Browselist      *bl = (Browselist *)c->browselist;
83
84         if (bl->bl_pending_message_up == False) {
85                 /* NL_COMMENT
86                    Attention Translator:
87
88                    Message 841 is used in the Menu Editor's footer.  The
89                    Menu Editor is accessed through the browse menu.  The 
90                    message is displayed when something is typed into the User
91                    Name field in the editor.  If the translated footer message 
92                    is too long it causes the menu editor to grow horizontally
93                    which we do not want.  If you notice that the translated
94                    string causes the editor to grow horizontally please
95                    insert a newline (\n) character somewhere in the middle
96                    of the string so the footer will use two lines and the
97                    editor will grow vertically.
98                 */
99                 set_message(bl->message, catgets(c->DT_catd, 1, 841, "Click on \"Add Name\" to add a name, \"Apply\" to commit changes."));
100                 bl->bl_pending_message_up = True;
101                 XtSetSensitive(bl->add_button, True);
102         }
103 }
104
105 static void
106 bl_clear_pending_change(Browselist *bl) {
107
108         if (bl->bl_pending_message_up == True) {
109                 set_message(bl->message, " ");
110                 bl->bl_pending_message_up = False;
111                 XtSetSensitive(bl->add_button, False);
112         }
113 }
114
115 static void
116 bl_list_is_changed(Browselist *bl) {
117
118         if (bl->bl_list_changed == False) {
119                 bl->bl_list_changed = True;
120                 XtSetSensitive(bl->ok_button, True);
121                 XtSetSensitive(bl->apply_button, True);
122                 XtSetSensitive(bl->reset_button, True);
123                 XtVaSetValues(bl->form, XmNdefaultButton, bl->apply_button, NULL);
124         }
125 }
126
127 static void
128 bl_list_not_changed(Browselist *bl) {
129
130         bl->bl_list_changed = False;
131         XtSetSensitive(bl->ok_button, False);
132         XtSetSensitive(bl->apply_button, False);
133         XtSetSensitive(bl->reset_button, False);
134         XtVaSetValues(bl->form, XmNdefaultButton, bl->cancel_button, NULL);
135 }
136
137 static void
138 bl_list_selection_cb(Widget w, XtPointer data, XtPointer cbs) {
139         Calendar *c = (Calendar *) data;
140         Browselist      *bl = (Browselist *)c->browselist;
141         int             *pos_list, pos_cnt;
142
143         XmListGetSelectedPos(bl->browse_list, &pos_list, &pos_cnt);
144         if (pos_cnt <= 0) 
145                 XtSetSensitive(bl->remove_button, False);
146         else
147                 XtSetSensitive(bl->remove_button, True);
148 }
149
150 /*
151  * Remove the name from the UI and from the list if the calendar handle is NULL.
152  * If the calendar handle is not null, tag it as deleted and it will be taken
153  * care of later.
154  */
155 static void
156 blist_removenames(Widget widget, XtPointer client_data, XtPointer call_data) {
157         int             i, idx, valid_cnt, *pos_list, pos_cnt;
158         Calendar        *c = (Calendar *)client_data;
159         BlistData       *bd = NULL;
160         Browselist      *bl = (Browselist *)c->browselist;
161         int             rejected_name = 0;
162
163         set_message(bl->message, " ");
164         XmListGetSelectedPos(bl->browse_list, &pos_list, &pos_cnt);
165         if (pos_cnt <= 0) {
166                 set_message(bl->message, catgets(calendar->DT_catd, 1, 17,
167                                               "Select a name to remove"));
168                 return;
169         }
170
171         for (i = 0; i < pos_cnt; i++) {
172                 if (pos_list[i] == 1) {
173                         set_message(bl->message, catgets(calendar->DT_catd, 1,
174                                 16, "You may not remove the default calendar"));
175                         rejected_name++;
176                         continue;
177                 }
178
179                 XmListDeletePos(bl->browse_list, pos_list[i] - i + rejected_name);
180                 bd = (BlistData *)CmDataListGetData(bl->blist_data, pos_list[i]);
181
182                 if (bd)
183                 {
184                         bd->tag = BLIST_DELETE;
185                 }
186         }
187         blist_clean(bl, False);
188         bl_list_is_changed(bl);
189 }
190
191 /*
192  * Append the new name to the list and set the necessary tags.  Note this only
193  * adds the name to the linked list - not to the UI.  Also, it won't add a
194  * duplicate name.
195  */
196 static int
197 blist_name_append(Calendar *c, char *name, BlistTag t) {
198         int             i = 1;
199         Boolean         marked = False;
200         int             location = 2;
201         BlistData       *bd;
202         Browselist      *bl = (Browselist *)c->browselist;
203         char            *defname;
204  
205
206         /* This while loop is doing double duty here.  The primary 
207            purpose of the list is to find out if the name we're 
208            inserting is already in the list.  While looping thru, 
209            the secondary purpose is to find the lexicographical 
210            position of the name relative to the current set of entries.  
211            The business about marked and location is related to that 
212            second purpose. */
213
214         while ((bd = (BlistData *)CmDataListGetData(bl->blist_data, i)) &&
215                strcmp(bd->name, name) != 0)
216         {
217                 if ((marked == False) && (strcoll(name, bd->name) < 0) && 
218                     (i != 1)) {
219                         location = i;
220                         marked = True;
221                 }
222                 ++i;
223         }
224
225         if (bd) {
226                 /* Since the user may have hit the reset button, any items
227                  * that had been marked for deletion need to be made active.
228                  */
229                 if (bd->tag == BLIST_DELETE)
230                         bd->tag = BLIST_ACTIVE;
231
232                 return -1;
233         }
234         
235         /* 2 special cases here.  If the name is that of the calendar 
236            owner, it should always be at the head of the list.  If the 
237            name wasn't maked against any of the people on the list, 
238            then it should be inserted at the end. */
239
240         defname = get_user_calendar();
241         if (strcmp(defname, name) == 0) {
242                 location = 1;
243         } else if (marked == False) {
244                 location = i;
245         }
246         free(defname);
247  
248         bd = (BlistData *)ckalloc(sizeof(BlistData));
249         bd->name = cm_strdup(name);
250         bd->tag = t;
251         bd->cal_handle = NULL;
252         CmDataListAdd(bl->blist_data, (void *)bd, location);
253  
254         return location;
255
256 }
257
258 /*
259  * Callback for the add name button.  This simply calls the blist_name_append
260  * function and adds the name to the UI.
261  */
262 static void
263 blist_addname(Widget widget, XtPointer client_data, XtPointer cbs) {
264         char            *new_name, *end_ptr, buf[MAXNAMELEN];
265         XEvent          *e = ((XmAnyCallbackStruct *)cbs)->event;
266         XmString        xmstr;
267         Calendar        *c = (Calendar *)client_data;
268         Browselist      *bl = (Browselist *)c->browselist;
269         int             insert_location;
270
271
272         XtVaSetValues(bl->form, XmNresizePolicy, XmRESIZE_NONE, NULL);
273         bl_clear_pending_change(bl);
274         bl_list_is_changed(bl);
275         set_message(bl->message, " ");
276         new_name = XmTextFieldGetString(bl->username);
277
278         /* crush out leading white space for the name 
279            comparison/insert process */
280         
281         while ((*new_name == ' ') || (*new_name == '\t'))
282                 new_name++;
283
284         /* compress off trailing whitespace */
285
286         end_ptr = new_name;
287         while (*end_ptr)
288                 end_ptr++;
289         while ((end_ptr > new_name) && 
290                ((*(end_ptr - 1) == ' ') || (*(end_ptr - 1) == '\t')))
291                 end_ptr--;
292
293         *end_ptr = NULL;
294
295
296         if (blank_buf(new_name)) {
297                 set_message(bl->message, catgets(c->DT_catd, 1, 603,
298                         "Type a name to add in the User Name field"));
299                 return;
300         }
301
302         if (embedded_blank(new_name)) {
303                 set_message(bl->message, catgets(c->DT_catd, 1, 684,
304                         "User Names may not have embedded blanks or tabs"));
305                 return;
306         }
307
308
309         if ((insert_location = blist_name_append(c, new_name, BLIST_INSERT)) != -1) {
310                 xmstr = XmStringCreateLocalized(new_name);
311                 XmListAddItem(bl->browse_list, xmstr, insert_location);
312                 XmStringFree(xmstr);
313                 cm_select_text(bl->username, e->xbutton.time);
314         } else {
315                 sprintf(buf, "%s %s", new_name,
316                         catgets(c->DT_catd, 1, 604, "is already in the list"));
317                 set_message(bl->message, buf);
318         }
319         XtVaSetValues(bl->form, XmNresizePolicy, XmRESIZE_ANY, NULL);
320 }
321
322 /*
323  * This sends the new list of names to the properties database.  Note it ignores
324  * items that have been tagged for deletion.
325  */
326 static void
327 blist_write_list(Browselist *bl, Props *p) {
328         int             i, len = 0;
329         char            *buf;
330         BlistData       *bd;
331
332         /*
333          * First pass, count the number of bytes we're going to need
334          */
335         for (i = 1; i <= bl->blist_data->count; i++) {
336                 bd = (BlistData *)CmDataListGetData(bl->blist_data, i);
337                 if (bd && bd->name && bd->tag != BLIST_DELETE)
338                         len += cm_strlen(bd->name) + 2; /* one for spacing */
339         }
340         if (len <= 0)
341                 return;
342
343         /*
344          * We have names, so build the string, making sure to exclude items
345          * tagged for delete.
346          */
347         buf = (char *)ckalloc(len);
348         memset(buf, '\0', len);
349         for (i = 1; i <= bl->blist_data->count; i++) {
350                 bd = (BlistData *)CmDataListGetData(bl->blist_data, i);
351                 if (bd && bd->name && bd->tag != BLIST_DELETE) {
352                         cm_strcat(buf, bd->name);
353                         cm_strcat(buf, " ");
354                         bd->tag = BLIST_ACTIVE;
355                 }
356         }
357         set_char_prop(p, CP_DAYCALLIST, buf);
358         save_props(p);
359         free(buf);
360 }
361
362 /*
363  * Callback for the OK button - will write the list to the properties
364  * database, will update the browse menu on the main menu, and will update the
365  * menu on the multi browser if it's up.
366  */
367 static void
368 blist_ok(Widget widget, XtPointer client_data, XtPointer call_data) {
369         Calendar        *c = (Calendar *)client_data;
370         Browselist      *bl = (Browselist *)c->browselist;
371         Browser         *b = (Browser *)c->browser;
372         Props           *p = (Props *)c->properties;
373
374         bl_clear_pending_change(bl);
375         bl_list_not_changed(bl);
376         set_message(bl->message, " ");
377         blist_write_list(bl, p);
378
379         XtVaSetValues(c->browse_button, XmNsubMenuId, NULL, NULL);
380         update_browse_menu_names(c);
381         XtVaSetValues(c->browse_button, XmNsubMenuId, c->browse_menu, NULL);
382         if (b && b->frame)
383                 browser_reset_list(c);
384
385         XtPopdown(bl->frame);
386 }
387
388 /*
389  * Callback for the apply button - will write the list to the properties
390  * database, will update the browse menu on the main menu, and will update the
391  * menu on the multi browser if it's up.
392  */
393 static void
394 blist_apply(Widget widget, XtPointer client_data, XtPointer call_data) {
395         Calendar        *c = (Calendar *)client_data;
396         Browselist      *bl = (Browselist *)c->browselist;
397         Browser         *b = (Browser *)c->browser;
398         Props           *p = (Props *)c->properties;
399
400         bl_clear_pending_change(bl);
401         bl_list_not_changed(bl);
402         set_message(bl->message, " ");
403         blist_write_list(bl, p);
404
405         XtVaSetValues(c->browse_button, XmNsubMenuId, NULL, NULL);
406         update_browse_menu_names(c);
407         XtVaSetValues(c->browse_button, XmNsubMenuId, c->browse_menu, NULL);
408         if (b && b->frame)
409                 browser_reset_list(c);
410 }
411
412 static void
413 blist_cancel_cb(Widget widget, XtPointer client_data, XtPointer call_data) {
414         Calendar        *c = (Calendar *)client_data;
415         Browselist      *bl = (Browselist *)c->browselist;
416
417         blist_reset(c);
418
419         XtPopdown(bl->frame);
420 }
421
422 static void
423 blist_reset_cb(Widget widget, XtPointer client_data, XtPointer call_data) {
424         Calendar        *c = (Calendar *)client_data;
425         Browselist      *bl = (Browselist *)c->browselist;
426
427         blist_reset(c);
428 }
429
430 extern void
431 blist_init_names(Calendar *c) {
432         char            *name, *namelist;
433         Props           *p = (Props*)c->properties;
434         Browselist      *bl = (Browselist *)c->browselist;
435  
436         if (!bl->blist_data)
437                 bl->blist_data = CmDataListCreate();
438
439         /*
440          * Make sure the default calendar is in list
441          */
442         name = get_user_calendar();
443         blist_name_append(c, name, BLIST_ACTIVE);
444         free(name);
445
446         /*
447          * Make sure user's calendar is in list
448          */
449         blist_name_append(c, c->calname, BLIST_ACTIVE);
450
451         /* make sure the intiial view name is in the list. */
452
453         blist_name_append(c, get_char_prop(p, CP_DEFAULTCAL), BLIST_ACTIVE);
454
455         namelist = cm_strdup(get_char_prop(p, CP_DAYCALLIST));
456         if (namelist == NULL || *namelist == NULL )
457                 return;
458
459         name = strtok(namelist, " ");
460         while (name) {
461                 blist_name_append(c, name, BLIST_ACTIVE);
462                 name = strtok(NULL, " ");
463         }
464         free(namelist);
465 }
466
467 extern void
468 blist_init_ui(Calendar *c) {
469         int             i;
470         XmString        xmstr;
471         BlistData       *bd;
472         Browselist      *bl = (Browselist *)c->browselist;
473
474         XtVaSetValues(bl->form, XmNresizePolicy, XmRESIZE_NONE, NULL);
475         XmListDeleteAllItems(bl->browse_list);
476         for (i = 1; i <= bl->blist_data->count; i++) {
477                 bd = (BlistData *)CmDataListGetData(bl->blist_data, i);
478                 if (bd && bd->name && bd->tag != BLIST_DELETE) {
479                         xmstr = XmStringCreateLocalized(bd->name);
480                         if (!XmListItemExists(bl->browse_list, xmstr))
481                                 XmListAddItem(bl->browse_list, xmstr, 0);
482                         XmStringFree(xmstr);
483                 }
484         }
485         XmTextFieldSetString(bl->username, "");
486         XtVaSetValues(bl->form, XmNresizePolicy, XmRESIZE_ANY, NULL);
487 }
488
489 extern void
490 blist_clean(Browselist *bl, Boolean clean_all) {
491         int             i, left_cnt = 1, cnt;
492         BlistData       *bd;
493
494         if (NULL == bl->blist_data) return;
495
496         cnt = bl->blist_data->count;
497         for (i = 1; i <= cnt; i++) {
498                 bd = (BlistData *)CmDataListGetData(bl->blist_data, left_cnt);
499                 if (bd && bd->cal_handle == NULL &&
500                     (clean_all || bd->tag != BLIST_ACTIVE)) {
501                         if (bd->name)
502                                 free(bd->name);
503                         CmDataListDeletePos(bl->blist_data, left_cnt, True);
504                 } else
505                         ++left_cnt;
506         }
507 }
508
509 extern void
510 blist_reset(Calendar *c) {
511         Browselist      *bl = (Browselist *)c->browselist;
512
513         blist_clean(bl, True);
514         blist_init_names(c);
515         blist_init_ui(c);
516         bl_clear_pending_change(bl);
517         bl_list_not_changed(bl);
518         XtSetSensitive(bl->remove_button, False);
519 }
520
521 static void
522 blist_quit_handler(Widget w, XtPointer cdata, XtPointer data) {
523         Browselist      *bl = (Browselist *)cdata;
524
525         XtPopdown(w);
526 }
527
528 extern void
529 make_browselist(Calendar *c)
530 {
531         int             ac;
532         Arg             args[15];
533         XmString        label_str;
534         Widget          separator,
535                         button_form;
536         Browselist      *bl = (Browselist *)c->browselist;
537         Dimension       label_width;
538         char            *title;
539
540         if (!bl)
541                 return;
542
543         title = XtNewString(catgets(c->DT_catd, 1, 963, 
544                                     "Calendar : Menu Editor"));
545         bl->frame = XtVaCreatePopupShell("menu_editor_frame",
546                 xmDialogShellWidgetClass, c->frame,
547                 XmNdeleteResponse,      XmDO_NOTHING,
548                 XmNtitle, title,
549                 XmNallowShellResize,    True,
550                 XmNmappedWhenManaged,   False,
551                 NULL);
552         setup_quit_handler(bl->frame, blist_quit_handler, (caddr_t)bl);
553         XtFree(title);
554
555         bl->form = XtVaCreateWidget("menu_editor_form",
556                 xmFormWidgetClass, bl->frame,
557                 XmNautoUnmanage,        False,
558                 XmNfractionBase,        5,
559                 NULL);
560
561         label_str = XmStringCreateLocalized(
562                                 catgets(c->DT_catd, 1, 410, "User Name:"));
563         bl->username_label = XtVaCreateWidget("name_label",
564                 xmLabelGadgetClass, bl->form,
565                 XmNlabelString,         label_str,
566                 NULL);
567         XmStringFree(label_str);
568
569         ac = 0;
570         XtSetArg(args[ac], XmNorientation,      XmVERTICAL);    ++ac;
571         XtSetArg(args[ac], XmNpacking,          XmPACK_COLUMN); ++ac;
572         XtSetArg(args[ac], XmNtopAttachment,    XmATTACH_FORM); ++ac;
573         XtSetArg(args[ac], XmNtopOffset,        6);             ++ac;
574         XtSetArg(args[ac], XmNrightAttachment,  XmATTACH_FORM); ++ac;
575         XtSetArg(args[ac], XmNrightOffset,      5);             ++ac;
576         bl->edit_rc_mgr = XmCreateRowColumn(bl->form, "edit_rc_mgr", args, ac);
577
578         label_str = XmStringCreateLocalized(
579                                 catgets(c->DT_catd, 1, 686, "Add Name"));
580         bl->add_button = XtVaCreateWidget("add_button",
581                 xmPushButtonWidgetClass, bl->edit_rc_mgr,
582                 XmNlabelString,         label_str,
583                 XmNnavigationType,      XmTAB_GROUP,
584                 NULL);
585         XmStringFree(label_str);
586         XtAddCallback(bl->add_button, XmNactivateCallback,
587                                 blist_addname, (XtPointer)c);
588
589         label_str = XmStringCreateLocalized(
590                                 catgets(c->DT_catd, 1, 687, "Remove Name"));
591         bl->remove_button = XtVaCreateWidget("remove_button",
592                 xmPushButtonWidgetClass, bl->edit_rc_mgr,
593                 XmNlabelString,         label_str,
594                 XmNnavigationType,      XmTAB_GROUP,
595                 NULL);
596         XmStringFree(label_str);
597         XtAddCallback(bl->remove_button, XmNactivateCallback, 
598                                 blist_removenames, (XtPointer)c);
599         ManageChildren(bl->edit_rc_mgr);
600
601         XtVaGetValues(bl->username_label, XmNwidth, &label_width, NULL);
602
603         bl->username = XtVaCreateWidget("username",
604                 xmTextFieldWidgetClass, bl->form,
605                 XmNleftAttachment,      XmATTACH_FORM,
606                 XmNleftOffset,          label_width + 15,
607                 XmNrightAttachment,     XmATTACH_WIDGET,
608                 XmNrightWidget,         bl->edit_rc_mgr,
609                 XmNrightOffset,         5,
610                 XmNtopAttachment,       XmATTACH_FORM,
611                 XmNtopOffset,           5,
612                 XmNcolumns,             40,
613                 NULL);
614         XtAddCallback(bl->username, XmNactivateCallback, blist_addname,
615                                 (XtPointer)c);
616         XtAddCallback(bl->username, XmNvalueChangedCallback, 
617                                 bl_pending_change, (XtPointer)c);
618
619         XtVaSetValues(bl->username_label,
620                 XmNbottomAttachment,    XmATTACH_OPPOSITE_WIDGET,
621                 XmNbottomWidget,        bl->username,
622                 XmNbottomOffset,        5,
623                 XmNrightAttachment,     XmATTACH_WIDGET,
624                 XmNrightWidget,         bl->username,
625                 XmNrightOffset,         5,
626                 NULL);
627
628         label_str = XmStringCreateLocalized(
629                         catgets(c->DT_catd, 1, 688, "Browse Menu Items"));
630         bl->list_label = XtVaCreateWidget("list_label", 
631                 xmLabelWidgetClass, bl->form,
632                 XmNlabelString,         label_str,
633                 XmNtopAttachment,       XmATTACH_WIDGET,
634                 XmNtopWidget,           bl->username,
635                 XmNtopOffset,           10,
636                 XmNleftAttachment,      XmATTACH_FORM,
637                 XmNleftOffset,          5,
638                 NULL);
639         XmStringFree(label_str);
640
641         bl->message = XtVaCreateWidget("message_text",
642                 xmLabelGadgetClass, 
643                 bl->form,
644                 XmNalignment,           XmALIGNMENT_BEGINNING,
645                 XmNleftAttachment,      XmATTACH_FORM,
646                 XmNleftOffset,          5,
647                 XmNrightAttachment,     XmATTACH_FORM,
648                 XmNrightOffset,         5,
649                 XmNbottomAttachment,    XmATTACH_FORM,
650                 XmNbottomOffset,        5,
651                 NULL);
652
653         button_form = XtVaCreateWidget("menu_editor_button_form_mgr",
654                 xmFormWidgetClass,
655                 bl->form,
656                 XmNautoUnmanage,        False,
657                 XmNfractionBase,        5,
658                 XmNhorizontalSpacing,   5,
659                 XmNleftAttachment,      XmATTACH_FORM,
660                 XmNleftOffset,          5,
661                 XmNrightAttachment,     XmATTACH_FORM,
662                 XmNrightOffset,         5,
663                 XmNbottomAttachment,    XmATTACH_WIDGET,
664                 XmNbottomWidget,        bl->message,
665                 XmNbottomOffset,        5,
666                 NULL);
667         
668         label_str = XmStringCreateLocalized(catgets(c->DT_catd, 1, 655, "OK"));
669         bl->ok_button = XtVaCreateWidget("ok_button",
670                 xmPushButtonWidgetClass,
671                 button_form,
672                 XmNlabelString,         label_str,
673                 XmNleftAttachment,      XmATTACH_POSITION,
674                 XmNleftPosition,        0,
675                 XmNleftOffset,          5,
676                 XmNrightAttachment,     XmATTACH_POSITION,
677                 XmNrightPosition,       1,
678                 XmNrightOffset,         5,
679                 XmNbottomAttachment,    XmATTACH_FORM,
680                 NULL);
681         XmStringFree(label_str);
682         XtAddCallback(bl->ok_button, XmNactivateCallback, blist_ok,
683                                 (XtPointer)c);
684
685         label_str = XmStringCreateLocalized(
686                                 catgets(c->DT_catd, 1, 460, "Apply"));
687         bl->apply_button = XtVaCreateWidget("apply_button",
688                 xmPushButtonWidgetClass,
689                 button_form,
690                 XmNlabelString,         label_str,
691                 XmNleftAttachment,      XmATTACH_POSITION,
692                 XmNleftPosition,        1,
693                 XmNleftOffset,          5,
694                 XmNrightAttachment,     XmATTACH_POSITION,
695                 XmNrightPosition,       2,
696                 XmNrightOffset,         5,
697                 XmNbottomAttachment,    XmATTACH_FORM,
698                 NULL);
699         XmStringFree(label_str);
700         XtAddCallback(bl->apply_button, XmNactivateCallback, blist_apply,
701                                 (XtPointer)c);
702
703         label_str = XmStringCreateLocalized(
704                                 catgets(c->DT_catd, 1, 691, "Reset"));
705         bl->reset_button = XtVaCreateWidget("reset_button",
706                 xmPushButtonWidgetClass,
707                 button_form,
708                 XmNlabelString,         label_str,
709                 XmNleftAttachment,      XmATTACH_POSITION,
710                 XmNleftPosition,        2,
711                 XmNleftOffset,          5,
712                 XmNrightAttachment,     XmATTACH_POSITION,
713                 XmNrightPosition,       3,
714                 XmNrightOffset,         5,
715                 XmNbottomAttachment,    XmATTACH_FORM,
716                 NULL);
717         XmStringFree(label_str);
718         XtAddCallback(bl->reset_button, XmNactivateCallback,
719                         blist_reset_cb, (XtPointer)c);
720
721         label_str = XmStringCreateLocalized(
722                                 catgets(c->DT_catd, 1, 923, "Cancel"));
723         bl->cancel_button = XtVaCreateWidget("cancel_button",
724                 xmPushButtonWidgetClass,
725                 button_form,
726                 XmNlabelString,         label_str,
727                 XmNleftAttachment,      XmATTACH_POSITION,
728                 XmNleftPosition,        3,
729                 XmNleftOffset,          5,
730                 XmNrightAttachment,     XmATTACH_POSITION,
731                 XmNrightPosition,       4,
732                 XmNrightOffset,         5,
733                 XmNbottomAttachment,    XmATTACH_FORM,
734                 NULL);
735         XmStringFree(label_str);
736         XtAddCallback(bl->cancel_button, XmNactivateCallback, blist_cancel_cb,
737                                 (XtPointer)c);
738
739         label_str = XmStringCreateLocalized(catgets(c->DT_catd, 1, 77, "Help"));
740         bl->help_button = XtVaCreateWidget("help_button",
741                 xmPushButtonWidgetClass,
742                 button_form,
743                 XmNlabelString,         label_str,
744                 XmNleftAttachment,      XmATTACH_POSITION,
745                 XmNleftPosition,        4,
746                 XmNleftOffset,          5,
747                 XmNrightAttachment,     XmATTACH_POSITION,
748                 XmNrightPosition,       5,
749                 XmNrightOffset,         5,
750                 XmNbottomAttachment,    XmATTACH_FORM,
751                 NULL);
752         XmStringFree(label_str);
753         XtAddCallback(bl->help_button, XmNactivateCallback, 
754                 (XtCallbackProc)help_cb, MENU_EDITOR_HELP_BUTTON);
755         XtAddCallback(bl->form, XmNhelpCallback,
756                 (XtCallbackProc)help_cb, (XtPointer) MENU_EDITOR_HELP_BUTTON);
757
758         ManageChildren(button_form);
759
760         separator = XtVaCreateWidget("separator",
761                 xmSeparatorGadgetClass,
762                 bl->form,
763                 XmNleftAttachment,      XmATTACH_FORM,
764                 XmNrightAttachment,     XmATTACH_FORM,
765                 XmNbottomAttachment,    XmATTACH_WIDGET,
766                 XmNbottomWidget,        button_form,
767                 XmNbottomOffset,        5,
768                 NULL);
769         ac = 0;
770         XtSetArg(args[ac], XmNvisibleItemCount, 8); ++ac;
771         XtSetArg(args[ac], XmNselectionPolicy, XmMULTIPLE_SELECT); ++ac;
772         XtSetArg(args[ac], XmNdoubleClickInterval, 5); ++ac;
773         bl->browse_list = (Widget)XmCreateScrolledList(bl->form, "browse_list",
774                                                        args, ac);
775         bl->browse_list_sw = XtParent(bl->browse_list);
776
777         XtVaSetValues(bl->browse_list_sw,
778                 XmNvisualPolicy,        XmVARIABLE,
779                 XmNtopAttachment,       XmATTACH_WIDGET,
780                 XmNtopWidget,           bl->list_label,
781                 XmNtopOffset,           5,
782                 XmNleftAttachment,      XmATTACH_OPPOSITE_WIDGET,
783                 XmNleftWidget,          bl->list_label,
784                 XmNrightAttachment,     XmATTACH_OPPOSITE_WIDGET,
785                 XmNrightWidget,         bl->username,
786                 XmNrightOffset,         5,
787                 XmNbottomAttachment,    XmATTACH_WIDGET,
788                 XmNbottomWidget,        separator,
789                 XmNbottomOffset,        5,
790                 XmNwidth, 50,
791                 NULL);
792         XtManageChild(bl->browse_list);
793
794         XtAddCallback(bl->browse_list, XmNmultipleSelectionCallback, 
795                                 bl_list_selection_cb, (XtPointer)c);
796
797         ManageChildren(bl->form);
798         XtManageChild(bl->form);
799
800         /*
801          * Set default button
802          */
803         XtVaSetValues(bl->form, XmNcancelButton, bl->cancel_button, NULL);
804         XmProcessTraversal(bl->username, XmTRAVERSE_CURRENT);
805         XtVaSetValues(bl->form, XmNinitialFocus, bl->username, NULL);
806
807         /*
808          * For storing the list of names
809          */
810         if (!bl->blist_data)
811                 bl->blist_data = CmDataListCreate();
812 }
813
814 extern void
815 show_browselist(Calendar *c) {
816         Browselist      *bl;
817
818         if (c->browselist == NULL)
819                 c->browselist = (caddr_t)ckalloc(sizeof(Browselist));
820         bl = (Browselist *)c->browselist;
821
822         if (!bl->frame)
823                 make_browselist(c);
824         blist_reset(c);
825         XtVaSetValues(bl->frame, XmNmappedWhenManaged, True, NULL);
826         /*
827          * Set default button
828          */
829         XtVaSetValues(bl->form, XmNcancelButton, bl->cancel_button, NULL);
830         XmProcessTraversal(bl->username, XmTRAVERSE_CURRENT);
831         XtVaSetValues(bl->form, XmNinitialFocus, bl->username, NULL);
832
833         XtPopup(bl->frame, XtGrabNone);
834         set_message(bl->message, "\0");
835 }
836