source: dev/ProjectEditor/ClassTree.cpp@ 87

Last change on this file since 87 was 81, checked in by dai_9181, 18 years ago

プロジェクトを開いていないときでもクラスビューの機能を有効にした。

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