source: dev/ProjectEditor/ClassTree.cpp@ 56

Last change on this file since 56 was 24, checked in by dai_9181, 18 years ago

保存されていないドキュメントのタブに(*)をつける機能に対応。
MDITEXTEDITINFOをCMdiTextEditに変更。今後、オブジェクト指向化を進める。

File size: 13.9 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
317
318void SetClassTreeFromOneFile(char *lpszFilePath,int iFileNum){
319 extern PROJECTINFO ProjectInfo;
320 extern MDIINFO MdiInfo[MAX_WNDNUM];
321 int i2,i3,i4,WndNum;
322 char *pBuf;
323 HWND hChild;
324 char temporary[GENERAL_SIZE];
325
326 hChild=GetWindow(hClient,GW_CHILD);
327 while(hChild){
328 WndNum=GetWndNum(hChild);
329 if(IS_DOCUMENT_TEXT(MdiInfo[WndNum].DocType)){
330 if(lstrcmpi(MdiInfo[WndNum].path,lpszFilePath)==0) break;
331 }
332 hChild=GetNextWindow(hChild,GW_HWNDNEXT);
333 }
334
335 if(hChild){
336 //すでに指定されたファイルが開かれている場合
337 pBuf=MdiInfo[WndNum].pMdiTextEdit->buffer;
338 }
339 else{
340 //開かれていない場合
341 pBuf=ReadBuffer(lpszFilePath);
342 if(!pBuf) pBuf=(char *)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,1);
343 }
344 for(i2=0;;i2++){
345 if(pBuf[i2]=='\0') break;
346 while(pBuf[i2]=='\r'&&pBuf[i2+1]=='\n'&&pBuf[i2+2]=='\r'&&pBuf[i2+3]=='\n') i2+=2;
347 if(i2==0||(pBuf[i2]=='\r'&&pBuf[i2+1]=='\n')){
348 if(pBuf[i2]=='\r'&&pBuf[i2+1]=='\n') i2+=2;
349 while(pBuf[i2]>='0'&&pBuf[i2]<='9') i2++;
350 while(pBuf[i2]==' '||pBuf[i2]=='\t') i2++;
351
352 i4=i2;
353 for(i3=0;;i2++,i3++){
354 if(!IsVariableChar(pBuf[i2])){
355 temporary[i3]=0;
356 break;
357 }
358 temporary[i3]=pBuf[i2];
359 }
360 if(pBuf[i2]=='\0') break;
361
362 if(lstrcmpi(temporary,"Class")==0||
363 lstrcmpi(temporary,"Type")==0||
364 lstrcmpi(temporary,"Interface")==0){
365
366 /////////////////////////////
367 // クラスの解析
368 /////////////////////////////
369 AnalysisClass(pBuf,&i4,iFileNum);
370
371 i2=i4-1;
372 continue;
373 }
374
375 int sw;
376 if(lstrcmpi(temporary,"Sub")==0) sw=1;
377 else if(lstrcmpi(temporary,"Function")==0) sw=2;
378 else sw=0;
379
380 if(sw){
381 //Sub/Function
382 while(pBuf[i2]==' '||pBuf[i2]=='\t') i2++;
383 for(i3=0;;i2++,i3++){
384 if(!IsVariableChar(pBuf[i2])){
385 temporary[i3]=0;
386 break;
387 }
388 temporary[i3]=pBuf[i2];
389 }
390
391 if(lstrcmpi(temporary,"Export")==0){
392 //Export修飾子はとばす
393 while(pBuf[i2]==' '||pBuf[i2]=='\t') i2++;
394
395 for(i3=0;;i2++,i3++){
396 if(!IsVariableChar(pBuf[i2])){
397 temporary[i3]=0;
398 break;
399 }
400 temporary[i3]=pBuf[i2];
401 }
402 }
403
404 i4=pobj_ClassTreeView->NumberOfProcedures;
405 pobj_ClassTreeView->pProcInfo=(PROCINFO *)HeapReAlloc(hHeap,0,pobj_ClassTreeView->pProcInfo,sizeof(PROCINFO)*(i4+1));
406 pobj_ClassTreeView->pProcInfo[i4].name=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1);
407 lstrcpy(pobj_ClassTreeView->pProcInfo[i4].name,temporary);
408 pobj_ClassTreeView->pProcInfo[i4].FileNum=iFileNum;
409
410 //定義行の選択範囲
411 pobj_ClassTreeView->pProcInfo[i4].code_pos=i2;
412
413 //パラメータ部
414 while(pBuf[i2]==' '||pBuf[i2]=='\t') i2++;
415 if(pBuf[i2]=='('){
416 int IsStr,PareNum;
417 for(i2++,i3=0,IsStr=0,PareNum=0;;i2++,i3++){
418 if(pBuf[i2]=='\"') IsStr^=1;
419 if(pBuf[i2]=='('&&IsStr==0) PareNum++;
420 if(pBuf[i2]==')'&&IsStr==0){
421 PareNum--;
422 if(PareNum<0){
423 temporary[i3]=0;
424 break;
425 }
426 }
427 if(pBuf[i2]=='\0') break;
428 temporary[i3]=pBuf[i2];
429 }
430 //temporaryはパラメータの内容が格納されるが、不要
431 }
432
433 for(;;i2++){
434 if(IsCommandDelimitation(pBuf,i2)){
435 break;
436 }
437 if((pBuf[i2]=='a'||pBuf[i2]=='A')&&(pBuf[i2+1]=='s'||pBuf[i2+1]=='S')&&(pBuf[i2+2]==' '||pBuf[i2+2]=='\t')){
438 i2+=3;
439 while(pBuf[i2]==' '||pBuf[i2]=='\t') i2++;
440 for(i3=0;;i2++,i3++){
441 if(!IsVariableChar(pBuf[i2])){
442 temporary[i3]=0;
443 break;
444 }
445 temporary[i3]=pBuf[i2];
446 }
447 //temporaryには型情報が格納されるが、不要
448 break;
449 }
450 }
451
452 //ツリーアイテムを挿入
453 HTREEITEM hTempItem;
454 hTempItem=pobj_ClassTreeView->InsertGlobalProcedure(
455 CTV_GLOBAL_PROC,
456 pobj_ClassTreeView->pProcInfo[i4].name,
457 iFileNum);
458 pobj_ClassTreeView->pProcInfo[i4].hTreeItem=hTempItem;
459
460 pobj_ClassTreeView->NumberOfProcedures++;
461
462 i2--;
463 }
464 }
465 }
466
467 if(!hChild) HeapDefaultFree(pBuf);
468}
469
470void SetProcedureTreeData(void *temp_iFileNum){
471 extern PROJECTINFO ProjectInfo;
472 int i;
473 char temporary[MAX_PATH];
474 BOOL bExpand;
475 TVITEM tvItem;
476 SCROLLINFO si;
477
478 int iFileNum;
479 iFileNum=(int)temp_iFileNum;
480
481 if(bSearchingClasses){
482 bRetrySearchingClasses=1;
483 _endthread();
484 return;
485 }
486 bSearchingClasses=1;
487
488 if(pobj_ClassTreeView->pProcInfo){
489wait_repeat:
490 Sleep(700);
491 if(bRetrySearchingClasses){
492 bRetrySearchingClasses=0;
493 goto wait_repeat;
494 }
495
496 PROCINFO *pNewProcInfo;
497 pNewProcInfo=(PROCINFO *)HeapAlloc(hHeap,0,pobj_ClassTreeView->NumberOfProcedures*sizeof(PROCINFO));
498 int NewProcNum;
499 NewProcNum=0;
500
501 //プロシージャ情報のメモリを解放
502 for(i=0;i<pobj_ClassTreeView->NumberOfProcedures;i++){
503 if(iFileNum==-1 || iFileNum==pobj_ClassTreeView->pProcInfo[i].FileNum){
504 HeapDefaultFree(pobj_ClassTreeView->pProcInfo[i].name);
505 }
506 else{
507 pNewProcInfo[NewProcNum]=pobj_ClassTreeView->pProcInfo[i];
508 NewProcNum++;
509 }
510 }
511 HeapDefaultFree(pobj_ClassTreeView->pProcInfo);
512
513 pobj_ClassTreeView->pProcInfo=pNewProcInfo;
514 pobj_ClassTreeView->NumberOfProcedures=NewProcNum;
515 }
516 else{
517 pobj_ClassTreeView->pProcInfo=(PROCINFO *)HeapAlloc(hHeap,0,1);
518 pobj_ClassTreeView->NumberOfProcedures=0;
519 }
520
521 extern HWND hProcedureTreeView;
522 tvItem.hItem=TreeView_GetRoot(hProcedureTreeView);
523 if(tvItem.hItem){
524 TreeView_GetItem(hProcedureTreeView,&tvItem);
525 if(tvItem.state&TVIS_EXPANDED){
526 bExpand=1;
527
528 si.cbSize=sizeof(SCROLLINFO);
529 si.fMask=SIF_POS;
530 GetScrollInfo(hProcedureTreeView,SB_VERT,&si);
531 }
532 else bExpand=0;
533 }
534 else bExpand=1;
535
536
537 pobj_ClassTreeView->init(hProcedureTreeView,iFileNum);
538
539 //ルートフォルダ
540 pobj_ClassTreeView->InsertRootFolder();
541
542 //グローバル関数フォルダ
543 pobj_ClassTreeView->InsertGlobalProcedureFolder();
544
545
546 //描画をロック
547 LockWindowUpdate(hProcedureTreeView);
548
549 if(iFileNum==-1){
550 //プロジェクトのすべてのファイルを解析
551 for(i=0;i<ProjectInfo.pobj_DBFileInfo->iNum;i++){
552 ProjectInfo.pobj_DBFileInfo->ppobj_FileInfo[i]->GetFullPath(temporary);
553
554 SetClassTreeFromOneFile(temporary,i);
555 }
556
557 //不要になったアイテムを除去
558 pobj_ClassTreeView->finish();
559 }
560 else{
561 /////////////////////////////////
562 // 編集中のファイルのみを解析
563 /////////////////////////////////
564
565 ProjectInfo.pobj_DBFileInfo->ppobj_FileInfo[iFileNum]->GetFullPath(temporary);
566
567 SetClassTreeFromOneFile(temporary,iFileNum);
568 }
569
570 //不要になったアイテムを除去
571 pobj_ClassTreeView->finish();
572
573 //描画ロックを解除
574 LockWindowUpdate(0);
575
576
577 if(bExpand){
578 TreeView_Expand(hProcedureTreeView,pobj_ClassTreeView->hRootFolder,TVE_EXPAND);
579
580 SetScrollInfo(hProcedureTreeView,SB_VERT,&si,1);
581 }
582
583
584 bSearchingClasses=0;
585 if(bRetrySearchingClasses){
586 bRetrySearchingClasses=0;
587 ResetClassTree(iFileNum);
588 }
589
590 if(pobj_ClassTreeView->bCloseSwitch){
591 //コード解析中に終了ボタンが押されたとき
592 PostMessage(hOwner,WM_CLOSE,0,0);
593 }
594 if(pobj_ClassTreeView->bShowSwitch){
595 //コード解析中にクラスビューがダブルクリックされたとき
596 extern HWND hProjectViewTab;
597 PostMessage(hProjectViewTab,WM_COMMAND,IDM_PROCEDURETREE_SHOW,0);
598 pobj_ClassTreeView->bShowSwitch=0;
599 }
600
601 _endthread();
602}
603void ResetClassTree(int iFileNum){
604 _beginthread(SetProcedureTreeData,0,(void *)iFileNum);
605}
Note: See TracBrowser for help on using the repository browser.