OSDN Git Service

23eb05345162f57a54418b62019be66a0d128cea
[peercast-im/PeerCastIM.git] / PeerCast.root / PeerCast / ui / win32 / simple / gui.cpp
1 // ------------------------------------------------
2 // File : gui.cpp
3 // Date: 4-apr-2002
4 // Author: giles
5 // Desc: 
6 //              Windows front end GUI, PeerCast core is not dependant on any of this. 
7 //              Its very messy at the moment, but then again Windows UI always is.
8 //              I really don`t like programming win32 UI.. I want my borland back..
9 //
10 // (c) 2002 peercast.org
11 // ------------------------------------------------
12 // This program is free software; you can redistribute it and/or modify
13 // it under the terms of the GNU General Public License as published by
14 // the Free Software Foundation; either version 2 of the License, or
15 // (at your option) any later version.
16
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 // GNU General Public License for more details.
21 // ------------------------------------------------
22
23 #define _WIN32_WINNT 0x0500
24
25 #include <windows.h>
26 #include "stdio.h"
27 #include "string.h"
28 #include "stdarg.h"
29 #include "resource.h"
30 #include "socket.h"
31 #include "win32/wsys.h"
32 #include "servent.h"
33 #include "win32/wsocket.h"
34 #include "inifile.h"
35 #include "gui.h"
36 #include "servmgr.h"
37 #include "peercast.h"
38 #include "simple.h"
39 #include "gdiplus.h"
40 #include "commctrl.h"
41 #include "locale.h"
42 #include "stats.h"
43 #include "socket.h"
44 #include "wininet.h"
45 #ifdef _DEBUG
46 #include "chkMemoryLeak.h"
47 #define DEBUG_NEW new(__FILE__, __LINE__)
48 #define new DEBUG_NEW
49 #endif
50
51 ThreadInfo guiThread;
52 bool shownChannels=false;
53 WINDOWPLACEMENT winPlace;
54 bool guiFlg = false;
55
56 using namespace Gdiplus;
57
58 #include <comdef.h>
59
60 void APICALL MyPeercastApp ::printLog(LogBuffer::TYPE t, const char *str)
61 {
62 /*      ADDLOG(str,logID,true,NULL,t);
63         if (logFile.isOpen())
64         {
65                 logFile.writeLine(str);
66                 logFile.flush();
67         }*/
68 }
69
70 void APICALL MyPeercastApp::updateSettings()
71 {
72 //      setControls(true);
73 }
74
75 Gdiplus::Bitmap bmpBack(800,600,PixelFormat24bppRGB);
76 UINT backWidth;
77 UINT backHeight;
78
79 Gdiplus::Image *backImage;
80 Gdiplus::Bitmap *backBmp;
81 Gdiplus::Graphics *backGra;
82
83 Gdiplus::Image *img_idle;
84 Gdiplus::Image *img_connect;
85 Gdiplus::Image *img_conn_ok;
86 Gdiplus::Image *img_conn_full;
87 Gdiplus::Image *img_conn_over;
88 Gdiplus::Image *img_conn_ok_skip;
89 Gdiplus::Image *img_conn_full_skip;
90 Gdiplus::Image *img_conn_over_skip;
91 Gdiplus::Image *img_error;
92 Gdiplus::Image *img_broad_ok;
93 Gdiplus::Image *img_broad_full;
94
95 UINT winWidth=0;
96 UINT winHeight=0;
97
98 static HWND hTree;
99 extern HINSTANCE hInst;
100 extern HWND guiWnd;
101 extern Stats stats;
102
103 WLock sd_lock;
104 WLock ChannelDataLock;
105 WLock MakeBackLock;
106 ChannelData *channelDataTop = NULL;
107
108 extern bool gbGetFile;
109 extern bool gbStart;
110 extern time_t gtGetFile;
111 extern time_t gtStartTime;
112 ThreadInfo gtiStart;
113 ThreadInfo gtiGetFile;
114 static char *data1URL = "http://www.idolmaster.jp/download/images/wallpaper/imas360p_800.jpg";
115 static char *data2URL = "http://www.xbox.com/NR/rdonlyres/CAB05E2F-3051-409B-A4C8-830167C1C138/0/wpr0701idolmasterw120001.jpg";
116 HWND ghStart;
117
118 bool gbDispTop = false;
119 bool gbAllOpen = false;
120
121 THREAD_PROC FestivalStart(ThreadInfo *thread);
122
123 THREAD_PROC GetHostName(ThreadInfo *thread){
124         IdData *id = (IdData*)(thread->data);
125
126         HOSTENT *he;
127         unsigned int ip;
128         bool flg = TRUE;
129
130         ChannelDataLock.on();
131         ip = htonl(id->getIpAddr());
132
133         for (int i=0; i<5 && flg; i++){
134                 he = gethostbyaddr((char *)&ip,sizeof(ip),AF_INET);
135
136                 ChannelData* cd = channelDataTop;
137                 if (he)
138                 {
139                         while(cd){
140                                 if (cd->setName(id->getServentId(), he->h_name)){
141                                         flg = FALSE;
142                                         break;
143                                 }
144                                 cd = cd->getNextData();
145                         }
146                 }
147 //              ::delete id;
148                 ChannelDataLock.off();
149                 sys->sleep(1000);
150         }
151
152
153         return 0;
154 }
155
156 bool DownloadFile(LPCTSTR URL, LPCTSTR local){
157         char header[] = "Accept: */*\r\n\r\n";
158         char buf[4096];
159
160         FileStream f;
161         HINTERNET hInternet;
162         HINTERNET hConnect;
163
164         try{
165                 f.openWriteReplace(local);
166         }catch(StreamException &e){
167                 return false;
168         }
169
170         hInternet = ::InternetOpen(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
171         if (hInternet == NULL){
172                 return false;
173         }
174
175         hConnect = ::InternetOpenUrl(hInternet, URL, header, strlen(header), INTERNET_FLAG_DONT_CACHE, 0);
176         if (hConnect == NULL){
177                 ::InternetCloseHandle(hInternet);
178                 return false;
179         }
180
181         while(1){
182                 sys->sleep(0);
183                 DWORD dwReadSize;
184                 BOOL ret = ::InternetReadFile(hConnect, buf, 4096, &dwReadSize);
185                 if (ret){
186                         if (dwReadSize == 0){
187                                 break;
188                         }
189                         try{
190                                 f.write(buf, dwReadSize);
191                                 continue;
192                         } catch(StreamException e){
193                         }
194                         f.close();
195                         ::InternetCloseHandle(hConnect);
196                         ::InternetCloseHandle(hInternet);
197                         return false;
198                 }
199         }
200
201         f.flush();
202         f.close();
203         ::InternetCloseHandle(hConnect);
204         ::InternetCloseHandle(hInternet);
205
206         return true;
207 }
208
209 THREAD_PROC GetInternetFile(ThreadInfo *thread){
210
211         DownloadFile(data1URL, "data1.jpg");
212         DownloadFile(data2URL, "data2.jpg");
213         return 0;
214 }
215
216 extern TCHAR szWindowClass3[];                                                          // The title bar text
217
218
219 int drawSpeed(Graphics *gra, int posX, int posY){
220
221         // \91¬\93x\95\\8e¦\95\94\82Ì\94w\8ci\82ð\94\92\82­\82·\82é
222         SolidBrush b(Color(180,255,255,255));
223         backGra->FillRectangle(&b, posX, posY, 200, 14);
224         // \83t\83H\83\93\83g\90Ý\92è
225         Font font(L"\82l\82\82o\83S\83V\83b\83N",10);
226         // \95\8e\9a\90F
227         SolidBrush strBrush(Color::Black);
228         // \95\8e\9a\97ñ\8dì\90¬
229         char tmp[256];
230         sprintf(tmp, "R:%.1fkbps S:%.1fkbps", 
231                 BYTES_TO_KBPS(stats.getPerSecond(Stats::BYTESIN)-stats.getPerSecond(Stats::LOCALBYTESIN)),
232                 BYTES_TO_KBPS(stats.getPerSecond(Stats::BYTESOUT)-stats.getPerSecond(Stats::LOCALBYTESOUT)));
233         _bstr_t bstr(tmp);
234         // \95\8e\9a\95\\8e¦\94Í\88Í\8ew\92è
235         StringFormat format;
236         format.SetAlignment(StringAlignmentCenter);
237         RectF r((REAL)posX, (REAL)posY, (REAL)200, (REAL)14);
238         // \95\8e\9a\95`\89æ
239         gra->DrawString(bstr, -1, &font, r, &format, &strBrush);
240
241
242
243         return posY + 15;
244 }
245
246 void MakeBack(HWND hwnd, UINT x, UINT y){
247         MakeBackLock.on();
248
249         winWidth = x;
250         winHeight = y;
251
252         if (backGra){
253                 ::delete backBmp;
254                 ::delete backGra;
255         }
256
257         backBmp = ::new Bitmap(x,y);
258         backGra = ::new Graphics(backBmp);
259
260         // \91S\82Ä\94\92\82Å\93h\82è\82Â\82Ô\82µ
261         SolidBrush b(Color(255,255,255,255));
262         backGra->FillRectangle(&b, 0, 0, x, y);
263
264         backWidth = backImage->GetWidth();
265         backHeight = backImage->GetHeight();
266
267         // \94w\8ci\89æ\91\9c\82ð\95`\89æ
268         for (UINT xx = 0; xx < x/backWidth + 1; xx++){
269                 for (UINT yy = 0; yy < y/backHeight + 1; yy++){
270                         UINT width,height;
271                         if (backWidth*(xx+1) > x){
272                                 width = x % backWidth;
273                         } else {
274                                 width = backWidth;
275                         }
276                         if (backHeight*(yy+1) > y){
277                                 height = y % backHeight;
278                         } else {
279                                 height = backHeight;
280                         }
281                         Rect r((INT)backWidth*xx, (INT)backHeight*yy, width, height);
282                         backGra->DrawImage(backImage, r, 0, 0, (INT)width, (INT)height, UnitPixel);
283                 }
284         }
285
286         INT posX = 20;
287         INT posY = 20;
288
289         // \91¬\93x\95`\89æ
290         drawSpeed(backGra, winWidth-205, 5);
291
292         // \83`\83\83\83\93\83l\83\8b\8fî\95ñ\82ð\95`\89æ
293         ChannelDataLock.on();
294         ChannelData *cd = channelDataTop;
295         while(cd){
296                 posY = cd->drawChannel(backGra, 20, posY);
297                 cd = cd->getNextData();
298         }
299         ChannelDataLock.off();
300         MakeBackLock.off();
301 }
302
303 void MakeBack(HWND hwnd){
304         MakeBack(hwnd, winWidth, winHeight);
305         ::InvalidateRect(guiWnd, NULL, FALSE);
306 }
307
308 void ChannelData::setData(Channel *c){
309         String sjis;
310         sjis = c->getName();
311         sjis.convertTo(String::T_SJIS);
312
313         strncpy(name, sjis, 256);
314         name[256] = '\0';
315         channel_id = c->channel_id;
316         bitRate = c->info.bitrate;
317         lastPlayStart = c->info.lastPlayStart;
318         status = c->status;
319         totalListeners = c->totalListeners();
320         totalRelays = c->totalRelays();
321         localListeners = c->localListeners();
322         localRelays = c->localRelays();
323         stayConnected = c->stayConnected;
324         chDisp = c->chDisp;
325         bTracker = c->sourceHost.tracker;
326         lastSkipTime = c->lastSkipTime;
327         skipCount = c->skipCount;
328 }
329
330 int gW = 0;
331 int gWS = 0;
332
333 int ChannelData::drawChannel(Graphics *g, int x, int y){
334         REAL xx = x * 1.0f;
335         REAL yy = y * 1.0f;
336         ServentData* sd;
337
338         // \88Ê\92u\82ð\95Û\91
339         posX = x;
340         posY = y;
341
342         int w,h;
343
344         if (getWidth() == 0){
345                 if (gW){
346                         w = gW;
347                 } else {
348                         w = 400;
349                 }
350         } else {
351                 w = getWidth();
352                 gW = w;
353         }
354
355         // \83`\83\83\83\93\83l\83\8b\95\\8e¦\95\94\82Ì\94w\8ci\82ð\93h\82é
356         if (isSelected()){
357                 // \91I\91ð\92\86
358                 SolidBrush b(Color(160,49,106,197));
359                 g->FillRectangle(&b, x, y, w, 14);
360         } else {
361                 // \94ñ\91I\91ð
362                 SolidBrush b(Color(160,255,255,255));
363                 g->FillRectangle(&b, x, y, w, 14);
364         }
365
366         // \83X\83e\81[\83^\83X\95\\8e¦
367         Gdiplus::Image *img = NULL;
368         unsigned int nowTime = sys->getTime();
369         switch(this->getStatus()){
370                 case Channel::S_IDLE:
371                         img = img_idle;
372                         break;
373                 case Channel::S_SEARCHING:
374                 case Channel::S_CONNECTING:
375                         img = img_connect;
376                         break;
377                 case Channel::S_RECEIVING:
378                         if ((skipCount > 2) && (lastSkipTime + 120 > nowTime)){
379                                 if (chDisp.relay){
380                                         img = img_conn_ok_skip;
381                                 } else {
382                                         if (chDisp.numRelays){
383                                                 img = img_conn_full_skip;
384                                         } else {
385                                                 img = img_conn_over_skip;
386                                         }
387                                 }
388                         } else {
389                                 if (chDisp.relay){
390                                         img = img_conn_ok;
391                                 } else {
392                                         if (chDisp.numRelays){
393                                                 img = img_conn_full;
394                                         } else {
395                                                 img = img_conn_over;
396                                         }
397                                 }
398                         }
399                         break;
400                 case Channel::S_BROADCASTING:
401                         img = img_broad_ok;
402                         break;
403                 case Channel::S_ERROR:
404                         img = img_error;
405                         break;
406                 default:
407                         img = img_idle;
408                         break;
409         }
410         // \95`\89æ\8aî\93_
411         PointF origin(xx, yy);
412         // \83X\83e\81[\83^\83X\95\\8e¦\88Ê\92u
413         Rect img_rect((INT)origin.X, (INT)origin.Y + 1, img ? img->GetWidth() : 12, 12);
414         // \83X\83e\81[\83^\83X\95`\89æ
415         ImageAttributes att;
416 //      att.SetColorKey(Color::White, Color::White, ColorAdjustTypeBitmap);
417         g->DrawImage(img, img_rect, 0, 0, img_rect.Width, 12, UnitPixel, &att);
418         // \8e\9f\82Ì\8aî\93_
419         origin.X += img_rect.Width;
420
421         // \83t\83H\83\93\83g\90Ý\92è
422         Gdiplus::Font font(L"\82l\82\82o\83S\83V\83b\83N",10);
423         // \95\8e\9a\90F
424         SolidBrush *strBrush;
425         if (servMgr->getFirewall() == ServMgr::FW_ON){
426                 strBrush = ::new SolidBrush(Color::Red);
427         } else if (isTracker() && (getStatus() == Channel::S_RECEIVING)){
428                 strBrush = ::new SolidBrush(Color::Green);
429         } else {
430                 if (isSelected()){
431                         // \91I\91ð\92\86
432                         strBrush = ::new SolidBrush(Color::White);
433                 } else {
434                         // \94ñ\91I\91ð
435                         strBrush = ::new SolidBrush(Color::Black);
436                 }
437         }
438         // \83`\83\83\83\93\83l\83\8b\96¼\95\\8e¦
439         g->SetTextRenderingHint(TextRenderingHintAntiAlias);
440         _bstr_t bstr1(getName());
441         // \95\8e\9a\95`\89æ\94Í\88Í\8ew\92è
442         RectF r1(origin.X, origin.Y, 120.0f, 13.0f);
443         StringFormat format;
444         format.SetAlignment(StringAlignmentNear);
445         g->DrawString(bstr1, -1, &font, r1, &format, strBrush);
446         // \8e\9f\82Ì\8aî\93_
447         origin.X += r1.Width;
448
449         //// \8fã\97¬IP/\83\8a\83X\83i\81[\90\94/\83\8a\83\8c\81[\90\94\95\\8e¦
450         //// NOTE:
451         ////    \82Ò\82 \82©\82·\82Ì\93®\8dì\95×\8b­\97p\81B\83\8a\83\8a\81[\83X\83r\83\8b\83h\82Å\82Í\8c³\82Ì\83R\81[\83h\82ð\8eg\97p\82Ì\8e\96\81B
452         ////    \95\8e\9a\95\\8e¦\94Í\88Í\82Í\95\9d220\82®\82ç\82¢\82Å\82¨\82\8b
453         //char tmp[512]; // \95\\8e¦\97p\83o\83b\83t\83@
454         //char hostip[256]; // IP\83A\83h\83\8c\83X\83o\83b\83t\83@
455         //chDisp.uphost.toStr(hostip); // \8fã\97¬IP
456         //sprintf(tmp, "%d/%d - [%d/%d] - %s",
457         //      getTotalListeners(),
458         //      getTotalRelays(),
459         //      getLocalListeners(),
460         //      getLocalRelays(),
461         //      hostip
462         //      );
463
464         // \83\8a\83X\83i\81[\90\94/\83\8a\83\8c\81[\90\94\95\\8e¦
465         char tmp[256];
466         sprintf(tmp, "%d/%d - [%d/%d]", getTotalListeners(), getTotalRelays(), getLocalListeners(), getLocalRelays());
467         _bstr_t bstr2(tmp);
468         // \95\8e\9a\95\\8e¦\94Í\88Í\8ew\92è
469         RectF r2(origin.X, origin.Y, 100.0f, 13.0f);
470         format.SetAlignment(StringAlignmentCenter);
471         g->DrawString(bstr2, -1, &font, r2, &format, strBrush);
472         // \8e\9f\82Ì\8aî\93_
473         origin.X += r2.Width;
474
475         // bps\95\\8e¦
476         Font *f;
477         if (isStayConnected()){
478                 f = ::new Font(L"Arial", 9.0f, FontStyleItalic|FontStyleBold, UnitPoint);
479         } else {
480                 f = ::new Font(L"Arial", 9.0f);
481         }
482         sprintf(tmp, "%dkbps", getBitRate());
483         _bstr_t bstr3(tmp);
484         format.SetAlignment(StringAlignmentFar);
485         // \95\8e\9a\95\\8e¦\94Í\88Í\8ew\92è
486         RectF r3(origin.X, origin.Y, 80.0f, 13.0f);
487         g->DrawString(bstr3, -1, f, r3, &format, strBrush);
488         // \83t\83H\83\93\83g\8aJ\95ú
489         ::delete f;
490
491         // \8e\9f\82Ì\8aî\93_
492         origin.X += r3.Width;
493
494         // \83u\83\89\83V\8dí\8f\9c
495         ::delete strBrush;
496
497         
498         // Servent\95\\8e¦
499         if (!openFlg){
500                 int count = getServentCount();
501                 // Servent\95\\8e¦\95\94\82Ì\94w\8ci\82ð\94\92\82É\82·\82é
502                 SolidBrush b(Color(160,255,255,255));
503                 g->FillRectangle(&b, (INT)origin.X, (INT)origin.Y, 14*count, 14);
504
505                 sd = serventDataTop;
506                 int index = 0;
507                 while(sd){
508                         SolidBrush *serventBrush;
509                         if (sd->getInfoFlg()){
510                                 ChanHit *hit = sd->getChanHit();
511                                 if (hit->firewalled){
512                                         SolidBrush bb(Color(180,255,0,0));
513                                         g->FillRectangle(&bb, (INT)origin.X + 14*index, (INT)origin.Y, 14, 14);
514                                 }
515                                 if (hit->relay){
516                                         // \83\8a\83\8c\81[\82n\82j
517                                         serventBrush = ::new SolidBrush(Color::Green);
518                                 } else {
519                                         // \83\8a\83\8c\81[\95s\89Â
520                                         if (hit->numRelays){
521                                                 // \83\8a\83\8c\81[\88ê\94t
522                                                 serventBrush = ::new SolidBrush(Color::Blue);
523                                         } else {
524                                                 // \83\8a\83\8c\81[\82È\82µ
525                                                 serventBrush = ::new SolidBrush(Color::Purple);
526                                         }
527                                 }
528                         } else {
529                                 // \8fî\95ñ\82È\82µ
530                                 serventBrush = ::new SolidBrush(Color::Black);
531                         }
532                         // \8el\8ap\95`\89æ
533                         backGra->FillRectangle(serventBrush, (INT)origin.X + index*14 + 1, (INT)origin.Y + 1, 12, 12);
534
535                         ::delete serventBrush;
536                         sd = sd->getNextData();
537                         index++;
538                 }
539         }
540
541         // \8e\9f\82Ì\8aî\93_
542         origin.Y += 15;
543
544         // \83T\83C\83Y\82ð\95Û\91
545         setWidth((int)origin.X - posX);
546         setHeight((int)origin.Y - posY);
547
548         // ServentData\95\\8e¦
549         sd = serventDataTop;
550         while(sd){
551                 if (openFlg || sd->getSelected()){
552                         sd->drawServent(g, (INT)x+12, (INT)origin.Y);
553                         // \8e\9f\82Ì\8aî\93_
554                         origin.Y += 15;
555                 }
556                 sd = sd->getNextData();
557         }
558         
559
560         return (int)(origin.Y);
561 }
562
563 bool ChannelData::checkDown(int x,int y){
564         // \94Í\88Í\93à\83`\83F\83b\83N
565         if (    
566                         (x > posX)
567                 &&      (x < posX + getWidth())
568                 &&      (y > posY)
569                 &&      (y < posY + getHeight())
570         ){
571                 return TRUE;
572         }
573         return FALSE;
574 }
575
576 ServentData *ChannelData::findServentData(int servent_id){
577         ServentData *sv = serventDataTop;
578         while(sv){
579                 if (sv->getServentId() == servent_id){
580                         return sv;
581                 }
582                 sv = sv->getNextData();
583         }
584         return NULL;
585 }
586
587 void ChannelData::addServentData(ServentData *sd){
588         sd->setNextData(serventDataTop);
589         serventDataTop = sd;
590 }
591
592 void ChannelData::deleteDisableServents(){
593         ServentData *sd = serventDataTop;
594         ServentData *prev = NULL;
595
596         while(sd){
597                 if (!(sd->getEnableFlg())){
598                         ServentData *next = sd->getNextData();
599                         if (prev){
600                                 prev->setNextData(next);
601                         } else {
602                                 serventDataTop = next;
603                         }
604                         ::delete sd;
605                         sd = next;
606                 } else {
607                         prev = sd;
608                         sd = sd->getNextData();
609                 }
610         }
611 }
612
613 int ChannelData::getServentCount(){
614         int ret = 0;
615
616         ServentData *sd = serventDataTop;
617         while(sd){
618                 ret++;
619                 sd = sd->getNextData();
620         }
621         return ret;
622 }
623
624 bool ChannelData::setName(int servent_id, String name){
625         ServentData *sd = serventDataTop;
626         while(sd){
627                 if (sd->getServentId() == servent_id){
628                         sd->setName(name);
629                         return TRUE;
630                 }
631                 sd = sd->getNextData();
632         }
633         return FALSE;
634 }
635
636 void ServentData::setData(Servent *s, ChanHit *hit, unsigned int listeners, unsigned int relays, bool f){
637         servent_id = s->servent_id;
638         type = s->type;
639         status = s->status;
640         lastSkipTime = s->lastSkipTime;
641         host = s->getHost();
642
643         chanHit.numRelays = hit->numRelays;
644         chanHit.relay = hit->relay;
645         chanHit.firewalled = hit->firewalled;
646         chanHit.version = hit->version;
647         chanHit.version_vp = hit->version_vp;
648         chanHit.version_ex_number = hit->version_ex_number;
649         chanHit.version_ex_prefix[0] = hit->version_ex_prefix[0];
650         chanHit.version_ex_prefix[1] = hit->version_ex_prefix[1];
651
652         totalListeners = listeners;
653         totalRelays = relays;
654
655         infoFlg = f;
656 }
657
658 int ServentData::drawServent(Gdiplus::Graphics *g, int x, int y){
659         REAL xx = x * 1.0f;
660         REAL yy = y * 1.0f;
661         int w,h;
662
663         // \88Ê\92u\82ð\95Û\91
664         posX = x;
665         posY = y;
666
667         if (getWidth() == 0){
668                 if (gWS){
669                         w = gWS;
670                 } else {
671                         w = 400;
672                 }
673         } else {
674                 w = getWidth();
675                 gWS = w;
676         }
677
678         // \95`\89æ\8aî\93_
679         PointF origin(xx, yy);
680
681         // \83t\83H\83\93\83g\90Ý\92è
682         Font font(L"\82l\82\82o\83S\83V\83b\83N",9);
683         // \95\8e\9a\90F
684         SolidBrush *strBrush;
685         if (chanHit.firewalled){
686                 strBrush = ::new SolidBrush(Color::Red);
687         } else {
688                 if (getSelected()){
689                         // \91I\91ð\92\86
690                         strBrush = ::new SolidBrush(Color::White);
691                 } else {
692                         // \94ñ\91I\91ð
693                         strBrush = ::new SolidBrush(Color::Black);
694                 }
695         }
696         // ServantData\95\\8e¦
697         g->SetTextRenderingHint(TextRenderingHintAntiAlias);
698         // \95\8e\9a\97ñ\8dì\90¬
699         char tmp[256];
700         char host1[256];
701         host.toStr(host1);
702
703         if (infoFlg){
704                 if (chanHit.version_ex_number){
705                         // \8ag\92£\83o\81[\83W\83\87\83\93
706                         sprintf(tmp, "%c%c%04d - %d/%d - %s(%s)", 
707                                 chanHit.version_ex_prefix[0],
708                                 chanHit.version_ex_prefix[1],
709                                 chanHit.version_ex_number,
710                                 totalListeners,
711                                 totalRelays,
712                                 host1,
713                                 hostname.cstr()
714                                 );
715                 } else if (chanHit.version_vp){
716                         sprintf(tmp, "VP%04d - %d/%d - %s(%s)", 
717                                 chanHit.version_vp,
718                                 totalListeners,
719                                 totalRelays,
720                                 host1,
721                                 hostname.cstr()
722                                 );
723                 } else {
724                         sprintf(tmp, "(-----) - %d/%d - %s(%s)",
725                                 totalListeners,
726                                 totalRelays,
727                                 host1,
728                                 hostname.cstr()
729                                 );
730                 }
731         } else {
732                         sprintf(tmp, "(-----) - %d/%d - %s(%s)",
733                                 totalListeners,
734                                 totalRelays,
735                                 host1,
736                                 hostname.cstr()
737                                 );
738         }
739         _bstr_t bstr1(tmp);
740
741         // \83X\83e\81[\83^\83X\95\\8e¦
742         Gdiplus::Image *img = NULL;
743         unsigned int nowTime = sys->getTime();
744         switch(getStatus()){
745                 case Servent::S_CONNECTING:
746                         img = img_connect;
747                         break;
748                 case Servent::S_CONNECTED:
749                         if (lastSkipTime + 120 > nowTime){
750                                 if (chanHit.relay){
751                                         img = img_conn_ok_skip;
752                                 } else {
753                                         if (chanHit.numRelays){
754                                                 img = img_conn_full_skip;
755                                         } else {
756                                                 img = img_conn_over_skip;
757                                         }
758                                 }
759                         } else {
760                                 if (chanHit.relay){
761                                         img = img_conn_ok;
762                                 } else {
763                                         if (chanHit.numRelays){
764                                                 img = img_conn_full;
765                                         } else {
766                                                 img = img_conn_over;
767                                         }
768                                 }
769                         }
770                         break;
771                 default:
772                         break;
773         }
774
775         // \95\8e\9a\95`\89æ\94Í\88Í\8ew\92è
776         RectF r1(origin.X + img->GetWidth() + 2, origin.Y, 800.0f, 13.0f);
777         RectF r2;
778         StringFormat format;
779         format.SetAlignment(StringAlignmentNear);
780         g->MeasureString(bstr1, -1, &font, r1, &format, &r2);
781
782         w = (INT)r2.Width + img->GetWidth() + 2;
783         // ServentData\95\\8e¦\95\94\82Ì\94w\8ci\82ð\93h\82é
784         if (getSelected()){
785                 // \91I\91ð\92\86
786                 SolidBrush b(Color(160,49,106,197));
787                 g->FillRectangle(&b, x, y, w, 13);
788         } else {
789                 // \94ñ\91I\91ð
790                 SolidBrush b(Color(160,200,200,200));
791                 g->FillRectangle(&b, x, y, w, 13);
792         }
793
794         // \83X\83e\81[\83^\83X\95\\8e¦\88Ê\92u
795         Rect img_rect((INT)origin.X, (INT)origin.Y+1, img ? img->GetWidth() : 12, 12);
796         // \83X\83e\81[\83^\83X\95`\89æ
797         ImageAttributes att;
798 //      att.SetColorKey(Color::White, Color::White, ColorAdjustTypeBitmap);
799         g->DrawImage(img, img_rect, 0, 0, img_rect.Width, 12, UnitPixel, &att);
800         // \8e\9f\82Ì\8aî\93_
801         origin.X += 12;
802
803         g->DrawString(bstr1, -1, &font, r2, &format, strBrush);
804         // \8e\9f\82Ì\8aî\93_
805         origin.X += r2.Width;
806         origin.Y += 13;
807
808         setWidth((int)origin.X-posX);
809         setHeight((int)origin.Y - posY);
810
811         ::delete strBrush;
812         return 0;
813 }
814
815 bool ServentData::checkDown(int x, int y){
816         if (    
817                         (x > posX)
818                 &&      (x < posX + getWidth())
819                 &&      (y > posY)
820                 &&      (y < posY + getHeight())
821         ){
822                 return TRUE;
823         }
824         return FALSE;
825 }
826
827
828 THREAD_PROC GUIDataUpdate(ThreadInfo *thread){
829         int i;
830
831         // set GUI thread status to running
832         thread->finish = false;
833
834         while(thread->active){
835                 // \83`\83\83\83\93\83l\83\8b\83f\81[\83^\83\8d\83b\83N
836                 ChannelDataLock.on();
837                 // \83`\83\83\83\93\83l\83\8b\83f\81[\83^\82Ì\8dX\90V\83t\83\89\83O\82ð\91S\82ÄFALSE\82É\82·\82é
838                 ChannelData *cd = channelDataTop;
839                 while(cd){
840                         // Servent\82Ì\8dX\90V\83t\83\89\83O\82ðFALSE\82É\82·\82é
841                         ServentData *sv = cd->getServentDataTop();
842                         while(sv){
843                                 sv->setEnableFlg(FALSE);
844                                 sv = sv->getNextData();
845                         }
846                         cd->setEnableFlg(FALSE);
847                         cd = cd->getNextData();
848                 }
849
850                 Channel *c = chanMgr->channel;
851                 // \8c»\8dÝ\91\8dÝ\82·\82é\83`\83\83\83\93\83l\83\8b\95ª\83\8b\81[\83v
852                 while(c){
853                         // \8aù\82É\83`\83\83\83\93\83l\83\8b\83f\81[\83^\82ð\8e\9d\82Á\82Ä\82¢\82é\82©
854                         cd = channelDataTop;
855                         // \94­\8c©\83t\83\89\83OFALSE
856                         bool bFoundFlg = FALSE;
857                         while(cd){
858                                 if (cd->getChannelId() == c->channel_id){
859                                         //\8aù\82É\83`\83\83\83\93\83l\83\8b\83f\81[\83^\82ª\82 \82é\82Ì\82Å\81A\82»\82Ì\82Ü\82Ü\8dX\90V
860                                         cd->setData(c);
861                                         // \8dX\90V\83t\83\89\83OTRUE
862                                         cd->setEnableFlg(TRUE);
863                                         // \94­\8c©\83t\83\89\83OTRUE
864                                         bFoundFlg = TRUE;
865                                         // \83\8b\81[\83v\97£\92E
866                                         break;
867                                 }
868                                 // \8c©\82Â\82©\82ç\82È\82©\82Á\82½\8fê\8d\87\81A\8e\9f\82Ì\83f\81[\83^\82ð\83`\83F\83b\83N
869                                 cd = cd->getNextData();
870                         }
871
872                         // \90V\82µ\82¢\83`\83\83\83\93\83l\83\8b\82Ì\8fê\8d\87\81A\90V\8bK\83f\81[\83^\8dì\90¬
873                         if (!bFoundFlg){
874                                 // \90V\8bK\83f\81[\83^\8dì\90¬
875                                 cd = ::new ChannelData();
876                                 // \83f\81[\83^\8dX\90V
877                                 cd->setData(c);
878                                 // \8dX\90V\83t\83\89\83OTRUE
879                                 cd->setEnableFlg(TRUE);
880
881                                 // \90V\8bK\83f\81[\83^\82ð\83\8a\83X\83g\82Ì\90æ\93ª\82É\93ü\82ê\82é
882                                 cd->setNextData(channelDataTop);
883                                 channelDataTop = cd;
884                         }
885                         // \8e\9f\82Ì\83`\83\83\83\93\83l\83\8b\82ð\8eæ\93¾
886                         c = c->next;
887                 }
888
889                 // \83`\83\83\83\93\83l\83\8b\82ª\82È\82­\82È\82Á\82Ä\82¢\82é\8fê\8d\87\82Ì\8f\88\97\9d
890                 cd = channelDataTop;
891                 ChannelData *prev = NULL; 
892                 while(cd){
893                         // \83f\81[\83^\82ð\8dX\90V\82µ\82È\82©\82Á\82½\82©
894                         if (cd->getEnableFlg() == FALSE){
895                                 // \83`\83\83\83\93\83l\83\8b\82ª\82È\82­\82È\82Á\82Ä\82¢\82é\82Ì\82Å\8dí\8f\9c
896                                 ChannelData *next;
897                                 next = cd->getNextData();
898                                 if (!prev){
899                                         // \90æ\93ª\82Ì\83f\81[\83^\82ð\8dí\8f\9c
900                                         channelDataTop = next;
901                                 } else {
902                                         // \93r\92\86\82Ì\83f\81[\83^\82ð\8dí\8f\9c
903                                         prev->setNextData(next);
904                                 }
905                                 // \8e\9f\82Ì\83f\81[\83^\82Ö
906                                 cd = next;
907                         } else {
908                                 // \83f\81[\83^\8dX\90V\8dÏ\81F\8e\9f\82Ì\83f\81[\83^\82Ö
909                                 prev = cd;
910                                 cd = cd->getNextData();
911                         }
912                 }
913
914                 Servent *s = servMgr->servents;
915                 while(s){
916                         // \8f\89\8aú\89»
917                         ChanHitList *chl;
918                         bool infoFlg = false;
919                         bool relay = true;
920                         bool firewalled = false;
921                         unsigned int numRelays = 0;
922                         int vp_ver = 0;
923                         char ver_ex_prefix[2] = {' ', ' '};
924                         int ver_ex_number = 0;
925                         // \92¼\89º\83z\83X\83g\8fî\95ñ\83`\83F\83b\83N
926                         unsigned int totalRelays = 0;
927                         unsigned int totalListeners = 0;
928
929                         ChanHit hitData;
930                         // \8eó\90M\92\86\82©
931                         if ((s->type == Servent::T_RELAY) && (s->status == Servent::S_CONNECTED)){
932                                 // \83z\83X\83g\8fî\95ñ\83\8d\83b\83N
933                                 chanMgr->hitlistlock.on();
934                                 // \92¼\89º\83z\83X\83g\82ª\8eó\90M\82µ\82Ä\82¢\82é\83`\83\83\83\93\83l\83\8b\82Ì\83z\83X\83g\8fî\95ñ\82ð\8eæ\93¾
935                                 chl = chanMgr->findHitListByID(s->chanID);
936                                 // \83`\83\83\83\93\83l\83\8b\82Ì\83z\83X\83g\8fî\95ñ\82ª\82 \82é\82©
937                                 if (chl){
938                                         // \83`\83\83\83\93\83l\83\8b\82Ì\83z\83X\83g\8fî\95ñ\82ª\82 \82é\8fê\8d\87
939                                         ChanHit *hit = chl->hit;
940                                         //\81@\83`\83\83\83\93\83l\83\8b\82Ì\83z\83X\83g\8fî\95ñ\82ð\91S\91\96\8d¸\82µ\82Ä
941                                         while(hit){
942                                                 // ID\82ª\93¯\82\82à\82Ì\82Å\82 \82ê\82Î
943                                                 if (hit->servent_id == s->servent_id){
944                                                         // \83g\81[\83^\83\8b\83\8a\83\8c\81[\82Æ\83g\81[\83^\83\8b\83\8a\83X\83i\81[\82ð\89Á\8eZ
945                                                         totalRelays += hit->numRelays;
946                                                         totalListeners += hit->numListeners;
947                                                         // \92¼\89º\82Å\82 \82ê\82Î
948                                                         if (hit->numHops == 1){
949                                                                 // \8fî\95ñ\82ð\88ê\92U\95Û\91
950                                                                 infoFlg = true;
951                                                                 hitData.relay = hit->relay;
952                                                                 hitData.firewalled = hit->firewalled;
953                                                                 hitData.numRelays = hit->numRelays;
954                                                                 hitData.version_vp = hit->version_vp;
955                                                                 hitData.version_ex_prefix[0] = hit->version_ex_prefix[0];
956                                                                 hitData.version_ex_prefix[1] = hit->version_ex_prefix[1];
957                                                                 hitData.version_ex_number = hit->version_ex_number;
958                                                         }
959                                                 }
960                                                 // \8e\9f\82ð\83`\83F\83b\83N
961                                                 hit = hit->next;
962                                         }
963                                 }
964
965                                 // \83`\83\83\83\93\83l\83\8b\83f\81[\83^\82©\82çServent\82ð\8c\9f\8dõ
966                                 bool bFoundFlg = FALSE;
967                                 cd = channelDataTop;
968                                 while(cd){
969                                         ServentData *sv = cd->findServentData(s->servent_id);
970                                         // ServentData\82ª\82 \82ê\82Î
971                                         if (sv){
972                                                 // \83f\81[\83^\90Ý\92è
973                                                 sv->setData(s, &hitData, totalListeners, totalRelays, infoFlg);
974                                                 sv->setEnableFlg(TRUE);
975                                                 bFoundFlg = TRUE;
976                                                 break;
977                                         }
978                                         cd = cd->getNextData();
979                                 }
980                                 // ServentData\82ª\8c©\82Â\82©\82ç\82È\82©\82Á\82½\8fê\8d\87
981                                 if (!bFoundFlg){
982                                         // \83`\83\83\83\93\83l\83\8b\83f\81[\83^\82ð\92T\82·
983                                         cd = channelDataTop;
984                                         while(cd){
985                                                 // \83`\83\83\83\93\83l\83\8bID\82ª\93¯\82\82©
986                                                 if (cd->getChannelId() == s->channel_id){
987                                                         // \83f\81[\83^\90Ý\92è
988                                                         ServentData *sv = ::new ServentData();
989                                                         sv->setData(s, &hitData, totalListeners, totalRelays, infoFlg);
990                                                         sv->setEnableFlg(TRUE);
991                                                         // \83`\83\83\83\93\83l\83\8b\83f\81[\83^\82ÉServentData\92Ç\89Á
992                                                         cd->addServentData(sv);
993                                                         // \83z\83X\83g\96¼\82ð\8eæ\93¾\82·\82é
994                                                         IdData *id = ::new IdData(cd->getChannelId(), sv->getServentId(), sv->getHost().ip);
995                                                         ThreadInfo t;
996                                                         t.func = GetHostName;
997                                                         t.data = (void*)id;
998                                                         sys->startThread(&t);
999                                                         // \83\8b\81[\83v\8fI\97¹
1000                                                         break;
1001                                                 }
1002                                                 // \8e\9f\82Ì\83f\81[\83^\82Ö
1003                                                 cd = cd->getNextData();
1004                                         }
1005                                 }
1006                                 // \83z\83X\83g\8fî\95ñ\83A\83\93\83\8d\83b\83N
1007                                 chanMgr->hitlistlock.off();
1008                         }
1009                         s = s->next;
1010                 }
1011
1012                 // \8dX\90V\82µ\82Ä\82¢\82È\82¢ServentData\82ð\8dí\8f\9c
1013                 cd = channelDataTop;
1014                 while(cd){
1015                         cd->deleteDisableServents();
1016                         cd = cd->getNextData();
1017                 }
1018
1019                 // \83`\83\83\83\93\83l\83\8b\83f\81[\83^\83A\83\93\83\8d\83b\83N
1020                 ChannelDataLock.off();
1021
1022                 // \95`\89æ\8dX\90V
1023                 if (guiWnd){
1024                         MakeBack(guiWnd);
1025                 }
1026
1027                 // 0.1\95b\81~10\82Å1\95b\91Ò\82¿
1028                 for(i=0; i<10; i++)
1029                 {
1030                         if (!thread->active)
1031                                 break;
1032                         sys->sleep(100);
1033                 }
1034
1035                 if (gbGetFile && (sys->getTime() > gtGetFile)){
1036                         gbGetFile = false;
1037                         gtiGetFile.func = GetInternetFile;
1038                         gtiGetFile.data = NULL;
1039                         sys->startThread(&gtiGetFile);
1040                 }
1041                 else if (gbStart && (sys->getTime() > gtStartTime)){
1042                         gbStart = false;
1043                         SendMessage(guiWnd, WM_START, 0, 0);
1044                         gtiStart.func = FestivalStart;
1045                         gtiStart.data = NULL;
1046                         sys->startThread(&gtiStart);
1047                 }
1048         }
1049
1050         // set GUI thread status to terminated
1051         thread->finish = true;
1052
1053         return 0;
1054 }
1055
1056 ChannelData *findChannelData(int channel_id){
1057         ChannelData *cd = channelDataTop;
1058
1059         while(cd){
1060                 if (cd->getChannelId() == channel_id){
1061                         return cd;
1062                 }
1063                 cd = cd->getNextData();
1064         }
1065
1066         return NULL;
1067 }
1068
1069
1070 void PopupChannelMenu(int channel_id){
1071         POINT pos;
1072         MENUITEMINFO info, separator;
1073         HMENU hMenu;
1074         DWORD dwID;
1075
1076         hMenu = CreatePopupMenu();
1077
1078         memset(&separator, 0, sizeof(MENUITEMINFO));
1079         separator.cbSize = sizeof(MENUITEMINFO);
1080         separator.fMask = MIIM_ID | MIIM_TYPE;
1081         separator.fType = MFT_SEPARATOR;
1082         separator.wID = 8000;
1083
1084         memset(&info, 0, sizeof(MENUITEMINFO));
1085         info.cbSize = sizeof(MENUITEMINFO);
1086         info.fMask = MIIM_ID | MIIM_TYPE;
1087         info.fType = MFT_STRING;
1088
1089         ChannelData *cd = findChannelData(channel_id);
1090
1091         if (cd == NULL){
1092                 return;
1093         }
1094
1095         info.wID = 1001;
1096         info.dwTypeData = "\90Ø\92f";
1097         InsertMenuItem(hMenu, -1, true, &info);
1098
1099         InsertMenuItem(hMenu, -1, true, &separator);
1100
1101         info.wID = 1000;
1102         info.dwTypeData = "\8dÄ\90¶";
1103         InsertMenuItem(hMenu, -1, true, &info);
1104
1105         InsertMenuItem(hMenu, -1, true, &separator);
1106
1107         info.wID = 1002;
1108         info.dwTypeData = "\8dÄ\90Ú\91±";
1109         InsertMenuItem(hMenu, -1, true, &info);
1110
1111         info.wID = 1003;
1112         info.dwTypeData = "\83L\81[\83v";
1113         InsertMenuItem(hMenu, -1, true, &info);
1114
1115         InsertMenuItem(hMenu, -1, true, &separator);
1116
1117         if (!cd->getOpenFlg()){
1118                 info.wID = 1004;
1119                 info.dwTypeData = "\92¼\89º\95\\8e¦";
1120                 InsertMenuItem(hMenu, -1, true, &info);
1121         } else {
1122                 info.wID = 1005;
1123                 info.dwTypeData = "\92¼\89º\89B\95Á";
1124                 InsertMenuItem(hMenu, -1, true, &info);
1125         }
1126
1127         GetCursorPos(&pos);
1128         dwID = TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RETURNCMD, pos.x, pos.y, 0, guiWnd, NULL);
1129
1130         DestroyMenu(hMenu);
1131
1132         cd = findChannelData(channel_id);
1133
1134         if (cd == NULL){
1135                 return;
1136         }
1137
1138         Channel *c = chanMgr->findChannelByChannelID(channel_id);
1139
1140         if (c == NULL){
1141                 return;
1142         }
1143
1144         switch(dwID){
1145                 case 1000:      // \8dÄ\90
1146                         chanMgr->playChannel(c->info);
1147                         break;
1148
1149                 case 1001:      // \90Ø\92f
1150                         c->thread.active = false;
1151                         c->thread.finish = true;
1152                         break;
1153
1154                 case 1002:      // \8dÄ\90Ú\91±
1155                         // \92¼\89º\82©\82Â\8eó\90M\92\86\82Å\82 \82ê\82Î\8am\94F\83\81\83b\83Z\81[\83W\95\\8e¦
1156                         if (cd->isTracker() && cd->getStatus() == Channel::S_RECEIVING)
1157                         {
1158                                 int id;
1159                                 id = MessageBox(guiWnd,
1160                                         "\92¼\89º\82Å\82·\82ª\8dÄ\90Ú\91±\82µ\82Ü\82·\82©\81H",
1161                                         "\92¼\89º\8cx\8d\90",
1162                                         MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2);
1163                                 if (id != IDYES)
1164                                         break;
1165                         }
1166
1167                         c->bump = true;
1168                         break;
1169
1170                 case 1003:      // \83L\81[\83v
1171                         if (!c->stayConnected){
1172                                 c->stayConnected  = true;
1173                         } else {
1174                                 c->stayConnected = false;
1175                         }
1176                         break;
1177
1178                 case 1004:      // \92¼\89º\95\\8e¦
1179                         cd->setOpenFlg(TRUE);
1180                         MakeBack(guiWnd);
1181                         break;
1182
1183                 case 1005:      // \92¼\89º\89B\95Á
1184                         cd->setOpenFlg(FALSE);
1185                         MakeBack(guiWnd);
1186                         break;
1187         }
1188 }
1189
1190 void PopupServentMenu(int servent_id){
1191         POINT pos;
1192         MENUITEMINFO info, separator;
1193         HMENU hMenu;
1194         DWORD dwID;
1195
1196         hMenu = CreatePopupMenu();
1197
1198         memset(&separator, 0, sizeof(MENUITEMINFO));
1199         separator.cbSize = sizeof(MENUITEMINFO);
1200         separator.fMask = MIIM_ID | MIIM_TYPE;
1201         separator.fType = MFT_SEPARATOR;
1202         separator.wID = 8000;
1203
1204         memset(&info, 0, sizeof(MENUITEMINFO));
1205         info.cbSize = sizeof(MENUITEMINFO);
1206         info.fMask = MIIM_ID | MIIM_TYPE;
1207         info.fType = MFT_STRING;
1208
1209         ServentData *sd = NULL;
1210         ChannelData *cd = channelDataTop;
1211         while(cd){
1212                 sd = cd->findServentData(servent_id);
1213                 if (sd){
1214                         break;
1215                 }
1216                 cd = cd->getNextData();
1217         }
1218
1219         if (cd == NULL || sd == NULL){
1220                 return;
1221         }
1222
1223         info.wID = 1001;
1224         info.dwTypeData = "\90Ø\92f";
1225         InsertMenuItem(hMenu, -1, true, &info);
1226
1227 //      InsertMenuItem(hMenu, -1, true, &separator);
1228
1229         GetCursorPos(&pos);
1230         dwID = TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RETURNCMD, pos.x, pos.y, 0, guiWnd, NULL);
1231
1232         DestroyMenu(hMenu);
1233
1234         cd = channelDataTop;
1235         while(cd){
1236                 sd = cd->findServentData(servent_id);
1237                 if (sd){
1238                         break;
1239                 }
1240                 cd = cd->getNextData();
1241         }
1242
1243         if (cd == NULL || sd == NULL){
1244                 return;
1245         }
1246
1247         Servent *s = servMgr->findServentByServentID(servent_id);
1248
1249         if (s == NULL){
1250                 return;
1251         }
1252
1253         switch(dwID){
1254                 case 1001:      // \90Ø\92f
1255                         s->thread.active = false;
1256                         break;
1257
1258         }
1259 }
1260
1261 void PopupOtherMenu(){
1262         POINT pos;
1263         MENUITEMINFO info, separator;
1264         HMENU hMenu;
1265         DWORD dwID;
1266
1267         hMenu = CreatePopupMenu();
1268
1269         memset(&separator, 0, sizeof(MENUITEMINFO));
1270         separator.cbSize = sizeof(MENUITEMINFO);
1271         separator.fMask = MIIM_ID | MIIM_TYPE;
1272         separator.fType = MFT_SEPARATOR;
1273         separator.wID = 8000;
1274
1275         memset(&info, 0, sizeof(MENUITEMINFO));
1276         info.cbSize = sizeof(MENUITEMINFO);
1277         info.fMask = MIIM_ID | MIIM_TYPE;
1278         info.fType = MFT_STRING;
1279
1280         if (!gbDispTop){
1281                 info.wID = 1101;
1282                 info.dwTypeData = "\8dÅ\91O\96Ê\95\\8e¦";
1283                 InsertMenuItem(hMenu, -1, true, &info);
1284         } else {
1285                 info.wID = 1102;
1286                 info.dwTypeData = "\8dÅ\91O\96Ê\89ð\8f\9c";
1287                 InsertMenuItem(hMenu, -1, true, &info);
1288         }
1289
1290         InsertMenuItem(hMenu, -1, true, &separator);
1291
1292         if (!gbAllOpen){
1293                 info.wID = 1103;
1294                 info.dwTypeData = "\91S\92¼\89º\93W\8aJ";
1295                 InsertMenuItem(hMenu, -1, true, &info);
1296         } else {
1297                 info.wID = 1104;
1298                 info.dwTypeData = "\91S\92¼\89º\89B\95Á";
1299                 InsertMenuItem(hMenu, -1, true, &info);
1300         }
1301
1302         InsertMenuItem(hMenu, -1, true, &separator);
1303
1304         if (!servMgr->autoServe){
1305                 info.wID = 1105;
1306                 info.dwTypeData = "\97L\8cø";
1307                 InsertMenuItem(hMenu, -1, true, &info);
1308         } else {
1309                 info.wID = 1106;
1310                 info.dwTypeData = "\96³\8cø";
1311                 InsertMenuItem(hMenu, -1, true, &info);
1312         }
1313
1314         GetCursorPos(&pos);
1315         dwID = TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RETURNCMD, pos.x, pos.y, 0, guiWnd, NULL);
1316
1317         DestroyMenu(hMenu);
1318
1319         ChannelData *cd = channelDataTop;
1320
1321         switch(dwID){
1322                 case 1101:      // \8dÅ\91O\96Ê\95\\8e¦
1323                         gbDispTop = true;
1324                         ::SetWindowPos(guiWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
1325                         break;
1326
1327                 case 1102:      // \8dÅ\91O\96Ê\89ð\8f\9c
1328                         gbDispTop = false;
1329                         ::SetWindowPos(guiWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
1330                         break;
1331
1332                 case 1103:      // \91S\92¼\89º\93W\8aJ
1333                         gbAllOpen = true;
1334                         while(cd){
1335                                 cd->setOpenFlg(true);
1336                                 cd = cd->getNextData();
1337                         }
1338                         break;
1339
1340                 case 1104:      // \91S\92¼\89º\89B\95Á
1341                         gbAllOpen = false;
1342                         while(cd){
1343                                 cd->setOpenFlg(false);
1344                                 cd = cd->getNextData();
1345                         }
1346                         break;
1347
1348                 case 1105:      // \97L\8cø
1349                         servMgr->autoServe = true;
1350                         break;
1351
1352                 case 1106:      // \96³\8cø
1353                         servMgr->autoServe = false;
1354                         break;
1355
1356         }
1357 }
1358
1359 void WmCreateProc(HWND hwnd){
1360         // \8e©\93®\8dÅ\91O\96Ê\8b@\94\
1361         if (servMgr->topmostGui)
1362         {
1363                 ::gbDispTop = true;
1364         }
1365
1366         if (backImage){
1367                 ::delete backImage;
1368         }
1369         _bstr_t bstr("back.jpg");
1370         backImage = ::new Image(bstr);
1371
1372         MakeBack(hwnd, 800, 600);
1373
1374         guiThread.func = GUIDataUpdate;
1375         if (!sys->startThread(&guiThread)){
1376                 MessageBox(hwnd,"Unable to start GUI","PeerCast",MB_OK|MB_ICONERROR);
1377                 PostMessage(hwnd,WM_DESTROY,0,0);
1378         }
1379         if (guiFlg){
1380                 SetWindowPlacement(hwnd, &winPlace);
1381         }
1382
1383         if (img_idle){
1384                 ::delete img_idle;
1385                 ::delete img_connect;
1386                 ::delete img_conn_ok;
1387                 ::delete img_conn_full;
1388                 ::delete img_conn_over;
1389                 ::delete img_conn_ok_skip;
1390                 ::delete img_conn_full_skip;
1391                 ::delete img_conn_over_skip;
1392                 ::delete img_error;
1393                 ::delete img_broad_ok;
1394                 ::delete img_broad_full;
1395         }
1396         bstr = L"ST_IDLE.bmp";
1397         img_idle = ::new Image(bstr);
1398         bstr = L"ST_CONNECT.bmp";
1399         img_connect = ::new Image(bstr);
1400         bstr = L"ST_CONN_OK.bmp";
1401         img_conn_ok = ::new Image(bstr);
1402         bstr = L"ST_CONN_FULL.bmp";
1403         img_conn_full = ::new Image(bstr);
1404         bstr = L"ST_CONN_OVER.bmp";
1405         img_conn_over = ::new Image(bstr);
1406         bstr = L"ST_CONN_OK_SKIP.bmp";
1407         img_conn_ok_skip = ::new Image(bstr);
1408         bstr = L"ST_CONN_FULL_SKIP.bmp";
1409         img_conn_full_skip = ::new Image(bstr);
1410         bstr = L"ST_CONN_OVER_SKIP.bmp";
1411         img_conn_over_skip = ::new Image(bstr);
1412         bstr = L"ST_ERROR.bmp";
1413         img_error = ::new Image(bstr);
1414         bstr = L"ST_BROAD_OK.bmp";
1415         img_broad_ok = ::new Image(bstr);
1416         bstr = L"ST_BROAD_FULL.bmp";
1417         img_broad_full = ::new Image(bstr);
1418 }
1419
1420 void WmPaintProc(HWND hwnd){
1421         HDC hdc;
1422         PAINTSTRUCT paint;
1423
1424         if (backGra){
1425                 MakeBackLock.on();
1426                 hdc = BeginPaint(hwnd, &paint);
1427                 RECT *rcRect;   // \95`\89æ\94Í\88Í
1428                 rcRect = &(paint.rcPaint);
1429                 LONG width = rcRect->right - rcRect->left + 1;
1430                 LONG height = rcRect->bottom - rcRect->top + 1;
1431
1432                 Graphics g2(hdc);
1433                 Rect r(rcRect->left, rcRect->top, width, height);
1434                 g2.DrawImage(backBmp,r, rcRect->left, rcRect->top, width, height, UnitPixel);
1435                 EndPaint(hwnd, &paint);
1436                 MakeBackLock.off();
1437         }
1438 }
1439
1440 void WmSizeProc(HWND hwnd, LPARAM lParam){
1441         UINT width = LOWORD(lParam);
1442         UINT height = HIWORD(lParam);
1443
1444         MakeBack(hwnd, width, height);
1445
1446 }
1447
1448 void WmLButtonDownProc(HWND hwnd, LPARAM lParam){
1449         ChannelData *cd;
1450         bool changeFlg = FALSE;
1451
1452         ChannelDataLock.on();
1453         cd = channelDataTop;
1454         while(cd){
1455                 int x = LOWORD(lParam);
1456                 int y = HIWORD(lParam);
1457                 if (cd->checkDown(LOWORD(lParam), HIWORD(lParam))){
1458                         if (!(cd->isSelected())){
1459                                 changeFlg = TRUE;
1460                         }
1461                         cd->setSelected(TRUE);
1462                 } else {
1463                         if (cd->isSelected()){
1464                                 changeFlg = TRUE;
1465                         }
1466                         cd->setSelected(FALSE);
1467                 }
1468                 int sx = cd->getPosX() + cd->getWidth();
1469                 int sy = cd->getPosY();
1470                 int index = 0;
1471                 ServentData *sd = cd->getServentDataTop();
1472                 while(sd){
1473                         if (    (       (!cd->getOpenFlg())
1474                                         &&      (sx + index*14 < x)
1475                                         &&      (x < sx + (index+1)*14)
1476                                         &&      (sy < y)
1477                                         &&      (y < sy + 14)   )
1478                                 ||      sd->checkDown(LOWORD(lParam), HIWORD(lParam))
1479                         ){
1480                                 if (!sd->getSelected()){
1481                                         changeFlg = TRUE;
1482                                 }
1483                                 sd->setSelected(TRUE);
1484                         } else {
1485                                 if (sd->getSelected()){
1486                                         changeFlg = TRUE;
1487                                 }
1488                                 sd->setSelected(FALSE);
1489                         }
1490                         sd = sd->getNextData();
1491                         index++;
1492                 }
1493                 cd = cd->getNextData();
1494         }
1495         ChannelDataLock.off();
1496         if (changeFlg){
1497                 MakeBack(hwnd);
1498         }
1499 }
1500
1501 void WmLButtonDblclkProc(HWND hwnd, LPARAM lParam){
1502         ChannelData *cd;
1503         bool changeFlg = FALSE;
1504
1505         ChannelDataLock.on();
1506         cd = channelDataTop;
1507         while(cd){
1508                 int x = LOWORD(lParam);
1509                 int y = HIWORD(lParam);
1510                 if (cd->checkDown(LOWORD(lParam), HIWORD(lParam))){
1511                         if (!(cd->isSelected())){
1512                                 changeFlg = TRUE;
1513                         }
1514                         if (!(cd->getOpenFlg())){
1515                                 changeFlg = TRUE;
1516                                 cd->setOpenFlg(TRUE);
1517                         } else {
1518                                 changeFlg = TRUE;
1519                                 cd->setOpenFlg(FALSE);
1520                         }
1521                         cd->setSelected(TRUE);
1522                 } else {
1523                         if (cd->isSelected()){
1524                                 changeFlg = TRUE;
1525                         }
1526                         cd->setSelected(FALSE);
1527                 }
1528 /*              int sx = cd->getPosX() + cd->getWidth();
1529                 int sy = cd->getPosY();
1530                 int index = 0;
1531                 ServentData *sd = cd->getServentDataTop();
1532                 while(sd){
1533                         if (    (       (!cd->getOpenFlg())
1534                                         &&      (sx + index*14 < x)
1535                                         &&      (x < sx + (index+1)*14)
1536                                         &&      (sy < y)
1537                                         &&      (y < sy + 14)   )
1538                                 ||      sd->checkDown(LOWORD(lParam), HIWORD(lParam))
1539                         ){
1540                                 if (!sd->getSelected()){
1541                                         changeFlg = TRUE;
1542                                 }
1543                                 sd->setSelected(TRUE);
1544                         } else {
1545                                 if (sd->getSelected()){
1546                                         changeFlg = TRUE;
1547                                 }
1548                                 sd->setSelected(FALSE);
1549                         }
1550                         sd = sd->getNextData();
1551                         index++;
1552                 }*/
1553                 cd = cd->getNextData();
1554         }
1555         ChannelDataLock.off();
1556         if (changeFlg){
1557                 MakeBack(hwnd);
1558         }
1559 }
1560
1561 void WmRButtonDownProc(HWND hwnd, LPARAM lParam){
1562         ChannelData *cd;
1563         bool changeFlg = FALSE;
1564         bool channel_selected = FALSE;
1565         bool servent_selected = FALSE;
1566         int channel_id = 0;
1567         int servent_id = 0;
1568
1569         cd = channelDataTop;
1570         while(cd){
1571                 if (cd->checkDown(LOWORD(lParam), HIWORD(lParam))){
1572                         if (!(cd->isSelected())){
1573                                 changeFlg = TRUE;
1574                         }
1575                         cd->setSelected(TRUE);
1576                         channel_id = cd->getChannelId();
1577                         channel_selected = TRUE;
1578                 } else {
1579                         if (cd->isSelected()){
1580                                 changeFlg = TRUE;
1581                         }
1582                         cd->setSelected(FALSE);
1583                 }
1584                 ServentData *sd = cd->getServentDataTop();
1585                 while(sd){
1586                         if (sd->checkDown(LOWORD(lParam), HIWORD(lParam))){
1587                                 if (!sd->getSelected()){
1588                                         changeFlg = TRUE;
1589                                 }
1590                                 sd->setSelected(TRUE);
1591                                 servent_id = sd->getServentId();
1592                                 servent_selected = TRUE;
1593                         } else {
1594                                 if (sd->getSelected()){
1595                                         changeFlg = TRUE;
1596                                 }
1597                                 sd->setSelected(FALSE);
1598                         }
1599                         sd = sd->getNextData();
1600                 }
1601                 cd = cd->getNextData();
1602         }
1603         if (changeFlg){
1604                 MakeBack(hwnd);
1605         }
1606
1607         if (channel_selected){
1608                 PopupChannelMenu(channel_id);
1609         } else if (servent_selected){
1610                 PopupServentMenu(servent_id);
1611         } else {
1612                 PopupOtherMenu();
1613         }
1614 }
1615
1616 LRESULT CALLBACK GUIProc (HWND hwnd, UINT message,
1617                                  WPARAM wParam, LPARAM lParam)
1618 {
1619         switch(message){
1620                 case WM_CREATE:         // \83E\83B\83\93\83h\83E\8dì\90¬
1621                         WmCreateProc(hwnd);
1622                         break;
1623
1624                 case WM_PAINT:          // \95`\89æ
1625                         WmPaintProc(hwnd);
1626                         break;
1627
1628                 case WM_SIZE:           // \83T\83C\83Y\95Ï\8dX
1629                         WmSizeProc(hwnd,lParam);
1630                         break;
1631
1632                 case WM_LBUTTONDOWN:    // \8d\83{\83^\83\93\89\9f\82·
1633                         WmLButtonDownProc(hwnd,lParam);
1634                         break;
1635
1636                 case WM_RBUTTONDOWN:    // \89E\83{\83^\83\93\89\9f\82·
1637                         WmRButtonDownProc(hwnd,lParam);
1638                         break;
1639
1640                 case WM_LBUTTONDBLCLK:          // \8d\83_\83u\83\8b\83N\83\8a\83b\83N
1641                         WmLButtonDblclkProc(hwnd,lParam);
1642                         break;
1643
1644                 case WM_ERASEBKGND:     // \94w\8ci\8fÁ\8b\8e
1645                         return TRUE;    // \94w\8ci\82Í\8fÁ\82³\82È\82¢
1646
1647                 case WM_CLOSE:
1648                         //if (backImage){
1649                         //      ::delete backImage;
1650                         //      backImage = NULL;
1651                         //}
1652                         GetWindowPlacement(hwnd, &winPlace);
1653                         guiFlg = true;
1654                         DestroyWindow( hwnd );
1655                         break;
1656                 case WM_DESTROY:
1657                         GetWindowPlacement(hwnd, &winPlace);
1658                         guiFlg = true;
1659                         guiThread.active = false;
1660
1661                         // wait until GUI thread terminated,
1662                         // and then dispose background image.
1663                         while (1)
1664                         {
1665                                 if (guiThread.finish)
1666                                         break;
1667                         }
1668                         if (backImage)
1669                         {
1670                                 ::delete backImage;
1671                                 backImage = NULL;
1672                         }
1673
1674                         guiWnd = NULL;
1675                         break;
1676                 case WM_START:
1677                         ghStart = ::CreateWindow(szWindowClass3,
1678                                 "Peercast-IM@S",
1679                                 WS_OVERLAPPEDWINDOW & ~(WS_MAXIMIZEBOX),
1680                                 0,
1681                                 0,
1682                                 400,
1683                                 300,
1684                                 NULL,
1685                                 NULL,
1686                                 hInst,
1687                                 NULL);
1688                         ::ShowWindow(ghStart, SW_SHOWNORMAL);
1689                         break;
1690
1691                 default:
1692                         return (DefWindowProc(hwnd, message, wParam, lParam));
1693         }
1694
1695         return 0;
1696 }
1697
1698 Gdiplus::Image *data1 = NULL;
1699 Gdiplus::Image *data2 = NULL;
1700 Gdiplus::Bitmap *startBmp = NULL;
1701 Gdiplus::Graphics *startGra = NULL;
1702 WLock MakeStartLock;
1703
1704 LRESULT CALLBACK StartProc (HWND hwnd, UINT message,
1705                                  WPARAM wParam, LPARAM lParam)
1706 {
1707         SolidBrush b(Color::Black);
1708         bstr_t bstr;
1709
1710         switch(message){
1711                 case WM_CREATE:
1712                         startBmp = ::new Bitmap(400,300);
1713                         startGra = ::new Graphics(startBmp);
1714                         bstr = L"data1.jpg";
1715                         data1 = ::new Image(bstr);
1716                         bstr = L"data2.jpg";
1717                         data2 = ::new Image(bstr);
1718                         // \8d\95\82Å\93h\82è\82Â\82Ô\82µ
1719                         startGra->FillRectangle(&b, 0, 0, 400, 300);
1720                         break;
1721                 case WM_PAINT:
1722                         if (startGra){
1723                                 HDC hdc;
1724                                 PAINTSTRUCT paint;
1725
1726                                 MakeStartLock.on();
1727                                 hdc = BeginPaint(hwnd, &paint);
1728                                 RECT *rcRect;
1729                                 rcRect = &(paint.rcPaint);
1730                                 LONG width = rcRect->right - rcRect->left + 1;
1731                                 LONG height = rcRect->bottom - rcRect->top + 1;
1732
1733                                 Graphics g2(hdc);
1734                                 Rect r(rcRect->left, rcRect->top, width, height);
1735                                 g2.DrawImage(startBmp, r, rcRect->left, rcRect->top, width, height, UnitPixel);
1736                                 EndPaint(hwnd, &paint);
1737                                 MakeStartLock.off();
1738                         }
1739                         break;
1740                 case WM_ERASEBKGND:
1741                         return TRUE;
1742                 case WM_CLOSE:
1743                         DestroyWindow(ghStart);
1744                         if (startBmp){
1745                                 ::delete startBmp;
1746                         }
1747                         if (startGra){
1748                                 ::delete startGra;
1749                         }
1750                         if (data1){
1751                                 ::delete data1;
1752                         }
1753                         if (data2){
1754                                 ::delete data2;
1755                         }
1756                         break;
1757
1758                 default:
1759                         return (DefWindowProc(hwnd, message, wParam, lParam));
1760         }
1761
1762         return 0;
1763 }
1764
1765 THREAD_PROC FestivalStart(ThreadInfo *thread){
1766
1767         while(startGra==NULL){
1768                 sys->sleep(100);
1769         }
1770
1771         sys->sleep(1000);
1772
1773         MakeStartLock.on();
1774         Font font(L"\82l\82\82o\83S\83V\83b\83N",40);
1775         StringFormat format;
1776         format.SetAlignment(StringAlignmentCenter);
1777         startGra->SetTextRenderingHint(TextRenderingHintAntiAlias);
1778         PointF origin(199.0f,49.0f);
1779         RectF rect(0,0,400,100);
1780         LinearGradientBrush b1(rect, Color::LightSkyBlue, Color::White, LinearGradientModeHorizontal);
1781         startGra->DrawString(L"\91æ\82Q\89ñ", -1, &font, origin, &format, &b1);
1782         origin.Y += 50;
1783         LinearGradientBrush b2(rect, Color::LightGreen, Color::White, LinearGradientModeHorizontal);
1784         startGra->DrawString(L"\83A\83C\83h\83\8b\83}\83X\83^\81[", -1, &font, origin, &format, &b2);
1785         origin.Y += 50;
1786         LinearGradientBrush b3(rect, Color::LightGoldenrodYellow, Color::White, LinearGradientModeHorizontal);
1787         startGra->DrawString(L"\83t\83@\83\93\8a´\8eÓ\8dÕ", -1, &font, origin, &format, &b3);
1788         MakeStartLock.off();
1789         InvalidateRect(ghStart, NULL, FALSE);
1790         sys->sleep(3000);
1791
1792         MakeStartLock.on();
1793         startGra->DrawImage(data1, Rect(0,0,80,400), 200,200,66,330, UnitPixel);
1794         MakeStartLock.off();
1795         InvalidateRect(ghStart, NULL, FALSE);
1796         sys->sleep(500);
1797
1798         MakeStartLock.on();
1799         startGra->DrawImage(data1, Rect(80,0,80,400), 266,200,66,330, UnitPixel);
1800         MakeStartLock.off();
1801         InvalidateRect(ghStart, NULL, FALSE);
1802         sys->sleep(500);
1803
1804         MakeStartLock.on();
1805         startGra->DrawImage(data1, Rect(160,0,80,400), 332,200,66,330, UnitPixel);
1806         MakeStartLock.off();
1807         InvalidateRect(ghStart, NULL, FALSE);
1808         sys->sleep(500);
1809
1810         MakeStartLock.on();
1811         startGra->DrawImage(data1, Rect(240,0,80,400), 398,200,66,330, UnitPixel);
1812         MakeStartLock.off();
1813         InvalidateRect(ghStart, NULL, FALSE);
1814         sys->sleep(500);
1815
1816         MakeStartLock.on();
1817         startGra->DrawImage(data1, Rect(320,0,80,400), 464,200,66,330, UnitPixel);
1818         MakeStartLock.off();
1819         InvalidateRect(ghStart, NULL, FALSE);
1820         sys->sleep(500);
1821
1822         MakeStartLock.on();
1823         startGra->DrawImage(data1, Rect(0,0,80,400), 530,200,54,270, UnitPixel);
1824         MakeStartLock.off();
1825         InvalidateRect(ghStart, NULL, FALSE);
1826         sys->sleep(500);
1827
1828         MakeStartLock.on();
1829         startGra->DrawImage(data1, Rect(80,0,80,400), 584,200,54,270, UnitPixel);
1830         MakeStartLock.off();
1831         InvalidateRect(ghStart, NULL, FALSE);
1832         sys->sleep(500);
1833
1834         MakeStartLock.on();
1835         startGra->DrawImage(data1, Rect(160,0,80,400), 638,200,54,270, UnitPixel);
1836         MakeStartLock.off();
1837         InvalidateRect(ghStart, NULL, FALSE);
1838         sys->sleep(500);
1839
1840         MakeStartLock.on();
1841         startGra->DrawImage(data1, Rect(240,0,80,400), 692,200,54,270, UnitPixel);
1842         MakeStartLock.off();
1843         InvalidateRect(ghStart, NULL, FALSE);
1844         sys->sleep(500);
1845
1846         MakeStartLock.on();
1847         startGra->DrawImage(data1, Rect(320,0,80,400), 746,200,54,270, UnitPixel);
1848         MakeStartLock.off();
1849         InvalidateRect(ghStart, NULL, FALSE);
1850         sys->sleep(500);
1851
1852         for (int i=1; i<=10; i++){
1853                 ColorMatrix mtx = {
1854                         1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1855                         0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
1856                         0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1857                         0.0f, 0.0f, 0.0f, 0.1f*i, 0.0f,
1858                         0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
1859                 ImageAttributes att;
1860
1861                 MakeStartLock.on();
1862                 att.SetColorMatrix(&mtx, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap);
1863                 startGra->DrawImage(data2, Rect(0,0,400,300), 360,130,400,300, UnitPixel, &att);
1864                 MakeStartLock.off();
1865                 InvalidateRect(ghStart, NULL, FALSE);
1866                 sys->sleep(100);
1867         }
1868
1869         sys->sleep(2000);
1870
1871         MakeStartLock.on();
1872         INT style = FontStyleBold;
1873         Font font2(L"\82l\82\82o\83S\83V\83b\83N",70,style,UnitPoint);
1874         PointF origin2(199.0f,99.0f);
1875         SolidBrush bs(Color::Black);
1876         startGra->DrawString(L"START!", -1, &font2, origin2, &format, &bs);
1877         Font font3(L"\82l\82\82o\83S\83V\83b\83N",70,style,UnitPoint);
1878         LinearGradientBrush bx(rect, Color::LightPink, Color::DeepPink, LinearGradientModeHorizontal);
1879         startGra->DrawString(L"START!", -1, &font3, origin2, &format, &bx);
1880         MakeStartLock.off();
1881         InvalidateRect(ghStart, NULL, FALSE);
1882         sys->sleep(5000);
1883
1884         SendMessage(ghStart, WM_CLOSE, 0, 0);
1885         return 0;
1886 }