source: dev/trunk/ab5.0/abdev/abdev/DrawBuffer.cpp @ 681

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

・TinyXMLをabdevプロジェクトで使えるようにした。
・コードハイライターを汎用的に実装しなおした。syntaxファイルを読み込む仕様とした。

File size: 14.6 KB
Line 
1#include "stdafx.h"
2
3#include "Common.h"
4
5extern HFONT hFont_TextEdit;
6extern int font_width,font_height;
7
8class CDrawReserve{
9    int x,y;
10    COLORREF NowColor,NowBackColor;
11    int bNowUnder;
12    char *lpszBuffer;
13    int length;
14    int m_WndNum;
15    HDC hdc;
16    HBITMAP hMemBmp,hOldBitmap;
17    HFONT hOldFont;
18    SIZE ClientSize;
19    int iControlTabSpace;
20    int iOnePage_CharHeight;
21    int iLineNumberTextCount;
22    int iMax_OneLine_TextLength;
23public:
24    HDC memdc;
25    CDrawReserve(int WndNum,HDC _hDC,int cx,int cy,int ctrl_tab_space,int nMaxOnePageChar,int linenum_textcount){
26        m_WndNum=WndNum;
27        x=-1;
28        y=-1;
29        bNowUnder=0;
30        hdc=_hDC;
31        ClientSize.cx=cx;
32        ClientSize.cy=cy;
33        iControlTabSpace=ctrl_tab_space;
34        iOnePage_CharHeight=nMaxOnePageChar;
35        iMax_OneLine_TextLength=cx/font_width+1;
36        iLineNumberTextCount=linenum_textcount;
37        memdc=CreateCompatibleDC(hdc);
38        hMemBmp=CreateCompatibleBitmap(hdc,cx,cy);
39        hOldBitmap=(HBITMAP)SelectObject(memdc,hMemBmp);
40
41        //背景色でメモリ画面を初期化
42        HBRUSH hBrush,hOldBrush;
43        hBrush=CreateSolidBrush(tci.rgbBackground);
44        hOldBrush=(HBRUSH)SelectObject(memdc,hBrush);
45        PatBlt(memdc,0,0,cx,cy,PATCOPY);
46        DeleteObject(hBrush);
47
48        //背景ビットマップ
49#ifdef THETEXT
50        if(pobj_DBTheme->hBackBmp){
51            HDC memdc2;
52            memdc2=CreateCompatibleDC(memdc);
53            SelectObject(memdc2,pobj_DBTheme->hBackBmp);
54            BitBlt(memdc,
55                cx-(pobj_DBTheme->sizeBackBmp.cx),
56                cy-(pobj_DBTheme->sizeBackBmp.cy),
57                pobj_DBTheme->sizeBackBmp.cx,pobj_DBTheme->sizeBackBmp.cy,
58                memdc2,0,0,SRCCOPY);
59            DeleteDC(memdc2);
60        }
61#endif
62
63        //フォントを設定
64        extern HFONT hFont_TextEdit;
65        hOldFont=(HFONT)SelectObject(memdc,hFont_TextEdit);
66
67        lpszBuffer=(char *)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,1);
68        length=0;
69    }
70    ~CDrawReserve(){
71        SelectObject(memdc,hOldBitmap);
72        DeleteObject(hMemBmp);
73
74        SelectObject(memdc,hOldFont);
75
76        DeleteDC(memdc);
77
78        HeapDefaultFree(lpszBuffer);
79    }
80
81    void draw(){
82        if(length==0) return;
83        SetTextColor(memdc,NowColor);
84        if(NowBackColor==tci.rgbBackground){
85            SetBkMode(memdc,TRANSPARENT);
86        }
87        else{
88            SetBkMode(memdc,OPAQUE);
89            SetBkColor(memdc,NowBackColor);
90        }
91
92        HFONT hBeforeFont;
93        if(bNowUnder){
94            //下線付きフォントに設定
95            extern HFONT hFont_HyperLink_TextEdit;
96            hBeforeFont=(HFONT)SelectObject(memdc,hFont_HyperLink_TextEdit);
97        }
98
99        int offset=0;
100        if(x<0){
101            offset=-x;
102
103            //左端の全角文字の文字化けを避けるために10バイトの余裕を作る
104            offset-=10;
105            if(offset<0) offset=0;
106
107            length-=offset;
108            if(length<0) return;
109        }
110
111        if(length>iMax_OneLine_TextLength+10){
112            length=iMax_OneLine_TextLength+10;
113        }
114
115        int i;
116        int *lpDxWidths;
117        lpDxWidths=(int *)malloc((length+1)*sizeof(int));
118        for(i=0;i<length+1;i++){
119            lpDxWidths[i]=font_width;
120        }
121        ExtTextOut(memdc,
122            (x+offset)*(font_width)     +iControlTabSpace,
123            y*font_height,
124            0,NULL,
125            lpszBuffer+offset,length,
126            lpDxWidths);
127
128        if(bNowUnder){
129            SelectObject(memdc,hBeforeFont);
130        }
131
132        free(lpDxWidths);
133    }
134
135    void DrawReserve(int nXStart,int nYStart,COLORREF NextColor,COLORREF NextBackColor,BOOL bUnder,LPSTR lpString,int cbString){
136        if(nYStart!=y || NextColor!=NowColor || NextBackColor!=NowBackColor || bUnder!=bNowUnder){
137            //描画
138            draw();
139
140            x=nXStart;
141            y=nYStart;
142            NowColor=NextColor;
143            NowBackColor=NextBackColor;
144            bNowUnder=bUnder;
145
146            lpszBuffer[0]=0;
147            length=0;
148        }
149
150        //予約
151        lpszBuffer=(char *)HeapReAlloc(hHeap,0,lpszBuffer,length+cbString+1);
152        memcpy(lpszBuffer+length,lpString,cbString);
153        length+=cbString;
154        lpszBuffer[length]=0;
155    }
156
157    void finish(int BaseY){
158        draw();
159
160        HBRUSH hBrush,hOldBrush;
161        if(pobj_nv->bEditor_LineNumber){
162            hBrush=CreateSolidBrush(RGB(220,220,220));
163            hOldBrush=(HBRUSH)SelectObject(memdc,hBrush);
164
165
166            /////////////////////////////////////////////////////
167            // エディタ画面左端のコントロールタブの行番号を描画
168            /////////////////////////////////////////////////////
169
170            //灰色で塗りつぶす
171            PatBlt(memdc,
172                0,
173                0,
174                iControlTabSpace,
175                ClientSize.cy,
176                PATCOPY);
177
178            extern HFONT hFont_LineNumber;
179            int LineNumberFontHeight;
180
181            HFONT hOldFont;
182            hOldFont=(HFONT)SelectObject(memdc,hFont_LineNumber);
183            SetTextColor(memdc,RGB(60,60,60));
184            SetBkColor(memdc,RGB(220,220,220));
185
186            SIZE size;
187            GetTextExtentPoint32(memdc,"A",1,&size);
188            LineNumberFontHeight=size.cy;
189
190
191            //ブレークポイントの描画を準備
192            BreakPointsPerFile *pobj_FileBreakPoint=0;
193            if( projectInfo.IsOpened() ){
194                pobj_FileBreakPoint=
195                    projectInfo.pobj_DBBreakPoint->EnumLines(MdiInfo[m_WndNum]->path.c_str());
196            }
197            else{
198                extern CDBBreakPoint *pobj_DBBreakPoint;
199                pobj_FileBreakPoint=pobj_DBBreakPoint->EnumLines(MdiInfo[m_WndNum]->path.c_str());
200            }
201
202
203            int i,i2;
204            char temporary[255],temp2[255];
205            if(y<iOnePage_CharHeight) i2=y;
206            else i2=iOnePage_CharHeight;
207            for(i=0;i<=i2;i++){
208
209                BOOL bBreakPoint;
210                bBreakPoint=0;
211                if(pobj_FileBreakPoint){
212                    if(pobj_FileBreakPoint->check(i-BaseY)){
213                        bBreakPoint=1;
214                    }
215                }
216
217                if(bBreakPoint){
218                    DrawIconEx(memdc,3,i*font_height+(font_height-16)/2,
219                        (HICON)LoadImage(hIconResInst,MAKEINTRESOURCE(IDI_BREAKPOINT_FLAG),IMAGE_ICON,16,16,LR_SHARED),
220                        16,16,0,NULL,DI_NORMAL);
221                }
222                else{
223                    sprintf(temp2,"%%%dd:",iLineNumberTextCount);
224                    sprintf(temporary,temp2,(i-BaseY)+1);
225
226                    TextOut(memdc,
227                        3,
228                        i*font_height+(font_height-LineNumberFontHeight)/2,
229                        temporary,
230                        lstrlen(temporary));
231                }
232            }
233
234            SelectObject(memdc,hOldFont);
235
236
237            //ブラシを破棄
238            SelectObject(memdc,hOldBrush);
239            DeleteObject(hBrush);
240        }
241        else{
242            ////////////////////////////////////////////
243            // エディタ画面左端のコントロールタブを描画
244            // ※行番号は非表示
245            ////////////////////////////////////////////
246
247            hBrush=CreateSolidBrush(RGB(220,220,220));
248            hOldBrush=(HBRUSH)SelectObject(memdc,hBrush);
249
250            PatBlt(memdc,
251                0,
252                0,
253                iControlTabSpace,
254                ClientSize.cy,
255                PATCOPY);
256
257            SelectObject(memdc,hOldBrush);
258            DeleteObject(hBrush);
259        }
260
261
262        //メモリDCの内容を画面に描画
263        BitBlt(hdc,0,0,ClientSize.cx,ClientSize.cy,memdc,0,0,SRCCOPY);
264    }
265};
266
267void TextEdit_DrawBuffer(HDC hdc,int WndNum){
268    int i,i2;
269    int x,y;
270    int BaseX,BaseY,CharX;
271    char *pBuf,temporary[255];
272    HWND hEdit;
273
274
275    //背景モード、カラーの設定
276    COLORREF DefaultBackColor,CaretBackColor;
277    DefaultBackColor=tci.rgbBackground;
278
279    RECT ClientRect;
280    hEdit=GetWindow(MdiInfo[WndNum]->hwnd,GW_CHILD);
281    GetClientRect(hEdit,&ClientRect);
282
283    //エディタ画面左端のコントロールタブ
284    int iControlTabSpace;
285    int iLineNumberTextCount;
286    iControlTabSpace=MdiInfo[WndNum]->pMdiTextEdit->iWidth_ControlTabSpace;
287    iLineNumberTextCount=MdiInfo[WndNum]->pMdiTextEdit->iLineNumberTextCount;
288
289    //一ページ中に表示できる行数を取得
290    int OnePage_CharHeight;
291    OnePage_CharHeight=(ClientRect.bottom/font_height)+1;
292
293    //描画用クラス
294    CDrawReserve obj_dr(
295        WndNum,
296        hdc,
297        ClientRect.right-ClientRect.left,ClientRect.bottom-ClientRect.top,
298        iControlTabSpace,
299        OnePage_CharHeight,
300        iLineNumberTextCount);
301
302
303    //テキストバッファをコード内で参照しやすいようにポインタ変数を利用する
304    pBuf=MdiInfo[WndNum]->pMdiTextEdit->buffer;
305
306    //選択範囲を取得
307    CHARRANGE CharRange;
308    TextEdit_GetSel(WndNum,&CharRange);
309
310    //ベース描画ポジションを取得(文字単位)
311    BaseX=0;
312    BaseY=0;
313    GetScrollBaseCaretPos(MdiInfo[WndNum],&BaseX,&BaseY);
314
315    if(pobj_nv->bEditor_CaretLine_BackGround){
316        //カーソル行の色を変える
317        CaretBackColor=tci.rgbCursorBack;
318    }
319    else{
320        //カーソル行の色を変えない
321        CaretBackColor=tci.rgbBackground;
322    }
323    HBRUSH hCaretBackBrush;
324    hCaretBackBrush=CreateSolidBrush(CaretBackColor);
325
326    BOOL IsStr=0;
327    DWORD dwComment=0;
328    BOOL bMultiLineComment;
329    COLORREF NextColor,NextBackColor;
330    int MaxX=0;
331    x=BaseX;
332    y=BaseY;
333    CharX=0;    //左端から何文字目かを示す
334    int bHyperLinkUnderBar=0;   //ハイパーリンク用下線の表示スイッチ
335    for(i=0;;i++){
336        if(pBuf[i]=='\0'){
337            if(0<=y&&y<=OnePage_CharHeight){
338                if(MdiInfo[WndNum]->pMdiTextEdit->StartCaretPos.y==y-BaseY){
339                    ////////////////////////////////////
340                    // カーソル行では余白を塗りつぶす
341                    ////////////////////////////////////
342
343                    HBRUSH hTempBrush;
344                    hTempBrush=(HBRUSH)SelectObject(obj_dr.memdc,hCaretBackBrush);
345
346                    //終端コードよりも右側はブラシで塗りつぶす
347                    PatBlt(obj_dr.memdc,
348                        x*font_width     +iControlTabSpace,
349                        y*font_height,
350                        ClientRect.right-(x*font_width     +iControlTabSpace),
351                        font_height,
352                        PATCOPY);
353
354                    //カーソル行
355                    SelectObject(obj_dr.memdc,hTempBrush);
356                }
357
358                //行番号が末端行にも表示されるようにするために描画予約を行う
359                obj_dr.DrawReserve(
360                    x,
361                    y,
362                    NULL,
363                    NULL,
364                    bHyperLinkUnderBar,
365                    "",0);
366            }
367
368            if(MaxX<CharX) MaxX=CharX;
369
370            break;
371        }
372
373        if(IsRightTurn(pBuf,i,x)){
374            /////////////////
375            // 自動折り返し
376            /////////////////
377
378            if(MdiInfo[WndNum]->pMdiTextEdit->StartCaretPos.y==y-BaseY){
379                ///////////////////////////////////////////////////////////
380                //改行コードよりも右側は白いブラシで塗りつぶす(カーソル行用)
381                ///////////////////////////////////////////////////////////
382
383                HBRUSH hTempBrush;
384
385                //カーソル行
386                hTempBrush=(HBRUSH)SelectObject(obj_dr.memdc,hCaretBackBrush);
387
388                PatBlt(obj_dr.memdc,
389                    x*font_width     +iControlTabSpace,
390                    y*font_height,
391                    ClientRect.right-(x*font_width     +iControlTabSpace),
392                    font_height,
393                    PATCOPY);
394
395                //カーソル行
396                SelectObject(obj_dr.memdc,hTempBrush);
397            }
398
399            y++;
400
401            x=BaseX;
402            CharX=0;
403            i--;
404            continue;
405        }
406
407        if(MdiInfo[WndNum]->DocType==WNDTYPE_BASIC){
408
409            if(pBuf[i]=='\"'&&dwComment==0) IsStr^=1;
410
411            //複数行に渡るコメントを考慮
412            if( memicmp( pBuf+i, ActiveBasic::IDE::Program::ablang->GetSyntax().commentMultiBegin.c_str(), ActiveBasic::IDE::Program::ablang->GetSyntax().commentMultiBegin.size() ) == 0
413                && IsStr == 0
414                && dwComment == 0 )
415            {
416                // /*
417                dwComment=12;
418                bMultiLineComment=1;
419            }
420            if( memicmp( pBuf+i, ActiveBasic::IDE::Program::ablang->GetSyntax().commentMultiEnd.c_str(), ActiveBasic::IDE::Program::ablang->GetSyntax().commentMultiEnd.size() ) == 0
421                && dwComment == 10
422                && bMultiLineComment )
423            {
424                // */
425                dwComment=3;
426            }
427
428            //単行コメント
429            if( memicmp( pBuf+i, ActiveBasic::IDE::Program::ablang->GetSyntax().commentSingle.c_str(), ActiveBasic::IDE::Program::ablang->GetSyntax().commentSingle.size() ) == 0
430                && dwComment == 0
431                && IsStr == 0 )
432            {
433                // '
434                dwComment=10;
435                bMultiLineComment=0;
436            }
437
438            if(pBuf[i]=='\r'&&pBuf[i+1]=='\n'){
439                //単行コメント中での改行は、コメントを解除
440                if(dwComment&&bMultiLineComment==0){
441                    IsStr=0;
442                    dwComment=0;
443                }
444            }
445            if(dwComment!=0&&dwComment!=10) dwComment--;
446        }
447        if(MdiInfo[WndNum]->DocType==WNDTYPE_HTML){
448            //複数行に渡るコメントを考慮
449            if(pBuf[i]=='<'&&pBuf[i+1]=='!'&&pBuf[i+2]=='-'&&pBuf[i+3]=='-'&&IsStr==0&&dwComment==0){
450                dwComment=10;
451            }
452            if(pBuf[i]=='-'&&pBuf[i+1]=='-'&&pBuf[i+2]=='>'&&
453                dwComment){
454                dwComment=4;
455            }
456            if(dwComment!=0&&dwComment!=10) dwComment--;
457        }
458
459        //ハイパーリンク用下線
460        if(MdiInfo[WndNum]->pMdiTextEdit->iUnderStart<=i&&i<MdiInfo[WndNum]->pMdiTextEdit->iUnderEnd)
461            bHyperLinkUnderBar=1;
462        else bHyperLinkUnderBar=0;
463
464        if(0<=y&&y<=OnePage_CharHeight){
465            //////////////////////////////////
466            // 表示中ページでは文字単位で描画
467            //////////////////////////////////
468            //※i2に描画する文字数を格納する
469
470            NextBackColor=DefaultBackColor;
471            if(dwComment){
472                //複数行に渡るコメント
473                NextColor=tci.rgbComment;
474            }
475            else{
476                //通常カラー
477                NextColor=MdiInfo[WndNum]->pMdiTextEdit->pColorRef[i];
478            }
479
480            if(CharRange.cpMin<=i&&i<CharRange.cpMax){
481                //選択されているバッファは反転表示する
482                NextColor=NextColor^0x00FFFFFF;
483                NextBackColor=NextBackColor^0x00FFFFFF;
484            }
485            else{
486                if(MdiInfo[WndNum]->pMdiTextEdit->StartCaretPos.y==y-BaseY){
487                    //カーソル行
488                    NextBackColor=CaretBackColor;
489                }
490            }
491
492            if(IsDBCSLeadByte(pBuf[i])){
493                //マルチバイト文字
494                i2=2;
495                obj_dr.DrawReserve(
496                    x,
497                    y,
498                    NextColor,
499                    NextBackColor,
500                    bHyperLinkUnderBar,
501                    pBuf+i,i2);
502
503                i++;
504            }
505            else if(pBuf[i]=='\t'){
506                //タブ文字
507                int tab;
508                tab=pobj_nv->TabSize;
509
510                if((x-BaseX)%tab==0) i2=tab;
511                else i2=tab-(x-BaseX)%tab;
512                memset(temporary,' ',i2);
513                temporary[i2]=0;
514
515                obj_dr.DrawReserve(
516                    x,
517                    y,
518                    NextColor,
519                    NextBackColor,
520                    bHyperLinkUnderBar,
521                    temporary,i2);
522            }
523            else if(pBuf[i]=='\r'&&pBuf[i+1]=='\n'){
524                //改行文字は1スペースだけ空白を描画しておく(反転表示をするため)
525                i2=1;
526                temporary[0]=' ';
527                temporary[1]=0;
528                obj_dr.DrawReserve(
529                    x,
530                    y,
531                    NextColor,
532                    NextBackColor,
533                    bHyperLinkUnderBar,
534                    temporary,i2);
535
536
537                if(MdiInfo[WndNum]->pMdiTextEdit->StartCaretPos.y==y-BaseY){
538                    ///////////////////////////////////////////////////////////
539                    //改行コードよりも右側は白いブラシで塗りつぶす(カーソル行用)
540                    ///////////////////////////////////////////////////////////
541
542                    HBRUSH hTempBrush;
543
544                    //カーソル行
545                    hTempBrush=(HBRUSH)SelectObject(obj_dr.memdc,hCaretBackBrush);
546
547                    PatBlt(obj_dr.memdc,
548                        (x+i2)*font_width     +iControlTabSpace,
549                        y*font_height,
550                        ClientRect.right-((x+i2)*font_width     +iControlTabSpace),
551                        font_height,
552                        PATCOPY);
553
554                    //カーソル行
555                    SelectObject(obj_dr.memdc,hTempBrush);
556                }
557            }
558            else{
559                //通常のキャラ文字
560                i2=1;
561                obj_dr.DrawReserve(
562                    x,
563                    y,
564                    NextColor,
565                    NextBackColor,
566                    bHyperLinkUnderBar,
567                    pBuf+i,i2);
568            }
569        }
570        else{
571            ////////////////////////////////////////
572            // 非表示ページでは文字数の計算だけ行う
573            ////////////////////////////////////////
574            //※i2に描画する文字数を格納する
575
576            if(IsDBCSLeadByte(pBuf[i])){
577                //マルチバイト文字
578                i2=2;
579                i++;
580            }
581            else if(pBuf[i]=='\t'){
582                //タブ文字
583                int tab;
584                tab=pobj_nv->TabSize;
585
586                if((x-BaseX)%tab==0) i2=tab;
587                else i2=tab-(x-BaseX)%tab;
588            }
589            else{
590                //通常のキャラ文字(改行文字を含む)
591                i2=1;
592            }
593        }
594
595        if(pBuf[i]=='\r'&&pBuf[i+1]=='\n'){
596            y++;
597
598            if(MaxX<CharX) MaxX=CharX;
599
600            x=BaseX;
601            CharX=0;
602
603            i++;
604        }
605        else{
606            x+=i2;
607            CharX+=i2;
608        }
609    }
610
611    obj_dr.finish(BaseY);
612
613    DeleteObject(hCaretBackBrush);
614
615
616    //////////////////////////////////
617    // スクロールバーの範囲をセット
618    //////////////////////////////////
619
620    if(pobj_nv->bRightTurn){
621        MaxX=0;
622    }
623
624    ResetScrollbar(WndNum,MaxX,(-BaseY)+y);
625}
Note: See TracBrowser for help on using the repository browser.