1 /*
2    XMascot Ver 2.6
3    Copyright(c) 1996,1997 Go Watanabe     go@cclub.tutcc.tut.ac.jp
4                           Tsuyoshi IIda   iida@cclub.tutcc.tut.ac.jp
5 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <ctype.h>
9 #include <math.h>
10 #include <signal.h>
11 #include <string.h>
12 
13 #include <sys/types.h>
14 #include <sys/wait.h>
15 #include <unistd.h>
16 
17 #include <X11/Xlib.h>
18 #include <X11/Xutil.h>
19 #include <X11/Intrinsic.h>
20 #include <X11/StringDefs.h>
21 #include <X11/Shell.h>
22 #include <X11/Xmu/Converters.h>
23 #include <X11/Xlocale.h>
24 
25 #include "CascadeMenu.h"
26 #include "xmascot.h"
27 
28 /* ������ɥ�����°�� */
29 double          disp_dpm;
30 Atom            wm_protocols[2];
31 
32 XtAppContext    app;
33 
34 /* ���������å� */
35 Widget          top, mascot;
36 Widget         *chain = NULL;
37 #ifdef BIFF
38 Widget          biff;
39 #endif
40 
41 /* �꥽���� */
42 extern AppData  adat;		/* �꥽�����ǡ�����¤��     */
43 
44 /* �ѹ���˥塼�Ѥ�����ޡ��� */
45 Pixmap          select_mark;
46 #include "xbmfile/select.xbm"
47 
48 /* �������� */
49 Pixmap          icon;
50 #include "xbmfile/icon.xbm"
51 
52 /* ���ޥ�ɥ饤���ץ���� */
53 static XrmOptionDescRec options[] = {
54 	{"-verbose", ".verbose", XrmoptionNoArg, "True"},
55 	{"-gravity", ".gravity", XrmoptionSepArg, NULL},
56 	{"-chainlength", ".chainLen", XrmoptionSepArg, NULL},
57 	{"-damping", ".dampCoeff", XrmoptionSepArg, NULL},
58 	{"-degree", ".degree", XrmoptionSepArg, NULL},
59 	{"-menuno", ".menuNo", XrmoptionSepArg, NULL},
60 	{"-no", ".mascotNo", XrmoptionSepArg, NULL},
61 	{"-magnify", ".magnifyBase", XrmoptionSepArg, NULL},
62 	{"-pinpat", ".pinPattern", XrmoptionSepArg, NULL},
63 	{"-random", ".random", XrmoptionNoArg, "True"},
64 	{"-changetime", ".changeTime", XrmoptionSepArg, NULL},
65 	{"-allmenu", ".allMenu", XrmoptionNoArg, "True"},
66 	{"-chainnum", ".chainNum", XrmoptionSepArg, NULL},
67 #ifdef USE_CHAINPAT
68 	{"-chainpat", ".chainPattern", XrmoptionSepArg, NULL},
69 #endif
70 	{"-searchpath", ".search", XrmoptionSepArg, NULL},
71 #ifdef SOUND
72 	{"-soundcmd", ".soundCommand", XrmoptionSepArg, NULL},
73 	{"-soundstart", ".masDatX.startSnd", XrmoptionSepArg, NULL},
74 	{"-soundclick", ".masDatX.clickSnd", XrmoptionSepArg, NULL},
75 	{"-soundend", ".masDatX.endSnd", XrmoptionSepArg, NULL},
76 #ifdef BIFF
77 	{"-soundmail", ".masDatX.mailSnd", XrmoptionSepArg, NULL},
78 #endif				/* BIFF */
79 #endif				/* SOUND */
80 #ifdef BIFF
81 	{"-nobiff", ".biff", XrmoptionNoArg, "False"},
82 	{"-update", ".update", XrmoptionSepArg, NULL},
83 	{"-noonce", ".biffOnce", XrmoptionNoArg, "False"},
84 	{"-biffcmd", ".biffCmd", XrmoptionSepArg, NULL},
85 	{"-biffpat", ".biffPattern", XrmoptionSepArg, NULL},
86 	{"-biffpos", ".MasDat.biffPos", XrmoptionSepArg, NULL},
87 #ifdef BIFF_LIST
88 	{"-biffgeometry", ".biffList.geometry", XrmoptionSepArg, NULL},
89 	{"-bifffilter", ".biffFilter", XrmoptionSepArg, NULL},
90 	{"-popdowntime", ".biffPopdown", XrmoptionSepArg, NULL},
91 	{"-nobifflists", ".biffPopdown", XrmoptionNoArg, "0"},
92 #endif
93 #ifdef YOUBIN
94 	{"-noyoubin", ".youbin", XrmoptionNoArg, "False"},
95 	{"-server", ".server", XrmoptionSepArg, NULL},
96 #endif
97 #endif
98 #ifdef SHADOW
99 	{"-shadow", ".shadow", XrmoptionSepArg, NULL},
100 	{"-noshadow", ".shadow", XrmoptionNoArg, "0"},
101 #endif
102 	{"-drawtiming", ".drawTiming", XrmoptionSepArg, NULL},
103 };
104 
105 /* �ԥ�Υǥե���ȥ�������� */
106 String          trans =
107 "<Message>WM_PROTOCOLS: quitmsg()\n"
108 "<MapNotify>: map()\n"
109 "<UnmapNotify>: unmap()\n"
110 "<ConfigureNotify>: config()\n"
111 "<Btn1Down>: press()\n"
112 "<Btn1Up>: release_pin()\n"
113 "<Btn1Motion>: motion_pin()\n"
114 "<Btn3Down>: XawPositionSimpleMenu(popup) XtMenuPopup(popup)";
115 
116 /* �ޥ����åȤΥǥե���ȥ�������� */
117 String          trans_mas =
118 "<Btn1Down>: press()\n"
119 "<Btn1Up>: release_mascot()\n"
120 "<Btn1Motion>: motion_mascot()\n"
121 "<Btn3Down>: snd_click()";
122 
123 #ifdef BIFF
124 #ifdef BIFF_LIST
125 String          trans_biff = "<Btn1Down>: showbiff()";
126 #endif
127 #endif
128 
129 /* ���������ꥹ�� */
130 static XtActionsRec actions[] = {
131 	{"map", MapWin},
132 	{"unmap", UnMapWin},
133 	{"config", ConfigWin},
134 	{"press", Press},
135 	{"release_pin", ReleasePin},
136 	{"release_mascot", ReleaseMascot},
137 	{"motion_pin", MotionPin},
138 	{"motion_mascot", MotionMascot},
139 
140 	{"quit", Quit},
141 	{"quitmsg", QuitMsg},
142 	{"change", ChangeMascot},
143 	{"chg_file", ChangeMascotFile},
144 	{"chg_next", ChangeMascotNext},
145 	{"chg_next_all", ChangeMascotNextAll},
146 	{"chg_random", ChangeMascotRandom},
147 	{"chg_random_all", ChangeMascotRandomAll},
148 	{"start_move", StartMove},
149 
150 	{"sound", Sound},
151 	{"snd_start", SoundStart},
152 	{"snd_click", SoundClick},
153 	{"snd_end", SoundEnd},
154 	{"snd_mail", SoundMail},
155 
156 	{"system", System},
157 	{"chg_param", ChangeParam},
158 	{"bell", Bell},
159 #ifdef BIFF
160 #ifdef BIFF_LIST
161 	{"showbiff", ShowBiffNotice},
162 	{"biffnopdown", BiffEnter},
163 #endif
164 #endif
165 };
166 
167 /* RGBʸ���� -> long �Υ���С��� */
168 static Boolean
XtRgbCvt(Display * dpy,XrmValue * args,Cardinal * num,XrmValue * from,XrmValue * to,XtPointer * converter_data)169 XtRgbCvt(Display * dpy, XrmValue * args, Cardinal * num,
170 	 XrmValue * from, XrmValue * to, XtPointer * converter_data)
171 {
172 	char            str[20];
173 	static int     rgb;
174 	strcpy(str, (String) from->addr);
175 
176 	if (!strcmp(str, "auto") || !strcmp(str, "AUTO")) {
177 		to->size = sizeof(rgb);
178 		rgb = -1;
179 		to->addr = (XtPointer)&rgb;
180 		return True;
181 	}
182 	if (strlen(str) == 6) {
183 		if (isxdigit(str[0]) &&
184 		    isxdigit(str[1]) &&
185 		    isxdigit(str[2]) &&
186 		    isxdigit(str[3]) &&
187 		    isxdigit(str[4]) &&
188 		    isxdigit(str[5])) {
189 			sscanf(str, "%x", &rgb);
190 			to->size = sizeof(int);
191 			to->addr = (XtPointer) & rgb;
192 			return True;
193 		}
194 	}
195 	XtDisplayStringConversionWarning(dpy, from->addr, "XtRRgb");
196 	to->addr = NULL;
197 	to->size = 0;
198 	return False;
199 }
200 
201 /* �������� (2��ʾ�ƤӽФ���ǽ) */
202 void
create_chains(int num)203 create_chains(int num)
204 {
205 	int             i;
206 	XTextProperty   winname;
207 	char           *window_name = "xmascot_chain";
208 	XStringListToTextProperty(&window_name, 1, &winname);
209 
210 	if (chain) {
211 		for (i = 0; i < adat.chain_num; i++)
212 			XtDestroyWidget(chain[i]);
213 		XtFree((char *) chain);
214 	}
215 	chain = (Widget *) XtMalloc(sizeof(Widget) * num);
216 	for (i = 0; i < num; i++) {
217 		chain[i] = XtCreateWidget("chains",
218 								  overrideShellWidgetClass, top, NULL, 0);
219 		XtSetMappedWhenManaged(chain[i], False);
220 		XtVaSetValues(chain[i],
221 					  XtNwidth, (Dimension)CHAIN_SIZE,
222 					  XtNheight,(Dimension)CHAIN_SIZE,
223 					  XtNborderWidth, (Dimension)1, NULL);
224 		XtRealizeWidget(chain[i]);
225 	}
226 	adat.chain_num = num;
227 }
228 
229 /* ��˥塼��Ϣ */
230 
231 #if defined(BIFF) && defined(BIFF_LIST)
232 /* �᡼����� */
233 static Widget   ml_menu;
234 extern int      mbox_flag;
235 static void
MailLists(Widget w,XtPointer dat,XtPointer call)236 MailLists(Widget w, XtPointer dat, XtPointer call)
237 {
238 	ShowBiffNotice(NULL, NULL, NULL, NULL);
239 }
240 /* �ᥤ���˥塼�ν������ */
241 static void
set_main_menu(Widget w,XtPointer dat,XtPointer call)242 set_main_menu(Widget w, XtPointer dat, XtPointer call)
243 {
244 	if (mbox_flag)
245 		XtVaSetValues(ml_menu, XtNsensitive, True, NULL);
246 	else
247 		XtVaSetValues(ml_menu, XtNsensitive, False, NULL);
248 }
249 #endif
250 
251 /* ��λ */
252 void
ExitDialog(Widget w,XtPointer dat,XtPointer call)253 ExitDialog(Widget w, XtPointer dat, XtPointer call)
254 {
255 	ExitApp();
256 }
257 
258 
259 /* X ��Ϣ�ν���� */
260 void
xinit(int * argc,char ** argv)261 xinit(int *argc, char **argv)
262 {
263 	int             i;
264 	Widget          popup;
265 
266 	/* ���ץ�ν���� */
267 #ifdef USE_SESSION
268 	top = XtVaOpenApplication(&app, "XMascot", options, XtNumber(options),
269 			  argc, argv, NULL, sessionShellWidgetClass, NULL);
270 #else
271 	top = XtVaAppInitialize(&app, "XMascot", options, XtNumber(options),
272 				argc, argv, NULL, NULL);
273 #endif
274 
275 	/* �꥽��������С�������Ͽ */
276 	XtAppAddConverter(app, XtRString, XtRJustify, XmuCvtStringToJustify,
277 			  (XtConvertArgList) NULL, 0);
278 	XtAppSetTypeConverter(app, XtRString, XtRRgb, XtRgbCvt,
279 			      (XtConvertArgList) NULL, 0, XtCacheNone,
280 			      (XtDestructor) NULL);
281 
282 	/* �Ƽ�ѥ�᡼���ѿ� */
283 	disp_dpm = HeightOfScreen(XtScreen(top))
284 		/ HeightMMOfScreen(XtScreen(top));
285 
286 	get_resources(top);
287 
288 	/* �����˥ޥ����åȤΥե�����̾����ꤷ����� */
289 	if (*argc != 1) {
290 		MascotMenu *m = &adat.mascot_menus[0];
291 		adat.mascot_number = m->n_mascots;
292 		m->mascots[m->n_mascots].fname =
293 			m->mascots[m->n_mascots].title = argv[1];
294 	}
295 	XawSimpleMenuAddGlobalActions(app);
296 	XtAppAddActions(app, actions, XtNumber(actions));
297 	XtOverrideTranslations(top, XtParseTranslationTable(trans));
298 	XtVaSetValues(top,
299 				  XtNwidth, (Dimension)1,
300 				  XtNheight,(Dimension)1,
301 				  XtNborderWidth, (Dimension)0, NULL);
302 	XtSetMappedWhenManaged(top, False);
303 	XtRealizeWidget(top);
304 	XSelectInput(XtDisplay(top), XtWindow(top),
305 				 XtBuildEventMask(top) | PointerMotionHintMask);
306 
307 	/* ����ޡ����Υӥåȥޥå����� */
308 	select_mark = XCreateBitmapFromData(XtDisplay(top), XtWindow(top),
309 										(char *) select_bits,
310 										select_width, select_height);
311 	/* ��������Υӥåȥޥå����� */
312 	icon = XCreateBitmapFromData(XtDisplay(top), XtWindow(top),
313 								 (char *) icon_bits,
314 								 icon_width, icon_height);
315 	XtVaSetValues(top, XtNiconPixmap, icon, NULL);
316 
317 	/* ��λ�ѥץ�ѥƥ� */
318 	wm_protocols[0] = XInternAtom(XtDisplay(top), "WM_DELETE_WINDOW", False);
319 	wm_protocols[1] = XInternAtom(XtDisplay(top), "WM_SAVEYOURSELF", False);
320 	XSetWMProtocols(XtDisplay(top), XtWindow(top), wm_protocols, 2);
321 
322 	/* �ᥤ���˥塼 */
323 	popup = XtVaCreatePopupShell("popup", cascadeMenuWidgetClass, top, NULL);
324 
325 	menu_add_line(popup);
326 	for (i = 0; i < adat.menus_num; i++)
327 		menu_add_cascade(popup, adat.mascot_menus[i].title,
328 						 change_menu(top, i));
329 	menu_add_line(popup);
330 	menu_add_dialog(popup, "preference", preference_dialog(top));
331 	menu_add_dialog(popup, "alarm", alarm_dialog(top));
332 #if defined(BIFF) && defined(BIFF_LIST)
333 	ml_menu = menu_add_callback(popup, "list", MailLists);
334 	XtAddCallback(popup, XtNpopupCallback, set_main_menu, NULL);
335 #endif
336 	menu_add_line(popup);
337 	menu_add_dialog(popup, "about", about_dialog(top));
338 	menu_add_callback(popup, "exit", ExitDialog);
339 
340 	/* mascot Window */
341 	mascot = XtCreateWidget("mascot_base",
342 							overrideShellWidgetClass, top, NULL, 0);
343 	XtOverrideTranslations(mascot, XtParseTranslationTable(trans_mas));
344 	XtSetMappedWhenManaged(mascot, False);
345 	XtVaSetValues(mascot,
346 				  XtNwidth, (Dimension)1,
347 				  XtNheight,(Dimension)1,
348 				  XtNborderWidth, (Dimension)0, NULL);
349 	XtRealizeWidget(mascot);
350 	XSelectInput(XtDisplay(mascot), XtWindow(mascot),
351 				 XtBuildEventMask(mascot) | PointerMotionHintMask);
352 
353 	/* chains Window */
354 	create_chains(adat.chain_num);
355 
356 #ifdef BIFF
357 	/* biff Window */
358 	biff = XtCreateWidget("biff", overrideShellWidgetClass, top, NULL, 0);
359 	XtVaSetValues(biff, XtNsaveUnder, True, XtNoverrideRedirect, True, NULL);
360 #ifdef BIFF_LIST
361 	XtOverrideTranslations(biff, XtParseTranslationTable(trans_biff));
362 #endif
363 	XtSetMappedWhenManaged(biff, False);
364 	XtVaSetValues(biff,
365 				  XtNwidth, (Dimension)1,
366 				  XtNheight,(Dimension)1,
367 				  XtNborderWidth, (Dimension)0, NULL);
368 	XtRealizeWidget(biff);
369 #endif
370 
371 	/* shell widget �ϥ����������äƤʤ�.. */
372 	XDefineCursor(XtDisplay(top), XtWindow(top), adat.cursor_normal);
373 	XDefineCursor(XtDisplay(mascot), XtWindow(mascot), adat.cursor_normal);
374 }
375 
376 extern volatile int time_fl;	/* �������ѥե饰     */
377 
378 /* �ҥץ����ν��� */
379 static void
ChildTerm(int dummy)380 ChildTerm(int dummy)
381 {
382 	int s;
383 	wait(&s);
384 }
385 
386 /* �ޥ����å�������ؤ��ѥϥ�ɥ� (�̾�) */
387 static void
ChangeHand1(XtPointer cl,XtIntervalId * id)388 ChangeHand1(XtPointer cl, XtIntervalId * id)
389 {
390 	if (adat.all_menu)
391 		ChangeMascotNextAll(NULL, NULL, NULL, NULL);
392 	else
393 		ChangeMascotNext(NULL, NULL, NULL, NULL);
394 	XtAppAddTimeOut(app, adat.change_time * 60000, ChangeHand1, NULL);
395 }
396 
397 /* �ޥ����å�������ؤ��ѥϥ�ɥ� (������) */
398 static void
ChangeHand2(XtPointer cl,XtIntervalId * id)399 ChangeHand2(XtPointer cl, XtIntervalId * id)
400 {
401 	if (adat.all_menu)
402 		ChangeMascotRandomAll(NULL, NULL, NULL, NULL);
403 	else
404 		ChangeMascotRandom(NULL, NULL, NULL, NULL);
405 	XtAppAddTimeOut(app, adat.change_time * 60000, ChangeHand2, NULL);
406 }
407 
408 
409 #ifdef DUMMY_SETLOCALE
410 char *
setlocale(int cat,const char * locale)411 setlocale(int cat, const char *locale)
412 {
413 	static char name[100] = "C";	/* XXX */
414 	if (locale) {
415 		if (!*locale) {
416 			char *s;
417 			if ((s = getenv("LC_CTYPE")) || (s = getenv("LANG")))
418 				strncpy(name, s, sizeof(name)-1);
419 			else
420 				strcpy(name, "C");
421 		} else {
422 			strncpy(name, locale, sizeof(name)-1);
423 		}
424 	}
425 	return name;
426 }
427 #endif
428 
429 /* �ᥤ�� */
430 int
main(int argc,char * argv[])431 main(int argc, char *argv[])
432 {
433 	signal(SIGCHLD, ChildTerm);
434 	srand((unsigned) getpid());	/* ����Ͻ���� */
435 
436 #ifdef I18N
437 	/* Athene Widget I18N client */
438 	XtSetLanguageProc(NULL, NULL, NULL);
439 #endif
440 	xinit(&argc, argv);	/* widget/window ���� */
441 	usage(&argc, argv);	/* ���ץ����Υ����å� */
442 	get_rcfile();		/* ����ե�������ɤ߹��� */
443 
444 #ifndef USE_DOUBLE
445 	isin_init();		/* isin,icos ����� */
446 #endif
447 
448 	/* pin  �Υѥ��������� */
449 	set_widget_pattern(top, adat.pin_pat, adat.pcol0, adat.prgb0);
450 #ifdef BIFF
451 	/* biff �Υѥ��������� */
452 	set_widget_pattern(biff, adat.biff_pat, adat.bcol0, adat.brgb0);
453 #endif
454 
455 #ifdef USE_CHAINPAT
456 	/* chain �Υѥ��������� */
457 	set_chain_pat(adat.chain_pat, adat.ccol0, adat.crgb0);
458 #endif
459 
460 	/* �ޥ����åȤΥѥ��������� */
461 	set_mas(&adat);
462 	XtMapWidget(top);	/* �ޥåԥ�   */
463 	set_alarms();		/* ���顼������ */
464 #ifdef BIFF
465 	set_biff();		/* biff ����    */
466 #endif
467 
468 	if (adat.change_time) {
469 		if (adat.random)
470 			XtAppAddTimeOut(app, adat.change_time * 60000, ChangeHand1, NULL);
471 		else
472 			XtAppAddTimeOut(app, adat.change_time * 60000, ChangeHand2, NULL);
473 	}
474 
475 	/* ���٥�ȥ롼�� */
476 	while (1) {
477 		if (XtAppPending(app) || time_fl <= 0)
478 			XtAppProcessEvent(app, XtIMAll);
479 		else
480 			sim();
481 	}
482 }
483