source: dev/trunk/ab5.0/abdev/abdev/ClassTree.cpp @ 655

Last change on this file since 655 was 655, checked in by dai_9181, 15 years ago

FileManager周りをリファクタリング

File size: 14.9 KB
Line 
1#include "stdafx.h"
2
3#include "Common.h"
4
5#if defined(JPN)
6//日本語
7#include "pj_msg_jpn.h"
8#else
9//英語
10#include "pj_msg_eng.h"
11#endif
12
13
14CClassTreeView *pobj_ClassTreeView;
15
16BOOL bSearchingClasses,bRetrySearchingClasses;
17
18
19int CClassTreeView::hash_default(LONG_PTR lpdata){
20    return lpdata%MAX_HASH;
21}
22void CClassTreeView::AddValidItem(HTREEITEM hItem,HTREEITEM hFileTreeItem){
23    //ハッシュ値を取得
24    int key;
25    key=hash_default((LONG_PTR)hItem);
26
27    //格納位置を取得
28    TREEHASH *pth;
29    pth=&tree_data[key];
30    while(pth->hItem){
31        if(pth->hItem==hItem){
32            //既に存在するときは抜け出す
33            return;
34        }
35        if(pth->pNextData==0){
36            pth->pNextData=(TREEHASH *)HeapAlloc(hHeap,0,sizeof(TREEHASH));
37            pth=pth->pNextData;
38            break;
39        }
40        pth=pth->pNextData;
41    }
42
43    pth->hItem=hItem;
44    pth->hFileTreeItem = hFileTreeItem;
45    pth->pNextData=0;
46}
47
48BOOL CClassTreeView::delete_check(HTREEITEM hItem){
49    //ハッシュ値を取得
50    int key;
51    key=hash_default((LONG_PTR)hItem);
52
53    TREEHASH *pth;
54    pth=&tree_data[key];
55    while(pth->hItem){
56        if(pth->hItem==hItem) return 1;
57
58        if(pth->pNextData==0) break;
59        pth=pth->pNextData;
60    }
61    return 0;
62}
63
64void CClassTreeView::DeleteInvalidItems(HTREEITEM hItem){
65    HTREEITEM hChildItem;
66    while(hItem){
67        if(!delete_check(hItem)){
68            HTREEITEM hTemp;
69            hTemp=hItem;
70
71            hItem=TreeView_GetNextSibling(hTreeWnd,hItem);
72
73            TreeView_DeleteItem(hTreeWnd,hTemp);
74            continue;
75        }
76
77        hChildItem=TreeView_GetChild(hTreeWnd,hItem);
78        if(hChildItem){
79            DeleteInvalidItems(hChildItem);
80        }
81
82        hItem=TreeView_GetNextSibling(hTreeWnd,hItem);
83    }
84}
85
86void CClassTreeView::DeleteTreeHash(TREEHASH *pth){
87    if(pth->hItem && (hNowFileTreeItem==(HTREEITEM)-1 || hNowFileTreeItem==pth->hFileTreeItem)){
88        if(pth->pNextData){
89            DeleteTreeHash(pth->pNextData);
90            HeapDefaultFree(pth->pNextData);
91            pth->pNextData=0;
92        }
93        pth->hItem=0;
94    }
95}
96
97
98HTREEITEM CClassTreeView::insert(HTREEITEM hParentItem,int flag,char *lpszName,HTREEITEM hFileTreeItem){
99    char temporary[255];
100
101    TVITEM tvItem;
102    tvItem.pszText=temporary;
103    tvItem.cchTextMax=255;
104    HTREEITEM hNextItem;
105    hNextItem=TreeView_GetChild(hTreeWnd,hParentItem);
106    while(hNextItem){
107        tvItem.mask=TVIF_HANDLE|TVIF_TEXT;
108        tvItem.hItem=hNextItem;
109        TreeView_GetItem(hTreeWnd,&tvItem);
110        if(lstrcmp(lpszName,tvItem.pszText)==0){
111            //既に挿入済みの場合
112            AddValidItem(hNextItem,hFileTreeItem);
113            return hNextItem;
114        }
115
116        hNextItem=TreeView_GetNextSibling(hTreeWnd,hNextItem);
117    }
118
119
120    TV_INSERTSTRUCT tv;
121    tv.hInsertAfter=TVI_SORT;
122    tv.item.mask=TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIS_EXPANDED ;
123    tv.hParent=hParentItem;
124    tv.item.pszText=lpszName;
125
126    if(flag==CTV_ROOT){
127        tv.item.iImage=3;
128        tv.item.iSelectedImage=3;
129    }
130    if(flag==CTV_FOLDER){
131        tv.item.iImage=0;
132        tv.item.iSelectedImage=0;
133    }
134    else if(flag==CTV_GLOBAL_PROC){
135        tv.item.iImage=5;
136        tv.item.iSelectedImage=5;
137    }
138    else if(flag==CTV_CLASS){
139        tv.item.iImage=2;
140        tv.item.iSelectedImage=2;
141    }
142    else if(flag==CTV_PUBLIC_MEMBER){
143        tv.item.iImage=4;
144        tv.item.iSelectedImage=4;
145    }
146    else if(flag==CTV_PUBLIC_METHOD){
147        tv.item.iImage=5;
148        tv.item.iSelectedImage=5;
149    }
150    else if(flag==CTV_PRIVATE_MEMBER){
151        tv.item.iImage=6;
152        tv.item.iSelectedImage=6;
153    }
154    else if(flag==CTV_PRIVATE_METHOD){
155        tv.item.iImage=7;
156        tv.item.iSelectedImage=7;
157    }
158
159    hNextItem=TreeView_InsertItem(hTreeWnd,&tv);
160    AddValidItem(hNextItem,hFileTreeItem);
161    return hNextItem;
162}
163
164
165
166CClassTreeView::CClassTreeView(){
167    memset(this,0,sizeof(CClassTreeView));
168}
169CClassTreeView::~CClassTreeView(){
170    while(bSearchingClasses) Sleep(10);
171
172    this->hNowFileTreeItem = (HTREEITEM)-1;
173
174    int i;
175    for(i=0;i<MAX_HASH;i++){
176        DeleteTreeHash(&tree_data[i]);
177    }
178
179    if(pobj_ClassTreeView->pProcInfo){
180        //プロシージャ情報のメモリを解放
181        for(i=0;i<pobj_ClassTreeView->NumberOfProcedures;i++){
182            HeapDefaultFree(pobj_ClassTreeView->pProcInfo[i].name);
183        }
184        HeapDefaultFree(pobj_ClassTreeView->pProcInfo);
185        pobj_ClassTreeView->pProcInfo=0;
186    }
187}
188void CClassTreeView::init(HWND hwnd,HTREEITEM hFileTreeItem){
189    hTreeWnd=hwnd;
190
191    this->hNowFileTreeItem = hFileTreeItem;
192
193    int i;
194    for(i=0;i<MAX_HASH;i++){
195        DeleteTreeHash(&tree_data[i]);
196    }
197}
198
199void CClassTreeView::InsertRootFolder(void){
200    char temporary[VN_SIZE];
201    sprintf(temporary,"%s クラス",projectInfo.GetName().c_str());
202    hRootFolder=insert(
203        TVI_ROOT,
204        CTV_ROOT,
205        temporary,(HTREEITEM)-1);
206}
207void CClassTreeView::InsertGlobalProcedureFolder(void){
208    hGlobalProcedureFolder=insert(
209        hRootFolder,
210        CTV_FOLDER,
211        "グローバル関数",(HTREEITEM)-1);
212}
213
214HTREEITEM CClassTreeView::InsertGlobalProcedure(int flag,char *lpszName,HTREEITEM hFileTreeItem){
215    return pobj_ClassTreeView->insert(
216        hGlobalProcedureFolder,
217        CTV_GLOBAL_PROC,
218        lpszName,
219        hFileTreeItem);
220}
221
222HTREEITEM CClassTreeView::insert_code_item(HTREEITEM hParentItem,int flag,char *lpszName,HTREEITEM hFileTreeItem,char *pBuf,int p){
223    int i4;
224    i4=NumberOfProcedures;
225    pProcInfo=(PROCINFO *)HeapReAlloc(hHeap,0,pProcInfo,sizeof(PROCINFO)*(i4+1));
226    pProcInfo[i4].name=(char *)HeapAlloc(hHeap,0,lstrlen(lpszName)+1);
227    lstrcpy(pProcInfo[i4].name,lpszName);
228    pProcInfo[i4].hFileTreeItem = hFileTreeItem;
229
230    //コード位置
231    pProcInfo[i4].code_pos=p;
232
233    //ツリーアイテムを挿入
234    HTREEITEM hTempItem;
235    hTempItem=insert(
236        hParentItem,
237        flag,
238        lpszName,
239        hFileTreeItem);
240
241    pProcInfo[i4].hTreeItem=hTempItem;
242
243    NumberOfProcedures++;
244
245    return hTempItem;
246}
247
248void CClassTreeView::InsertClassFolder(char *lpszName,HTREEITEM hFileTreeItem,char *pBuf,int p){
249    hNowClassFolder=insert_code_item(hRootFolder,CTV_CLASS,lpszName,hFileTreeItem,pBuf,p);
250}
251void CClassTreeView::InsertClassMember(int flag,char *lpszName,HTREEITEM hFileTreeItem,char *pBuf,int p){
252    insert_code_item(hNowClassFolder,flag,lpszName,hFileTreeItem,pBuf,p);
253}
254
255void CClassTreeView::finish(){
256    DeleteInvalidItems(TreeView_GetRoot(hTreeWnd));
257}
258
259
260void AnalysisClass(char *pBuf,int *p,HTREEITEM hFileTreeItem){
261    int i2;
262    i2=*p;
263
264
265    CClassInfo *pobj_ClassInfo;
266    pobj_ClassInfo=new CClassInfo();
267
268    pobj_ClassInfo->Analyze(pBuf,p);
269
270
271    //クラスフォルダを挿入
272    pobj_ClassTreeView->InsertClassFolder(
273        pobj_ClassInfo->ClassName,
274        hFileTreeItem,
275        pBuf,
276        i2);
277
278
279
280    ///////////////////////////////
281    // メンバ及びメソッドを挿入
282    ///////////////////////////////
283
284    int i;
285    for(i=0;i<pobj_ClassInfo->MemberNum;i++){
286        int flag;
287        if(pobj_ClassInfo->pMemberInfo[i].dwProc==0){
288            //メンバ変数
289            if(pobj_ClassInfo->pMemberInfo[i].dwAccess==ACCESS_PUBLIC){
290                //公開
291                flag=CTV_PUBLIC_MEMBER;
292            }
293            else{
294                //非公開
295                flag=CTV_PRIVATE_MEMBER;
296            }
297        }
298        else{
299            //メソッド
300            if(pobj_ClassInfo->pMemberInfo[i].dwAccess==ACCESS_PUBLIC){
301                //公開
302                flag=CTV_PUBLIC_METHOD;
303            }
304            else{
305                //非公開
306                flag=CTV_PRIVATE_METHOD;
307            }
308        }
309        pobj_ClassTreeView->InsertClassMember(flag,pobj_ClassInfo->pMemberInfo[i].pName,hFileTreeItem,pBuf,pobj_ClassInfo->pMemberInfo[i].code_pos);
310    }
311
312
313    delete pobj_ClassInfo;
314    pobj_ClassInfo=0;
315}
316
317
318void SetClassTreeFromOneFile_Buf( char *pBuf, HTREEITEM hFileTreeItem ){
319    int i2,i3,i4;
320    char temporary[GENERAL_SIZE];
321
322    for(i2=0;;i2++){
323        if(pBuf[i2]=='\0') break;
324        while(pBuf[i2]=='\r'&&pBuf[i2+1]=='\n'&&pBuf[i2+2]=='\r'&&pBuf[i2+3]=='\n') i2+=2;
325        if(i2==0||(pBuf[i2]=='\r'&&pBuf[i2+1]=='\n')){
326            if(pBuf[i2]=='\r'&&pBuf[i2+1]=='\n') i2+=2;
327            while(pBuf[i2]>='0'&&pBuf[i2]<='9') i2++;
328            while(pBuf[i2]==' '||pBuf[i2]=='\t') i2++;
329
330            i4=i2;
331            for(i3=0;;i2++,i3++){
332                if(!IsVariableChar(pBuf[i2])){
333                    temporary[i3]=0;
334                    break;
335                }
336                temporary[i3]=pBuf[i2];
337            }
338            if(pBuf[i2]=='\0') break;
339
340            if(lstrcmpi(temporary,"Class")==0||
341                lstrcmpi(temporary,"Type")==0||
342                lstrcmpi(temporary,"Interface")==0){
343
344                /////////////////////////////
345                // クラスの解析
346                /////////////////////////////
347                AnalysisClass(pBuf,&i4,hFileTreeItem);
348
349                i2=i4-1;
350                continue;
351            }
352
353            int sw;
354            if(lstrcmpi(temporary,"Sub")==0) sw=1;
355            else if(lstrcmpi(temporary,"Function")==0) sw=2;
356            else sw=0;
357
358            if(sw){
359                //Sub/Function
360                while(pBuf[i2]==' '||pBuf[i2]=='\t') i2++;
361                for(i3=0;;i2++,i3++){
362                    if(!IsVariableChar(pBuf[i2])){
363                        temporary[i3]=0;
364                        break;
365                    }
366                    temporary[i3]=pBuf[i2];
367                }
368
369                if(lstrcmpi(temporary,"Export")==0){
370                    //Export修飾子はとばす
371                    while(pBuf[i2]==' '||pBuf[i2]=='\t') i2++;
372
373                    for(i3=0;;i2++,i3++){
374                        if(!IsVariableChar(pBuf[i2])){
375                            temporary[i3]=0;
376                            break;
377                        }
378                        temporary[i3]=pBuf[i2];
379                    }
380                }
381
382                i4=pobj_ClassTreeView->NumberOfProcedures;
383                pobj_ClassTreeView->pProcInfo=(PROCINFO *)HeapReAlloc(hHeap,0,pobj_ClassTreeView->pProcInfo,sizeof(PROCINFO)*(i4+1));
384                pobj_ClassTreeView->pProcInfo[i4].name=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1);
385                lstrcpy(pobj_ClassTreeView->pProcInfo[i4].name,temporary);
386                pobj_ClassTreeView->pProcInfo[i4].hFileTreeItem = hFileTreeItem;
387
388                //定義行の選択範囲
389                pobj_ClassTreeView->pProcInfo[i4].code_pos=i2;
390
391                //パラメータ部
392                while(pBuf[i2]==' '||pBuf[i2]=='\t') i2++;
393                if(pBuf[i2]=='('){
394                    int IsStr,PareNum;
395                    for(i2++,i3=0,IsStr=0,PareNum=0;;i2++,i3++){
396                        if(pBuf[i2]=='\"') IsStr^=1;
397                        if(pBuf[i2]=='('&&IsStr==0) PareNum++;
398                        if(pBuf[i2]==')'&&IsStr==0){
399                            PareNum--;
400                            if(PareNum<0){
401                                temporary[i3]=0;
402                                break;
403                            }
404                        }
405                        if(pBuf[i2]=='\0') break;
406                        temporary[i3]=pBuf[i2];
407                    }
408                    //temporaryはパラメータの内容が格納されるが、不要
409                }
410
411                for(;;i2++){
412                    if(IsCommandDelimitation(pBuf,i2)){
413                        break;
414                    }
415                    if((pBuf[i2]=='a'||pBuf[i2]=='A')&&(pBuf[i2+1]=='s'||pBuf[i2+1]=='S')&&(pBuf[i2+2]==' '||pBuf[i2+2]=='\t')){
416                        i2+=3;
417                        while(pBuf[i2]==' '||pBuf[i2]=='\t') i2++;
418                        for(i3=0;;i2++,i3++){
419                            if(!IsVariableChar(pBuf[i2])){
420                                temporary[i3]=0;
421                                break;
422                            }
423                            temporary[i3]=pBuf[i2];
424                        }
425                        //temporaryには型情報が格納されるが、不要
426                        break;
427                    }
428                }
429
430                //ツリーアイテムを挿入
431                HTREEITEM hTempItem;
432                hTempItem=pobj_ClassTreeView->InsertGlobalProcedure(
433                    CTV_GLOBAL_PROC,
434                    pobj_ClassTreeView->pProcInfo[i4].name,
435                    hFileTreeItem);
436                pobj_ClassTreeView->pProcInfo[i4].hTreeItem=hTempItem;
437
438                pobj_ClassTreeView->NumberOfProcedures++;
439
440                i2--;
441            }
442        }
443    }
444}
445void SetClassTreeFromOneFile( const ActiveBasic::PM::FM::File &file){
446    int WndNum;
447    HWND hChild=GetWindow(hClient,GW_CHILD);
448    while(hChild){
449        WndNum=GetWndNum(hChild);
450        if( WndNum != -1 )
451        {
452            if(IS_DOCUMENT_TEXT(MdiInfo[WndNum]->DocType)){
453                if(lstrcmpi(MdiInfo[WndNum]->path.c_str(),file.GetFullPath().c_str())==0) break;
454            }
455            hChild=GetNextWindow(hChild,GW_HWNDNEXT);
456        }
457    }
458
459    char *pBuf;
460    if(hChild){
461        //すでに指定されたファイルが開かれている場合
462        pBuf=MdiInfo[WndNum]->pMdiTextEdit->buffer;
463    }
464    else{
465        //開かれていない場合
466        pBuf=ReadBuffer(file.GetFullPath());
467        if(!pBuf) pBuf=(char *)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,1);
468    }
469
470    SetClassTreeFromOneFile_Buf( pBuf, file.GetTreeItemHandle() );
471
472    if(!hChild) HeapDefaultFree(pBuf);
473}
474void SetClassTreeFromAllFile( ActiveBasic::PM::FM::Folder &folder )
475{
476    BOOST_FOREACH( ActiveBasic::PM::FM::Folder &childFolder, folder.folders )
477    {
478        SetClassTreeFromAllFile( childFolder );
479    }
480
481    BOOST_FOREACH( ActiveBasic::PM::FM::File &file, folder.files )
482    {
483        SetClassTreeFromOneFile( file );
484    }
485}
486
487void SetProcedureTreeData(void *temp_hFileTreeItem)
488{
489    BOOL bExpand;
490    TVITEM tvItem;
491    SCROLLINFO si;
492
493    HTREEITEM hFileTreeItem = (HTREEITEM)temp_hFileTreeItem;
494
495    if(bSearchingClasses){
496        bRetrySearchingClasses=1;
497        _endthread();
498        return;
499    }
500    bSearchingClasses=1;
501
502    if(pobj_ClassTreeView->pProcInfo){
503wait_repeat:
504        Sleep(700);
505        if(bRetrySearchingClasses){
506            bRetrySearchingClasses=0;
507            goto wait_repeat;
508        }
509
510        PROCINFO *pNewProcInfo;
511        pNewProcInfo=(PROCINFO *)HeapAlloc(hHeap,0,pobj_ClassTreeView->NumberOfProcedures*sizeof(PROCINFO));
512        int NewProcNum;
513        NewProcNum=0;
514
515        //プロシージャ情報のメモリを解放
516        for(int i=0;i<pobj_ClassTreeView->NumberOfProcedures;i++){
517            if(hFileTreeItem==(HTREEITEM)-1 || hFileTreeItem==pobj_ClassTreeView->pProcInfo[i].hFileTreeItem){
518                HeapDefaultFree(pobj_ClassTreeView->pProcInfo[i].name);
519            }
520            else{
521                pNewProcInfo[NewProcNum]=pobj_ClassTreeView->pProcInfo[i];
522                NewProcNum++;
523            }
524        }
525        HeapDefaultFree(pobj_ClassTreeView->pProcInfo);
526
527        pobj_ClassTreeView->pProcInfo=pNewProcInfo;
528        pobj_ClassTreeView->NumberOfProcedures=NewProcNum;
529    }
530    else{
531        pobj_ClassTreeView->pProcInfo=(PROCINFO *)HeapAlloc(hHeap,0,1);
532        pobj_ClassTreeView->NumberOfProcedures=0;
533    }
534
535    extern HWND hProcedureTreeView;
536    tvItem.hItem=TreeView_GetRoot(hProcedureTreeView);
537    if(tvItem.hItem){
538        TreeView_GetItem(hProcedureTreeView,&tvItem);
539        if(tvItem.state&TVIS_EXPANDED){
540            bExpand=1;
541
542            si.cbSize=sizeof(SCROLLINFO);
543            si.fMask=SIF_POS;
544            GetScrollInfo(hProcedureTreeView,SB_VERT,&si);
545        }
546        else bExpand=0;
547    }
548    else bExpand=1;
549
550
551    pobj_ClassTreeView->init(hProcedureTreeView,hFileTreeItem);
552
553    //ルートフォルダ
554    pobj_ClassTreeView->InsertRootFolder();
555
556    //グローバル関数フォルダ
557    pobj_ClassTreeView->InsertGlobalProcedureFolder();
558
559
560    //描画をロック
561    LockWindowUpdate(hProcedureTreeView);
562
563    if( projectInfo.IsOpened() ){
564        // プロジェクトが開かれているとき
565        if(hFileTreeItem==(HTREEITEM)-1){
566            boost::mutex::scoped_lock lock( projectInfo.fileSystem.mutex );
567
568            //プロジェクトのすべてのファイルを解析
569            SetClassTreeFromAllFile( projectInfo.fileSystem.root );
570
571            //不要になったアイテムを除去
572            //pobj_ClassTreeView->finish();
573        }
574        else{
575            /////////////////////////////////
576            // 編集中のファイルのみを解析
577            /////////////////////////////////
578
579            SetClassTreeFromOneFile( projectInfo.fileSystem.root.FindFile( hFileTreeItem ) );
580        }
581    }
582    else{
583        // 編集中の単体ファイルを解析
584
585        HWND hChild=GetWindow(hClient,GW_CHILD);
586        int WndNum=GetWndNum(hChild);
587        char *pBuf=MdiInfo[WndNum]->pMdiTextEdit->buffer;
588        SetClassTreeFromOneFile_Buf( pBuf, (HTREEITEM)-1 );
589
590    }
591
592    //不要になったアイテムを除去
593    pobj_ClassTreeView->finish();
594
595    //描画ロックを解除
596    LockWindowUpdate(0);
597
598
599    if(bExpand){
600        TreeView_Expand(hProcedureTreeView,pobj_ClassTreeView->hRootFolder,TVE_EXPAND);
601
602        SetScrollInfo(hProcedureTreeView,SB_VERT,&si,1);
603    }
604
605
606    bSearchingClasses=0;
607    if(bRetrySearchingClasses){
608        bRetrySearchingClasses=0;
609        ResetClassTree(hFileTreeItem);
610    }
611
612    if(pobj_ClassTreeView->bCloseSwitch){
613        //コード解析中に終了ボタンが押されたとき
614        PostMessage(hOwner,WM_CLOSE,0,0);
615    }
616    if(pobj_ClassTreeView->bShowSwitch){
617        //コード解析中にクラスビューがダブルクリックされたとき
618        extern HWND hProjectViewTab;
619        PostMessage(hProjectViewTab,WM_COMMAND,IDM_PROCEDURETREE_SHOW,0);
620        pobj_ClassTreeView->bShowSwitch=0;
621    }
622
623    _endthread();
624}
625void ResetClassTree(HTREEITEM hFileTreeItem){
626    _beginthread(SetProcedureTreeData,0,(void *)hFileTreeItem);
627}
Note: See TracBrowser for help on using the repository browser.