OSDN Git Service

refactor compare_weapon_aux
[hengband/hengband.git] / src / chuukei.c
1 /* chuukei.c */
2
3 #include "angband.h"
4
5 #include <stdio.h>
6 #include <stdarg.h>
7 #include <ctype.h>
8 #ifdef WINDOWS
9 #include <windows.h>
10 #endif
11
12 #ifdef CHUUKEI
13 #if defined(WINDOWS)
14 #include <winsock.h>
15 #elif defined(MACINTOSH)
16 #include <OpenTransport.h>
17 #include <OpenTptInternet.h>
18 #else
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <netdb.h>
23 #include <sys/time.h>
24 #include <arpa/inet.h>
25
26 #include <setjmp.h>
27 #include <signal.h>
28 #endif
29
30 #define MAX_HOSTNAME 256
31 #endif
32
33 #define RINGBUF_SIZE 1024*1024
34 #define FRESH_QUEUE_SIZE 4096
35 #ifdef WINDOWS
36 #define WAIT 100
37 #else
38 #define WAIT 100*1000 /* ¥Ö¥é¥¦¥ºÂ¦¤Î¥¦¥¨¥¤¥È(usñ°Ì) */
39 #endif
40 #define DEFAULT_DELAY 50
41 #define RECVBUF_SIZE 1024
42
43 static long epoch_time;  /* ¥Ð¥Ã¥Õ¥¡³«»Ï»þ¹ï */
44 static int browse_delay; /* É½¼¨¤¹¤ë¤Þ¤Ç¤Î»þ´Ö(100msñ°Ì)(¤³¤Î´Ö¤Ë¥é¥°¤òµÛ¼ý¤¹¤ë) */
45 #ifdef CHUUKEI
46 static int sd; /* ¥½¥±¥Ã¥È¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿ */
47 static long time_diff;   /* ¥×¥ì¥¤Â¦¤È¤Î»þ´Ö¤Î¤º¤ì(¤³¤ì¤ò¸«¤Ê¤¬¤é¥Ç¥£¥ì¥¤¤òÄ´À°¤·¤Æ¤¤¤¯) */
48 static int server_port;
49 static char server_name[MAX_HOSTNAME];
50 #endif
51
52 static int movie_fd;
53 static int movie_mode;
54
55 #ifdef CHUUKEI
56 #ifdef WINDOWS
57 #define close closesocket
58 #endif
59
60 #ifdef MACINTOSH
61 static InetSvcRef inet_services = nil;
62 static EndpointRef ep                   = kOTInvalidEndpointRef;
63 #endif
64 #endif
65 /* ÉÁ²è¤¹¤ë»þ¹ï¤ò³Ð¤¨¤Æ¤ª¤¯¥­¥å¡¼¹½Â¤ÂΠ*/
66 static struct
67 {
68         int time[FRESH_QUEUE_SIZE];
69         int next;
70         int tail;
71 }fresh_queue;
72
73
74 /* ¥ê¥ó¥°¥Ð¥Ã¥Õ¥¡¹½Â¤ÂΠ*/
75 static struct
76 {
77         char *buf;
78         int wptr;
79         int rptr;
80         int inlen;
81 }ring;
82
83 #ifdef MACINTOSH
84 int recv(int s, char *buffer, size_t buflen, int flags)
85 {
86         OTFlags         junkFlags;
87         int n = OTRcv(ep, (void *) buffer, buflen, &junkFlags);
88         if( n <= 0 )
89                 return n;
90         return n;
91 }
92 #endif
93
94 /*
95  * Original hooks
96  */
97 static errr (*old_xtra_hook)(int n, int v);
98 static errr (*old_curs_hook)(int x, int y);
99 static errr (*old_bigcurs_hook)(int x, int y);
100 static errr (*old_wipe_hook)(int x, int y, int n);
101 static errr (*old_text_hook)(int x, int y, int n, byte a, cptr s);
102
103 static void disable_chuukei_server(void)
104 {
105         term *t = angband_term[0];
106 #ifdef CHUUKEI
107         chuukei_server = FALSE;
108 #endif /* CHUUKEI */
109         t->xtra_hook = old_xtra_hook;
110         t->curs_hook = old_curs_hook;
111         t->bigcurs_hook = old_bigcurs_hook;
112         t->wipe_hook = old_wipe_hook;
113         t->text_hook = old_text_hook;
114 }
115
116 /* ANSI C¤Ë¤è¤ì¤ÐstaticÊÑ¿ô¤Ï0¤Ç½é´ü²½¤µ¤ì¤ë¤¬°ì±þ½é´ü²½¤¹¤ë */
117 static errr init_buffer(void)
118 {
119         fresh_queue.next = fresh_queue.tail = 0;
120         ring.wptr = ring.rptr = ring.inlen = 0;
121         fresh_queue.time[0] = 0;
122         ring.buf = malloc(RINGBUF_SIZE);
123         if (ring.buf == NULL) return (-1);
124
125         return (0);
126 }
127
128 /* ¸½ºß¤Î»þ´Ö¤ò100msñ°Ì¤Ç¼èÆÀ¤¹¤ë */
129 static long get_current_time(void)
130 {
131 #ifdef WINDOWS
132         return timeGetTime() / 100;
133 #elif defined(MACINTOSH)
134         return TickCount();
135 #else
136         struct timeval tv;
137         gettimeofday(&tv, NULL);
138
139         return (tv.tv_sec * 10 + tv.tv_usec / 100000);
140 #endif
141 }
142
143
144 /* ¥ê¥ó¥°¥Ð¥Ã¥Õ¥¡¹½Â¤ÂΤˠbuf ¤ÎÆâÍƤò²Ã¤¨¤ë */
145 static errr insert_ringbuf(char *buf)
146 {
147         int len;
148         len = strlen(buf) + 1; /* +1¤Ï½ªÃ¼Ê¸»úʬ */
149
150         if (movie_mode)
151         {
152                 fd_write(movie_fd, buf, len);
153 #ifdef CHUUKEI
154                 if (!chuukei_server) return 0;
155 #else
156                 return 0;
157 #endif
158         }
159
160         /* ¥Ð¥Ã¥Õ¥¡¤ò¥ª¡¼¥Ð¡¼ */
161         if (ring.inlen + len >= RINGBUF_SIZE)
162         {
163 #ifdef CHUUKEI
164                 if (chuukei_server) disable_chuukei_server();
165                 else chuukei_client = FALSE;
166
167                 prt("Á÷¼õ¿®¥Ð¥Ã¥Õ¥¡¤¬°î¤ì¤Þ¤·¤¿¡£¥µ¡¼¥Ð¤È¤ÎÀܳ¤òÀÚÃǤ·¤Þ¤¹¡£", 0, 0);
168                 inkey();
169
170                 close(sd);
171 #endif
172                 return (-1);
173         }
174
175         /* ¥Ð¥Ã¥Õ¥¡¤Î½ªÃ¼¤Þ¤Ç¤Ë¼ý¤Þ¤ë */
176         if (ring.wptr + len < RINGBUF_SIZE)
177         {
178                 memcpy(ring.buf + ring.wptr, buf, len);
179                 ring.wptr += len;
180         }
181         /* ¥Ð¥Ã¥Õ¥¡¤Î½ªÃ¼¤Þ¤Ç¤Ë¼ý¤Þ¤é¤Ê¤¤(¥Ô¥Ã¥¿¥ê¼ý¤Þ¤ë¾ì¹ç¤â´Þ¤à) */
182         else
183         {
184                 int head = RINGBUF_SIZE - ring.wptr;  /* Á°È¾ */
185                 int tail = len - head;               /* ¸åȾ */
186
187                 memcpy(ring.buf + ring.wptr, buf, head);
188                 memcpy(ring.buf, buf + head, tail);
189                 ring.wptr = tail;
190         }
191
192         ring.inlen += len;
193
194         /* Success */
195         return (0);
196 }
197
198 #ifdef CHUUKEI
199 void flush_ringbuf(void)
200 {
201 #ifndef MACINTOSH
202         fd_set fdset;
203         struct timeval tv;
204
205         if (!chuukei_server) return;
206
207         if (ring.inlen == 0) return;
208
209         tv.tv_sec = 0;
210         tv.tv_usec = 0;
211
212         FD_ZERO(&fdset);
213         FD_SET(sd, &fdset);
214
215         while (1)
216         {
217                 fd_set tmp_fdset;
218                 int result;
219
220                 tmp_fdset = fdset;
221
222                 /* ¥½¥±¥Ã¥È¤Ë¥Ç¡¼¥¿¤ò½ñ¤­¹þ¤á¤ë¤«¤É¤¦¤«Ä´¤Ù¤ë */
223                 select(sd+1, (fd_set *)NULL, &tmp_fdset, (fd_set *)NULL, &tv);
224
225                 /* ½ñ¤­¹þ¤á¤Ê¤±¤ì¤ÐÌá¤ë */
226                 if (FD_ISSET(sd, &tmp_fdset) == 0) break;
227
228                 result = send(sd, ring.buf + ring.rptr, ((ring.wptr > ring.rptr ) ? ring.wptr : RINGBUF_SIZE) - ring.rptr, 0);
229
230                 if (result <= 0)
231                 {
232                         /* ¥µ¡¼¥Ð¤È¤ÎÀܳÃÇ¡© */
233                         if (chuukei_server) disable_chuukei_server();
234
235                         prt("¥µ¡¼¥Ð¤È¤ÎÀܳ¤¬ÀÚÃǤµ¤ì¤Þ¤·¤¿¡£", 0, 0);
236                         inkey();
237                         close(sd);
238
239                         return;
240                 }
241
242                 ring.rptr += result;
243                 ring.inlen -= result;
244
245                 if (ring.rptr == RINGBUF_SIZE) ring.rptr = 0;
246                 if (ring.inlen == 0) break;
247         }
248 #else
249         if (!chuukei_server) return;
250
251         if (ring.inlen == 0) return;
252
253         while (1)
254         {
255                 int result;
256
257                 /* ¥½¥±¥Ã¥È¤Ë¥Ç¡¼¥¿¤ò½ñ¤­¹þ¤á¤ë¤«¤É¤¦¤«Ä´¤Ù¤ë */
258                 result = OTSnd(ep, ring.buf + ring.rptr, ((ring.wptr > ring.rptr ) ? ring.wptr : RINGBUF_SIZE) - ring.rptr, 0);
259
260                 if (result <= 0)
261                 {
262                         /* ¥µ¡¼¥Ð¤È¤ÎÀܳÃÇ¡© */
263                         if (chuukei_server) disable_chuukei_server();
264
265                         prt("¥µ¡¼¥Ð¤È¤ÎÀܳ¤¬ÀÚÃǤµ¤ì¤Þ¤·¤¿¡£", 0, 0);
266                         inkey();
267                         close(sd);
268
269                         return;
270                 }
271
272                 ring.rptr += result;
273                 ring.inlen -= result;
274
275                 if (ring.rptr == RINGBUF_SIZE) ring.rptr = 0;
276                 if (ring.inlen == 0) break;
277         }
278 #endif
279 }
280
281
282 static int read_chuukei_prf(cptr prf_name)
283 {
284         char buf[1024];
285         FILE *fp;
286
287         path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA, prf_name);
288         fp = my_fopen(buf, "r");
289
290         if (!fp) return (-1);
291
292         /* ½é´ü²½ */
293         server_port = -1;
294         server_name[0] = 0;
295         browse_delay = DEFAULT_DELAY;
296
297         while (0 == my_fgets(fp, buf, sizeof(buf)))
298         {
299                 /* ¥µ¡¼¥Ð̾ */
300                 if (!strncmp(buf, "server:", 7))
301                 {
302                         strncpy(server_name, buf + 7, MAX_HOSTNAME - 1);
303                         server_name[MAX_HOSTNAME - 1] = '\0';
304                 }
305
306                 /* ¥Ý¡¼¥ÈÈÖ¹æ */
307                 if (!strncmp(buf, "port:", 5))
308                 {
309                         server_port = atoi(buf + 5);
310                 }
311
312                 /* ¥Ç¥£¥ì¥¤ */
313                 if (!strncmp(buf, "delay:", 6))
314                 {
315                         browse_delay = atoi(buf + 6);
316                 }
317         }
318
319         my_fclose(fp);
320
321         /* prf¥Õ¥¡¥¤¥ë¤¬´°Á´¤Ç¤Ê¤¤ */
322         if (server_port == -1 || server_name[0] == 0) return (-1);
323
324         return (0);
325 }
326
327 int connect_chuukei_server(char *prf_name)
328 {
329 #ifndef MACINTOSH
330
331 #ifdef WINDOWS
332         WSADATA wsaData;
333         WORD wVersionRequested = (WORD) (( 1) |  ( 1 << 8));
334 #endif
335
336         struct sockaddr_in ask;
337         struct hostent *hp;
338
339         if (read_chuukei_prf(prf_name) < 0)
340         {
341                 printf("Wrong prf file\n");
342                 return (-1);
343         }
344
345         if (init_buffer() < 0)
346         {
347                 printf("Malloc error\n");
348                 return (-1);
349         }
350
351 #ifdef WINDOWS
352         if (WSAStartup(wVersionRequested, &wsaData))
353         {
354                 msg_print("Report: WSAStartup failed.");
355                 return (-1);
356         }
357 #endif
358
359         printf("server = %s\nport = %d\n", server_name, server_port);
360
361         if ((hp = gethostbyname(server_name)) != NULL)
362         {
363                 memset(&ask, 0, sizeof(ask));
364                 memcpy(&ask.sin_addr, hp->h_addr_list[0], hp->h_length);
365         }
366         else
367         {
368                 if ((ask.sin_addr.s_addr=inet_addr(server_name)) == 0)
369                 {
370                         printf("Bad hostname\n");
371                         return (-1);
372                 }
373         }
374
375         ask.sin_family = AF_INET;
376         ask.sin_port = htons((unsigned short)server_port);
377
378 #ifndef WINDOWS
379         if ((sd=socket(PF_INET,SOCK_STREAM, 0)) < 0)
380 #else
381         if ((sd=socket(PF_INET,SOCK_STREAM, 0)) == INVALID_SOCKET)
382 #endif
383         {
384                 printf("Can't create socket\n");
385                 return (-1);
386         }
387
388         if (connect(sd, (struct sockaddr *)&ask, sizeof(ask)) < 0)
389         {
390                 close(sd);
391                 printf("Can't connect %s port %d\n", server_name, server_port);
392                 return (-1);
393         }
394
395         return (0);
396 #else   /* MACINTOSH */
397         OSStatus err;
398         InetHostInfo    response;
399         InetHost                host_addr;
400         InetAddress     inAddr;
401         TCall                   sndCall;
402         Boolean                 bind    = false;
403         OSStatus        junk;
404
405         if (read_chuukei_prf(prf_name) < 0){
406                 printf("Wrong prf file\n");
407                 return (-1);
408         }
409         
410         init_buffer();
411         
412         printf("server = %s\nport = %d\n", server_name, server_port);
413
414
415 #if TARGET_API_MAC_CARBON
416         err = InitOpenTransportInContext(kInitOTForApplicationMask, NULL);
417 #else
418         err = InitOpenTransport();
419 #endif
420
421         memset(&response, 0, sizeof(response));
422
423
424 #if TARGET_API_MAC_CARBON
425         inet_services = OTOpenInternetServicesInContext(kDefaultInternetServicesPath, 0, &err, NULL);
426 #else
427         inet_services = OTOpenInternetServices(kDefaultInternetServicesPath, 0, &err);
428 #endif
429         
430         if (err == noErr) {
431                 err = OTInetStringToAddress(inet_services, (char *)server_name, &response);
432                 
433                 if (err == noErr) {
434                         host_addr = response.addrs[0];
435                 } else {
436                         printf("Bad hostname\n");
437                 }
438                 
439 #if TARGET_API_MAC_CARBON
440                 ep = (void *)OTOpenEndpointInContext(OTCreateConfiguration(kTCPName), 0, nil, &err, NULL);
441 #else
442                 ep = (void *)OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, nil, &err);
443 #endif
444
445                 if (err == noErr) {
446                         err = OTBind(ep, nil, nil);
447                         bind = (err == noErr);
448             }
449             if (err == noErr){
450                 OTInitInetAddress(&inAddr, server_port, host_addr);
451                         
452                         sndCall.addr.len        = sizeof(InetAddress);                          
453                         sndCall.addr.buf        = (unsigned char*) &inAddr;
454                         sndCall.opt.buf         = nil;          /* no connection options */
455                         sndCall.opt.len         = 0;
456                         sndCall.udata.buf       = nil;          /* no connection data */
457                         sndCall.udata.len       = 0;
458                         sndCall.sequence        = 0;            /* ignored by OTConnect */
459                         
460                         err = OTConnect(ep, &sndCall, NULL);
461                         
462                         if( err != noErr ){
463                                 printf("Can't connect %s port %d\n", server_name, server_port);
464                         }
465                 }
466                 
467                 err = OTSetSynchronous(ep);
468                 if (err == noErr)               
469                         err = OTSetBlocking(ep);
470                 
471         }
472         
473         if( err != noErr ){
474                 if( bind ){
475                         OTUnbind(ep);
476                 }
477                 /* Clean up. */
478                 if (ep != kOTInvalidEndpointRef) {
479                         OTCloseProvider(ep);
480                         ep = nil;
481                 }
482                 if (inet_services != nil) {
483                         OTCloseProvider(inet_services);
484                         inet_services = nil;
485                 }
486         
487                 return -1;
488         }
489         
490         return 0;
491
492 #endif
493 }
494 #endif /* CHUUKEI */
495
496 /* str¤¬Æ±¤¸Ê¸»ú¤Î·«¤êÊÖ¤·¤«¤É¤¦¤«Ä´¤Ù¤ë */
497 static bool string_is_repeat(char *str, int len)
498 {
499         char c = str[0];
500         int i;
501
502         if (len < 2) return (FALSE);
503 #ifdef JP
504         if (iskanji(c)) return (FALSE);
505 #endif
506
507         for (i = 1; i < len; i++)
508         {
509 #ifdef JP
510                 if(c != str[i] || iskanji(str[i])) return (FALSE);
511 #else
512                 if(c != str[i]) return (FALSE);
513 #endif
514         }
515
516         return (TRUE);
517 }
518
519 static errr send_text_to_chuukei_server(int x, int y, int len, byte col, cptr str)
520 {
521         char buf[1024];
522         char buf2[1024];
523
524         strncpy(buf2, str, len);
525         buf2[len] = '\0';
526
527         if (len == 1)
528         {
529                 sprintf(buf, "s%c%c%c%c", x+1, y+1, col, buf2[0]);
530         }
531         else if(string_is_repeat(buf2, len))
532         {
533                 int i;
534                 for (i = len; i > 0; i -= 127)
535                 {
536                         sprintf(buf, "n%c%c%c%c%c", x+1, y+1, MIN(i, 127), col, buf2[0]);
537                 }
538         }
539         else
540         {
541 #ifdef SJIS
542                 sjis2euc(buf2);
543 #endif
544                 sprintf(buf, "t%c%c%c%c%s", x+1, y+1, len, col, buf2);
545         }
546
547         insert_ringbuf(buf);
548
549         return (*old_text_hook)(x, y, len, col, str);
550 }
551
552 static errr send_wipe_to_chuukei_server(int x, int y, int len)
553 {
554         char buf[1024];
555
556         sprintf(buf, "w%c%c%c", x+1, y+1, len);
557
558         insert_ringbuf(buf);
559
560         return (*old_wipe_hook)(x, y, len);
561 }
562
563 static errr send_xtra_to_chuukei_server(int n, int v)
564 {
565         char buf[1024];
566
567         if (n == TERM_XTRA_CLEAR || n == TERM_XTRA_FRESH || n == TERM_XTRA_SHAPE)
568         {
569                 sprintf(buf, "x%c", n+1);
570                 
571                 insert_ringbuf(buf);
572                 
573                 if (n == TERM_XTRA_FRESH)
574                 {
575                         sprintf(buf, "d%ld", get_current_time() - epoch_time);
576                         insert_ringbuf(buf);
577                 }
578         }
579
580         /* Verify the hook */
581         if (!old_xtra_hook) return -1;
582
583         return (*old_xtra_hook)(n, v);
584 }
585
586 static errr send_curs_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_curs_hook)(x, y);
595 }
596
597 static errr send_bigcurs_to_chuukei_server(int x, int y)
598 {
599         char buf[1024];
600
601         sprintf(buf, "C%c%c", x+1, y+1);
602
603         insert_ringbuf(buf);
604
605         return (*old_bigcurs_hook)(x, y);
606 }
607
608
609 /*
610  * Prepare z-term hooks to call send_*_to_chuukei_server()'s
611  */
612 void prepare_chuukei_hooks(void)
613 {
614         term *t0 = angband_term[0];
615
616         /* Save original z-term hooks */
617         old_xtra_hook = t0->xtra_hook;
618         old_curs_hook = t0->curs_hook;
619         old_bigcurs_hook = t0->bigcurs_hook;
620         old_wipe_hook = t0->wipe_hook;
621         old_text_hook = t0->text_hook;
622
623         /* Prepare z-term hooks */
624         t0->xtra_hook = send_xtra_to_chuukei_server;
625         t0->curs_hook = send_curs_to_chuukei_server;
626         t0->bigcurs_hook = send_bigcurs_to_chuukei_server;
627         t0->wipe_hook = send_wipe_to_chuukei_server;
628         t0->text_hook = send_text_to_chuukei_server;
629 }
630
631
632 /*
633  * Prepare z-term hooks to call send_*_to_chuukei_server()'s
634  */
635 void prepare_movie_hooks(void)
636 {
637         char buf[1024];
638         char tmp[80];
639
640         if (movie_mode)
641         {
642                 movie_mode = 0;
643 #ifdef CHUUKEI
644                 if (!chuukei_server) disable_chuukei_server();
645 #else
646                 disable_chuukei_server();
647 #endif
648                 fd_close(movie_fd);
649 #ifdef JP
650                 msg_print("Ï¿²è¤ò½ªÎ»¤·¤Þ¤·¤¿¡£");
651 #else
652                 msg_print("Stopped recording.");
653 #endif
654         }
655         else
656         {
657                 sprintf(tmp, "%s.amv", player_base);
658 #ifdef JP
659                 if (get_string("¥à¡¼¥Ó¡¼µ­Ï¿¥Õ¥¡¥¤¥ë: ", tmp, 80))
660 #else
661                 if (get_string("Movie file name: ", tmp, 80))
662 #endif
663                 {
664                         int fd;
665
666                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
667
668                         fd = fd_open(buf, O_RDONLY);
669
670                         /* Existing file */
671                         if (fd >= 0)
672                         {
673                                 char out_val[160];
674
675                                 /* Close the file */
676                                 (void)fd_close(fd);
677
678                                 /* Build query */
679 #ifdef JP
680                                 (void)sprintf(out_val, "¸½Â¸¤¹¤ë¥Õ¥¡¥¤¥ë¤Ë¾å½ñ¤­¤·¤Þ¤¹¤«? (%s)", buf);
681 #else
682                                 (void)sprintf(out_val, "Replace existing file %s? ", buf);
683 #endif
684
685                                 /* Ask */
686                                 if (!get_check(out_val)) return;
687
688                                 movie_fd = fd_open(buf, O_WRONLY | O_TRUNC);
689                         }
690                         else
691                         {
692                                 movie_fd = fd_make(buf, 0644);
693                         }
694
695                         if (!movie_fd)
696                         {
697 #ifdef JP
698                                 msg_print("¥Õ¥¡¥¤¥ë¤ò³«¤±¤Þ¤»¤ó¡ª");
699 #else
700                                 msg_print("Can not open file.");
701 #endif
702                                 return;
703                         }
704
705                         movie_mode = 1;
706 #ifdef CHUUKEI
707                         if (!chuukei_server) prepare_chuukei_hooks();
708 #else
709                         prepare_chuukei_hooks();
710 #endif
711                         do_cmd_redraw();
712                 }
713         }
714 }
715
716 #ifdef CHUUKEI
717 static int handle_timestamp_data(int timestamp)
718 {
719         long current_time = get_current_time();
720
721         /* ÉÁ²è¥­¥å¡¼¤Ï¶õ¤«¤É¤¦¤«¡© */
722         if (fresh_queue.tail == fresh_queue.next)
723         {
724                 /* ¥Ð¥Ã¥Õ¥¡¥ê¥ó¥°¤·»Ï¤á¤Î»þ´Ö¤òÊݸ¤·¤Æ¤ª¤¯ */
725                 epoch_time = current_time;
726                 epoch_time += browse_delay;
727                 epoch_time -= timestamp;
728                 time_diff = current_time - timestamp;
729         }
730
731         /* ÉÁ²è¥­¥å¡¼¤ËÊݸ¤·¡¢Êݸ°ÌÃÖ¤ò¿Ê¤á¤ë */
732         fresh_queue.time[fresh_queue.tail] = timestamp;
733         fresh_queue.tail ++;
734
735         /* ¥­¥å¡¼¤ÎºÇ¸åÈø¤ËÅþ㤷¤¿¤éÀèƬ¤ËÌ᤹ */
736         fresh_queue.tail %= FRESH_QUEUE_SIZE;
737
738         if (fresh_queue.tail == fresh_queue.next)
739         {
740                 /* ÉÁ²è¥­¥å¡¼°î¤ì */
741                 prt("ÉÁ²è¥¿¥¤¥ß¥ó¥°¥­¥å¡¼¤¬°î¤ì¤Þ¤·¤¿¡£¥µ¡¼¥Ð¤È¤ÎÀܳ¤òÀÚÃǤ·¤Þ¤¹¡£", 0, 0);
742                 inkey();
743                 close(sd);
744
745                 return -1;
746         }
747
748         /* ¥×¥ì¥¤Â¦¤È¤Î¥Ç¥£¥ì¥¤¤òÄ´À° */
749         if (time_diff != current_time - timestamp)
750         {
751                 long old_time_diff = time_diff;
752                 time_diff = current_time - timestamp;
753                 epoch_time -= (old_time_diff - time_diff);
754         }
755
756         /* Success */
757         return 0;
758 }
759 #endif /* CHUUKEI */
760
761 static int handle_movie_timestamp_data(int timestamp)
762 {
763         static int initialized = FALSE;
764
765         /* ÉÁ²è¥­¥å¡¼¤Ï¶õ¤«¤É¤¦¤«¡© */
766         if (!initialized)
767         {
768                 /* ¥Ð¥Ã¥Õ¥¡¥ê¥ó¥°¤·»Ï¤á¤Î»þ´Ö¤òÊݸ¤·¤Æ¤ª¤¯ */
769                 epoch_time = get_current_time();
770                 epoch_time += browse_delay;
771                 epoch_time -= timestamp;
772                 //time_diff = current_time - timestamp;
773                 initialized = TRUE;
774         }
775
776         /* ÉÁ²è¥­¥å¡¼¤ËÊݸ¤·¡¢Êݸ°ÌÃÖ¤ò¿Ê¤á¤ë */
777         fresh_queue.time[fresh_queue.tail] = timestamp;
778         fresh_queue.tail ++;
779
780         /* ¥­¥å¡¼¤ÎºÇ¸åÈø¤ËÅþ㤷¤¿¤éÀèƬ¤ËÌ᤹ */
781         fresh_queue.tail %= FRESH_QUEUE_SIZE;
782
783         /* Success */
784         return 0;
785 }
786
787 #ifdef CHUUKEI
788 static int read_sock(void)
789 {
790         static char recv_buf[RECVBUF_SIZE];
791         static int remain_bytes = 0;
792         int recv_bytes;
793         int i;
794
795         /* Á°²ó»Ä¤Ã¤¿¥Ç¡¼¥¿¤Î¸å¤Ë¤Ä¤Å¤±¤ÆÇÛ¿®¥µ¡¼¥Ð¤«¤é¥Ç¡¼¥¿¼õ¿® */
796         recv_bytes = recv(sd, recv_buf + remain_bytes, RECVBUF_SIZE - remain_bytes, 0);
797
798         if (recv_bytes <= 0)
799                 return -1;
800
801         /* Á°²ó»Ä¤Ã¤¿¥Ç¡¼¥¿Î̤˺£²óÆɤó¤À¥Ç¡¼¥¿Î̤òÄɲà*/
802         remain_bytes += recv_bytes;
803
804         for (i = 0; i < remain_bytes; i ++)
805         {
806                 /* ¥Ç¡¼¥¿¤Î¤¯¤®¤ê('\0')¤òõ¤¹ */
807                 if (recv_buf[i] == '\0')
808                 {
809                         /* 'd'¤Ç»Ï¤Þ¤ë¥Ç¡¼¥¿(¥¿¥¤¥à¥¹¥¿¥ó¥×)¤Î¾ì¹ç¤Ï
810                            ÉÁ²è¥­¥å¡¼¤ËÊݸ¤¹¤ë½èÍý¤ò¸Æ¤Ö */
811                         if ((recv_buf[0] == 'd') &&
812                             (handle_timestamp_data(atoi(recv_buf + 1)) < 0))
813                                 return -1;
814
815                         /* ¼õ¿®¥Ç¡¼¥¿¤òÊݸ */
816                         if (insert_ringbuf(recv_buf) < 0) 
817                                 return -1;
818
819                         /* ¼¡¤Î¥Ç¡¼¥¿°Ü¹Ô¤òrecv_buf¤ÎÀèƬ¤Ë°ÜÆ° */
820                         memmove(recv_buf, recv_buf + i + 1, remain_bytes - i - 1);
821
822                         remain_bytes -= (i+1);
823                         i = 0;
824                 }
825         }
826
827         return 0;
828 }
829 #endif
830
831 static int read_movie_file(void)
832 {
833         static char recv_buf[RECVBUF_SIZE];
834         static int remain_bytes = 0;
835         int recv_bytes;
836         int i;
837
838         recv_bytes = read(movie_fd, recv_buf + remain_bytes, RECVBUF_SIZE - remain_bytes);
839
840         if (recv_bytes <= 0)
841                 return -1;
842
843         /* Á°²ó»Ä¤Ã¤¿¥Ç¡¼¥¿Î̤˺£²óÆɤó¤À¥Ç¡¼¥¿Î̤òÄɲà*/
844         remain_bytes += recv_bytes;
845
846         for (i = 0; i < remain_bytes; i ++)
847         {
848                 /* ¥Ç¡¼¥¿¤Î¤¯¤®¤ê('\0')¤òõ¤¹ */
849                 if (recv_buf[i] == '\0')
850                 {
851                         /* 'd'¤Ç»Ï¤Þ¤ë¥Ç¡¼¥¿(¥¿¥¤¥à¥¹¥¿¥ó¥×)¤Î¾ì¹ç¤Ï
852                            ÉÁ²è¥­¥å¡¼¤ËÊݸ¤¹¤ë½èÍý¤ò¸Æ¤Ö */
853                         if ((recv_buf[0] == 'd') &&
854                             (handle_movie_timestamp_data(atoi(recv_buf + 1)) < 0))
855                                 return -1;
856
857                         /* ¼õ¿®¥Ç¡¼¥¿¤òÊݸ */
858                         if (insert_ringbuf(recv_buf) < 0) 
859                                 return -1;
860
861                         /* ¼¡¤Î¥Ç¡¼¥¿°Ü¹Ô¤òrecv_buf¤ÎÀèƬ¤Ë°ÜÆ° */
862                         memmove(recv_buf, recv_buf + i + 1, remain_bytes - i - 1);
863
864                         remain_bytes -= (i+1);
865                         i = 0;
866                 }
867         }
868
869         return 0;
870 }
871
872
873 #ifndef WINDOWS
874 /* WinÈǤÎÃæÅÀ¤ÈÊɤÎƦÉå¤ò¥Ô¥ê¥ª¥É¤È¥·¥ã¡¼¥×¤Ë¤¹¤ë¡£*/
875 static void win2unix(int col, char *buf)
876 {
877         char kabe;
878         if ( col == 9 ) kabe = '%';
879         else            kabe = '#';
880
881         while (*buf)
882         {
883 #ifdef JP
884                 if (iskanji(*buf))
885                 {
886                         buf += 2;
887                         continue;
888                 }
889 #endif
890                 if (*buf == 127) *buf = kabe;
891                 else if(*buf == 31) *buf = '.';
892                 buf++;
893         }
894 }
895 #endif
896
897 static bool get_nextbuf(char *buf)
898 {
899         char *ptr = buf;
900
901         while (1)
902         {
903                 *ptr = ring.buf[ring.rptr ++];
904                 ring.inlen --;
905                 if (ring.rptr == RINGBUF_SIZE) ring.rptr = 0;
906                 if (*ptr++ == '\0') break;
907         }
908
909         if (buf[0] == 'd') return (FALSE);
910
911         return (TRUE);
912 }
913
914 /* ¥×¥ì¥¤¥Û¥¹¥È¤Î¥Þ¥Ã¥×¤¬Â礭¤¤¤È¤­¥¯¥é¥¤¥¢¥ó¥È¤Î¥Þ¥Ã¥×¤â¥ê¥µ¥¤¥º¤¹¤ë */
915 static void update_term_size(int x, int y, int len)
916 {
917         int ox, oy;
918         int nx, ny;
919         Term_get_size(&ox, &oy);
920         nx = ox;
921         ny = oy;
922
923         /* ²£Êý¸þ¤Î¥Á¥§¥Ã¥¯ */
924         if (x + len > ox) nx = x + len;
925         /* ½ÄÊý¸þ¤Î¥Á¥§¥Ã¥¯ */
926         if (y + 1 > oy) ny = y + 1;
927
928         if (nx != ox || ny != oy) Term_resize(nx, ny);
929 }
930
931 static bool flush_ringbuf_client(void)
932 {
933         char buf[1024];
934
935         /* ½ñ¤¯¥Ç¡¼¥¿¤Ê¤· */
936         if (fresh_queue.next == fresh_queue.tail) return (FALSE);
937
938         /* ¤Þ¤À½ñ¤¯¤Ù¤­»þ¤Ç¤Ê¤¤ */
939         if (fresh_queue.time[fresh_queue.next] > get_current_time() - epoch_time) return (FALSE);
940
941         /* »þ´Ö¾ðÊó(¶èÀÚ¤ê)¤¬ÆÀ¤é¤ì¤ë¤Þ¤Ç½ñ¤¯ */
942         while (get_nextbuf(buf))
943         {
944                 char id;
945                 int x, y, len, col;
946                 int i;
947                 unsigned char tmp1, tmp2, tmp3, tmp4;
948                 char *mesg;
949
950                 sscanf(buf, "%c%c%c%c%c", &id, &tmp1, &tmp2, &tmp3, &tmp4);
951                 x = tmp1-1; y = tmp2-1; len = tmp3; col = tmp4;
952                 if (id == 's')
953                 {
954                         col = tmp3;
955                         mesg = &buf[4];
956                 }
957                 else mesg = &buf[5];
958 #ifndef WINDOWS
959                 win2unix(col, mesg);
960 #endif
961
962                 switch (id)
963                 {
964                 case 't': /* Ä̾ï */
965 #ifdef SJIS
966                         euc2sjis(mesg);
967 #endif
968                         update_term_size(x, y, len);
969                         (void)((*angband_term[0]->text_hook)(x, y, len, (byte)col, mesg));
970                         strncpy(&Term->scr->c[y][x], mesg, len);
971                         for (i = x; i < x+len; i++)
972                         {
973                                 Term->scr->a[y][i] = col;
974                         }
975                         break;
976
977                 case 'n': /* ·«¤êÊÖ¤· */
978                         for (i = 1; i < len; i++)
979                         {
980                                 mesg[i] = mesg[0];
981                         }
982                         mesg[i] = '\0';
983                         update_term_size(x, y, len);
984                         (void)((*angband_term[0]->text_hook)(x, y, len, (byte)col, mesg));
985                         strncpy(&Term->scr->c[y][x], mesg, len);
986                         for (i = x; i < x+len; i++)
987                         {
988                                 Term->scr->a[y][i] = col;
989                         }
990                         break;
991
992                 case 's': /* °ìʸ»ú */
993                         update_term_size(x, y, 1);
994                         (void)((*angband_term[0]->text_hook)(x, y, 1, (byte)col, mesg));
995                         strncpy(&Term->scr->c[y][x], mesg, 1);
996                         Term->scr->a[y][x] = col;
997                         break;
998
999                 case 'w':
1000                         update_term_size(x, y, len);
1001                         (void)((*angband_term[0]->wipe_hook)(x, y, len));
1002                         break;
1003
1004                 case 'x':
1005                         if (x == TERM_XTRA_CLEAR) Term_clear();
1006                         (void)((*angband_term[0]->xtra_hook)(x, 0));
1007                         break;
1008
1009                 case 'c':
1010                         update_term_size(x, y, 1);
1011                         (void)((*angband_term[0]->curs_hook)(x, y));
1012                         break;
1013                 case 'C':
1014                         update_term_size(x, y, 1);
1015                         (void)((*angband_term[0]->bigcurs_hook)(x, y));
1016                         break;
1017                 }
1018         }
1019
1020         fresh_queue.next++;
1021         if (fresh_queue.next == FRESH_QUEUE_SIZE) fresh_queue.next = 0;
1022         return (TRUE);
1023 }
1024
1025 #ifdef CHUUKEI
1026 void browse_chuukei()
1027 {
1028 #ifndef MACINTOSH
1029         fd_set fdset;
1030         struct timeval tv;
1031
1032         tv.tv_sec = 0;
1033         tv.tv_usec = WAIT;
1034
1035         FD_ZERO(&fdset);
1036         FD_SET(sd, &fdset);
1037
1038         Term_clear();
1039         Term_fresh();
1040         Term_xtra(TERM_XTRA_REACT, 0);
1041
1042         while (1)
1043         {
1044                 fd_set tmp_fdset;
1045                 struct timeval tmp_tv;
1046
1047                 if (flush_ringbuf_client()) continue;
1048
1049                 tmp_fdset = fdset;
1050                 tmp_tv = tv;
1051
1052                 /* ¥½¥±¥Ã¥È¤Ë¥Ç¡¼¥¿¤¬Íè¤Æ¤¤¤ë¤«¤É¤¦¤«Ä´¤Ù¤ë */
1053                 select(sd+1, &tmp_fdset, (fd_set *)NULL, (fd_set *)NULL, &tmp_tv);
1054                 if (FD_ISSET(sd, &tmp_fdset) == 0)
1055                 {
1056                         Term_xtra(TERM_XTRA_FLUSH, 0);
1057                         continue;
1058                 }
1059
1060                 if (read_sock() < 0)
1061                 {
1062                         chuukei_client = FALSE;
1063                 }
1064
1065                 /* Àܳ¤¬Àڤ줿¾õÂ֤ǽñ¤¯¤Ù¤­¥Ç¡¼¥¿¤¬¤Ê¤¯¤Ê¤Ã¤Æ¤¤¤¿¤é½ªÎ» */
1066                 if (!chuukei_client && fresh_queue.next == fresh_queue.tail ) break;
1067         }
1068 #else
1069         Term_clear();
1070         Term_fresh();
1071         Term_xtra(TERM_XTRA_REACT, 0);
1072
1073         while (1)
1074         {
1075                 UInt32  unreadData = 0;
1076                 int n;
1077
1078                 if (flush_ringbuf_client()) continue;
1079
1080                 /* ¥½¥±¥Ã¥È¤Ë¥Ç¡¼¥¿¤¬Íè¤Æ¤¤¤ë¤«¤É¤¦¤«Ä´¤Ù¤ë */
1081
1082                 OTCountDataBytes(ep, &unreadData);
1083                 if(unreadData <= 0 ){
1084                         Term_xtra(TERM_XTRA_FLUSH, 0);
1085                         continue;
1086                 }
1087                 if (read_sock() < 0)
1088                 {
1089                         chuukei_client = FALSE;
1090                 }
1091
1092                 /* Àܳ¤¬Àڤ줿¾õÂ֤ǽñ¤¯¤Ù¤­¥Ç¡¼¥¿¤¬¤Ê¤¯¤Ê¤Ã¤Æ¤¤¤¿¤é½ªÎ» */
1093                 if (!chuukei_client && fresh_queue.next == fresh_queue.tail ) break;
1094         }
1095 #endif /*MACINTOSH*/
1096 }
1097 #endif /* CHUUKEI */
1098
1099 void prepare_browse_movie_aux(cptr filename)
1100 {
1101         movie_fd = fd_open(filename, O_RDONLY);
1102         
1103         browsing_movie = TRUE;
1104
1105         init_buffer();
1106 }
1107
1108 void prepare_browse_movie(cptr filename)
1109 {
1110         char buf[1024];
1111         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
1112
1113         prepare_browse_movie_aux(buf);
1114 }
1115
1116 void browse_movie(void)
1117 {
1118         Term_clear();
1119         Term_fresh();
1120         Term_xtra(TERM_XTRA_REACT, 0);
1121
1122         while (read_movie_file() == 0)
1123         {
1124                 while (fresh_queue.next != fresh_queue.tail)
1125                 {
1126                         if (!flush_ringbuf_client())
1127                         {
1128                                 Term_xtra(TERM_XTRA_FLUSH, 0);
1129
1130                                 /* ¥½¥±¥Ã¥È¤Ë¥Ç¡¼¥¿¤¬Íè¤Æ¤¤¤ë¤«¤É¤¦¤«Ä´¤Ù¤ë */
1131 #ifdef WINDOWS
1132                                 Sleep(WAIT);
1133 #else
1134                                 usleep(WAIT);
1135 #endif
1136                         }
1137                 }
1138         }
1139 }