1 /*
2  *
3  * Copyright (C) 1988 Massachusetts Institute of Technology
4  *
5  */
6 
7 
8 /*
9  * Permission to use, copy, modify, and distribute this software and its
10  * documentation for any purpose and without fee is hereby granted, provided
11  * that the above copyright notice appear in all copies and that both that
12  * copyright notice and this permission notice appear in supporting
13  * documentation, and that the name of M.I.T. not be used in advertising or
14  * publicity pertaining to distribution of the software without specific,
15  * written prior permission. M.I.T. makes no representations about the
16  * suitability of this software for any purpose.  It is provided "as is"
17  * without express or implied warranty.
18  *
19  */
20 
21 /***********************************************************************
22 * Copyright 1990-1994 by Richard Bingle and Purdue University.  All rights
23 * reserved.  Some individual files may be covered by other copyrights.
24 *
25 * Redistribution and use in source and binary forms are permitted
26 * provided that this entire copyright notice is duplicated in all such
27 * copies.  Neither the name of the University, nor the name of the author
28 * may be used to endorse or promote products derived from this material
29 * without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
32 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
33 * MERCHANTIBILITY AND FITNESS FOR ANY PARTICULAR PURPOSE.
34 ************************************************************************/
35 
36 /** Written by Roman J. Budzianowski - Project Athena, MIT **/
37 /** Modified by Richard Bingle - Purdue University **/
38 
39 #include "xcalendar.h"
40 
41 char           *GetHoliday();
42 
43 static XtCallbackRec callbacks[] = {
44     {NULL, NULL},
45     {NULL, NULL}
46 };
47 
48 List            editorList = NULL;
49 Boolean         initialized = False;
50 char           *homedir = NULL;
51 char           *calendarDir = NULL;
52 
53 extern Cardinal displayedMonth, displayedYear;
54 void            SaveButtonHandler();
55 
56 
57 Boolean         already_open();
58 void            SaveText();
59 
60 /*
61  * ChangeDay() - Edit a new day with an existing dayeditor.
62  */
63 
64 void
ChangeDay(editor)65 ChangeDay(editor)
66     DayEditor       editor;
67 
68 {
69     Arg             args[10];
70     int             n;
71     char            mon[4];
72     char            title[80];
73 #ifndef ATHENA
74     XmString        xms;
75 #endif
76 
77     if (appResources.oldStyle) {
78 	strncpy(mon, smonth[editor->month], 3);
79 	mon[3] = '\0';
80 	sprintf(editor->filename, "xc%d%s%d", editor->day, mon, editor->year);
81     } else {
82 	sprintf(editor->filename, "xc%d.%02d.%02d", editor->year,
83 		editor->month, editor->day);
84     }
85 
86     editor->open = False;
87 
88     if (!ReadFile(editor))
89 	return;
90 
91     editor->used = True;
92 
93     sprintf(title, " %d %s %d ",
94 	    editor->day, smonth[editor->month], editor->year);
95 
96     n = 0;
97 #ifdef ATHENA
98     XtSetArg(args[n], XtNlabel, title);
99     n++;
100     XtSetValues(editor->title, args, n);
101 #else
102     xms = XMS(title);
103     XtSetArg(args[n], XmNlabelString, xms);
104     n++;
105     XtSetValues(editor->title, args, n);
106     XmStringFree(xms);
107 #endif
108 
109     n = 0;
110     XtSetArg(args[n], XtNiconName, title);
111     n++;
112     XtSetValues(editor->shell, args, n);
113 
114     XtSetSensitive(editor->saveButton, False);
115 
116     n = 0;
117     callbacks[0].callback = (XtCallbackProc) SaveButtonHandler;
118     callbacks[0].closure = (XtPointer) editor;
119 #ifdef ATHENA
120     XtSetArg(args[n], XtNcallback, callbacks);
121     n++;
122     XtSetValues(XawTextGetSource(editor->editor), args, n);
123 #else
124     XtSetArg(args[n], XmNmodifyVerifyCallback, callbacks);
125     n++;
126     XtSetValues(editor->editor, args, n);
127 #endif
128 
129     if (EmptyBuffer(editor) || already_open(editor->filename))
130 	XtSetSensitive(editor->clearEntry, False);
131     else
132 	XtSetSensitive(editor->clearEntry, True);
133 
134     if (!already_open(editor->filename))
135 	editor->open = True;
136 }
137 
138 /*
139  * PrevDay() - Previous day callback.
140  */
141 
142 void
PrevDay(w,closure,call_data)143 PrevDay(w, closure, call_data)
144     Widget          w;
145     XtPointer       closure;
146     XtPointer       call_data;
147 {
148     DayEditor       editor = (DayEditor) closure;
149     Cardinal        numberofDays;
150 
151     XtUnmapWidget(w);
152 
153     if (editor->saved == False) {
154 	SaveText(w, closure, call_data);
155     }
156     if (editor->day == 1) {
157 	if (editor->month == 1) {
158 	    editor->month = 12;
159 	    editor->year--;
160 	} else
161 	    editor->month--;
162 	numberofDays = NumberOfDays(editor->month, editor->year);
163 	editor->day = numberofDays;
164     } else
165 	editor->day--;
166 
167     ChangeDay(editor);
168     XtMapWidget(w);
169 }
170 
171 /*
172  * SuccDay() - Next day callback.
173  */
174 
175 void
SuccDay(w,closure,call_data)176 SuccDay(w, closure, call_data)
177     Widget          w;
178     XtPointer       closure;
179     XtPointer       call_data;
180 {
181     DayEditor       editor = (DayEditor) closure;
182     Cardinal        numberofDays;
183 
184     XtUnmapWidget(w);
185 
186     if (editor->saved == False) {
187 	SaveText(w, closure, call_data);
188     }
189     numberofDays = NumberOfDays(editor->month, editor->year);
190     if (editor->day == numberofDays) {
191 	if (editor->month == 12) {
192 	    editor->month = 1;
193 	    editor->year++;
194 	} else
195 	    editor->month++;
196 	editor->day = 1;
197     } else
198 	editor->day++;
199 
200     ChangeDay(editor);
201     XtMapWidget(w);
202 }
203 
204 /*
205  * already_open() - Returns true if there is already an editor
206  * open for that day (within this process).
207  */
208 
209 Boolean
already_open(filename)210 already_open(filename)
211     char           *filename;
212 {
213     DayEditor       editor;
214     int             i;
215 
216     if (editorList == NULL)
217 	return (False);
218 
219     for (i = 1; i <= ListLength(editorList); i++) {
220 	editor = GetEditorFromList(editorList, i);
221 	if (!strcmp(editor->filename, filename)) {
222 	    if (editor->open == True) {
223 		return (True);
224 	    }
225 	}
226     }
227     return (False);
228 }
229 
230 /*
231  * InitEditors() - Initialize dayeditors.
232  */
233 
234 Boolean
InitEditors()235 InitEditors()
236 {
237     char           *getenv();
238     DIR            *dirp;
239 #if defined (SYSV) || defined(__osf__) || defined(SVR4) || defined(HAVE_DIRENT_H)
240     struct dirent  *dp;
241 #else
242     struct direct  *dp;
243 #endif
244     char            yearStr[5];
245     char            MoYear[16];
246     Cardinal        firstDay;
247     int             error_status;
248     struct stat     dir_status;
249 
250     sprintf(yearStr, "%d", displayedYear);
251     sprintf(MoYear, "xc%d.%02d.", displayedYear, displayedMonth);
252     firstDay = FirstDay(month, year);
253 
254     if (calendarDir == NULL) {
255 	if (appResources.calendarDir == NULL) {
256 	    /* open the ~/Calendar directory - create if necessary */
257 	    homedir = getenv("HOME");
258 
259 	    calendarDir = XtMalloc(strlen(homedir) + 10);
260 	    strcpy(calendarDir, homedir);
261 	    strcat(strcat(calendarDir, "/"), "Calendar");
262 	} else {
263 	    calendarDir = XtMalloc(strlen(appResources.calendarDir) + 3);
264 	    strcpy(calendarDir, appResources.calendarDir);
265 	}
266     }
267     error_status = stat(calendarDir, &dir_status);
268 
269     if (error_status == -1)
270 	if (errno == ENOENT) {	/* not found */
271 	    /* it should be a popup asking the user ... */
272 	    fprintf(stderr, "%s doesn't exist : Creating...", calendarDir);
273 
274 	    if (mkdir(calendarDir, 0700) == -1) {
275 		XBell(XtDisplay(toplevel), 100);
276 		fprintf(stderr, "Couldn't create %s directory.\n");
277 		perror("xcalendar:mkdir:");
278 		return False;
279 	    }
280 	} else {
281 	    XtWarning("Cannot stat calendar directory");
282 	    return False;
283 	}
284 
285     chdir(calendarDir);
286 
287     dirp = (DIR *) opendir(calendarDir);
288 
289     if (dirp == NULL) {
290 	XtWarning("Cannot open calendar (maybe it's not a directory)");
291 	return False;
292     }
293     while ((dp = readdir(dirp)) != NULL) {
294 	char           *s;
295 	/* find entries from the displayedMonth and store them in a list */
296 
297 	if (appResources.oldStyle) {
298 	    s = (char *) strchr(dp->d_name, *smonth[displayedMonth]);
299 
300 	    if (s != NULL && !strncmp(s + 3, yearStr, 4) &&
301 		!strncmp(s, smonth[displayedMonth], 3))
302 		MarkDayEntry(GetWidgetFromList(daylist, atoi(dp->d_name + 2) +
303 					       firstDay - 1), True);
304 	} else {
305 	    if (!strncmp(dp->d_name, MoYear, strlen(MoYear))) {
306 		s = dp->d_name + strlen(MoYear);
307 		MarkDayEntry(GetWidgetFromList(daylist, atoi(s) + firstDay - 1),
308 			     True);
309 	    }
310 	}
311     }
312 
313     if (!editorList)
314 	editorList = CreateList(5, sizeof(DayEditor));
315 
316     closedir(dirp);
317 
318     initialized = True;
319     return True;
320 }
321 
322 /*
323  * EditDayEntry() - Callback for day buttons.
324  */
325 
326 void
EditDayEntry(w,closure,call_data)327 EditDayEntry(w, closure, call_data)
328     Widget          w;
329     XtPointer       closure;
330     XtPointer       call_data;
331 {
332     int             i;
333     DayEditor       editor = NULL;
334     Arg             args[10];
335     int             n;
336     char            title[80];
337     Boolean         success;
338     char            mon[4];
339 #ifndef ATHENA
340     XmString        xms;
341 #endif
342 
343     if (!initialized) {
344 	success = InitEditors();
345 	if (!success)
346 	    return;
347     }
348     /* find free editor */
349 
350     for (i = 1; i <= ListLength(editorList); i++) {
351 	editor = GetEditorFromList(editorList, i);
352 	if (editor->used)
353 	    editor = NULL;
354 	else
355 	    break;
356     }
357 
358     if (editor == NULL) {
359 #ifdef ATHENA
360 #ifdef XI18N
361 	editor = CreateDayEditor("dayEditor", XawtextWrapLine, NULL);
362 #else
363 	editor = CreateDayEditor("dayEditor", XawtextWrapWord, NULL);
364 #endif
365 #else
366 	editor = CreateMotifDayEditor("dayEditor", NULL, NULL);
367 #endif
368 	PushEditorOnList(editorList, editor);
369     }
370     editor->button = w;
371     editor->day = (int) closure;
372     editor->month = displayedMonth;
373     editor->year = displayedYear;
374     editor->saved = True;
375 
376     editor->filename = XtMalloc(12);
377 
378     if (appResources.oldStyle) {
379 	strncpy(mon, smonth[editor->month], 3);
380 	mon[3] = '\0';
381 	sprintf(editor->filename, "xc%d%s%d", editor->day, mon, editor->year);
382     } else {
383 	sprintf(editor->filename, "xc%d.%02d.%02d", editor->year, editor->month,
384 		editor->day);
385     }
386 
387     if (!ReadFile(editor))
388 	return;
389 
390     editor->used = True;
391 
392     sprintf(title, " %d %s %d ",
393 	    editor->day, smonth[editor->month], editor->year);
394 
395     n = 0;
396 #ifdef ATHENA
397     XtSetArg(args[n], XtNlabel, title);
398     n++;
399     XtSetValues(editor->title, args, n);
400 #else
401     xms = XMS(title);
402     XtSetArg(args[n], XmNlabelString, xms);
403     n++;
404     XtSetValues(editor->title, args, n);
405     XmStringFree(xms);
406 #endif
407 
408     XtSetArg(args[n], XtNiconName, title);
409     n++;
410     XtSetValues(editor->shell, args, n);
411 
412     XtSetSensitive(editor->saveButton, False);
413 
414     n = 0;
415     callbacks[0].callback = (XtCallbackProc) SaveButtonHandler;
416     callbacks[0].closure = (XtPointer) editor;
417 #ifdef ATHENA
418     XtSetArg(args[n], XtNcallback, callbacks);
419     n++;
420     XtSetValues(XawTextGetSource(editor->editor), args, n);
421 #else
422     XtSetArg(args[n], XmNmodifyVerifyCallback, callbacks);
423     n++;
424     XtSetValues(editor->editor, args, n);
425 #endif
426 
427     if (EmptyBuffer(editor) || already_open(editor->filename))
428 	XtSetSensitive(editor->clearEntry, False);
429     else
430 	XtSetSensitive(editor->clearEntry, True);
431 
432     if (!already_open(editor->filename))
433 	editor->open = True;
434 
435     StartEditor(editor);
436 
437 }
438 
439 /*
440  * SaveButtonHandler() - Updates sensitivity of save and clear buttons
441  * once text is entered.
442  */
443 
444 void
SaveButtonHandler(w,data,call_data)445 SaveButtonHandler(w, data, call_data)
446     Widget          w;
447     XtPointer       data;
448     XtPointer       call_data;
449 {
450     DayEditor       editor = (DayEditor) data;
451     Arg             args[10];
452     int             n;
453     char            temp;
454 
455     if (editor->open == False)
456 	return;
457 
458     XtSetSensitive(editor->saveButton, True);
459     editor->saved = False;
460     XtSetSensitive(editor->clearEntry, True);
461 
462     n = 0;
463 #ifdef ATHENA
464     XtSetArg(args[n], XtNcallback, NULL);
465     n++;
466     XtSetValues(XawTextGetSource(editor->editor), args, n);
467 #else
468     XtSetArg(args[n], XmNmodifyVerifyCallback, NULL);
469     n++;
470     XtSetValues(editor->editor, args, n);
471 #endif
472 }
473 
474 /*
475  * SaveText() - Save callback.
476  */
477 
478 void
SaveText(w,closure,call_data)479 SaveText(w, closure, call_data)
480     Widget          w;
481     XtPointer       closure;
482     XtPointer       call_data;
483 {
484     DayEditor       editor = (DayEditor) closure;
485     Arg             args[10];
486     int             n;
487     int             saveStatus;
488 #ifndef ATHENA
489     char           *sb;
490 #endif
491 
492     if (editor->filename == NULL)
493 	return;
494 
495     if (editor->open == False)
496 	return;
497 
498 #ifdef XI18N
499     {
500 	String          str;
501 	Arg             args[10];
502 	int             n;
503 
504 	n = 0;
505 	XtSetArg(args[n], XtNstring, &str);
506 	n++;
507 	XtGetValues(editor->editor, args, n);
508 	strcpy(editor->buffer, str);
509 	/* XawAsciiSourceFreeString(w); */
510     }
511 #endif
512 
513 #ifdef ATHENA
514     if ((saveStatus = write_to_file(editor->filename, editor->buffer, TextSize(editor))) == -1)
515 	return;
516 #else
517     sb = XmTextGetString(editor->editor);
518     if ((saveStatus = write_to_file(editor->filename, sb, strlen(sb))) == -1) {
519 	XtFree(sb);
520 	return;
521     }
522     XtFree(sb);
523 #endif
524 
525     if (saveStatus == 0) {
526 
527 	if (editor->month == displayedMonth && editor->year == displayedYear)
528 	    MarkDayEntry(GetWidgetFromList(daylist,
529 		 editor->day + FirstDay(displayedMonth, displayedYear) - 1),
530 			 False);
531 	XtSetSensitive(editor->clearEntry, False);
532     } else if (editor->month == displayedMonth && editor->year == displayedYear)
533 	MarkDayEntry(GetWidgetFromList(daylist, editor->day +
534 			FirstDay(displayedMonth, displayedYear) - 1), True);
535 
536     XtSetSensitive(editor->saveButton, False);
537 
538     n = 0;
539     callbacks[0].callback = (XtCallbackProc) SaveButtonHandler;
540     callbacks[0].closure = (XtPointer) editor;
541 #ifdef ATHENA
542     XtSetArg(args[n], XtNcallback, callbacks);
543     n++;
544     XtSetValues(XawTextGetSource(editor->editor), args, n);
545 #else
546     XtSetArg(args[n], XmNmodifyVerifyCallback, callbacks);
547     n++;
548     XtSetValues(editor->editor, args, n);
549 #endif
550 
551     editor->saved = True;
552 }
553 
554 /*
555  * ExitEditor() - Done callback.
556  */
557 
558 void
ExitEditor(w,closure,call_data)559 ExitEditor(w, closure, call_data)
560     Widget          w;
561     XtPointer       closure;
562     XtPointer       call_data;
563 {
564     DayEditor       editor = (DayEditor) closure;
565     Arg             args[10];
566     int             n;
567 
568     if (editor->saved == False)
569 	SaveText(w, closure, call_data);
570 
571     n = 0;
572 #ifdef ATHENA
573     XtSetArg(args[n], XtNcallback, NULL);
574     n++;
575     XtSetValues(XawTextGetSource(editor->editor), args, n);
576 #else
577     XtSetArg(args[n], XmNmodifyVerifyCallback, callbacks);
578     n++;
579     XtSetValues(editor->editor, args, n);
580 #endif
581 
582     editor->used = False;
583 
584     XtPopdown(editor->shell);
585 
586     editor->open = False;
587     editor->year = displayedYear;
588     editor->month = displayedMonth;
589     if (editor->button == help_button)
590 	XtSetSensitive(editor->button, True);
591 }
592 
593 /*
594  * ClearEntry() - Clear callback.
595  */
596 
597 void
ClearEntry(w,closure,call_data)598 ClearEntry(w, closure, call_data)
599     Widget          w;
600     XtPointer       closure;
601     XtPointer       call_data;
602 {
603     DayEditor       editor = (DayEditor) closure;
604 
605     bzero(editor->buffer, appResources.textBufferSize);
606 
607     ChangeTextSource(editor, editor->buffer, "", True);
608 
609     SaveText(w, closure, call_data);
610 
611 }
612 
613 
614 #ifdef ATHENA
615 
616 /*
617  * CreateDayEditor() - Creates an individual day editor.
618  */
619 
620 DayEditor
CreateDayEditor(name,options,initialtext)621 CreateDayEditor(name, options, initialtext)
622     char           *name;
623     int             options;
624     char           *initialtext;
625 {
626     DayEditor       editor = (DayEditor) XtCalloc(1, sizeof(DayEditorRec));
627     Arg             args[10];
628     int             n;
629     Widget          frame, title, text, controls;
630 
631     Widget          daybuttons;
632 
633     editor->shell = XtCreatePopupShell(name, topLevelShellWidgetClass,
634 				       toplevel, NULL, 0);
635 
636     n = 0;
637     frame = XtCreateWidget("editorFrame", panedWidgetClass, editor->shell,
638 			   args, n);
639 
640     n = 0;
641     daybuttons = XtCreateManagedWidget("daybuttons", formWidgetClass, frame,
642 				       args, n);
643 
644     n = 0;
645     callbacks[0].callback = PrevDay;
646     callbacks[0].closure = (XtPointer) editor;
647     XtSetArg(args[n], XtNcallback, callbacks);
648     n++;
649     XtSetArg(args[n], XtNfromHoriz, NULL);
650     n++;
651     XtSetArg(args[n], XtNleft, XtChainLeft);
652     n++;
653     XtSetArg(args[n], XtNright, XtChainLeft);
654     n++;
655 
656     editor->prevday = XtCreateManagedWidget("prevday", commandWidgetClass,
657 					    daybuttons, args, n);
658 
659     /** create title **/
660 
661     n = 0;
662     XtSetArg(args[n], XtNskipAdjust, True);
663     n++;
664     XtSetArg(args[n], XtNfromHoriz, editor->prevday);
665     n++;
666     XtSetArg(args[n], XtNleft, XtChainLeft);
667     n++;
668     XtSetArg(args[n], XtNright, XtChainRight);
669     n++;
670 
671     title = XtCreateManagedWidget("editorTitle", labelWidgetClass, daybuttons,
672 				  args, n);
673     editor->title = title;
674 
675     editor->buffer = XtCalloc(appResources.textBufferSize, sizeof(char));
676 
677     n = 0;
678     callbacks[0].callback = SuccDay;
679     callbacks[0].closure = (XtPointer) editor;
680     XtSetArg(args[n], XtNcallback, callbacks);
681     n++;
682     XtSetArg(args[n], XtNfromHoriz, title);
683     n++;
684     XtSetArg(args[n], XtNleft, XtChainRight);
685     n++;
686     XtSetArg(args[n], XtNright, XtChainRight);
687     n++;
688 
689     editor->succday = XtCreateManagedWidget("succday", commandWidgetClass,
690 					    daybuttons, args, n);
691 
692     if (initialtext)
693 	strcpy(editor->buffer, initialtext);
694 
695     editor->bufSize = appResources.textBufferSize;
696 
697     n = 0;
698     XtSetArg(args[n], XtNstring, editor->buffer);
699     n++;
700     XtSetArg(args[n], XtNlength, appResources.textBufferSize);
701     n++;
702     XtSetArg(args[n], XtNwrap, options);
703     n++;
704 
705     text = XtCreateManagedWidget("editor", asciiTextWidgetClass, frame,
706 				 args, n);
707     editor->editor = text;
708 
709     n = 0;
710     XtSetArg(args[n], XtNstring, "");
711     n++;
712     XtSetArg(args[n], XtNlength, 1);
713     n++;
714     XtSetArg(args[n], XtNwrap, XawtextWrapNever);
715     n++;
716     XtSetArg(args[n], XtNskipAdjust, True);
717     n++;
718     editor->holiday = XtCreateManagedWidget("holiday", asciiTextWidgetClass,
719 					    frame, args, n);
720 
721     n = 0;
722     XtSetArg(args[n], XtNfromVert, editor->holiday);
723     n++;
724     XtSetArg(args[n], XtNskipAdjust, True);
725     n++;
726     controls = XtCreateManagedWidget("editorControls", boxWidgetClass,
727 				     frame, args, n);
728 
729     n = 0;
730     callbacks[0].callback = ExitEditor;
731     callbacks[0].closure = (XtPointer) editor;
732     XtSetArg(args[n], XtNcallback, callbacks);
733     n++;
734 
735     editor->doneButton = XtCreateManagedWidget("doneButton",
736                                     commandWidgetClass, controls, args, n);
737 
738     n = 0;
739     callbacks[0].callback = SaveText;
740     callbacks[0].closure = (XtPointer) editor;
741     XtSetArg(args[n], XtNcallback, callbacks);
742     n++;
743 
744     editor->saveButton = XtCreateManagedWidget("saveButton",
745 				     commandWidgetClass, controls, args, n);
746 
747     n = 0;
748     callbacks[0].callback = ClearEntry;
749     callbacks[0].closure = (XtPointer) editor;
750     XtSetArg(args[n], XtNcallback, callbacks);
751     n++;
752 
753     editor->clearEntry = XtCreateManagedWidget("clearEntry",
754 				     commandWidgetClass, controls, args, n);
755 
756     XtInstallAllAccelerators(editor->editor, editor->shell);
757 
758     XtManageChild(frame);
759 
760     XtRealizeWidget(editor->shell);
761 
762     return editor;
763 
764 }
765 #else
766 
767 /*
768  * CreateDayEditor() - Creates an individual day editor.
769  */
770 
771 DayEditor
CreateMotifDayEditor(name,options,initialtext)772 CreateMotifDayEditor(name, options, initialtext)
773     char           *name;
774     int             options;
775     char           *initialtext;
776 {
777     DayEditor       editor = (DayEditor) XtCalloc(1, sizeof(DayEditorRec));
778     Arg             args[10];
779     int             n;
780     Widget          frame, title, text, controls;
781 
782     Widget          daybuttons;
783     XtWidgetGeometry size;
784 
785     editor->shell = XtCreatePopupShell(name, topLevelShellWidgetClass,
786 				       toplevel, NULL, 0);
787 
788     XtAddEventHandler(editor->shell, (EventMask)0, True,
789                       _XEditResCheckMessages, NULL);
790 
791     n = 0;
792     frame = XtCreateWidget("editorFrame", xmPanedWindowWidgetClass,
793 			   editor->shell, args, n);
794 
795     n = 0;
796     daybuttons = XtCreateManagedWidget("daybuttons", xmFormWidgetClass,
797 				       frame, args, n);
798 
799     n = 0;
800     callbacks[0].callback = PrevDay;
801     callbacks[0].closure = (XtPointer) editor;
802     XtSetArg(args[n], XmNactivateCallback, callbacks);
803     n++;
804     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM);
805     n++;
806 
807     editor->prevday = XtCreateManagedWidget("prevday", xmPushButtonWidgetClass,
808 					    daybuttons, args, n);
809 
810     n = 0;
811     callbacks[0].callback = SuccDay;
812     callbacks[0].closure = (XtPointer) editor;
813     XtSetArg(args[n], XmNactivateCallback, callbacks);
814     n++;
815     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM);
816     n++;
817 
818     editor->succday = XtCreateManagedWidget("succday", xmPushButtonWidgetClass,
819 					    daybuttons, args, n);
820 
821     /** create title **/
822 
823     n = 0;
824     XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET);
825     n++;
826     XtSetArg(args[n], XmNleftWidget, editor->prevday);
827     n++;
828     XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET);
829     n++;
830     XtSetArg(args[n], XmNrightWidget, editor->succday);
831     n++;
832 
833     title = XtCreateManagedWidget("editorTitle", xmLabelWidgetClass, daybuttons,
834 				  args, n);
835     editor->title = title;
836 
837     editor->buffer = XtCalloc(appResources.textBufferSize, sizeof(char));
838 
839     if (initialtext)
840 	strcpy(editor->buffer, initialtext);
841 
842     editor->bufSize = appResources.textBufferSize;
843 
844     n = 0;
845     XtSetArg(args[n], XmNstring, editor->buffer);
846     n++;
847     XtSetArg(args[n], XmNlength, appResources.textBufferSize);
848     n++;
849     XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT);
850     n++;
851 
852     text = XmCreateScrolledText(frame, "editor", args, n);
853     XtManageChild(text);
854     editor->editor = text;
855 
856     n = 0;
857     XtSetArg(args[n], XmNeditMode, XmSINGLE_LINE_EDIT);
858     n++;
859     XtSetArg(args[n], XmNeditable, False);
860     n++;
861 
862     editor->holiday = XtCreateManagedWidget("holiday", xmTextWidgetClass,
863 					    frame, args, n);
864     size.request_mode = CWHeight;
865     XtQueryGeometry(editor->holiday, NULL, &size);
866 
867     n = 0;
868     XtSetArg(args[n], XmNpaneMinimum, size.height);
869     n++;
870     XtSetArg(args[n], XmNpaneMaximum, size.height);
871     n++;
872     XtSetValues(editor->holiday, args, n);
873 
874     n = 0;
875     XtSetArg(args[n], XmNfractionBase, 3);
876     n++;
877     controls = XtCreateManagedWidget("editorControls", xmFormWidgetClass,
878 				     frame, args, n);
879 
880     n = 0;
881     callbacks[0].callback = ExitEditor;
882     callbacks[0].closure = (XtPointer) editor;
883     XtSetArg(args[n], XmNactivateCallback, callbacks);
884     n++;
885     XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION);
886     n++;
887     XtSetArg(args[n], XmNleftPosition, 0);
888     n++;
889     XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION);
890     n++;
891     XtSetArg(args[n], XmNrightPosition, 1);
892     n++;
893 
894     editor->doneButton = XtCreateManagedWidget("doneButton",
895                                 xmPushButtonWidgetClass, controls, args, n);
896 
897     n = 0;
898     callbacks[0].callback = SaveText;
899     callbacks[0].closure = (XtPointer) editor;
900     XtSetArg(args[n], XmNactivateCallback, callbacks);
901     n++;
902     XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION);
903     n++;
904     XtSetArg(args[n], XmNleftPosition, 1);
905     n++;
906     XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION);
907     n++;
908     XtSetArg(args[n], XmNrightPosition, 2);
909     n++;
910 
911     editor->saveButton = XtCreateManagedWidget("saveButton",
912 				xmPushButtonWidgetClass, controls, args, n);
913 
914     n = 0;
915     callbacks[0].callback = ClearEntry;
916     callbacks[0].closure = (XtPointer) editor;
917     XtSetArg(args[n], XmNactivateCallback, callbacks);
918     n++;
919     XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION);
920     n++;
921     XtSetArg(args[n], XmNleftPosition, 2);
922     n++;
923     XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION);
924     n++;
925     XtSetArg(args[n], XmNrightPosition, 3);
926     n++;
927 
928     editor->clearEntry = XtCreateManagedWidget("clearEntry",
929 				xmPushButtonWidgetClass, controls, args, n);
930 
931     size.request_mode = CWHeight;
932     XtQueryGeometry(controls, NULL, &size);
933 
934     n = 0;
935     XtSetArg(args[n], XmNpaneMinimum, size.height);
936     n++;
937     XtSetArg(args[n], XmNpaneMaximum, size.height);
938     n++;
939     XtSetValues(controls, args, n);
940 
941     HideSashes(frame);
942     XtManageChild(frame);
943 
944     XtRealizeWidget(editor->shell);
945 
946     return editor;
947 
948 }
949 #endif
950 
951 /*
952  * ReadFile() - Returns true if it manages to read the file associated
953  * with editor.
954  */
955 
956 Boolean
ReadFile(editor)957 ReadFile(editor)
958     DayEditor       editor;
959 {
960     int             size;
961     Arg             args[10];
962     int             n;
963 
964     /*
965      * #ifdef ATHENA XtSetArg(args[0], XtNeditType, XawtextEdit); #else
966      * XtSetArg(args[0], XmNeditable, True); #endif
967      * XtSetValues(editor->editor, args, 1);
968      */
969 
970     bzero(editor->buffer, editor->bufSize);
971 
972     size = read_file(editor->filename, editor->buffer, editor->bufSize);
973 
974     if (size == -1)
975 	return False;
976     else if (size > editor->bufSize) {
977 	editor->buffer = XtRealloc(editor->buffer, size + 1);
978 	editor->bufSize = size + 1;
979 	size = read_file(editor->filename, editor->buffer, editor->bufSize);
980 	if (size == -1)
981 	    return False;
982     }
983 #define ALREADYOPEN "	** Editor Already Open! ** \n\n"
984 
985     n = 0;
986 #ifdef ATHENA
987     XtSetArg(args[n], XtNeditType, XawtextEdit);
988 #else
989     XtSetArg(args[n], XmNeditable, True);
990 #endif
991     if (already_open(editor->filename)) {
992 	static char    *sb_tmp;
993 
994 	sb_tmp = XtMalloc(editor->bufSize + strlen(ALREADYOPEN) + 1);
995 	strcpy(sb_tmp, ALREADYOPEN);
996 	strcat(sb_tmp, editor->buffer);
997 	XtFree(editor->buffer);
998 	editor->buffer = sb_tmp;
999 	editor->bufSize = editor->bufSize + strlen(ALREADYOPEN) + 1;
1000 #ifdef ATHENA
1001 	XtSetArg(args[n], XtNeditType, XawtextRead);
1002 	n++;
1003 #else
1004 	XtSetArg(args[n], XmNeditable, False);
1005 	n++;
1006 #endif
1007     }
1008     ChangeTextSource(editor, editor->buffer, GetHoliday(editor), False);
1009 
1010     /*
1011      * XtSetArg(args[n], XtNstring, editor->buffer); n++;
1012      */
1013     XtSetValues(editor->editor, args, n);
1014 
1015     return True;
1016 }
1017 
1018 /*
1019  * ChangeTextSource() - Changes the text in the dayeditor.
1020  */
1021 
1022 void
ChangeTextSource(editor,newtext,newhol,clear)1023 ChangeTextSource(editor, newtext, newhol, clear)
1024     DayEditor       editor;
1025     char           *newtext;
1026     char           *newhol;
1027     Boolean         clear;
1028 {
1029     Arg             args[10];
1030     int             n;
1031 #ifdef ATHENA
1032     Widget          old = XawTextGetSource(editor->editor);
1033     Widget          oldhol = XawTextGetSource(editor->holiday);
1034 #endif
1035 
1036     n = 0;
1037 #ifdef ATHENA
1038     XtSetArg(args[n], XtNstring, newtext);
1039     n++;
1040     XtSetArg(args[n], XtNlength, editor->bufSize);
1041     n++;
1042     XtSetArg(args[n], XtNeditType, XawtextEdit);
1043     n++;
1044     XtSetArg(args[n], XtNtype, XawAsciiString);
1045     n++;
1046 #ifdef XI18N
1047     XtSetArg(args[n], XtNuseStringInPlace, False);
1048     n++;
1049 #else
1050     XtSetArg(args[n], XtNuseStringInPlace, True);
1051     n++;
1052 #endif				/* XI18N */
1053     XawTextSetSource(editor->editor,
1054 #ifdef XI18N
1055 			(XtIsSubclass(old, multiSrcObjectClass) ?
1056 			 XtCreateWidget("textSource", multiSrcObjectClass,
1057 							editor->editor, args, n) :
1058 		     XtCreateWidget("textSource", asciiSrcObjectClass,
1059 							editor->editor, args, n) ),
1060 					 (XawTextPosition) 0);
1061 #else
1062 		     XtCreateWidget("textSource", asciiSrcObjectClass,
1063 			     editor->editor, args, n), (XawTextPosition) 0);
1064 #endif				/* XI18N */
1065     if (!clear) {
1066         XtSetArg(args[0], XtNstring, newhol);
1067         XtSetArg(args[1], XtNlength, strlen(newhol));
1068         XawTextSetSource(editor->holiday,
1069 #ifdef XI18N
1070 			    (XtIsSubclass(old, multiSrcObjectClass) ?
1071 				 XtCreateWidget("holSource", multiSrcObjectClass,
1072 								editor->holiday, args, n) :
1073 				 XtCreateWidget("holSource", asciiSrcObjectClass,
1074 								editor->holiday, args, n) ),
1075 						 (XawTextPosition) 0);
1076 #else
1077                  XtCreateWidget("holSource", asciiSrcObjectClass,
1078 					 editor->holiday, args, n), (XawTextPosition) 0);
1079 #endif				/* XI18N */
1080         XtDestroyWidget(oldhol);
1081     }
1082     XtDestroyWidget(old);
1083 #else
1084     XtSetArg(args[n], XmNeditable, True);
1085     n++;
1086     XtSetValues(editor->editor, args, n);
1087     XmTextSetString(editor->editor, newtext);
1088     if (!clear)
1089         if (strlen(newhol)) {
1090 	    XmTextSetString(editor->holiday, newhol);
1091             XtManageChild(editor->holiday);
1092         }
1093         else
1094             XtUnmanageChild(editor->holiday);
1095 #endif				/* ATHENA */
1096 }
1097 
1098 /*
1099  * StartEditor() - Pops up dayeditor.
1100  */
1101 
1102 void
StartEditor(editor)1103 StartEditor(editor)
1104     DayEditor       editor;
1105 {
1106 
1107     XtPopup(editor->shell, XtGrabNone);
1108 
1109 }
1110 
1111 /*
1112  * CloseEditor() - Pops down (and if needed, saves) dayeditor.
1113  */
1114 
1115 void
CloseEditors()1116 CloseEditors()
1117 {
1118     int             i;
1119     DayEditor       editor;
1120 
1121     if (editorList == NULL)
1122 	return;
1123 
1124     for (i = 1; i <= ListLength(editorList); i++) {
1125 	editor = GetEditorFromList(editorList, i);
1126 	if (editor->saved == False)
1127 	    SaveText(NULL, (XtPointer) editor, NULL);
1128     }
1129 }
1130 
1131 /*
1132  * read_file() - reads a file.
1133  */
1134 
1135 int
read_file(filename,buffer,size)1136 read_file(filename, buffer, size)
1137     char           *filename;
1138     char           *buffer;
1139     int             size;
1140 {
1141     int             fd, len;
1142     struct stat     sb;
1143 
1144     if ((fd = open(filename, O_RDONLY, 0666)) < 0) {
1145 	if (errno == ENOENT)
1146 	    return 0;
1147 	else {
1148 	    perror("xcalendar:open");
1149 	    return (-1);
1150 	}
1151     }
1152     if (fstat(fd, &sb) != 0) {
1153 	close(fd);
1154 	perror("xcalendar:fstat:");
1155 	return (-1);
1156     }
1157     if (sb.st_size == 0) {
1158 	unlink(filename);
1159 	return 0;
1160     }
1161     len = (size < sb.st_size) ? size : sb.st_size;
1162 
1163     if (read(fd, buffer, len) < len) {
1164 	close(fd);
1165 	fprintf(stderr, "Couldn't read all file %s\n", filename);
1166 	perror("xcalendar:read:");
1167 	return (-1);
1168     }
1169     close(fd);
1170 
1171     return sb.st_size;
1172 
1173 }
1174 
1175 /*
1176  * write_to_file() - writes to file.
1177  */
1178 
1179 int
write_to_file(filename,buffer,len)1180 write_to_file(filename, buffer, len)
1181     char           *filename;
1182     char           *buffer;
1183     int             len;
1184 {
1185     int             fd;
1186 
1187     if ((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0) {
1188 	perror("xcalendar:open");
1189 	return (-1);
1190     }
1191     if (len == 0) {
1192 	unlink(filename);
1193 	return 0;
1194     }
1195     if (write(fd, buffer, len) < len) {
1196 	fprintf(stderr, "Sorry couldn't write all file %s\n", filename);
1197 	perror("xcalendar:write:");
1198 	close(fd);
1199 	return (-1);
1200     }
1201     close(fd);
1202 
1203     return len;
1204 }
1205 
1206 /*
1207  * GetHoliday() - returns holiday text associated with editor.
1208  */
1209 
1210 char           *
GetHoliday(editor)1211 GetHoliday(editor)
1212     DayEditor       editor;
1213 {
1214     int             i;
1215     struct holiday *holi;
1216 
1217     for (i = 0; i < holilist->pos; i++) {
1218 	holi = *((Holiday *) holilist->list + i);
1219 	if ((holi->day == editor->day) &&
1220 	    (holi->month == editor->month) &&
1221 	    (holi->year == editor->year))
1222 	    return (holi->text);
1223     }
1224     return ("");
1225 }
1226