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