1 /*
2 * xosmulti.c
3 * Yet Another Osuwari Multi for X11
4 *
5 * Compile: cc -O xosmulti.c image.c message.c biff.c -o xosmulti -lX11 -lXext
6 * Program: T.Nakanishi (e-mail: nakanita@ka2.so-net.ne.jp)
7 * Original: for MS-Windows95 programed by Yoshy.
8 *
9 * History: '98/09/17 Beta Version.
10 * '98/09/22 ���ܸ� Beta Version.
11 * '98/10/01 �ե륫�顼�б� Beta Version(1).
12 * '98/10/16 Biff��ǽ���ɲ� Beta Version(2).
13 * '98/11/12 ���٥���Ԥ�����٤�ڤ�������delilah���ա�(^^)
14 */
15
16 static char Usage[] = {
17 "\n"
18 " <<< Yet Another Osuwari Multi * Version1.00 >>>\n"
19 "\tUsage: xosmulti [-font <fontname>] [-fg <color>] [-bg <color>] [-x <xpos>] [-y <ypos>]\n"
20 "\n"
21 };
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/time.h>
27
28 #include <X11/Xlib.h>
29 #include <X11/Xutil.h>
30 #include <X11/extensions/shape.h> /* �������ץ������ƥ��(X11R4�ʹ�) */
31
32 #include "mul_norm.c"
33 #include "mul_close.c"
34 #include "mul_urur.c"
35 #include "mul_uru2.c"
36 #include "mul_ohno.c"
37 #include "mul_psyu.c"
38
39 #include "mul_mask.xbm"
40
41 #include "nadecur.xbm"
42 #include "nademask.xbm"
43 #include "funicur.xbm"
44 #include "funimask.xbm"
45
46 /********
47 | ���롼�ɡ��ե�����ˤϰʲ��Υǡ������ޤޤ�Ƥ��ޤ�
48 |
49 | unsigned int osuwari_width; �ޥ������
50 | unsigned int osuwari_height; �ޥ���ι⤵
51 | unsigned char Palette[]; �ѥ�åȡʶ��̡�
52 |
53 | unsigned char mul_norm[]; �Ρ��ޥ�
54 | unsigned char mul_close[]; ���Ĥ�
55 | unsigned char mul_urur[]; ���뤦��
56 | unsigned char mul_uru2[]; ���뤦�롢���Σ�
57 | unsigned char mul_ohno[]; �ϣ衤�Σ
58 | unsigned char mul_psyu[]; �ץ��塼����
59 |
60 | unsigned char mul_mask_bits[]; �ޥ���Υޥ�����
61 |
62 | unsigned char nadecur_bits[]; �ʤǤʤǥ�������
63 | unsigned char nademask_bits[]; �ʤǤʤǥ�������ޥ���
64 | unsigned char funicur_bits[]; �դˤդ˥�������
65 | unsigned char funimask_bits[]; �դˤդ˥�������ޥ���
66 |
67 ********/
68
69 /******* External Value ********
70 * ��å��������ǡ����ϳ����ե����� message.c �ˤޤȤޤäƤ��ޤ�
71 */
72 extern char **NadeMsg; /* �ʤǤʤǥ�å����� */
73 extern char **FuniMsg; /* �դˤդ˥�å����� */
74 extern char *PsyuMsg; /* �ץ��塼��å����� */
75 extern char *QuitMsg; /* ��λ���Υ�å����� */
76
77 /******** External Function ********/
78
79 /* in image.c */
80 extern unsigned int GetXDepth( );
81 extern XImage *CreateMyImage( );
82 extern Cursor CreateMyCursor( );
83
84 /* in message.c */
85 extern void SetMsgLang( ); /* ���ܸ� <-> �Ѹ��ڤ��ؤ� */
86
87 /* in biff.c */
88 extern void CreateBiff();
89 extern void MoveBiff( );
90 extern void CheckBiff( );
91 extern void DownBiff( );
92 extern void DestroyBiff();
93
94 /******** Constant ********/
95
96 #define TIMER_WAIT 200000 /* �����ޡ��ֳ֡��������ۤ�®�� but�Ť� */
97
98 #define TALK_COUNT 15 /* �դ������νи����� */
99 #define PSYU_COUNT 60 /* ����Ƥ������ */
100 #define MAX_FUNIFUNI 30 /* �դˤդˤǤ�������ϰ� */
101
102 #define PRIVATE_CMAP 0 /* �������顼�ޥåס��̾�Ǥ褤 */
103
104 /* ����Ū���֤���(̤����ʤ��Ȥ�����) */
105 #ifndef EXIT_SUCCESS
106 #define EXIT_SUCCESS 0
107 #endif
108 #ifndef EXIT_FAILURE
109 #define EXIT_FAILURE 1
110 #endif
111
112 /******** Functions Prototype ********/
113
114 unsigned long MyColor( );
115 void TalkShape( );
116
117 int InitTalk( );
118 int ClearTalk( );
119 int NTalkLine( );
120 int AppendTalk( );
121 int MaxTalkWidth( );
122
123 XChar2b *Str2bCpy( );
124
125 void GetArgs( );
126 int main( );
127 void TimeHandler( );
128 void EventProc( );
129 void Do_Draw( );
130 void Do_NadeNade( );
131 void Do_FuniFuni( );
132 void Do_Quit( );
133 void Do_Talk( );
134
135 /******** Gloval Values ********/
136
137 Display *Disp;
138 Window RootWin;
139 static Window MainWin, TalkWin;
140 static GC TalkGC;
141
142 /* ����ե��å����ѥ����� */
143 #define NORM_PAT 0
144 #define CLOSE_PAT 1
145 #define URUR_PAT 2
146 #define URU2_PAT 3
147 #define OHNO_PAT 4
148 #define PSYU_PAT 5
149 #define MAX_PAT 6
150
151 static XImage *MyImage[ MAX_PAT ];
152 static Cursor NadeCur, FuniCur;
153
154 /* ư��⡼�� */
155 #define NORM_MODE 0
156 #define URUR_MODE 1
157 #define OHNO_MODE 2
158 #define PSYU_MODE 3
159 #define QUIT_MODE 4
160
161 static int theMode = NORM_MODE;
162
163 static unsigned int TalkCount = TALK_COUNT;
164 static unsigned int FuniCnt = 0;
165
166 Colormap MyColorMap;
167 unsigned long FgPixel, BgPixel;
168
169 /* �����֡��������Ф��룱����ʬΨ(%)���� */
170 #define XPOS_RATIO 10
171 static int XPosRatio = XPOS_RATIO;
172
173 /* �岼���֤���Ĵ�� */
174 #define YPOS_ADJUST 28
175 static int YPosAdjust = YPOS_ADJUST;
176
177 /* �Ļ롢�ԲĻ��ɽ���ե饰 */
178 static Bool isMapped = False;
179 static Bool isTalkMapped = False;
180
181 static char FontName[ 128 ] = ""; /* ���ץ�������Υե����̾ */
182
183 /* �ǥե���ȥե���ȤΥꥹ�� * �夫����֤ˤ��ƤϤ�Ƥߤ� */
184 static char *DefFontList[] = {
185 /*
186 * �ǥե���ȥե���Ȥ����ޥ����������Ȥ��ˤϡ�
187 * �����˥ե����̾���ɲä���
188 */
189 "-jis-fixed-medium-r-normal--16-*-*-*-*-*-*-*", /* Japanese */
190 "-adobe-courier-bold-r-normal-*-18-*-*-*-*-*-*-*", /* English */
191 NULL /* END MARK */
192 };
193
194 XFontStruct *theFont;
195 int FontHeight;
196 Bool isKanji = False; /* ��byteʸ���ե饰 */
197
198 static Bool Done = False; /* ��λ�ե饰 */
199
200 /******** MyColor ********
201 * ��̾����ԥ�����ǡ�������
202 */
MyColor(disp,color_name)203 unsigned long MyColor( disp, color_name )
204 Display *disp;
205 char *color_name;
206 {
207 Colormap cmap;
208 XColor c0, c1;
209
210 cmap = DefaultColormap( disp, DefaultScreen(disp) );
211 XAllocNamedColor( disp, cmap, color_name, &c1, &c0 );
212 return c1.pixel;
213 }
214
215 /******** TalkShepe ********
216 * ������ɥ���֤դ������פη����ڤ�Ф�
217 */
TalkShape(disp,win,width,height,option_flag)218 void TalkShape( disp, win, width, height, option_flag )
219 Display *disp;
220 Window win;
221 int width, height;
222 Bool option_flag;
223 {
224 GC gc_mask;
225 Pixmap bitmap;
226 int edge = width / 6;
227 XPoint p[ 3 ];
228
229 /* �ޥ����ѥӥåȥޥåפ����� */
230 bitmap = XCreatePixmap( disp, win, width, height, 1/*depth=1*/ );
231 gc_mask = XCreateGC( disp, bitmap, 0, NULL );
232
233 /* �ޤ����̥��ꥢ������ */
234 XSetForeground( disp, gc_mask, BlackPixel(disp,DefaultScreen(disp)) );
235 XFillRectangle( disp, bitmap, gc_mask, 0, 0, width, height );
236
237 /* �����Ĺ������ξ�����ɤ�Ⱦ�� */
238 XSetForeground( disp, gc_mask, WhitePixel(disp,DefaultScreen(disp)) );
239 XFillRectangle( disp, bitmap, gc_mask, edge, 0, width-2*edge, height );
240 XFillArc( disp, bitmap, gc_mask, 0, 0, edge*2, height, 0, 360*64 );
241 XFillArc( disp, bitmap, gc_mask, width-edge*2, 0, edge*2, height, 0, 360*64 );
242
243 /* �����ʻ��ѷ����դ��� */
244 /* option_flag �ˤ�äƻ��Ѥ��դ����֤��Ѥ�� */
245 if( option_flag )
246 { p[0].x = 0; p[0].y = height;
247 p[1].x = edge; p[1].y = height * 9 / 10;
248 p[2].x = edge; p[2].y = height / 2;
249 } else
250 { p[0].x = 0; p[0].y = 0;
251 p[1].x = edge; p[1].y = height / 10;
252 p[2].x = edge; p[2].y = height / 2;
253 }
254 XFillPolygon( disp, bitmap, gc_mask, p, 3, Convex, CoordModeOrigin );
255
256 XResizeWindow( disp, win, width, height );
257 XShapeCombineMask( disp, win, ShapeBounding, 0, 0, bitmap, ShapeSet );
258
259 XFreeGC( disp, gc_mask );
260 XFreePixmap( disp, bitmap );
261 }
262
263 /******** TalkLine ********
264 * ʣ���ԡ֤���աפν���
265 */
266
267 typedef struct tagTALK_LINE
268 { unsigned short len; /* = strlen */
269 unsigned short width; /* ������ɥ���ɽ�������Ȥ����� */
270 char *str;
271 } TALK_LINE;
272
273 #define N_TALKLINE 7 /* ����դκ���Կ� */
274 static TALK_LINE TalkLines[ N_TALKLINE + 1 ];
275
InitTalk()276 int InitTalk( )
277 {
278 int i;
279
280 for( i=0; i<N_TALKLINE +1; i++ )
281 { TalkLines[i].str = NULL;
282 TalkLines[i].len = 0;
283 TalkLines[i].width = 0;
284 }
285 return 0;
286 }
287
ClearTalk()288 int ClearTalk( )
289 {
290 int i;
291
292 for( i=0; i<N_TALKLINE; i++ )
293 { if( TalkLines[i].str != NULL )
294 { free( TalkLines[i].str );
295 TalkLines[i].str = NULL;
296 TalkLines[i].len = 0;
297 TalkLines[i].width = 0;
298 }
299 }
300 return 0;
301 }
302
NTalkLine()303 int NTalkLine( )
304 {
305 int i;
306 for( i=0; TalkLines[i].str != NULL; i++ )
307 /* LOOP */ ;
308 return i;
309 }
310
AppendTalk(font,str)311 int AppendTalk( font, str )
312 XFontStruct *font;
313 char *str;
314 {
315 int i, j;
316
317 if( (i = NTalkLine()) == N_TALKLINE )
318 {
319 free( TalkLines[0].str );
320 for( j=0; j<N_TALKLINE-1; j++ )
321 {
322 TalkLines[j].str = TalkLines[j+1].str;
323 TalkLines[j].len = TalkLines[j+1].len;
324 TalkLines[j].width = TalkLines[j+1].width;
325 }
326 i = N_TALKLINE -1;
327 }
328
329 TalkLines[i].str = malloc( strlen( str ) + 1 );
330 if( TalkLines[i].str == NULL )
331 { fprintf( stderr, "ERROR: malloc\n" );
332 ClearTalk();
333 return 0;
334 }
335 strcpy( TalkLines[i].str, str );
336 TalkLines[i].len = strlen( str );
337 if( isKanji )
338 { XChar2b kstr[ 128 ];
339 Str2bCpy( kstr, TalkLines[i].str );
340 TalkLines[i].width = XTextWidth16( font,
341 kstr, TalkLines[i].len /2 );
342 }else
343 { TalkLines[i].width = XTextWidth( font,
344 TalkLines[i].str , TalkLines[i].len );
345 }
346 return i+1;
347 }
348
MaxTalkWidth()349 int MaxTalkWidth( )
350 {
351 int i, max_width = 0;
352
353 for( i=0; TalkLines[i].str != NULL; i++ )
354 {
355 if( TalkLines[i].width > max_width )
356 max_width = TalkLines[i].width;
357 }
358 return max_width;
359 }
360
361 /******** Str2bCpy ********
362 * ʸ����char��XChar2b �˥��ԡ�����
363 */
Str2bCpy(dst,src)364 XChar2b *Str2bCpy( dst, src )
365 XChar2b *dst;
366 char *src;
367 {
368 int i;
369
370 for( i=0; i < strlen( src ) / 2; i++ )
371 {
372 dst[i].byte1 = src[ i*2 ] & 0x7f;
373 dst[i].byte2 = src[ i*2 + 1 ] & 0x7f;
374 }
375 dst[i].byte1 =
376 dst[i].byte2 = '\0';
377
378 return( dst );
379 }
380
381 /******** GetArgs ********
382 * �������
383 */
GetArgs(argc,argv)384 void GetArgs( argc, argv )
385 int argc;
386 char *argv[];
387 {
388 int i;
389
390 for( i=1; i<argc; i++ )
391 {
392 /**** �ե���� ****/
393 if( ! strcmp( argv[i], "-font" ) )
394 {
395 ++i;
396 if( argv[i] == NULL )
397 { fprintf( stderr, "WARNING: missing font name, use default\n" );
398 continue;
399 }
400
401 { int cnt;
402 XListFonts( Disp, argv[i], 1, &cnt );
403 if( cnt == 0 )
404 { fprintf( stderr, "WARNING: bad font name, use default\n" );
405 continue;
406 }
407 }
408 strcpy( FontName, argv[i] );
409 printf( "INFO: font = %s\n", FontName );
410 }
411
412 /**** �ذ��� ****/
413 else if( ! strncmp( argv[i], "-x", 2 ) )
414 {
415 ++i;
416 if( argv[i] == NULL )
417 { fprintf( stderr, "WARNING: missing X position, use default\n" );
418 continue;
419 }
420
421 XPosRatio = atoi( argv[i] );
422 if( XPosRatio < 0 || 100 < XPosRatio )
423 { fprintf( stderr, "WARNING: xpos(%%) must be in 0-100, use default\n" );
424 XPosRatio = XPOS_RATIO;
425 }
426 }
427
428 /**** �ٰ��� ****/
429 else if( ! strncmp( argv[i], "-y", 2 ) )
430 {
431 ++i;
432 if( argv[i] == NULL )
433 { fprintf( stderr, "WARNING: missing Y position, use default\n" );
434 continue;
435 }
436
437 YPosAdjust = YPOS_ADJUST + atoi( argv[i] );
438 }
439
440 /**** ���ʿ� ****/
441 else if( ! strcmp( argv[i], "-fg" ) )
442 {
443 ++i;
444 if( argv[i] == NULL )
445 { fprintf( stderr, "WARNING: missing Foreground, use default\n" );
446 continue;
447 }
448 FgPixel = MyColor( Disp, argv[i] );
449 }
450
451 /**** �طʿ� ****/
452 else if( ! strcmp( argv[i], "-bg" ) )
453 {
454 ++i;
455 if( argv[i] == NULL )
456 { fprintf( stderr, "WARNING: missing Background, use default\n" );
457 continue;
458 }
459 BgPixel = MyColor( Disp, argv[i] );
460 }
461
462 /**** �إ�� ****/
463 else if( ! strncmp( argv[i], "-h", 2 ) )
464 { printf( "%s", Usage );
465 exit( EXIT_SUCCESS );
466 }
467
468 /**** ���顼 ****/
469 else
470 { fprintf( stderr, "ERROR: unknown option \"%s\"\n", argv[i] );
471 exit( EXIT_FAILURE );
472 }
473 }
474 }/* END GetArgs */
475
476 /******** main ********/
main(argc,argv)477 int main( argc, argv )
478 int argc;
479 char *argv[];
480 {
481 struct timeval delay;
482 struct timeval tvnow;
483 struct timeval tvold;
484 int tm;
485
486 Disp = XOpenDisplay( NULL );
487 RootWin = RootWindow( Disp, DefaultScreen(Disp) );
488 FgPixel = BlackPixel( Disp, DefaultScreen(Disp) );
489 BgPixel = WhitePixel( Disp, DefaultScreen(Disp) );
490
491 GetArgs( argc, argv );
492
493 /**** Create Main Window ****/
494 {
495 XSetWindowAttributes xswa;
496
497 xswa.override_redirect = True;
498 xswa.event_mask =
499 ButtonPressMask | ButtonReleaseMask |
500 PointerMotionMask | ExposureMask;
501
502 MainWin = XCreateWindow( Disp, RootWin,
503 0/*x*/, 0/*y*/, osuwari_width, osuwari_height, 0,
504 CopyFromParent/*depth*/, InputOutput, CopyFromParent/*visual*/,
505 CWEventMask | CWOverrideRedirect, &xswa );
506 }
507
508 /**** Set Main Window Shape ****/
509 { Pixmap maskbit;
510
511 maskbit = XCreateBitmapFromData( Disp, RootWin,
512 mul_mask_bits, mul_mask_width, mul_mask_height );
513 XShapeCombineMask( Disp, MainWin, ShapeBounding, 0, 0, maskbit, ShapeSet );
514
515 XFreePixmap( Disp, maskbit );
516 }
517
518 #if PRIVATE_CMAP
519 MyColorMap = XCreateColormap( Disp, MainWin,
520 DefaultVisual(Disp,DefaultScreen(Disp)), AllocNone );
521 #else
522 MyColorMap = DefaultColormap( Disp, DefaultScreen(Disp) );
523 #endif
524
525 XSetWindowColormap( Disp, MainWin, MyColorMap );
526
527 /**** Create Talk Window ****/
528 {
529 XSetWindowAttributes xswa;
530 int talk_width = 120, talk_height = 64;
531
532 TalkWin = XCreateSimpleWindow( Disp, RootWin,
533 0, 0, talk_width, talk_height, 1,
534 FgPixel, BgPixel );
535
536 xswa.override_redirect = True;
537 XChangeWindowAttributes( Disp, TalkWin, CWOverrideRedirect, &xswa );
538 }
539
540 /**** Loading font ****/
541 {
542 XGCValues gcv;
543 memset( &gcv, 0, sizeof(XGCValues) );
544
545 if( FontName[0] != '\0' ) /* ���ץ����ǥե����̾����ꤷ�� */
546 { theFont = XLoadQueryFont( Disp, FontName );
547 }
548 else /* �ǥե���ȥե���ȤΥ��� */
549 { int i;
550 for( i=0; DefFontList[i] != NULL; i++ )
551 {
552 theFont = XLoadQueryFont( Disp, DefFontList[ i ] );
553 if( theFont != NULL ) /* �ե���Ȥ����Ĥ��ä� */
554 break;
555 }
556 }
557
558 /* �ե���Ȥ����Ĥ���ʤ��ä� */
559 if( theFont == NULL )
560 { fprintf( stderr, "ERROR: Can't find proper default fonts.\n" );
561 fprintf( stderr, " Please use -font option to use suitable font.\n" );
562 exit( EXIT_FAILURE );
563 }
564
565 /* 2byte�ե���Ȥ��ɤ��������å� */
566 if( theFont->min_byte1 | theFont->max_byte1 != 0 )
567 {
568 /* printf( "INFO: Using Japanese Message.\n" ); /* DEBUG */
569 SetMsgLang( isKanji = True );
570 }
571 else
572 { SetMsgLang( isKanji = False );
573 }
574
575 FontHeight = theFont->max_bounds.ascent + theFont->max_bounds.descent;
576 gcv.font = theFont->fid;
577 gcv.foreground = FgPixel;
578 gcv.background = BgPixel;
579 TalkGC = XCreateGC( Disp, RootWin,
580 GCForeground | GCBackground | GCFont, &gcv );
581 }
582
583 /******** ********/
584 CreateBiff();
585
586 /******** Loading Image & Cursor ********/
587 { unsigned int depth = GetXDepth( Disp ); /* �ǥ����ץ쥤�Υ��顼�⡼�ɤ����� */
588
589 MyImage[ NORM_PAT ] = CreateMyImage( osuwari_width, osuwari_height, Palette, 16, depth, mul_norm );
590 MyImage[ CLOSE_PAT] = CreateMyImage( osuwari_width, osuwari_height, Palette, 16, depth, mul_close );
591 MyImage[ URUR_PAT ] = CreateMyImage( osuwari_width, osuwari_height, Palette, 16, depth, mul_urur );
592 MyImage[ URU2_PAT ] = CreateMyImage( osuwari_width, osuwari_height, Palette, 16, depth, mul_uru2 );
593 MyImage[ OHNO_PAT ] = CreateMyImage( osuwari_width, osuwari_height, Palette, 16, depth, mul_ohno );
594 MyImage[ PSYU_PAT ] = CreateMyImage( osuwari_width, osuwari_height, Palette, 16, depth, mul_psyu );
595 }
596
597 FuniCur = CreateMyCursor( MainWin, funicur_bits, funimask_bits );
598 NadeCur = CreateMyCursor( MainWin, nadecur_bits, nademask_bits );
599
600 /**** Initialize ****/
601
602 InitTalk();
603
604 XStoreName( Disp, MainWin, "Osuwari-Multi" );
605
606 XUnmapWindow( Disp, MainWin );
607 isMapped = False;
608 XUnmapWindow( Disp, TalkWin );
609 isTalkMapped = False;
610
611 XFlush( Disp );
612
613 gettimeofday( &tvold, NULL/*&tzone*/ );
614 tm = 0;
615
616 /**** Main Loop ****/
617 while( ! Done )
618 {
619 /* int conNum = ConnectionNumber( Disp ); /*��ά*/
620 /* FD_ZERO( &writefd ); /*��ά*/
621 /* FD_ZERO( &exceptfd ); /*��ά*/
622 /* FD_ZERO( &readfd ); /*��ά*/
623 /* FD_SET( conNum, &readfd ); /*��ά*/
624
625 delay.tv_usec = TIMER_WAIT;
626 delay.tv_sec = 0;
627 select( 1, NULL, NULL, NULL, &delay );
628 /* select( conNum + 1, &readfd, &writefd, &exceptfd, &delay ); /*��ά*/
629 /* ������֤ޤ��Ԥ� */
630
631 while( XEventsQueued( Disp, QueuedAfterFlush ) != 0 )
632 { EventProc( ); /* ���٥�Ƚ��� */
633 }
634
635 gettimeofday( &tvnow, NULL/*&tzone*/ );
636 tm += (tvnow.tv_sec - tvold.tv_sec) * 1000000;
637 tm += (tvnow.tv_usec - tvold.tv_usec);
638 if ( tm > TIMER_WAIT )
639 {
640 TimeHandler(); /* �����ޡ��ϥ�ɥ顼 */
641 tm -= TIMER_WAIT;
642 tvold.tv_sec = tvnow.tv_sec;
643 tvold.tv_usec = tvnow.tv_usec;
644 }
645 }
646
647 /**** Exit ****/
648 DestroyBiff();
649
650 XDestroyWindow( Disp, TalkWin );
651 XDestroyWindow( Disp, MainWin );
652 #if PRIVATE_CMAP
653 XFreeColormap( Disp, MyColorMap );
654 #endif
655 XFreeGC( Disp, TalkGC );
656 XFreeFont( Disp, theFont );
657
658 ClearTalk( );
659
660 exit( EXIT_SUCCESS );
661
662 }/* END main */
663
664 /******** TimeHandler ********
665 * ������ֳִ֤ǸƤӽФ�������
666 */
TimeHandler()667 void TimeHandler( )
668 {
669 Window focus_win;
670 static Window prev_focus = 0;
671 static int prev_x = 0, prev_y = 0, prev_w = 0;
672 int x, y, w, h, border;
673
674 Window child;
675 int revert;
676 int depth;
677
678 static int Biff_x = 0, Biff_y = 0;
679
680 XRaiseWindow( Disp, MainWin ); /* ��˺����̤˽Ф� */
681
682 /******** �ե�������������ɥ��Υ����å� ********/
683
684 XGetInputFocus( Disp, &focus_win, &revert );
685
686 if( focus_win != MainWin && focus_win != PointerRoot &&
687 focus_win != TalkWin && focus_win != None )
688 {
689 XSync( Disp, 1 );
690
691 if( ! XGetGeometry( Disp, focus_win, &RootWin, &x, &y, &w, &h, &border, &depth ) )
692 { fprintf( stderr, "ERROR: failed XGetGeometry\n" );
693 return;
694 }
695
696 /* ���̤���礭�ʥ�����ɥ����Ф��ƤϽ�����Ԥ�ʤ�(��������) */
697 if( w > DisplayWidth(Disp,DefaultScreen(Disp)) ||
698 h > DisplayHeight(Disp,DefaultScreen(Disp)) )
699 return;
700
701 XTranslateCoordinates( Disp, focus_win, RootWin, 0, 0, &x, &y, &child );
702
703 /* ���̤�Ϥ߽Ф����Ȥ��ˤϽ�����Ԥ�ʤ�(��������) */
704 if( x > DisplayWidth(Disp,DefaultScreen(Disp)) ||
705 y > DisplayHeight(Disp,DefaultScreen(Disp)) )
706 return;
707
708 if(
709 focus_win != prev_focus || /* �ե�������������ɥ����Ѥ�ä� */
710 x != prev_x || /* ������ɥ��ΰ��֤��Ѥ�ä� */
711 y != prev_y ||
712 w != prev_w /* ������ɥ��η������Ѥ�ä� */
713 )
714 { int x_pos = x + (w - osuwari_width) * XPosRatio /100;
715 int y_pos = y - border + 30; /* 30 = ���� */
716
717 /* ��äƤ��륦����ɥ����롼�Ȥ�ľ�ܤλҶ����ɤ���Ĵ�٤� */
718 /* ������ɥ��ޥ͡����㡼�Υ����ȥ�С���̵ͭ���б�������� */
719 { Window root_return;
720 Window parent_return;
721 Window *children_return;
722 unsigned int n_children;
723
724 if( ! XQueryTree( Disp, focus_win, &root_return, &parent_return,
725 &children_return, &n_children ) )
726 { fprintf( stderr, "ERROR: on XQueryTree\n" );
727 }
728 XFree( children_return ); /* �Ҷ��Ϥ��κݴط��ʤ� */
729
730 /* ľ�ܤλҶ��Ǥʤ���С�������ɥ��ޥ͡����㡼����Ϳ */
731 if( parent_return != RootWin )
732 {
733 y_pos -= YPosAdjust; /* �岼���֤�Ĵ������ */
734 }
735 }
736
737 /* ���֤ΰ�ư */
738 XMoveWindow( Disp, MainWin,
739 x_pos,
740 y_pos - osuwari_height );
741
742 /* �֤դ������פΰ��֤ΰ�ư */
743 XMoveWindow( Disp, TalkWin,
744 x_pos + osuwari_width,
745 y_pos - osuwari_height /2 );
746
747 /* Biff �ΰ�ư */
748 Biff_x = x_pos + osuwari_width;
749 Biff_y = y_pos - osuwari_height / 2;
750 MoveBiff( Biff_x, Biff_y );
751
752 if( ! isMapped )
753 { XMapWindow( Disp, MainWin );
754 isMapped = True;
755 }
756
757 Do_Draw( True ); /* ���̺����� */
758
759 prev_focus = focus_win;
760 prev_x = x;
761 prev_y = y;
762 prev_w = w;
763 }
764 }
765
766 /******** ���Ū�ʺ����� ********/
767 Do_Draw( False );
768
769 /******** Biff�Υ����å� ********/
770 if( isMapped )
771 { CheckBiff( Biff_x, Biff_y );
772 }
773
774 /******** �֤դ������פνи�������� ********/
775 if( isTalkMapped )
776 {
777 if( --TalkCount <= 0 )
778 {
779 XUnmapWindow( Disp, TalkWin ); /* �դ�������ä� */
780 isTalkMapped = False;
781 ClearTalk( );
782
783 if( theMode != PSYU_MODE )
784 {
785 theMode = NORM_MODE; /* �Ρ��ޥ�⡼�ɤ���� */
786 Do_Draw( True );
787 }
788 }
789 }
790
791 /******** �֥ץ��塼���פ���β���������� ********/
792 if( theMode == PSYU_MODE )
793 {
794 static unsigned int PsyuCount = PSYU_COUNT;
795 if( --PsyuCount == 0 )
796 {
797 theMode = NORM_MODE; /* �Ρ��ޥ�⡼�ɤ���� */
798 Do_Draw( True );
799 PsyuCount = PSYU_COUNT;
800 }
801 }
802
803 }/* END TimeHandler */
804
805 /******** EventProc ********
806 * ���٥�Ƚ���
807 */
EventProc()808 void EventProc( )
809 {
810 /* �������롦�⡼�� */
811 #define NORM_CURMODE 0 /* �̾� */
812 #define NADE_CURMODE 1 /* �ʤǤʤ� */
813 #define FUNI_CURMODE 2 /* �դˤդ� */
814 static int CurMode = NORM_CURMODE;
815
816 static Bool ButtonPushed = False; /* ���ߥܥ�������Ƥ���ե饰 */
817 XEvent ev;
818
819 XNextEvent( Disp, &ev );
820 switch( ev.type )
821 {
822 case Expose:
823 Do_Draw( True );
824 break;
825
826 case ButtonPress:
827 ButtonPushed = True;
828
829 if( CurMode == FUNI_CURMODE )
830 {
831 XDefineCursor( Disp, MainWin, FuniCur );
832
833 /* �֤դˤդˡץ⡼�ɤ����� */
834 if( theMode != PSYU_MODE ) /* �ץ��塼����Ȳ���Ǥ��ʤ� */
835 {
836 if( theMode != OHNO_MODE )
837 {
838 if( theMode == QUIT_MODE )
839 { ClearTalk();
840 } else
841 { FuniCnt = 0;
842 }
843
844 theMode = OHNO_MODE;
845 Do_Draw( True );
846
847 }
848 Do_FuniFuni();
849 }
850 }
851 break;
852
853 case ButtonRelease:
854 ButtonPushed = False;
855
856 if( CurMode == FUNI_CURMODE )
857 { XDefineCursor( Disp, MainWin, NadeCur );
858 }
859
860 /* ����� */
861 /* �ܥ��� QUIT_MODE -> ���θ�ܥ��ǽ�λ */
862 switch( ev.xbutton.button )
863 {
864 case Button1:
865 if( theMode == QUIT_MODE )
866 { Done = True; /* �ץ���ཪλ */
867 }
868 break;
869
870 case Button2:
871 break;
872
873 case Button3:
874 if( theMode == PSYU_MODE ) /* �ץ��塼����Ȳ���Ǥ��ʤ� */
875 break;
876
877 if( theMode != QUIT_MODE )
878 { theMode = QUIT_MODE;
879 Do_Quit( );
880 }
881 else
882 /* �ܥ���Ϣ³���� -> ��λ����� */
883 { theMode = NORM_MODE;
884 TalkCount = 1; /* �դ�������ä� */
885 }
886 break;
887 }
888 break;
889
890 case MotionNotify:
891 /* �ݥ������֤ˤ�äƥ��������ѹ� */
892 if( ev.xbutton.y > 0 && ev.xbutton.y < 28 &&
893 ev.xbutton.x > 0 && ev.xbutton.x < 64 )
894 /*�֤ʤǤʤǡפǤ����ϰ� */
895 {
896 XDefineCursor( Disp, MainWin, NadeCur );
897 CurMode = NADE_CURMODE;
898 }
899 else if( 50 < ev.xbutton.y && ev.xbutton.y < 64 )
900 /*�֤դˤդˡפǤ����ϰ� */
901 {
902 if( ButtonPushed )
903 { XDefineCursor( Disp, MainWin, FuniCur );
904 }
905 else
906 { XDefineCursor( Disp, MainWin, NadeCur );
907 }
908 CurMode = FUNI_CURMODE;
909 }
910 else
911 {
912 XDefineCursor( Disp, MainWin, 0/*Default*/ );
913 CurMode = NORM_CURMODE;
914 }
915
916 if( theMode == PSYU_MODE ) /* �ץ��塼����Ȳ���Ǥ��ʤ� */
917 break;
918
919 /* �֤ʤǤʤǡץ⡼�ɤ����� */
920 if( CurMode == NADE_CURMODE && ButtonPushed )
921 {
922 if( theMode != URUR_MODE )
923 {
924 if( theMode == QUIT_MODE )
925 ClearTalk();
926
927 theMode = URUR_MODE;
928 Do_Draw( True );
929 }
930 Do_NadeNade();
931
932 DownBiff();
933 }
934 break;
935
936 default:
937 break;
938 }
939 }/* END EventProc */
940
941 /******** Do_Draw ********
942 * ��������
943 * �ܥѥ��Υ�����Ȥʤɤ�ԤäƤ���
944 * ���� True = ���̶�������
945 * False = ɬ�ײս�Τ�����
946 */
Do_Draw(forced)947 void Do_Draw( forced )
948 Bool forced;
949 {
950 static int Pat = NORM_PAT;
951 static unsigned int MepachiCount;
952 unsigned int pachi1, pachi2;
953 Bool drawface = False;
954
955 switch( theMode )
956 {
957 case NORM_MODE:
958 case QUIT_MODE:
959 pachi1 = MepachiCount % 15;
960 pachi2 = MepachiCount % 18;
961
962 if( pachi1 == 0 || pachi2 == 0 )
963 { Pat = CLOSE_PAT;
964 drawface = True;
965 }
966 else if( pachi1 == 1 || pachi2 == 1 )
967 { Pat = NORM_PAT;
968 drawface = True;
969 }
970 else if( forced )
971 { Pat = NORM_PAT;
972 }
973 MepachiCount++;
974 break;
975
976 case URUR_MODE:
977 if( Pat == URUR_PAT )
978 { Pat = URU2_PAT;
979 }else
980 { Pat = URUR_PAT;
981 }
982 drawface = True;
983 break;
984
985 case OHNO_MODE:
986 pachi1 = MepachiCount % 15;
987 pachi2 = MepachiCount % 18;
988
989 if( pachi1 == 0 || pachi2 == 0 )
990 { Pat = PSYU_PAT;
991 drawface = True;
992 }
993 else if( pachi1 == 1 || pachi2 == 1 )
994 { Pat = OHNO_PAT;
995 drawface = True;
996 }
997 else if( forced )
998 { Pat = OHNO_PAT;
999 }
1000 MepachiCount++;
1001 break;
1002
1003 case PSYU_MODE:
1004 Pat = PSYU_PAT;
1005 break;
1006
1007 default:
1008 break;
1009 }
1010
1011 if( forced ) /* ���̺����� */
1012 {
1013 XPutImage( Disp, MainWin, DefaultGC(Disp,DefaultScreen(Disp)),
1014 MyImage[ Pat ],
1015 0, 0, 0, 0, osuwari_width, osuwari_height );
1016 }
1017 else if( drawface ) /* ����ϰϤ��������褹�� */
1018 {
1019 XPutImage( Disp, MainWin, DefaultGC(Disp,DefaultScreen(Disp)),
1020 MyImage[ Pat ],
1021 12, 25, 12, 25, 40, 30 );
1022
1023 /* src_x, src_y, dest_x, dest_y, width, height )
1024 * Face Range : (12,25) - (52,55)
1025 */
1026 }
1027 }
1028
1029 /******** Do_NadeNade ********
1030 * �ʤǤʤǥ�å���������
1031 */
Do_NadeNade()1032 void Do_NadeNade( )
1033 {
1034 static unsigned int nade_cnt;
1035 char *str;
1036
1037 if( ++nade_cnt & 0x0F )
1038 return;
1039
1040 if( ! (nade_cnt % (5 * 0x10) ) )
1041 {
1042 str = NadeMsg[0]; /* ���������� */
1043 }
1044 else if( ! (nade_cnt % (12 * 0x10) ) )
1045 {
1046 str = NadeMsg[1]; /* ���������� */
1047 }
1048 else
1049 {
1050 str = NadeMsg[ 2 + ( (nade_cnt>>4) % 4) ];
1051 /* ��å��������ְʹߤΣ��Ĥ���֤˽Ф� */
1052 }
1053
1054 Do_Talk( str );
1055 }
1056
1057 /******** Do_FuniFuni ********
1058 * �դˤդ˥�å���������
1059 */
Do_FuniFuni()1060 void Do_FuniFuni( )
1061 {
1062 char *str;
1063
1064 /* �֤դˤդˡפ����ȥץ��塼������ */
1065 if( ++FuniCnt > MAX_FUNIFUNI )
1066 {
1067 str = PsyuMsg; /* �ץ��塼��å����� */
1068 theMode = PSYU_MODE;
1069 Do_Draw( True );
1070
1071 FuniCnt = 0;
1072 }
1073
1074 else if( ! (FuniCnt % 10) )
1075 {
1076 str = FuniMsg[0]; /* ���������� */
1077 }
1078 else if( ! (FuniCnt % 14) )
1079 {
1080 str = FuniMsg[1]; /* ���������� */
1081 }
1082 else
1083 {
1084 str = FuniMsg[ 2 + (FuniCnt % 4) ];
1085 /* ��å��������ְʹߤΣ��Ĥ���֤˽Ф� */
1086 }
1087
1088 Do_Talk( str );
1089 }
1090
1091 /******** Do_Quit ********
1092 * ��λ����å���������
1093 */
Do_Quit()1094 void Do_Quit( )
1095 {
1096 ClearTalk();
1097
1098 Do_Talk( QuitMsg );
1099 }
1100
1101 /******** Do_Talk ********
1102 * �֤դ������פ˥�å�������Ф�
1103 */
Do_Talk(str)1104 void Do_Talk( str )
1105 char *str;
1106 {
1107 int talk_width, talk_height;
1108 int n_line; /* �Կ� */
1109 int i;
1110
1111 n_line = AppendTalk( theFont, str );
1112 talk_height = n_line * FontHeight;
1113 talk_width = MaxTalkWidth( );
1114 talk_width = talk_width * 9 >> 3; /* ������ 9/8 �ܤ��� */
1115
1116 TalkShape( Disp, TalkWin, talk_width, talk_height, 0 );
1117
1118 if( ! isTalkMapped ) /* �դ��������ФƤ��ʤ���� */
1119 { XMapWindow( Disp, TalkWin ); /* ���̾�˽Ф� */
1120 isTalkMapped = True;
1121 }
1122 TalkCount = TALK_COUNT;
1123 XRaiseWindow( Disp, TalkWin );
1124
1125 XSetForeground( Disp, TalkGC, BgPixel ); /* �طʤ̤�Ĥ֤��õ� */
1126 XFillRectangle( Disp, TalkWin, TalkGC, 0, 0, talk_width, talk_height );
1127
1128 XSetForeground( Disp, TalkGC, FgPixel );
1129 for( i=0; i < n_line; i++ )
1130 {
1131 if( isKanji )
1132 { XChar2b kstr[ 128 ];
1133 Str2bCpy( kstr, TalkLines[i].str );
1134 XDrawString16( Disp, TalkWin, TalkGC,
1135 talk_width / 10,
1136 FontHeight * i + (FontHeight <<2) /5,
1137 kstr, TalkLines[i].len /2
1138 );
1139 }else
1140 {
1141 XDrawString( Disp, TalkWin, TalkGC,
1142 talk_width / 10,
1143 FontHeight * i + (FontHeight <<2) /5,
1144 TalkLines[i].str, TalkLines[i].len
1145 );
1146 }
1147 }
1148 }
1149
1150 /******** End of File ********/
1151
1152