2013年10月10日木曜日

lazarus版 synedit で crlf と eof の表示(暫定)

自前の過去のエディタで crlf と eof を表示していたので、現在のエディタにもやっぱり欲しくなったので実装しました。

とはいえ、私的な範囲以外での利用は推奨いたしかねる局所的で暫定的な対処で、派生などせず、synedit関連ファイルを書き換えて、デバイスコンテキストに直接描画をします。
変更箇所を抑えるために局所的に実装してあるため、フラグの状態を随時チェックしたり、デバイスコンテキストの操作も随時行うため効率もよくありません。
crlf は拾えなかったので、行末で描画します。
eof も同様に最終行の行末に描画します。
(highlighterが nil の場合に問題があります。仮対で最終行以降に[EOF]を表示しています。暫定に仮対も無い気もしますが) きちんと実装するなら、ラインバッファやTokenに #13と#10 を含める方向で広範囲にわたって書き直さないと駄目な気がします。 まあ、継承して対応できるかそのうちやってみます。
(lazarus 1.0.12,fpc 2.6.2 用です。既にgitやsvnの内容とは異なるようなので注意)

SynEditTypes.pp
  //TSynVisibleSpecialChar = (vscSpace, vscTabAtFirst, vscTabAtLast);
  TSynVisibleSpecialChar = (vscSpace, vscTabAtFirst, vscTabAtLast, vscCRLF, vscEOF); // # ADD
  TSynVisibleSpecialChars = set of TSynVisibleSpecialChar;         

LazSynTextArea.pp

583,591d582
<   {$DEFINE SHOW_CRLF_EOF}
<   {$IFDEF SHOW_CRLF_EOF}
<   bDoCRLF: boolean;   // # ADD
<   bDoEOF: boolean;    // # ADD
<   rcEOL: TRect;       // # ADD
<   EOLDone: boolean;   // # ADD
<   CRLFSZ: integer;    // # ADD
<   {$ENDIF}
<
617,678d607
<   {$IFDEF SHOW_CRLF_EOF}
<   procedure DrawCRLF; // # ADD
<   var
<     ExtSaveDC: HDC;
<     ExtPen: HPEN;
<   begin
<     if EOLDone then Exit;
<     ExtSaveDC:= SaveDC(dc);
<     try
<       ExtPen:= CreatePen(PS_INSIDEFRAME,1, ColorToRGB(clGray));
<       SelectObject(dc, ExtPen);
<       try
<         CRLFSZ := 4;//(rcEOL.Bottom - rcEOL.Top) div 2;
<         LCLIntf.MoveToEx(dc, rcEOL.Right + 1, rcEOL.Bottom - 2, nil);
<         LCLIntf.LineTo  (dc, rcEOL.Right + 1 + CRLFSZ, rcEOL.Bottom - 2);
<         LCLIntf.LineTo  (dc, rcEOL.Right + 1 + CRLFSZ, rcEOL.Bottom - 2 - CRLFSZ);
<         LCLIntf.LineTo  (dc, rcEOL.Right + 1, rcEOL.Bottom - 2);
<       finally
<         DeleteObject(ExtPen);
<       end;
<     finally
<       RestoreDC( dc, ExtSaveDC);
<       EOLDone:= True;
<     end;
<   end;
<   procedure DrawEOFText; // # ADD
<   var
<     ExtSaveDC: HDC;
<     hfNew,hfOld:HFONT;
<     lfText: TLOGFONT;
<   begin
<     if EOLDone then Exit;
<     ExtSaveDC:= SaveDC(dc);
<     try
<       LCLIntf.SetTextColor(dc,TColorRef(clSilver));
<       GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(TLOGFONT), @lfText);
<       lfText.lfHeight:= 10;
<       hfNew := CreateFontIndirect(lfText);
<       hfOld := SelectObject(dc, hfNew);
<       try
<         SetBkMode(dc,TRANSPARENT);
<         SetTextColor(dc,ColorToRGB(clGray));
<         TextOut(dc, rcEOL.Right, rcEOL.Top, '[EOF]', 5);
<       finally
<         hfNew:= SelectObject(dc, hfOld);
<         DeleteObject(hfNew);
<       end;
<     finally
<       RestoreDC( dc, ExtSaveDC);
<       EOLDone:= True;
<     end;
<   end;
<   procedure DrawEOFLine; // # ADD
<   var
<     ExtSaveDC: HDC;
<   begin
<     ExtSaveDC:= SaveDC(dc);
<     LCLIntf.MoveToEx(dc, AClip.Left, AClip.Top, nil);
<     LCLIntf.LineTo(dc, AClip.Right, AClip.Top);
<     RestoreDC( dc, ExtSaveDC);
<   end;
<   {$ENDIF}
963,968d891
<
<         {$IFDEF SHOW_CRLF_EOF}
<         rcEOL:= rcToken; // # ADD
<         EOLDone:= False; // # ADD
<         {$ENDIF}
<
1316,1319d1239
<       {$IFDEF SHOW_CRLF_EOF}
<       if bDoCRLF and (CurTextIndex<MaxLine) then DrawCRLF; // # ADD
<       {$ENDIF}
<
1332,1336d1251
<   {$IFDEF SHOW_CRLF_EOF}
<   bDoCRLF := vscCRLF in FVisibleSpecialChars; // # ADD
<   bDoEOF := vscEOF in FVisibleSpecialChars;   // # ADD
<   {$ENDIF}
<
1392,1410d1306
<   {$IFDEF SHOW_CRLF_EOF}
<   // # ADD
<   // if fHilighter=nil, it displays too mach EOF when
<   // editor adding lines with enter key.
<   //if bDoEOF and Assigned(fHighlighter) then DrawEOFText; // # ADD
<   if bDoEOF then
<   begin
<     if Assigned(fHighlighter) then
<       DrawEOFText
<     else
<     begin
<       DrawCRLF;
<       //rcEOL.Right:= AClip.Left;
<       //rcEOL.Top  := AClip.Top;
<       EOLDone:=False;
<     end;
<   end;
<   {$ENDIF}
<
1423,1433d1318
<     {$IFDEF SHOW_CRLF_EOF}
<     // # ADD
<     if bDoEOF then
<     begin
<       DrawEOFLine;
<       rcEOL.Right:= AClip.Left;
<       rcEOL.Top  := AClip.Top;
<       if not Assigned(fHighlighter) then
<         DrawEOFText;
<     end;
<     {$ENDIF}

Lazarus IDE も再構築して反映させたい場合はデフォルトSYNEDIT_DEFAULT_VISIBLESPECIALCHARSも変更する必要があります。

長いブロック内がビューに設定されている場合のIDE上部のツールチップ的なウィンドウにも[EOF]が出たりとか、いろいろ問題があるのでお勧め致しかねますが。

その後、IDEの設定で特殊文字の表示を有効にしてください。
(ツール→オプション→エディタ-一般-その他-特殊文字を表示) 特殊文字を表示すると、空白も「・」で表示されてしまいます。

空白の表示が見づらい場合は前景色のRGB値に+1する等して「既定のテキスト」の「バックグラウンド」とほぼ同じにしてください。(まったく同じにするとデフォルト色で描画されます)
(ツール→オプション→エディタ-表示-色-可視化された特殊文字-前景)

SynEdit.pp

324行目に追加
  SYNEDIT_DEFAULT_VISIBLESPECIALCHARS = [
    vscSpace,
    vscTabAtLast,
    vscCRLF,     // # ADD
    vscEOF       // # ADD
  ];   


IDEからCRLFの色やEOFのフォント設定の変更はできません。
SetTextColor や CreatePen、lfText を適当に書き換えればOKです。

以上。

0 件のコメント:

コメントを投稿