1 /*
2  * Create and destroy the recycle popup. Recycling an entry means to specify
3  * days on which it recurs; whenever its trigger time has passed, it it
4  * changed to the next trigger date (see recycle()). The popup is installed
5  * when the Recycle icon (looks like two round arrows) is pressed.
6  *
7  *	destroy_recycle_popup()
8  *	create_recycle_popup()
9  */
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <time.h>
14 #include <Xm/Xm.h>
15 #include <Xm/DialogS.h>
16 #include <Xm/Form.h>
17 #include <Xm/Frame.h>
18 #include <Xm/RowColumn.h>
19 #include <Xm/LabelP.h>
20 #include <Xm/LabelG.h>
21 #include <Xm/PushBP.h>
22 #include <Xm/PushBG.h>
23 #include <Xm/ToggleB.h>
24 #include <Xm/Text.h>
25 #include <Xm/Protocols.h>
26 #include "cal.h"
27 
28 static void done_callback	(Widget, int, XmToggleButtonCallbackStruct *);
29 static void wkday_callback	(Widget, int, XmToggleButtonCallbackStruct *);
30 static void nth_callback	(Widget, int, XmToggleButtonCallbackStruct *);
31 static void day_callback	(Widget, int, XmToggleButtonCallbackStruct *);
32 static void every_callback	(Widget, int, XmToggleButtonCallbackStruct *);
33 static void every_text_callback	(Widget, int, XmToggleButtonCallbackStruct *);
34 static void yearly_callback	(Widget, int, XmToggleButtonCallbackStruct *);
35 static void last_callback	(Widget, int, XmToggleButtonCallbackStruct *);
36 static void last_text_callback	(Widget, int, XmToggleButtonCallbackStruct *);
37 
38 extern Display		*display;	/* everybody uses the same server */
39 extern Widget		toplevel;	/* top-level shell for icon name */
40 extern struct edit	edit;		/* info about entry being edited */
41 extern struct config	config;		/* global configuration data */
42 extern Pixel		color[NCOLS];	/* colors: COL_* */
43 extern struct plist	*mainlist;	/* list of all schedule entries */
44 extern char		*weekday_name[];/* "Mon", "Tue", ... */
45 
46 static BOOL		have_shell;	/* message popup exists if TRUE */
47 static Widget		shell;		/* popup menu shell */
48 static Widget		nth_widget[7];	/* any, 1st..5th, last toggle buttons*/
49 static Widget		last;		/* last-on date text */
50 static Widget		last_toggle;	/* last-on date toggle button */
51 static Widget		every;		/* every n days text */
52 static Widget		every_toggle;	/* every n days toggle button */
53 static Widget		yearly_toggle;	/* every year togg�e button */
54 
55 
56 /*
57  * destroy a popup. Remove it from the screen, and destroy its widgets.
58  * It's too much trouble to keep them for next time.
59  */
60 
destroy_recycle_popup(void)61 void destroy_recycle_popup(void)
62 {
63 	char			*string;	/* contents of text widget */
64 
65 	if (have_shell && edit.editing) {
66 		if (edit.entry.rep_every) {
67 			string = XmTextGetString(every);
68 			edit.entry.rep_every = atoi(string) * 86400;
69 			if (edit.entry.rep_every < 0)
70 				edit.entry.rep_every = 0;
71 			XtFree(string);
72 		}
73 		if (edit.entry.rep_last) {
74 			string = XmTextGetString(last);
75 			edit.entry.rep_last =
76 				parse_datestring(string, edit.entry.time);
77 			XtFree(string);
78 		}
79 		edit.changed = TRUE;
80 		edit.entry.suspended = FALSE;
81 		print_pixmap(edit.menu->entry[edit.y][SC_RECYCLE], PIC_RECYCLE,
82 			     edit.entry.rep_yearly || edit.entry.rep_days ||
83 			     edit.entry.rep_every  || edit.entry.rep_weekdays);
84 	}
85 	if (have_shell) {
86 		XtPopdown(shell);
87 		XTDESTROYWIDGET(shell);
88 		have_shell = FALSE;
89 		confirm_new_entry();
90 	}
91 }
92 
93 
94 /*
95  * create a recycle popup as a separate application shell. The popup is
96  * initialized with data from edit.entry.
97  */
98 
99 static char *nth_name[] = { "every...", "first...", "second...",
100 			    "third...", "fourth...", "fifth...", "last..." };
101 
create_recycle_popup(void)102 void create_recycle_popup(void)
103 {
104 	Widget		frame, frame2, form, form2, rowcol, w;
105 	int		day;		/* weekdays and month days */
106 	char		buf[10];	/* month day names */
107 	struct entry	*ep = &edit.entry;
108 	Arg		args[20];
109 	int		n;
110 	Atom		closewindow;
111 
112 	destroy_recycle_popup();
113 
114 	n = 0;
115 	XtSetArg(args[n], XmNdeleteResponse,	XmDO_NOTHING);		n++;
116 	XtSetArg(args[n], XmNiconic,		False);			n++;
117 	shell = XtCreatePopupShell(_("Schedule Recycler"),
118 			applicationShellWidgetClass, toplevel, args, n);
119 #	ifdef EDITRES
120 	XtAddEventHandler(shell, (EventMask)0, TRUE,
121  			_XEditResCheckMessages, NULL);
122 #	endif
123 	set_icon(shell, 1);
124 	form = XtCreateManagedWidget("cycform1", xmFormWidgetClass,
125 			shell, NULL, 0);
126 	XtAddCallback(form, XmNhelpCallback, (XtCallbackProc)
127 			help_callback, (XtPointer)"cyc");
128 							/*-- buttons --*/
129 	n = 0;
130 	XtSetArg(args[n], XmNbottomAttachment,	XmATTACH_FORM);		n++;
131 	XtSetArg(args[n], XmNbottomOffset,	8);			n++;
132 	XtSetArg(args[n], XmNrightAttachment,	XmATTACH_FORM);		n++;
133 	XtSetArg(args[n], XmNrightOffset,	8);			n++;
134 	XtSetArg(args[n], XmNleftOffset,	32);			n++;
135 	XtSetArg(args[n], XmNwidth,		80);			n++;
136 	w = XtCreateManagedWidget(_("Done"), xmPushButtonWidgetClass,
137 			form, args, n);
138 	XtAddCallback(w, XmNactivateCallback, (XtCallbackProc)
139 			done_callback, (XtPointer)(size_t)0);
140 	XtAddCallback(w, XmNhelpCallback,     (XtCallbackProc)
141 			help_callback, (XtPointer)"cyc_done");
142 
143 	n = 0;
144 	XtSetArg(args[n], XmNbottomAttachment,	XmATTACH_FORM);		n++;
145 	XtSetArg(args[n], XmNbottomOffset,	8);			n++;
146 	XtSetArg(args[n], XmNrightAttachment,	XmATTACH_WIDGET);	n++;
147 	XtSetArg(args[n], XmNrightWidget,	w);			n++;
148 	XtSetArg(args[n], XmNrightOffset,	8);			n++;
149 	XtSetArg(args[n], XmNwidth,		80);			n++;
150 	w = XtCreateManagedWidget(_("Help"), xmPushButtonWidgetClass,
151 			form, args, n);
152 	XtAddCallback(w, XmNactivateCallback, (XtCallbackProc)
153 			help_callback, (XtPointer)"cyc");
154 	XtAddCallback(w, XmNhelpCallback,     (XtCallbackProc)
155 			help_callback, (XtPointer)"cyc");
156 							/*-- last on --*/
157 	n = 0;
158 	XtSetArg(args[n], XmNbottomAttachment,	XmATTACH_WIDGET);	n++;
159 	XtSetArg(args[n], XmNbottomWidget,	w);			n++;
160 	XtSetArg(args[n], XmNbottomOffset,	20);			n++;
161 	XtSetArg(args[n], XmNleftAttachment,	XmATTACH_FORM);		n++;
162 	XtSetArg(args[n], XmNleftOffset,	8);			n++;
163 	XtSetArg(args[n], XmNrightAttachment,	XmATTACH_FORM);		n++;
164 	XtSetArg(args[n], XmNrightOffset,	8);			n++;
165 	XtSetArg(args[n], XmNshadowType,	XmSHADOW_ETCHED_IN);	n++;
166 	frame = XtCreateManagedWidget("", xmFrameWidgetClass,
167 			form, args, n);
168 	form2 = XtCreateManagedWidget("cycform2", xmFormWidgetClass,
169 			frame, NULL, 0);
170 	XtAddCallback(form2, XmNhelpCallback, (XtCallbackProc)
171 			help_callback, (XtPointer)"cyc_last");
172 	n = 0;
173 	XtSetArg(args[n], XmNselectColor,	color[COL_TOGGLE]);	n++;
174 	XtSetArg(args[n], XmNtopAttachment,	XmATTACH_FORM);		n++;
175 	XtSetArg(args[n], XmNbottomAttachment,	XmATTACH_FORM);		n++;
176 	XtSetArg(args[n], XmNleftAttachment,	XmATTACH_FORM);		n++;
177 	XtSetArg(args[n], XmNleftOffset,	8);			n++;
178 	XtSetArg(args[n], XmNhighlightThickness,0);			n++;
179 	XtSetArg(args[n], XmNset,		ep->rep_last != 0);	n++;
180 	last_toggle = XtCreateManagedWidget(_("Last day: stop repeating on"),
181 			xmToggleButtonWidgetClass,
182 			form2, args, n);
183 	XtAddCallback(last_toggle, XmNvalueChangedCallback, (XtCallbackProc)
184 			last_callback, (XtPointer)(size_t)0);
185 
186 	n = 0;
187 	XtSetArg(args[n], XmNtopAttachment,	XmATTACH_FORM);		n++;
188 	XtSetArg(args[n], XmNtopOffset,		4);			n++;
189 	XtSetArg(args[n], XmNbottomAttachment,	XmATTACH_FORM);		n++;
190 	XtSetArg(args[n], XmNbottomOffset,	4);			n++;
191 	XtSetArg(args[n], XmNleftAttachment,	XmATTACH_WIDGET);	n++;
192 	XtSetArg(args[n], XmNleftWidget,	last_toggle);		n++;
193 	XtSetArg(args[n], XmNleftOffset,	8);			n++;
194 	XtSetArg(args[n], XmNwidth,		140);			n++;
195 	XtSetArg(args[n], XmNrecomputeSize,	False);			n++;
196 	XtSetArg(args[n], XmNpendingDelete,	True);			n++;
197 	XtSetArg(args[n], XmNhighlightThickness,0);			n++;
198 	XtSetArg(args[n], XmNbackground,	color[COL_TEXTBACK]);	n++;
199 	last = XtCreateManagedWidget("", xmTextWidgetClass,
200 			form2, args, n);
201 	XtAddCallback(last, XmNactivateCallback, (XtCallbackProc)
202 			last_text_callback, (XtPointer)NULL);
203 
204 							/*-- repeat every --*/
205 	n = 0;
206 	XtSetArg(args[n], XmNbottomAttachment,	XmATTACH_WIDGET);	n++;
207 	XtSetArg(args[n], XmNbottomWidget,	frame);			n++;
208 	XtSetArg(args[n], XmNbottomOffset,	8);			n++;
209 	XtSetArg(args[n], XmNleftAttachment,	XmATTACH_FORM);		n++;
210 	XtSetArg(args[n], XmNleftOffset,	8);			n++;
211 	XtSetArg(args[n], XmNrightAttachment,	XmATTACH_FORM);		n++;
212 	XtSetArg(args[n], XmNrightOffset,	8);			n++;
213 	XtSetArg(args[n], XmNshadowType,	XmSHADOW_ETCHED_IN);	n++;
214 	frame = XtCreateManagedWidget("", xmFrameWidgetClass,
215 			form, args, n);
216 	form2 = XtCreateManagedWidget("cycform3", xmFormWidgetClass,
217 			frame, NULL, 0);
218 	XtAddCallback(form2, XmNhelpCallback, (XtCallbackProc)
219 			help_callback, (XtPointer)"cyc_every");
220 
221 	n = 0;
222 	XtSetArg(args[n], XmNselectColor,	color[COL_TOGGLE]);	n++;
223 	XtSetArg(args[n], XmNtopAttachment,	XmATTACH_FORM);		n++;
224 	XtSetArg(args[n], XmNbottomAttachment,	XmATTACH_FORM);		n++;
225 	XtSetArg(args[n], XmNleftAttachment,	XmATTACH_FORM);		n++;
226 	XtSetArg(args[n], XmNleftOffset,	8);			n++;
227 	XtSetArg(args[n], XmNhighlightThickness,0);			n++;
228 	XtSetArg(args[n], XmNset,		ep->rep_every != 0);	n++;
229 	every_toggle = XtCreateManagedWidget(_("Repeat every"),
230 			xmToggleButtonWidgetClass,
231 			form2, args, n);
232 	XtAddCallback(every_toggle, XmNvalueChangedCallback, (XtCallbackProc)
233 			every_callback, (XtPointer)(size_t)0);
234 
235 	n = 0;
236 	XtSetArg(args[n], XmNtopAttachment,	XmATTACH_FORM);		n++;
237 	XtSetArg(args[n], XmNtopOffset,		4);			n++;
238 	XtSetArg(args[n], XmNbottomAttachment,	XmATTACH_FORM);		n++;
239 	XtSetArg(args[n], XmNbottomOffset,	4);			n++;
240 	XtSetArg(args[n], XmNleftAttachment,	XmATTACH_WIDGET);	n++;
241 	XtSetArg(args[n], XmNleftWidget,	every_toggle);		n++;
242 	XtSetArg(args[n], XmNleftOffset,	8);			n++;
243 	XtSetArg(args[n], XmNwidth,		60);			n++;
244 	XtSetArg(args[n], XmNrecomputeSize,	False);			n++;
245 	XtSetArg(args[n], XmNpendingDelete,	True);			n++;
246 	XtSetArg(args[n], XmNhighlightThickness,0);			n++;
247 	XtSetArg(args[n], XmNbackground,	color[COL_TEXTBACK]);	n++;
248 	every = XtCreateManagedWidget("", xmTextWidgetClass,
249 			form2, args, n);
250 	XtAddCallback(every, XmNactivateCallback, (XtCallbackProc)
251 			every_text_callback, (XtPointer)NULL);
252 
253 	n = 0;
254 	XtSetArg(args[n], XmNtopAttachment,	XmATTACH_FORM);		n++;
255 	XtSetArg(args[n], XmNbottomAttachment,	XmATTACH_FORM);		n++;
256 	XtSetArg(args[n], XmNleftAttachment,	XmATTACH_WIDGET);	n++;
257 	XtSetArg(args[n], XmNleftWidget,	every);			n++;
258 	XtSetArg(args[n], XmNleftOffset,	8);			n++;
259 	XtSetArg(args[n], XmNhighlightThickness,0);			n++;
260 	w = XtCreateManagedWidget(_("days"), xmLabelWidgetClass,
261 			form2, args, n);
262 
263 							/*-- yearly --*/
264 	n = 0;
265 	XtSetArg(args[n], XmNselectColor,	color[COL_TOGGLE]);	n++;
266 	XtSetArg(args[n], XmNtopAttachment,	XmATTACH_FORM);		n++;
267 	XtSetArg(args[n], XmNbottomAttachment,	XmATTACH_FORM);		n++;
268 	XtSetArg(args[n], XmNleftAttachment,	XmATTACH_WIDGET);	n++;
269 	XtSetArg(args[n], XmNleftWidget,	w);			n++;
270 	XtSetArg(args[n], XmNleftOffset,	40);			n++;
271 	XtSetArg(args[n], XmNhighlightThickness,0);			n++;
272 	XtSetArg(args[n], XmNset,		ep->rep_yearly);	n++;
273 	yearly_toggle = XtCreateManagedWidget(_("Repeat every year"),
274 			xmToggleButtonWidgetClass,
275 			form2, args, n);
276 	XtAddCallback(yearly_toggle, XmNvalueChangedCallback, (XtCallbackProc)
277 			yearly_callback, (XtPointer)(size_t)0);
278 	XtAddCallback(yearly_toggle, XmNhelpCallback, (XtCallbackProc)
279 			help_callback, (XtPointer)"cyc_yearly");
280 
281 							/*-- weekdays --*/
282 	n = 0;
283 	XtSetArg(args[n], XmNtopAttachment,	XmATTACH_FORM);		n++;
284 	XtSetArg(args[n], XmNtopOffset,		8);			n++;
285 	XtSetArg(args[n], XmNbottomAttachment,	XmATTACH_WIDGET);	n++;
286 	XtSetArg(args[n], XmNbottomWidget,	frame);			n++;
287 	XtSetArg(args[n], XmNbottomOffset,	8);			n++;
288 	XtSetArg(args[n], XmNleftAttachment,	XmATTACH_FORM);		n++;
289 	XtSetArg(args[n], XmNleftOffset,	8);			n++;
290 	XtSetArg(args[n], XmNshadowType,	XmSHADOW_ETCHED_IN);	n++;
291 	frame2 = XtCreateManagedWidget("", xmFrameWidgetClass,
292 			form, args, n);
293 	form2 = XtCreateManagedWidget("cycform4", xmFormWidgetClass,
294 			frame2, NULL, 0);
295 	XtAddCallback(form2, XmNhelpCallback, (XtCallbackProc)
296 			help_callback, (XtPointer)"cyc_weekdays");
297 
298 	n = 0;
299 	XtSetArg(args[n], XmNtopAttachment,	XmATTACH_FORM);		n++;
300 	XtSetArg(args[n], XmNtopOffset,		8);			n++;
301 	XtSetArg(args[n], XmNleftAttachment,	XmATTACH_FORM);		n++;
302 	XtSetArg(args[n], XmNleftOffset,	8);			n++;
303 	w = XtCreateManagedWidget(_("Repeat on"), xmLabelWidgetClass,
304 			form2, args, n);
305 	n = 0;
306 	XtSetArg(args[n], XmNtopAttachment,	XmATTACH_FORM);		n++;
307 	XtSetArg(args[n], XmNtopOffset,		8);			n++;
308 	XtSetArg(args[n], XmNleftAttachment,	XmATTACH_WIDGET);	n++;
309 	XtSetArg(args[n], XmNleftWidget,	w);			n++;
310 	XtSetArg(args[n], XmNleftOffset,	8);			n++;
311 	XtSetArg(args[n], XmNspacing,		4);			n++;
312 	rowcol = XtCreateManagedWidget("", xmRowColumnWidgetClass,
313 			form2, args, n);
314 	for (day=0; day < 7; day++) {
315 	   BOOL on = day==0 ? !(ep->rep_weekdays & 0x3f00)
316 			    :  (ep->rep_weekdays & 0x0080 << day) != 0;
317 	   n = 0;
318 	   XtSetArg(args[n], XmNselectColor,	color[COL_TOGGLE]);	n++;
319 	   XtSetArg(args[n], XmNhighlightThickness,0);			n++;
320 	   XtSetArg(args[n], XmNset,		on);			n++;
321 	   nth_widget[day] = XtCreateManagedWidget(_(nth_name[day]),
322 	  		xmToggleButtonWidgetClass,
323 			rowcol, args, n);
324 	   XtAddCallback(nth_widget[day], XmNvalueChangedCallback,
325 			(XtCallbackProc)nth_callback, (XtPointer)(size_t)day);
326 	}
327 	n = 0;
328 	XtSetArg(args[n], XmNtopAttachment,	XmATTACH_FORM);		n++;
329 	XtSetArg(args[n], XmNtopOffset,		8);			n++;
330 	XtSetArg(args[n], XmNleftAttachment,	XmATTACH_WIDGET);	n++;
331 	XtSetArg(args[n], XmNleftWidget,	rowcol);		n++;
332 	XtSetArg(args[n], XmNleftOffset,	8);			n++;
333 	XtSetArg(args[n], XmNspacing,		4);			n++;
334 	rowcol = XtCreateManagedWidget("", xmRowColumnWidgetClass,
335 			form2, args, n);
336 	for (day=0; day < 7; day++) {
337 	   int d = config.sunday_first ? day : (day+1)%7;
338 	   BOOL on = (ep->rep_weekdays & (1<<d)) != 0;
339 	   n = 0;
340 	   XtSetArg(args[n], XmNselectColor,	color[COL_TOGGLE]);	n++;
341 	   XtSetArg(args[n], XmNhighlightThickness,0);			n++;
342 	   XtSetArg(args[n], XmNset,		on);			n++;
343 	   w = XtCreateManagedWidget(_(weekday_name[(d+6)%7]),
344 	  		xmToggleButtonWidgetClass,
345 			rowcol, args, n);
346 	   XtAddCallback(w, XmNvalueChangedCallback, (XtCallbackProc)
347 			wkday_callback, (XtPointer)(size_t)d);
348 	}
349 
350 							/*-- month days --*/
351 	n = 0;
352 	XtSetArg(args[n], XmNtopAttachment,	XmATTACH_FORM);		n++;
353 	XtSetArg(args[n], XmNtopOffset,		8);			n++;
354 	XtSetArg(args[n], XmNbottomAttachment,	XmATTACH_WIDGET);	n++;
355 	XtSetArg(args[n], XmNbottomWidget,	frame);			n++;
356 	XtSetArg(args[n], XmNbottomOffset,	8);			n++;
357 	XtSetArg(args[n], XmNleftAttachment,	XmATTACH_WIDGET);	n++;
358 	XtSetArg(args[n], XmNleftWidget,	frame2);		n++;
359 	XtSetArg(args[n], XmNleftOffset,	8);			n++;
360 	XtSetArg(args[n], XmNrightAttachment,	XmATTACH_FORM);		n++;
361 	XtSetArg(args[n], XmNrightOffset,	8);			n++;
362 	XtSetArg(args[n], XmNshadowType,	XmSHADOW_ETCHED_IN);	n++;
363 	frame2 = XtCreateManagedWidget("", xmFrameWidgetClass,
364 			form, args, n);
365 	form2 = XtCreateManagedWidget("cycform5", xmFormWidgetClass,
366 			frame2, NULL, 0);
367 	XtAddCallback(form2, XmNhelpCallback, (XtCallbackProc)
368 			help_callback, (XtPointer)"cyc_days");
369 
370 	n = 0;
371 	XtSetArg(args[n], XmNtopAttachment,	XmATTACH_FORM);		n++;
372 	XtSetArg(args[n], XmNtopOffset,		8);			n++;
373 	XtSetArg(args[n], XmNleftAttachment,	XmATTACH_FORM);		n++;
374 	XtSetArg(args[n], XmNleftOffset,	8);			n++;
375 	w = XtCreateManagedWidget(_("Repeat on the"), xmLabelWidgetClass,
376 			form2, args, n);
377 	n = 0;
378 	XtSetArg(args[n], XmNtopAttachment,	XmATTACH_FORM);		n++;
379 	XtSetArg(args[n], XmNtopOffset,		8);			n++;
380 	XtSetArg(args[n], XmNleftAttachment,	XmATTACH_WIDGET);	n++;
381 	XtSetArg(args[n], XmNleftWidget,	w);			n++;
382 	XtSetArg(args[n], XmNleftOffset,	8);			n++;
383 	XtSetArg(args[n], XmNpacking,		XmPACK_COLUMN);		n++;
384 	XtSetArg(args[n], XmNnumColumns,	4);			n++;
385 	rowcol = XtCreateManagedWidget("", xmRowColumnWidgetClass,
386 			form2, args, n);
387 	for (day=1; day <= 32; day++) {
388 	   BOOL on = (ep->rep_days & (1<<(day&31))) != 0;
389 	   if (day == 32)
390 		strcpy(buf, _("Last"));
391 	   else
392 		sprintf(buf, "%d%s", day, (day%10)==1 && day!=11 ? _("st") :
393 					  (day%10)==2 && day!=12 ? _("nd") :
394 					  (day%10)==3 && day!=13 ? _("rd") :
395 					 			   _("th"));
396 	   n = 0;
397 	   XtSetArg(args[n], XmNselectColor,	color[COL_TOGGLE]);	n++;
398 	   XtSetArg(args[n], XmNhighlightThickness,0);			n++;
399 	   XtSetArg(args[n], XmNset,		on);			n++;
400 	   w = XtCreateManagedWidget(buf, xmToggleButtonWidgetClass,
401 			rowcol, args, n);
402 	   XtAddCallback(w, XmNvalueChangedCallback, (XtCallbackProc)
403 	  		day_callback, (XtPointer)(size_t)day);
404 	}
405 
406 	XtPopup(shell, XtGrabNone);
407 	closewindow = XmInternAtom(display, "WM_DELETE_WINDOW", False);
408 	XmAddWMProtocolCallback(shell, closewindow, (XtCallbackProc)
409 			done_callback, (XtPointer)shell);
410 
411 	if (ep->rep_last) {
412 		char *space, *text = mkdatestring(ep->rep_last);
413 		if ((space = strchr(text, ' ')))
414 			text = space+1;
415 		print_text_button(last, text);
416 	}
417 	if (ep->rep_every)
418 		print_text_button(every, "%d", ep->rep_every/86400);
419 	have_shell = TRUE;
420 }
421 
422 
423 /*-------------------------------------------------- callbacks --------------*/
424 /*
425  * All of these routines are direct X callbacks.
426  */
427 
428 /*ARGSUSED*/
done_callback(UNUSED Widget widget,UNUSED int item,UNUSED XmToggleButtonCallbackStruct * data)429 static void done_callback(
430 	UNUSED Widget			widget,
431 	UNUSED int			item,
432 	UNUSED XmToggleButtonCallbackStruct*data)
433 {
434 	destroy_recycle_popup();
435 }
436 
437 
438 /*ARGSUSED*/
wkday_callback(UNUSED Widget widget,int item,XmToggleButtonCallbackStruct * data)439 static void wkday_callback(
440 	UNUSED Widget			widget,
441 	int				item,
442 	XmToggleButtonCallbackStruct	*data)
443 {
444 	if (data->set)
445 		edit.entry.rep_weekdays |= 1 << item;
446 	else
447 		edit.entry.rep_weekdays &= ~(1 << item);
448 	edit.changed = TRUE;
449 	sensitize_edit_buttons();
450 }
451 
452 
453 /*ARGSUSED*/
nth_callback(UNUSED Widget widget,int item,XmToggleButtonCallbackStruct * data)454 static void nth_callback(
455 	UNUSED Widget			widget,
456 	int				item,
457 	XmToggleButtonCallbackStruct	*data)
458 {
459 	struct entry			*ep = &edit.entry;
460 	int				i;
461 	Arg				args;
462 
463 	if (item)
464 		if (data->set)
465 			ep->rep_weekdays |= 0x0080 << item;
466 		else
467 			ep->rep_weekdays &= ~(0x0080 << item);
468 	else
469 			ep->rep_weekdays &= ~0x3f00;
470 	for (i=0; i < 7; i++) {
471 		XtSetArg(args, XmNset, i ?  (ep->rep_weekdays & 0x0080<<i) != 0
472 					 : !(ep->rep_weekdays & 0x3f00));
473 		XtSetValues(nth_widget[i], &args, 1);
474 	}
475 	edit.changed = TRUE;
476 	sensitize_edit_buttons();
477 }
478 
479 
480 /*ARGSUSED*/
day_callback(UNUSED Widget widget,int item,XmToggleButtonCallbackStruct * data)481 static void day_callback(
482 	UNUSED Widget			widget,
483 	int				item,
484 	XmToggleButtonCallbackStruct	*data)
485 {
486 	if (data->set)
487 		edit.entry.rep_days |= 1 << (item&31);
488 	else
489 		edit.entry.rep_days &= ~(1 << (item&31));
490 	edit.changed = TRUE;
491 	sensitize_edit_buttons();
492 }
493 
494 
495 /*ARGSUSED*/
every_callback(UNUSED Widget widget,UNUSED int item,XmToggleButtonCallbackStruct * data)496 static void every_callback(
497 	UNUSED Widget			widget,
498 	UNUSED int			item,
499 	XmToggleButtonCallbackStruct	*data)
500 {
501 	if (data->set) {
502 		XmProcessTraversal(every, XmTRAVERSE_CURRENT);
503 		edit.entry.rep_every = 86400;
504 		print_text_button(every, "1");
505 	} else {
506 		edit.entry.rep_every = 0;
507 		print_text_button(every, "");
508 	}
509 	edit.changed = TRUE;
510 	sensitize_edit_buttons();
511 }
512 
513 
514 /*ARGSUSED*/
every_text_callback(Widget widget,UNUSED int item,UNUSED XmToggleButtonCallbackStruct * data)515 static void every_text_callback(
516 	Widget				widget,
517 	UNUSED int			item,
518 	UNUSED XmToggleButtonCallbackStruct*data)
519 {
520 	char				*text = XmTextGetString(widget);
521 	Arg				args;
522 
523 	edit.entry.rep_every = atoi(text) * 86400;
524 	if (edit.entry.rep_every < 0)
525 		edit.entry.rep_every = 0;
526 	XtSetArg(args, XmNset, edit.entry.rep_every > 0);
527 	XtSetValues(every_toggle, &args, 1);
528 	XtFree(text);
529 }
530 
531 
532 /*ARGSUSED*/
yearly_callback(UNUSED Widget widget,UNUSED int item,XmToggleButtonCallbackStruct * data)533 static void yearly_callback(
534 	UNUSED Widget			widget,
535 	UNUSED int			item,
536 	XmToggleButtonCallbackStruct	*data)
537 {
538 	edit.entry.rep_yearly = data->set;
539 	edit.changed = TRUE;
540 	sensitize_edit_buttons();
541 }
542 
543 
544 /*ARGSUSED*/
last_callback(UNUSED Widget widget,UNUSED int item,XmToggleButtonCallbackStruct * data)545 static void last_callback(
546 	UNUSED Widget			widget,
547 	UNUSED int			item,
548 	XmToggleButtonCallbackStruct	*data)
549 {
550 	if (data->set) {
551 		char *p, date[40];
552 		XmProcessTraversal(last, XmTRAVERSE_CURRENT);
553 		edit.entry.rep_last = edit.entry.time -
554 				      edit.entry.time % 86400 + 86400;
555 		strcpy(date, mkdatestring(edit.entry.rep_last));
556 		p = strchr(date, ' ');
557 		print_text_button(last, p ? p+1 : date);
558 	} else {
559 		edit.entry.rep_last = 0;
560 		print_text_button(last, "");
561 	}
562 	edit.changed = TRUE;
563 	sensitize_edit_buttons();
564 }
565 
566 
567 /*ARGSUSED*/
last_text_callback(Widget widget,UNUSED int item,UNUSED XmToggleButtonCallbackStruct * data)568 static void last_text_callback(
569 	Widget				widget,
570 	UNUSED int			item,
571 	UNUSED XmToggleButtonCallbackStruct*data)
572 {
573 	char				*text = XmTextGetString(widget);
574 	Arg				args;
575 
576 	edit.entry.rep_last = parse_datestring(text, edit.entry.time);
577 	if (edit.entry.rep_last < edit.entry.time + 86400-1) {
578 		char *p, date[40];
579 		strcpy(date, mkdatestring(edit.entry.time));
580 		p = strchr(date, ' ');
581 		print_text_button(last, p ? p+1 : date);
582 		create_error_popup(widget, 0,
583 			_("The new last-trigger date is before the\n"\
584 			  "first-trigger date, %s. Ignored."), date);
585 		edit.entry.rep_last = edit.entry.time;
586 	}
587 	XtSetArg(args, XmNset, edit.entry.rep_last > 0);
588 	XtSetValues(last_toggle, &args, 1);
589 	XtFree(text);
590 }
591