OSDN Git Service

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