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