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

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

構成管理を変更中・・・(いったんコミット)

File size: 14.3 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,int iFileNum){
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->iFileNum=iFileNum;
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 && (iNowFile==-1 || iNowFile==pth->iFileNum)){
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,int iFileNum){
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,iFileNum);
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,iFileNum);
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    iNowFile=-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,int iFileNum){
189    hTreeWnd=hwnd;
190
191    iNowFile=iFileNum;
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    extern PROJECTINFO ProjectInfo;
201    char temporary[VN_SIZE];
202    sprintf(temporary,"%s クラス",ProjectInfo.name);
203    hRootFolder=insert(
204        TVI_ROOT,
205        CTV_ROOT,
206        temporary,-1);
207}
208void CClassTreeView::InsertGlobalProcedureFolder(void){
209    hGlobalProcedureFolder=insert(
210        hRootFolder,
211        CTV_FOLDER,
212        "グローバル関数",-1);
213}
214
215HTREEITEM CClassTreeView::InsertGlobalProcedure(int flag,char *lpszName,int iFileNum){
216    return pobj_ClassTreeView->insert(
217        hGlobalProcedureFolder,
218        CTV_GLOBAL_PROC,
219        lpszName,
220        iFileNum);
221}
222
223HTREEITEM CClassTreeView::insert_code_item(HTREEITEM hParentItem,int flag,char *lpszName,int iFileNum,char *pBuf,int p){
224    int i4;
225    i4=NumberOfProcedures;
226    pProcInfo=(PROCINFO *)HeapReAlloc(hHeap,0,pProcInfo,sizeof(PROCINFO)*(i4+1));
227    pProcInfo[i4].name=(char *)HeapAlloc(hHeap,0,lstrlen(lpszName)+1);
228    lstrcpy(pProcInfo[i4].name,lpszName);
229    pProcInfo[i4].FileNum=iFileNum;
230
231    //コード位置
232    pProcInfo[i4].code_pos=p;
233
234    //ツリーアイテムを挿入
235    HTREEITEM hTempItem;
236    hTempItem=insert(
237        hParentItem,
238        flag,
239        lpszName,
240        iFileNum);
241
242    pProcInfo[i4].hTreeItem=hTempItem;
243
244    NumberOfProcedures++;
245
246    return hTempItem;
247}
248
249void CClassTreeView::InsertClassFolder(char *lpszName,int iFileNum,char *pBuf,int p){
250    hNowClassFolder=insert_code_item(hRootFolder,CTV_CLASS,lpszName,iFileNum,pBuf,p);
251}
252void CClassTreeView::InsertClassMember(int flag,char *lpszName,int iFileNum,char *pBuf,int p){
253    insert_code_item(hNowClassFolder,flag,lpszName,iFileNum,pBuf,p);
254}
255
256void CClassTreeView::finish(){
257    DeleteInvalidItems(TreeView_GetRoot(hTreeWnd));
258}
259
260
261void AnalysisClass(char *pBuf,int *p,int iFileNum){
262    int i2;
263    i2=*p;
264
265
266    CClassInfo *pobj_ClassInfo;
267    pobj_ClassInfo=new CClassInfo();
268
269    pobj_ClassInfo->Analyze(pBuf,p);
270
271
272    //クラスフォルダを挿入
273    pobj_ClassTreeView->InsertClassFolder(
274        pobj_ClassInfo->ClassName,
275        iFileNum,
276        pBuf,
277        i2);
278
279
280
281    ///////////////////////////////
282    // メンバ及びメソッドを挿入
283    ///////////////////////////////
284
285    int i;
286    for(i=0;i<pobj_ClassInfo->MemberNum;i++){
287        int flag;
288        if(pobj_ClassInfo->pMemberInfo[i].dwProc==0){
289            //メンバ変数
290            if(pobj_ClassInfo->pMemberInfo[i].dwAccess==ACCESS_PUBLIC){
291                //公開
292                flag=CTV_PUBLIC_MEMBER;
293            }
294            else{
295                //非公開
296                flag=CTV_PRIVATE_MEMBER;
297            }
298        }
299        else{
300            //メソッド
301            if(pobj_ClassInfo->pMemberInfo[i].dwAccess==ACCESS_PUBLIC){
302                //公開
303                flag=CTV_PUBLIC_METHOD;
304            }
305            else{
306                //非公開
307                flag=CTV_PRIVATE_METHOD;
308            }
309        }
310        pobj_ClassTreeView->InsertClassMember(flag,pobj_ClassInfo->pMemberInfo[i].pName,iFileNum,pBuf,pobj_ClassInfo->pMemberInfo[i].code_pos);
311    }
312
313
314    delete pobj_ClassInfo;
315    pobj_ClassInfo=0;
316}
317
318
319void SetClassTreeFromOneFile_Buf( char *pBuf, int iFileNum ){
320    int i2,i3,i4;
321    char temporary[GENERAL_SIZE];
322
323    for(i2=0;;i2++){
324        if(pBuf[i2]=='\0') break;
325        while(pBuf[i2]=='\r'&&pBuf[i2+1]=='\n'&&pBuf[i2+2]=='\r'&&pBuf[i2+3]=='\n') i2+=2;
326        if(i2==0||(pBuf[i2]=='\r'&&pBuf[i2+1]=='\n')){
327            if(pBuf[i2]=='\r'&&pBuf[i2+1]=='\n') i2+=2;
328            while(pBuf[i2]>='0'&&pBuf[i2]<='9') i2++;
329            while(pBuf[i2]==' '||pBuf[i2]=='\t') i2++;
330
331            i4=i2;
332            for(i3=0;;i2++,i3++){
333                if(!IsVariableChar(pBuf[i2])){
334                    temporary[i3]=0;
335                    break;
336                }
337                temporary[i3]=pBuf[i2];
338            }
339            if(pBuf[i2]=='\0') break;
340
341            if(lstrcmpi(temporary,"Class")==0||
342                lstrcmpi(temporary,"Type")==0||
343                lstrcmpi(temporary,"Interface")==0){
344
345                /////////////////////////////
346                // クラスの解析
347                /////////////////////////////
348                AnalysisClass(pBuf,&i4,iFileNum);
349
350                i2=i4-1;
351                continue;
352            }
353
354            int sw;
355            if(lstrcmpi(temporary,"Sub")==0) sw=1;
356            else if(lstrcmpi(temporary,"Function")==0) sw=2;
357            else sw=0;
358
359            if(sw){
360                //Sub/Function
361                while(pBuf[i2]==' '||pBuf[i2]=='\t') i2++;
362                for(i3=0;;i2++,i3++){
363                    if(!IsVariableChar(pBuf[i2])){
364                        temporary[i3]=0;
365                        break;
366                    }
367                    temporary[i3]=pBuf[i2];
368                }
369
370                if(lstrcmpi(temporary,"Export")==0){
371                    //Export修飾子はとばす
372                    while(pBuf[i2]==' '||pBuf[i2]=='\t') i2++;
373
374                    for(i3=0;;i2++,i3++){
375                        if(!IsVariableChar(pBuf[i2])){
376                            temporary[i3]=0;
377                            break;
378                        }
379                        temporary[i3]=pBuf[i2];
380                    }
381                }
382
383                i4=pobj_ClassTreeView->NumberOfProcedures;
384                pobj_ClassTreeView->pProcInfo=(PROCINFO *)HeapReAlloc(hHeap,0,pobj_ClassTreeView->pProcInfo,sizeof(PROCINFO)*(i4+1));
385                pobj_ClassTreeView->pProcInfo[i4].name=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1);
386                lstrcpy(pobj_ClassTreeView->pProcInfo[i4].name,temporary);
387                pobj_ClassTreeView->pProcInfo[i4].FileNum=iFileNum;
388
389                //定義行の選択範囲
390                pobj_ClassTreeView->pProcInfo[i4].code_pos=i2;
391
392                //パラメータ部
393                while(pBuf[i2]==' '||pBuf[i2]=='\t') i2++;
394                if(pBuf[i2]=='('){
395                    int IsStr,PareNum;
396                    for(i2++,i3=0,IsStr=0,PareNum=0;;i2++,i3++){
397                        if(pBuf[i2]=='\"') IsStr^=1;
398                        if(pBuf[i2]=='('&&IsStr==0) PareNum++;
399                        if(pBuf[i2]==')'&&IsStr==0){
400                            PareNum--;
401                            if(PareNum<0){
402                                temporary[i3]=0;
403                                break;
404                            }
405                        }
406                        if(pBuf[i2]=='\0') break;
407                        temporary[i3]=pBuf[i2];
408                    }
409                    //temporaryはパラメータの内容が格納されるが、不要
410                }
411
412                for(;;i2++){
413                    if(IsCommandDelimitation(pBuf,i2)){
414                        break;
415                    }
416                    if((pBuf[i2]=='a'||pBuf[i2]=='A')&&(pBuf[i2+1]=='s'||pBuf[i2+1]=='S')&&(pBuf[i2+2]==' '||pBuf[i2+2]=='\t')){
417                        i2+=3;
418                        while(pBuf[i2]==' '||pBuf[i2]=='\t') i2++;
419                        for(i3=0;;i2++,i3++){
420                            if(!IsVariableChar(pBuf[i2])){
421                                temporary[i3]=0;
422                                break;
423                            }
424                            temporary[i3]=pBuf[i2];
425                        }
426                        //temporaryには型情報が格納されるが、不要
427                        break;
428                    }
429                }
430
431                //ツリーアイテムを挿入
432                HTREEITEM hTempItem;
433                hTempItem=pobj_ClassTreeView->InsertGlobalProcedure(
434                    CTV_GLOBAL_PROC,
435                    pobj_ClassTreeView->pProcInfo[i4].name,
436                    iFileNum);
437                pobj_ClassTreeView->pProcInfo[i4].hTreeItem=hTempItem;
438
439                pobj_ClassTreeView->NumberOfProcedures++;
440
441                i2--;
442            }
443        }
444    }
445}
446void SetClassTreeFromOneFile(char *lpszFilePath,int iFileNum){
447    extern MDIINFO MdiInfo[MAX_WNDNUM];
448    int WndNum;
449    HWND hChild=GetWindow(hClient,GW_CHILD);
450    while(hChild){
451        WndNum=GetWndNum(hChild);
452        if(IS_DOCUMENT_TEXT(MdiInfo[WndNum].DocType)){
453            if(lstrcmpi(MdiInfo[WndNum].path,lpszFilePath)==0) break;
454        }
455        hChild=GetNextWindow(hChild,GW_HWNDNEXT);
456    }
457
458    char *pBuf;
459    if(hChild){
460        //すでに指定されたファイルが開かれている場合
461        pBuf=MdiInfo[WndNum].pMdiTextEdit->buffer;
462    }
463    else{
464        //開かれていない場合
465        pBuf=ReadBuffer(lpszFilePath);
466        if(!pBuf) pBuf=(char *)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,1);
467    }
468
469    SetClassTreeFromOneFile_Buf( pBuf, iFileNum );
470
471    if(!hChild) HeapDefaultFree(pBuf);
472}
473
474void SetProcedureTreeData(void *temp_iFileNum){
475    int i;
476    char temporary[MAX_PATH];
477    BOOL bExpand;
478    TVITEM tvItem;
479    SCROLLINFO si;
480
481    int iFileNum;
482    iFileNum=(int)temp_iFileNum;
483
484    if(bSearchingClasses){
485        bRetrySearchingClasses=1;
486        _endthread();
487        return;
488    }
489    bSearchingClasses=1;
490
491    if(pobj_ClassTreeView->pProcInfo){
492wait_repeat:
493        Sleep(700);
494        if(bRetrySearchingClasses){
495            bRetrySearchingClasses=0;
496            goto wait_repeat;
497        }
498
499        PROCINFO *pNewProcInfo;
500        pNewProcInfo=(PROCINFO *)HeapAlloc(hHeap,0,pobj_ClassTreeView->NumberOfProcedures*sizeof(PROCINFO));
501        int NewProcNum;
502        NewProcNum=0;
503
504        //プロシージャ情報のメモリを解放
505        for(i=0;i<pobj_ClassTreeView->NumberOfProcedures;i++){
506            if(iFileNum==-1 || iFileNum==pobj_ClassTreeView->pProcInfo[i].FileNum){
507                HeapDefaultFree(pobj_ClassTreeView->pProcInfo[i].name);
508            }
509            else{
510                pNewProcInfo[NewProcNum]=pobj_ClassTreeView->pProcInfo[i];
511                NewProcNum++;
512            }
513        }
514        HeapDefaultFree(pobj_ClassTreeView->pProcInfo);
515
516        pobj_ClassTreeView->pProcInfo=pNewProcInfo;
517        pobj_ClassTreeView->NumberOfProcedures=NewProcNum;
518    }
519    else{
520        pobj_ClassTreeView->pProcInfo=(PROCINFO *)HeapAlloc(hHeap,0,1);
521        pobj_ClassTreeView->NumberOfProcedures=0;
522    }
523
524    extern HWND hProcedureTreeView;
525    tvItem.hItem=TreeView_GetRoot(hProcedureTreeView);
526    if(tvItem.hItem){
527        TreeView_GetItem(hProcedureTreeView,&tvItem);
528        if(tvItem.state&TVIS_EXPANDED){
529            bExpand=1;
530
531            si.cbSize=sizeof(SCROLLINFO);
532            si.fMask=SIF_POS;
533            GetScrollInfo(hProcedureTreeView,SB_VERT,&si);
534        }
535        else bExpand=0;
536    }
537    else bExpand=1;
538
539
540    pobj_ClassTreeView->init(hProcedureTreeView,iFileNum);
541
542    //ルートフォルダ
543    pobj_ClassTreeView->InsertRootFolder();
544
545    //グローバル関数フォルダ
546    pobj_ClassTreeView->InsertGlobalProcedureFolder();
547
548
549    //描画をロック
550    LockWindowUpdate(hProcedureTreeView);
551
552    extern PROJECTINFO ProjectInfo;
553    if(ProjectInfo.name[0]){
554        // プロジェクトが開かれているとき
555        if(iFileNum==-1){
556            //プロジェクトのすべてのファイルを解析
557            for(i=0;i<ProjectInfo.pobj_DBFileInfo->iNum;i++){
558                ProjectInfo.pobj_DBFileInfo->ppobj_FileInfo[i]->GetFullPath(temporary);
559
560                SetClassTreeFromOneFile(temporary,i);
561            }
562
563            //不要になったアイテムを除去
564            //pobj_ClassTreeView->finish();
565        }
566        else{
567            /////////////////////////////////
568            // 編集中のファイルのみを解析
569            /////////////////////////////////
570
571            ProjectInfo.pobj_DBFileInfo->ppobj_FileInfo[iFileNum]->GetFullPath(temporary);
572
573            SetClassTreeFromOneFile(temporary,iFileNum);
574        }
575    }
576    else{
577        // 編集中の単体ファイルを解析
578
579        HWND hChild=GetWindow(hClient,GW_CHILD);
580        int WndNum=GetWndNum(hChild);
581        char *pBuf=MdiInfo[WndNum].pMdiTextEdit->buffer;
582        SetClassTreeFromOneFile_Buf( pBuf, -1 );
583
584    }
585
586    //不要になったアイテムを除去
587    pobj_ClassTreeView->finish();
588
589    //描画ロックを解除
590    LockWindowUpdate(0);
591
592
593    if(bExpand){
594        TreeView_Expand(hProcedureTreeView,pobj_ClassTreeView->hRootFolder,TVE_EXPAND);
595
596        SetScrollInfo(hProcedureTreeView,SB_VERT,&si,1);
597    }
598
599
600    bSearchingClasses=0;
601    if(bRetrySearchingClasses){
602        bRetrySearchingClasses=0;
603        ResetClassTree(iFileNum);
604    }
605
606    if(pobj_ClassTreeView->bCloseSwitch){
607        //コード解析中に終了ボタンが押されたとき
608        PostMessage(hOwner,WM_CLOSE,0,0);
609    }
610    if(pobj_ClassTreeView->bShowSwitch){
611        //コード解析中にクラスビューがダブルクリックされたとき
612        extern HWND hProjectViewTab;
613        PostMessage(hProjectViewTab,WM_COMMAND,IDM_PROCEDURETREE_SHOW,0);
614        pobj_ClassTreeView->bShowSwitch=0;
615    }
616
617    _endthread();
618}
619void ResetClassTree(int iFileNum){
620    _beginthread(SetProcedureTreeData,0,(void *)iFileNum);
621}
Note: See TracBrowser for help on using the repository browser.