OSDN Git Service

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