OSDN Git Service

幻覚に関するバグ修正.
[hengband/hengband.git] / src / chuukei.c
1 /* chuukei.c */
2
3 #include "angband.h"
4
5 #ifdef CHUUKEI
6
7 #include <stdio.h>
8 #include <stdarg.h>
9 #include <ctype.h>
10
11 #if defined(WINDOWS)
12 #include <winsock.h>
13 #elif defined(MACINTOSH)
14 #include <OpenTransport.h>
15 #include <OpenTptInternet.h>
16 #else
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <netdb.h>
21 #include <sys/time.h>
22 #include <arpa/inet.h>
23
24 #include <setjmp.h>
25 #include <signal.h>
26 #endif
27
28 #define MAX_HOSTNAME 256
29 #define RINGBUF_SIZE 65536*8
30 #define FRESH_QUEUE_SIZE 1024
31 #define WAIT 100*1000 /* ¥Ö¥é¥¦¥ºÂ¦¤Î¥¦¥¨¥¤¥È(usñ°Ì) */
32 #define DEFAULT_DELAY 50
33
34 static int sd; /* ¥½¥±¥Ã¥È¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿ */
35 static long epoch_time;  /* ³«»Ï»þ¹ï */
36 static long time_diff;   /* ¥×¥ì¥¤Â¦¤È¤Î»þ´Ö¤Î¤º¤ì(¤³¤ì¤ò¸«¤Ê¤¬¤é¥Ç¥£¥ì¥¤¤òÄ´À°¤·¤Æ¤¤¤¯) */
37 static int browse_delay; /* É½¼¨¤¹¤ë¤Þ¤Ç¤Î»þ´Ö(100msñ°Ì)(¤³¤Î´Ö¤Ë¥é¥°¤òµÛ¼ý¤¹¤ë) */
38 static int server_port;
39 static char server_name[MAX_HOSTNAME];
40
41
42 #ifdef WINDOWS
43 #define close closesocket
44 #endif
45
46 #ifdef MACINTOSH
47 static InetSvcRef inet_services = nil;
48 static EndpointRef ep                   = kOTInvalidEndpointRef;
49 #endif
50
51 /* ÉÁ²è¤¹¤ë»þ¹ï¤ò³Ð¤¨¤Æ¤ª¤¯¥­¥å¡¼¹½Â¤ÂΠ*/
52 static struct
53 {
54         int time[FRESH_QUEUE_SIZE];
55         int next;
56         int tail;
57 }fresh_queue;
58
59
60 /* ¥ê¥ó¥°¥Ð¥Ã¥Õ¥¡¹½Â¤ÂΠ*/
61 static struct
62 {
63         char *buf;
64         int wptr;
65         int rptr;
66         int inlen;
67 }ring;
68
69 #ifdef MACINTOSH
70 int recv(int s, char *buffer, size_t buflen, int flags)
71 {
72         OTFlags         junkFlags;
73         int n = OTRcv(ep, (void *) buffer, buflen, &junkFlags);
74         if( n <= 0 )
75                 return n;
76         return n;
77 }
78 #endif
79
80 /*
81  * Original hooks
82  */
83 static errr (*old_xtra_hook)(int n, int v);
84 static errr (*old_curs_hook)(int x, int y);
85 static errr (*old_bigcurs_hook)(int x, int y);
86 static errr (*old_wipe_hook)(int x, int y, int n);
87 static errr (*old_text_hook)(int x, int y, int n, byte a, cptr s);
88
89
90 static void disable_chuukei_server(void)
91 {
92         term *t = angband_term[0];
93
94         if (!chuukei_server) return;
95
96         chuukei_server = FALSE;
97
98         t->xtra_hook = old_xtra_hook;
99         t->curs_hook = old_curs_hook;
100         t->bigcurs_hook = old_bigcurs_hook;
101         t->wipe_hook = old_wipe_hook;
102         t->text_hook = old_text_hook;
103 }
104
105
106 /* ANSI C¤Ë¤è¤ì¤ÐstaticÊÑ¿ô¤Ï0¤Ç½é´ü²½¤µ¤ì¤ë¤¬°ì±þ½é´ü²½¤¹¤ë */
107 static errr init_chuukei(void)
108 {
109         fresh_queue.next = fresh_queue.tail = 0;
110         ring.wptr = ring.rptr = ring.inlen = 0;
111         fresh_queue.time[0] = 0;
112         ring.buf = malloc(RINGBUF_SIZE);
113         if (ring.buf == NULL) return (-1);
114
115         return (0);
116 }
117
118 /* ¸½ºß¤Î»þ´Ö¤ò100msñ°Ì¤Ç¼èÆÀ¤¹¤ë */
119 static long get_current_time(void)
120 {
121 #ifdef WINDOWS
122         return GetTickCount() / 100;
123 #elif defined(MACINTOSH)
124         return TickCount();
125 #else
126         struct timeval tv;
127         gettimeofday(&tv, NULL);
128
129         return (tv.tv_sec * 10 + tv.tv_usec / 100000);
130 #endif
131 }
132
133
134 /* ¥ê¥ó¥°¥Ð¥Ã¥Õ¥¡¹½Â¤ÂΤˠbuf ¤ÎÆâÍƤò²Ã¤¨¤ë */
135 static errr insert_ringbuf(char *buf)
136 {
137         int len;
138         len = strlen(buf) + 1; /* +1¤Ï½ªÃ¼Ê¸»úʬ */
139
140         /* ¥Ð¥Ã¥Õ¥¡¤ò¥ª¡¼¥Ð¡¼ */
141         if (ring.inlen + len >= RINGBUF_SIZE)
142         {
143                 if (chuukei_server) disable_chuukei_server();
144                 else chuukei_client = FALSE;
145
146                 prt("¥Ð¥Ã¥Õ¥¡¤¬°î¤ì¤Þ¤·¤¿¡£¥µ¡¼¥Ð¤È¤ÎÀܳ¤òÀÚÃǤ·¤Þ¤¹¡£", 0, 0);
147                 inkey();
148
149                 close(sd);
150
151                 return (-1);
152         }
153
154         /* ¥Ð¥Ã¥Õ¥¡¤Î½ªÃ¼¤Þ¤Ç¤Ë¼ý¤Þ¤ë */
155         if (ring.wptr + len < RINGBUF_SIZE)
156         {
157                 memcpy(ring.buf + ring.wptr, buf, len);
158                 ring.wptr += len;
159         }
160         /* ¥Ð¥Ã¥Õ¥¡¤Î½ªÃ¼¤Þ¤Ç¤Ë¼ý¤Þ¤é¤Ê¤¤(¥Ô¥Ã¥¿¥ê¼ý¤Þ¤ë¾ì¹ç¤â´Þ¤à) */
161         else
162         {
163                 int head = RINGBUF_SIZE - ring.wptr;  /* Á°È¾ */
164                 int tail = len - head;               /* ¸åȾ */
165
166                 memcpy(ring.buf + ring.wptr, buf, head);
167                 memcpy(ring.buf, buf + head, tail);
168                 ring.wptr = tail;
169         }
170
171         ring.inlen += len;
172
173         /* Success */
174         return (0);
175 }
176
177 void flush_ringbuf(void)
178 {
179 #ifndef MACINTOSH
180         fd_set fdset;
181         struct timeval tv;
182         int writen = 0;
183
184         if (!chuukei_server) return;
185
186         if (ring.inlen == 0) return;
187
188         tv.tv_sec = 0;
189         tv.tv_usec = 0;
190
191         FD_ZERO(&fdset);
192         FD_SET(sd, &fdset);
193
194         while (1)
195         {
196                 fd_set tmp_fdset;
197                 int result;
198
199                 tmp_fdset = fdset;
200
201                 /* ¥½¥±¥Ã¥È¤Ë¥Ç¡¼¥¿¤ò½ñ¤­¹þ¤á¤ë¤«¤É¤¦¤«Ä´¤Ù¤ë */
202                 select(sd+1, (fd_set *)NULL, &tmp_fdset, (fd_set *)NULL, &tv);
203
204                 /* ½ñ¤­¹þ¤á¤Ê¤±¤ì¤ÐÌá¤ë */
205                 if (FD_ISSET(sd, &tmp_fdset) == 0) break;
206
207                 result = send(sd, ring.buf + ring.rptr, ((ring.wptr > ring.rptr ) ? ring.wptr : RINGBUF_SIZE) - ring.rptr, 0);
208
209                 if (result <= 0)
210                 {
211                         /* ¥µ¡¼¥Ð¤È¤ÎÀܳÃÇ¡© */
212                         disable_chuukei_server();
213
214                         prt("¥µ¡¼¥Ð¤È¤ÎÀܳ¤¬ÀÚÃǤµ¤ì¤Þ¤·¤¿¡£", 0, 0);
215                         inkey();
216                         close(sd);
217
218                         return;
219                 }
220
221                 ring.rptr += result;
222                 ring.inlen -= result;
223                 writen += result;
224
225                 if (ring.rptr == RINGBUF_SIZE) ring.rptr = 0;
226                 if (ring.inlen == 0) break;
227         }
228 #else
229         struct timeval tv;
230         int writen = 0;
231
232         if (!chuukei_server) return;
233
234         if (ring.inlen == 0) return;
235
236         tv.tv_sec = 0;
237         tv.tv_usec = 0;
238
239         while (1)
240         {
241                 struct timeval tmp_tv;
242                 int result;
243
244                 tmp_tv = tv;
245
246                 /* ¥½¥±¥Ã¥È¤Ë¥Ç¡¼¥¿¤ò½ñ¤­¹þ¤á¤ë¤«¤É¤¦¤«Ä´¤Ù¤ë */
247                 result = OTSnd(ep, ring.buf + ring.rptr, ((ring.wptr > ring.rptr ) ? ring.wptr : RINGBUF_SIZE) - ring.rptr, 0);
248
249                 if (result <= 0)
250                 {
251                         /* ¥µ¡¼¥Ð¤È¤ÎÀܳÃÇ¡© */
252                         disable_chuukei_server();
253
254                         prt("¥µ¡¼¥Ð¤È¤ÎÀܳ¤¬ÀÚÃǤµ¤ì¤Þ¤·¤¿¡£", 0, 0);
255                         inkey();
256                         close(sd);
257
258                         return;
259                 }
260
261                 ring.rptr += result;
262                 ring.inlen -= result;
263                 writen += result;
264
265                 if (ring.rptr == RINGBUF_SIZE) ring.rptr = 0;
266                 if (ring.inlen == 0) break;
267         }
268 #endif
269 }
270
271 static int read_chuukei_prf(cptr prf_name)
272 {
273         char buf[1024];
274         FILE *fp;
275
276         path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA, prf_name);
277         fp = my_fopen(buf, "r");
278
279         if (!fp) return (-1);
280
281         /* ½é´ü²½ */
282         server_port = -1;
283         server_name[0] = 0;
284         browse_delay = DEFAULT_DELAY;
285
286         while (0 == my_fgets(fp, buf, sizeof(buf)))
287         {
288                 /* ¥µ¡¼¥Ð̾ */
289                 if (!strncmp(buf, "server:", 7))
290                 {
291                         strncpy(server_name, buf + 7, MAX_HOSTNAME - 1);
292                         server_name[MAX_HOSTNAME - 1] = '\0';
293                 }
294
295                 /* ¥Ý¡¼¥ÈÈÖ¹æ */
296                 if (!strncmp(buf, "port:", 5))
297                 {
298                         server_port = atoi(buf + 5);
299                 }
300
301                 /* ¥Ç¥£¥ì¥¤ */
302                 if (!strncmp(buf, "delay:", 6))
303                 {
304                         browse_delay = atoi(buf + 6);
305                 }
306         }
307
308         my_fclose(fp);
309
310         /* prf¥Õ¥¡¥¤¥ë¤¬´°Á´¤Ç¤Ê¤¤ */
311         if (server_port == -1 || server_name[0] == 0) return (-1);
312
313         return (0);
314 }
315
316 int connect_chuukei_server(char *prf_name)
317 {
318 #ifndef MACINTOSH
319
320 #ifdef WINDOWS
321         WSADATA wsaData;
322         WORD wVersionRequested = (WORD) (( 1) |  ( 1 << 8));
323 #endif
324
325         struct sockaddr_in ask;
326         struct hostent *hp;
327
328         if (read_chuukei_prf(prf_name) < 0)
329         {
330                 printf("Wrong prf file\n");
331                 return (-1);
332         }
333
334         if (init_chuukei() < 0)
335         {
336                 printf("Malloc error\n");
337                 return (-1);
338         }
339
340 #ifdef WINDOWS
341         if (WSAStartup(wVersionRequested, &wsaData))
342         {
343                 msg_print("Report: WSAStartup failed.");
344                 return (-1);
345         }
346 #endif
347
348         printf("server = %s\nport = %d\n", server_name, server_port);
349
350         if ((hp = gethostbyname(server_name)) != NULL)
351         {
352                 memset(&ask, 0, sizeof(ask));
353                 memcpy(&ask.sin_addr, hp->h_addr_list[0], hp->h_length);
354         }
355         else
356         {
357                 if ((ask.sin_addr.s_addr=inet_addr(server_name)) == 0)
358                 {
359                         printf("Bad hostname\n");
360                         return (-1);
361                 }
362         }
363
364         ask.sin_family = AF_INET;
365         ask.sin_port = htons((unsigned short)server_port);
366
367 #ifndef WINDOWS
368         if ((sd=socket(PF_INET,SOCK_STREAM, 0)) < 0)
369 #else
370         if ((sd=socket(PF_INET,SOCK_STREAM, 0)) == INVALID_SOCKET)
371 #endif
372         {
373                 printf("Can't create socket\n");
374                 return (-1);
375         }
376
377         if (connect(sd, (struct sockaddr *)&ask, sizeof(ask)) < 0)
378         {
379                 close(sd);
380                 printf("Can't connect %s port %d\n", server_name, server_port);
381                 return (-1);
382         }
383
384         epoch_time = get_current_time();
385
386         return (0);
387 #else   /* MACINTOSH */
388         OSStatus err;
389         InetHostInfo    response;
390         InetHost                host_addr;
391         InetAddress     inAddr;
392         TCall                   sndCall;
393         Boolean                 bind    = false;
394         OSStatus        junk;
395
396         if (read_chuukei_prf(prf_name) < 0){
397                 printf("Wrong prf file\n");
398                 return (-1);
399         }
400         
401         init_chuukei();
402         
403         printf("server = %s\nport = %d\n", server_name, server_port);
404
405
406 #if TARGET_API_MAC_CARBON
407         err = InitOpenTransportInContext(kInitOTForApplicationMask, NULL);
408 #else
409         err = InitOpenTransport();
410 #endif
411
412         memset(&response, 0, sizeof(response));
413
414
415 #if TARGET_API_MAC_CARBON
416         inet_services = OTOpenInternetServicesInContext(kDefaultInternetServicesPath, 0, &err, NULL);
417 #else
418         inet_services = OTOpenInternetServices(kDefaultInternetServicesPath, 0, &err);
419 #endif
420         
421         if (err == noErr) {
422                 err = OTInetStringToAddress(inet_services, (char *)server_name, &response);
423                 
424                 if (err == noErr) {
425                         host_addr = response.addrs[0];
426                 } else {
427                         printf("Bad hostname\n");
428                 }
429                 
430 #if TARGET_API_MAC_CARBON
431                 ep = (void *)OTOpenEndpointInContext(OTCreateConfiguration(kTCPName), 0, nil, &err, NULL);
432 #else
433                 ep = (void *)OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, nil, &err);
434 #endif
435
436                 if (err == noErr) {
437                         err = OTBind(ep, nil, nil);
438                         bind = (err == noErr);
439             }
440             if (err == noErr){
441                 OTInitInetAddress(&inAddr, server_port, host_addr);
442                         
443                         sndCall.addr.len        = sizeof(InetAddress);                          
444                         sndCall.addr.buf        = (unsigned char*) &inAddr;
445                         sndCall.opt.buf         = nil;        /* no connection options */
446                         sndCall.opt.len         = 0;
447                         sndCall.udata.buf       = nil;        /* no connection data */
448                         sndCall.udata.len       = 0;
449                         sndCall.sequence        = 0;          /* ignored by OTConnect */
450                         
451                         err = OTConnect(ep, &sndCall, NULL);
452                         
453                         if( err != noErr ){
454                                 printf("Can't connect %s port %d\n", server_name, server_port);
455                         }
456                 }
457                 
458                 err = OTSetSynchronous(ep);
459                 if (err == noErr)               
460                         err = OTSetBlocking(ep);
461                 
462         }
463         
464         if( err != noErr ){
465                 if( bind ){
466                         OTUnbind(ep);
467                 }
468                 /* Clean up. */
469                 if (ep != kOTInvalidEndpointRef) {
470                         OTCloseProvider(ep);
471                         ep = nil;
472                 }
473                 if (inet_services != nil) {
474                         OTCloseProvider(inet_services);
475                         inet_services = nil;
476                 }
477         
478                 return -1;
479         }
480         
481         return 0;
482
483 #endif
484 }
485
486
487 /* str¤¬Æ±¤¸Ê¸»ú¤Î·«¤êÊÖ¤·¤«¤É¤¦¤«Ä´¤Ù¤ë */
488 static bool string_is_repeat(char *str, int len)
489 {
490         char c = str[0];
491         int i;
492
493         if (len < 2) return (FALSE);
494 #ifdef JP
495         if (iskanji(c)) return (FALSE);
496 #endif
497
498         for (i = 1; i < len; i++)
499         {
500 #ifdef JP
501                 if(c != str[i] || iskanji(str[i])) return (FALSE);
502 #else
503                 if(c != str[i]) return (FALSE);
504 #endif
505         }
506
507         return (TRUE);
508 }
509
510 static errr send_text_to_chuukei_server(int x, int y, int len, byte col, cptr str)
511 {
512         char buf[1024];
513         char buf2[1024];
514
515         strncpy(buf2, str, len);
516         buf2[len] = '\0';
517
518         if (len == 1)
519         {
520                 sprintf(buf, "s%c%c%c%c", x+1, y+1, col, buf2[0]);
521         }
522         else if(string_is_repeat(buf2, len))
523         {
524                 sprintf(buf, "n%c%c%c%c%c", x+1, y+1, len, col, buf2[0]);
525         }
526         else
527         {
528 #ifdef SJIS
529                 sjis2euc(buf2);
530 #endif
531                 sprintf(buf, "t%c%c%c%c%s", x+1, y+1, len, col, buf2);
532         }
533
534         insert_ringbuf(buf);
535
536         return (*old_text_hook)(x, y, len, col, str);
537 }
538
539 static errr send_wipe_to_chuukei_server(int x, int y, int len)
540 {
541         char buf[1024];
542
543         sprintf(buf, "w%c%c%c", x+1, y+1, len);
544
545         insert_ringbuf(buf);
546
547         return (*old_wipe_hook)(x, y, len);
548 }
549
550 static errr send_xtra_to_chuukei_server(int n, int v)
551 {
552         char buf[1024];
553
554         (void)v;
555
556         if (n == TERM_XTRA_CLEAR || n == TERM_XTRA_FRESH || n == TERM_XTRA_SHAPE)
557         {
558                 sprintf(buf, "x%c", n+1);
559                 
560                 insert_ringbuf(buf);
561                 
562                 if (n == TERM_XTRA_FRESH)
563                 {
564                         sprintf(buf, "d%ld", get_current_time() - epoch_time);
565                         insert_ringbuf(buf);
566                 }
567         }
568
569         /* Verify the hook */
570         if (!old_xtra_hook) return -1;
571
572         return (*old_xtra_hook)(n, v);
573 }
574
575 static errr send_curs_to_chuukei_server(int x, int y)
576 {
577         char buf[1024];
578
579         sprintf(buf, "c%c%c", x+1, y+1);
580
581         insert_ringbuf(buf);
582
583         return (*old_curs_hook)(x, y);
584 }
585
586 static errr send_bigcurs_to_chuukei_server(int x, int y)
587 {
588         char buf[1024];
589
590         sprintf(buf, "C%c%c", x+1, y+1);
591
592         insert_ringbuf(buf);
593
594         return (*old_bigcurs_hook)(x, y);
595 }
596
597
598 /*
599  * Prepare z-term hooks to call send_*_to_chuukei_server()'s
600  */
601 void prepare_chuukei_hooks(void)
602 {
603         term *t0 = angband_term[0];
604
605         /* Save original z-term hooks */
606         old_xtra_hook = t0->xtra_hook;
607         old_curs_hook = t0->curs_hook;
608         old_bigcurs_hook = t0->bigcurs_hook;
609         old_wipe_hook = t0->wipe_hook;
610         old_text_hook = t0->text_hook;
611
612         /* Prepare z-term hooks */
613         t0->xtra_hook = send_xtra_to_chuukei_server;
614         t0->curs_hook = send_curs_to_chuukei_server;
615         t0->bigcurs_hook = send_bigcurs_to_chuukei_server;
616         t0->wipe_hook = send_wipe_to_chuukei_server;
617         t0->text_hook = send_text_to_chuukei_server;
618 }
619
620
621 static int read_sock(void)
622 {
623         char buf[1024];
624         int i;
625
626         for (i = 0;; i++)
627         {
628                 if (recv(sd, buf+i, 1, 0) <= 0) 
629                         return -1;
630
631                 if (buf[i] == '\0')
632                 {
633                         if (buf[0] == 'd')
634                         {
635                                 int timestamp = atoi(buf + 1);
636                                 long current_time = get_current_time();
637
638                                 /* ºÇ½é¤Î»þ´Ö¤òÊݸ¤·¤Æ¤ª¤¯ */
639                                 if (!fresh_queue.time[0])
640                                 {
641                                         epoch_time = current_time;
642                                         epoch_time += browse_delay;
643                                         epoch_time -= timestamp;
644                                         time_diff = current_time - timestamp;
645                                 }
646
647                                 fresh_queue.time[fresh_queue.tail] = timestamp;
648                                 fresh_queue.tail ++;
649
650                                 if (fresh_queue.tail == FRESH_QUEUE_SIZE)
651                                         fresh_queue.tail = 0;
652
653                                 /* ¥×¥ì¥¤Â¦¤È¤Î¥Ç¥£¥ì¥¤¤òÄ´À° */
654                                 if (time_diff > current_time - timestamp)
655                                 {
656                                         long old_time_diff = time_diff;
657                                         time_diff = current_time - timestamp;
658                                         epoch_time -= (old_time_diff - time_diff);
659                                 }
660
661                                 if (fresh_queue.tail == fresh_queue.next)
662                                 {
663                                         /* queue°î¤ì */
664                                         close(sd);
665                                         exit(1);
666                                 }
667
668                         }
669
670                         if (insert_ringbuf(buf) < 0) 
671                                 return -1;
672                         return (i);
673                 }
674         }
675 }
676
677
678 #ifndef WINDOWS
679 /* WinÈǤÎÃæÅÀ¤ÈÊɤÎƦÉå¤ò¥Ô¥ê¥ª¥É¤È¥·¥ã¡¼¥×¤Ë¤¹¤ë¡£ */
680 static void win2unix(int col, char *buf)
681 {
682         char kabe;
683         if ( col == 9 ) kabe = '%';
684         else            kabe = '#';
685
686         while (*buf)
687         {
688 #ifdef JP
689                 if (iskanji(*buf))
690                 {
691                         buf += 2;
692                         continue;
693                 }
694 #endif
695                 if (*buf == 127) *buf = kabe;
696                 else if(*buf == 31) *buf = '.';
697                 buf++;
698         }
699 }
700 #endif
701
702 static bool get_nextbuf(char *buf)
703 {
704         char *ptr = buf;
705
706         while (1)
707         {
708                 *ptr = ring.buf[ring.rptr ++];
709                 ring.inlen --;
710                 if (ring.rptr == RINGBUF_SIZE) ring.rptr = 0;
711                 if (*ptr++ == '\0') break;
712         }
713
714         if (buf[0] == 'd') return (FALSE);
715
716         return (TRUE);
717 }
718
719 static bool flush_ringbuf_client(void)
720 {
721         char buf[1024];
722
723         /* ½ñ¤¯¥Ç¡¼¥¿¤Ê¤· */
724         if (fresh_queue.next == fresh_queue.tail) return (FALSE);
725
726         /* ¤Þ¤À½ñ¤¯¤Ù¤­»þ¤Ç¤Ê¤¤ */
727         if (fresh_queue.time[fresh_queue.next] > get_current_time() - epoch_time) return (FALSE);
728
729         /* »þ´Ö¾ðÊó(¶èÀÚ¤ê)¤¬ÆÀ¤é¤ì¤ë¤Þ¤Ç½ñ¤¯ */
730         while (get_nextbuf(buf))
731         {
732                 char id;
733                 int x, y, len, col;
734                 int i;
735                 char tmp1, tmp2, tmp3, tmp4;
736                 char *mesg;
737
738                 sscanf(buf, "%c%c%c%c%c", &id, &tmp1, &tmp2, &tmp3, &tmp4);
739                 x = tmp1-1; y = tmp2-1; len = tmp3; col = tmp4;
740                 if (id == 's')
741                 {
742                         col = tmp3;
743                         mesg = &buf[4];
744                 }
745                 else mesg = &buf[5];
746 #ifndef WINDOWS
747                 win2unix(col, mesg);
748 #endif
749
750                 switch (id)
751                 {
752                 case 't': /* Ä̾ï */
753 #ifdef SJIS
754                         euc2sjis(mesg);
755 #endif
756                         (void)((*angband_term[0]->text_hook)(x, y, len, (byte)col, mesg));
757                         strncpy(&Term->scr->c[y][x], mesg, len);
758                         for (i = x; i < x+len; i++)
759                         {
760                                 Term->scr->a[y][i] = col;
761                         }
762                         break;
763
764                 case 'n': /* ·«¤êÊÖ¤· */
765                         for (i = 1; i < len; i++)
766                         {
767                                 mesg[i] = mesg[0];
768                         }
769                         mesg[i] = '\0';
770                         (void)((*angband_term[0]->text_hook)(x, y, len, (byte)col, mesg));
771                         strncpy(&Term->scr->c[y][x], mesg, len);
772                         for (i = x; i < x+len; i++)
773                         {
774                                 Term->scr->a[y][i] = col;
775                         }
776                         break;
777
778                 case 's': /* °ìʸ»ú */
779                         (void)((*angband_term[0]->text_hook)(x, y, 1, (byte)col, mesg));
780                         strncpy(&Term->scr->c[y][x], mesg, 1);
781                         Term->scr->a[y][x] = col;
782                         break;
783
784                 case 'w':
785                         (void)((*angband_term[0]->wipe_hook)(x, y, len));
786                         break;
787
788                 case 'x':
789                         if (x == TERM_XTRA_CLEAR) Term_clear();
790                         (void)((*angband_term[0]->xtra_hook)(x, 0));
791                         break;
792
793                 case 'c':
794                         (void)((*angband_term[0]->curs_hook)(x, y));
795                         break;
796                 case 'C':
797                         (void)((*angband_term[0]->bigcurs_hook)(x, y));
798                         break;
799                 }
800         }
801
802         fresh_queue.next++;
803         if (fresh_queue.next == FRESH_QUEUE_SIZE) fresh_queue.next = 0;
804         return (TRUE);
805 }
806
807 void browse_chuukei()
808 {
809 #ifndef MACINTOSH
810         fd_set fdset;
811         struct timeval tv;
812
813         tv.tv_sec = 0;
814         tv.tv_usec = WAIT;
815
816         FD_ZERO(&fdset);
817         FD_SET(sd, &fdset);
818
819         Term_clear();
820         Term_fresh();
821         Term_xtra(TERM_XTRA_REACT, 0);
822
823         while (1)
824         {
825                 fd_set tmp_fdset;
826                 struct timeval tmp_tv;
827
828                 if (flush_ringbuf_client()) continue;
829
830                 tmp_fdset = fdset;
831                 tmp_tv = tv;
832
833                 /* ¥½¥±¥Ã¥È¤Ë¥Ç¡¼¥¿¤¬Íè¤Æ¤¤¤ë¤«¤É¤¦¤«Ä´¤Ù¤ë */
834                 select(sd+1, &tmp_fdset, (fd_set *)NULL, (fd_set *)NULL, &tmp_tv);
835                 if (FD_ISSET(sd, &tmp_fdset) == 0)
836                 {
837                         Term_xtra(TERM_XTRA_FLUSH, 0);
838                         continue;
839                 }
840
841                 if (read_sock() < 0)
842                 {
843                         chuukei_client = FALSE;
844                 }
845
846                 /* Àܳ¤¬Àڤ줿¾õÂ֤ǽñ¤¯¤Ù¤­¥Ç¡¼¥¿¤¬¤Ê¤¯¤Ê¤Ã¤Æ¤¤¤¿¤é½ªÎ» */
847                 if (!chuukei_client && fresh_queue.next == fresh_queue.tail ) break;
848         }
849 #else
850         struct timeval tv;
851
852         tv.tv_sec = 0;
853         tv.tv_usec = WAIT;
854
855         Term_clear();
856         Term_fresh();
857         Term_xtra(TERM_XTRA_REACT, 0);
858
859         while (1)
860         {
861                 struct timeval tmp_tv;
862                 UInt32  unreadData = 0;
863                 int n;
864                 
865                 if (flush_ringbuf_client()) continue;
866
867                 tmp_tv = tv;
868
869                 /* ¥½¥±¥Ã¥È¤Ë¥Ç¡¼¥¿¤¬Íè¤Æ¤¤¤ë¤«¤É¤¦¤«Ä´¤Ù¤ë */
870                 
871                 OTCountDataBytes(ep, &unreadData);
872                 if(unreadData <= 0 ){
873                         Term_xtra(TERM_XTRA_FLUSH, 0);
874                         continue;
875                 }
876                 if (read_sock() < 0)
877                 {
878                         chuukei_client = FALSE;
879                 }
880
881                 /* Àܳ¤¬Àڤ줿¾õÂ֤ǽñ¤¯¤Ù¤­¥Ç¡¼¥¿¤¬¤Ê¤¯¤Ê¤Ã¤Æ¤¤¤¿¤é½ªÎ» */
882                 if (!chuukei_client && fresh_queue.next == fresh_queue.tail ) break;
883         }
884 #endif /*MACINTOSH*/
885 }
886
887 #endif /* CHUUKEI */