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

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

egtraブランチの内容をマージ。

File size: 15.1 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.