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

Last change on this file since 618 was 618, checked in by dai_9181, 16 years ago

・PROJECTINFO構造体を廃止し、Projectクラスを採用した。
・ProjectInfoをprojectInfoにリネーム

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 char temporary[VN_SIZE];
201 sprintf(temporary,"%s クラス",projectInfo.name);
202 hRootFolder=insert(
203 TVI_ROOT,
204 CTV_ROOT,
205 temporary,-1);
206}
207void CClassTreeView::InsertGlobalProcedureFolder(void){
208 hGlobalProcedureFolder=insert(
209 hRootFolder,
210 CTV_FOLDER,
211 "グローバル関数",-1);
212}
213
214HTREEITEM CClassTreeView::InsertGlobalProcedure(int flag,char *lpszName,int iFileNum){
215 return pobj_ClassTreeView->insert(
216 hGlobalProcedureFolder,
217 CTV_GLOBAL_PROC,
218 lpszName,
219 iFileNum);
220}
221
222HTREEITEM CClassTreeView::insert_code_item(HTREEITEM hParentItem,int flag,char *lpszName,int iFileNum,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].FileNum=iFileNum;
229
230 //コード位置
231 pProcInfo[i4].code_pos=p;
232
233 //ツリーアイテムを挿入
234 HTREEITEM hTempItem;
235 hTempItem=insert(
236 hParentItem,
237 flag,
238 lpszName,
239 iFileNum);
240
241 pProcInfo[i4].hTreeItem=hTempItem;
242
243 NumberOfProcedures++;
244
245 return hTempItem;
246}
247
248void CClassTreeView::InsertClassFolder(char *lpszName,int iFileNum,char *pBuf,int p){
249 hNowClassFolder=insert_code_item(hRootFolder,CTV_CLASS,lpszName,iFileNum,pBuf,p);
250}
251void CClassTreeView::InsertClassMember(int flag,char *lpszName,int iFileNum,char *pBuf,int p){
252 insert_code_item(hNowClassFolder,flag,lpszName,iFileNum,pBuf,p);
253}
254
255void CClassTreeView::finish(){
256 DeleteInvalidItems(TreeView_GetRoot(hTreeWnd));
257}
258
259
260void AnalysisClass(char *pBuf,int *p,int iFileNum){
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 iFileNum,
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,iFileNum,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, int iFileNum ){
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,iFileNum);
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].FileNum=iFileNum;
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 iFileNum);
436 pobj_ClassTreeView->pProcInfo[i4].hTreeItem=hTempItem;
437
438 pobj_ClassTreeView->NumberOfProcedures++;
439
440 i2--;
441 }
442 }
443 }
444}
445void SetClassTreeFromOneFile(char *lpszFilePath,int iFileNum){
446 extern MDIINFO MdiInfo[MAX_WNDNUM];
447 int WndNum;
448 HWND hChild=GetWindow(hClient,GW_CHILD);
449 while(hChild){
450 WndNum=GetWndNum(hChild);
451 if(IS_DOCUMENT_TEXT(MdiInfo[WndNum].DocType)){
452 if(lstrcmpi(MdiInfo[WndNum].path,lpszFilePath)==0) break;
453 }
454 hChild=GetNextWindow(hChild,GW_HWNDNEXT);
455 }
456
457 char *pBuf;
458 if(hChild){
459 //すでに指定されたファイルが開かれている場合
460 pBuf=MdiInfo[WndNum].pMdiTextEdit->buffer;
461 }
462 else{
463 //開かれていない場合
464 pBuf=ReadBuffer(lpszFilePath);
465 if(!pBuf) pBuf=(char *)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,1);
466 }
467
468 SetClassTreeFromOneFile_Buf( pBuf, iFileNum );
469
470 if(!hChild) HeapDefaultFree(pBuf);
471}
472
473void SetProcedureTreeData(void *temp_iFileNum){
474 int i;
475 char temporary[MAX_PATH];
476 BOOL bExpand;
477 TVITEM tvItem;
478 SCROLLINFO si;
479
480 int iFileNum;
481 iFileNum=(int)temp_iFileNum;
482
483 if(bSearchingClasses){
484 bRetrySearchingClasses=1;
485 _endthread();
486 return;
487 }
488 bSearchingClasses=1;
489
490 if(pobj_ClassTreeView->pProcInfo){
491wait_repeat:
492 Sleep(700);
493 if(bRetrySearchingClasses){
494 bRetrySearchingClasses=0;
495 goto wait_repeat;
496 }
497
498 PROCINFO *pNewProcInfo;
499 pNewProcInfo=(PROCINFO *)HeapAlloc(hHeap,0,pobj_ClassTreeView->NumberOfProcedures*sizeof(PROCINFO));
500 int NewProcNum;
501 NewProcNum=0;
502
503 //プロシージャ情報のメモリを解放
504 for(i=0;i<pobj_ClassTreeView->NumberOfProcedures;i++){
505 if(iFileNum==-1 || iFileNum==pobj_ClassTreeView->pProcInfo[i].FileNum){
506 HeapDefaultFree(pobj_ClassTreeView->pProcInfo[i].name);
507 }
508 else{
509 pNewProcInfo[NewProcNum]=pobj_ClassTreeView->pProcInfo[i];
510 NewProcNum++;
511 }
512 }
513 HeapDefaultFree(pobj_ClassTreeView->pProcInfo);
514
515 pobj_ClassTreeView->pProcInfo=pNewProcInfo;
516 pobj_ClassTreeView->NumberOfProcedures=NewProcNum;
517 }
518 else{
519 pobj_ClassTreeView->pProcInfo=(PROCINFO *)HeapAlloc(hHeap,0,1);
520 pobj_ClassTreeView->NumberOfProcedures=0;
521 }
522
523 extern HWND hProcedureTreeView;
524 tvItem.hItem=TreeView_GetRoot(hProcedureTreeView);
525 if(tvItem.hItem){
526 TreeView_GetItem(hProcedureTreeView,&tvItem);
527 if(tvItem.state&TVIS_EXPANDED){
528 bExpand=1;
529
530 si.cbSize=sizeof(SCROLLINFO);
531 si.fMask=SIF_POS;
532 GetScrollInfo(hProcedureTreeView,SB_VERT,&si);
533 }
534 else bExpand=0;
535 }
536 else bExpand=1;
537
538
539 pobj_ClassTreeView->init(hProcedureTreeView,iFileNum);
540
541 //ルートフォルダ
542 pobj_ClassTreeView->InsertRootFolder();
543
544 //グローバル関数フォルダ
545 pobj_ClassTreeView->InsertGlobalProcedureFolder();
546
547
548 //描画をロック
549 LockWindowUpdate(hProcedureTreeView);
550
551 if(projectInfo.name[0]){
552 // プロジェクトが開かれているとき
553 if(iFileNum==-1){
554 //プロジェクトのすべてのファイルを解析
555 for(i=0;i<projectInfo.pobj_DBFileInfo->iNum;i++){
556 projectInfo.pobj_DBFileInfo->ppobj_FileInfo[i]->GetFullPath(temporary);
557
558 SetClassTreeFromOneFile(temporary,i);
559 }
560
561 //不要になったアイテムを除去
562 //pobj_ClassTreeView->finish();
563 }
564 else{
565 /////////////////////////////////
566 // 編集中のファイルのみを解析
567 /////////////////////////////////
568
569 projectInfo.pobj_DBFileInfo->ppobj_FileInfo[iFileNum]->GetFullPath(temporary);
570
571 SetClassTreeFromOneFile(temporary,iFileNum);
572 }
573 }
574 else{
575 // 編集中の単体ファイルを解析
576
577 HWND hChild=GetWindow(hClient,GW_CHILD);
578 int WndNum=GetWndNum(hChild);
579 char *pBuf=MdiInfo[WndNum].pMdiTextEdit->buffer;
580 SetClassTreeFromOneFile_Buf( pBuf, -1 );
581
582 }
583
584 //不要になったアイテムを除去
585 pobj_ClassTreeView->finish();
586
587 //描画ロックを解除
588 LockWindowUpdate(0);
589
590
591 if(bExpand){
592 TreeView_Expand(hProcedureTreeView,pobj_ClassTreeView->hRootFolder,TVE_EXPAND);
593
594 SetScrollInfo(hProcedureTreeView,SB_VERT,&si,1);
595 }
596
597
598 bSearchingClasses=0;
599 if(bRetrySearchingClasses){
600 bRetrySearchingClasses=0;
601 ResetClassTree(iFileNum);
602 }
603
604 if(pobj_ClassTreeView->bCloseSwitch){
605 //コード解析中に終了ボタンが押されたとき
606 PostMessage(hOwner,WM_CLOSE,0,0);
607 }
608 if(pobj_ClassTreeView->bShowSwitch){
609 //コード解析中にクラスビューがダブルクリックされたとき
610 extern HWND hProjectViewTab;
611 PostMessage(hProjectViewTab,WM_COMMAND,IDM_PROCEDURETREE_SHOW,0);
612 pobj_ClassTreeView->bShowSwitch=0;
613 }
614
615 _endthread();
616}
617void ResetClassTree(int iFileNum){
618 _beginthread(SetProcedureTreeData,0,(void *)iFileNum);
619}
Note: See TracBrowser for help on using the repository browser.