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

Last change on this file was 829, checked in by イグトランス (egtra), 11 years ago

svn:eol-styleとsvn:mime-type(文字コード指定含む)の設定

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