OSDN Git Service

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