title: Phi::Editor
author: YOSHIDA Kazuhiro
mailto: moriq@moriq.com

1. Phi::Editor

Phi::Editor は，文字を描画する際に， 1 行文字列を語句に分解し，語句の種類に応じて定められた背景色・文字色・フォントスタイルでその語句を描画します。分解方法は， #view 内の各要素によって指定されます。

実際に 1 行文字列を語句に分解する仕事は， Phi::Editor::Parser が行っています。 Phi::Editor::Parser のコンストラクタを使い分けることで，分解方法を変えることが出来ます。

予約語は， #reserve_word_list に保持させます。

#caret では，キャレットの移動方法や，タブ文字の扱いを指定することが出来ます。

改行マークや， [EOF] マークなどの表示方法は， #marks に集約されています。

描画領域のトップマージン，レフトマージンなどは， #margin で指定することが出来ます。

ワードラップ処理の各オプションは， #wrap_option で指定します。

矩形選択処理を行うには， #selection_mode に %c:SM_BOX% を指定します。

行番号を表示させるには， Phi::Editor::Leftbar#visible を %c:true% に設定します。ルーラーを表示させるには， Phi::Editor::Ruler#visible を %c:true% に設定します。

%c:HEditReg.pas% をコンポーネントインストールすると下図のコンポーネントエディタが， Delphi-IDE に登録されますので，視覚的に TEditor の各機能を設定して頂けると思います。

1.1. TEditor の画面構成

以下は TEditor コンポーネントの画面構成です。

1.1. 矩形選択処理について

1.1.1. 説明

#selection_mode に %c:SM_BOX% を指定すると，矩形選択モードになります。通常の選択モードに戻すには， %c:SM_LINE% を指定します。

1.1.1. 矩形選択領域の仕様

* 矩形選択領域の左端が全角文字 2 バイト目の場合，領域はその文字を避けるように右に縮小されます。
* 矩形選択領域の右端が全角文字 1 バイト目の場合，領域はその文字を取り込むように右に拡張されます。
* 矩形選択領域の左端がタブ文字を展開した部分であっても，選択文字列にそのタブ文字が含まれることはありません。
* 矩形選択領域として描画されるのは，文字列があるところだけです。空白行や行文字列終端以降は対象になりません。
1.1.1. クリップボードとのデータ交換

クリップボードに TEditor が作成した矩形文字列があることを判別するには， Clipboard#has_format メソッドに %c:CF_BOXTEXT% を渡します。 %c:CF_BOXTEXT% は， %c:HEditor.pas% で宣言され，その %c:initialization% 部で以下のように Windows に登録されていますので， %c:HEditor.pas% を %c:uses% したユニット内から自由に使うことが出来ます。
--code
CF_BOXTEXT := RegisterClipboardFormat('TEditor Box Type');
--
矩形選択状態では #copy_to_clipboard メソッドが %c:CF_TEXT% フォーマットデータと， %c:CF_BOXTEXT% フォーマットデータをクリップボードへ転送します。

#paste_from_clipboard メソッドでは，この %c:CF_BOXTEXT% フォーマットを判別し，クリップボードデータを矩形に挿入します。

1.1.1. set_sel_text_box メソッド

Delphi のコードエディタなどから矩形選択文字列をクリップボードにコピーした後，そのデータを TEditor に矩形に挿入するためのメソッドとして #set_sel_text_box メソッドがあります。

#set_sel_text_box は，いわゆる「箱形挿入」機能として，改行文字を含む複数行の文字列を箱形に挿入する場合に利用出来ます。

1.1. MailChars, UrlChars グローバル変数

1.1.1. 適用

TEditor

1.1.1. 宣言

--code
var
  MailChars: TCharSet = ['!', '$'..'&', '*', ','..'9', ';', '=', '?'..'Z', '^'..'_', 'a'..'z', '~'];
  UrlChars: TCharSet = ['#', '%', '&', '-', '.', '/', '0'..'9', ':', '=', '?', 'A'..'Z', '_', 'a'..'z', '~'];
--
1.1.1. 説明

MailChars, UrlChars グローバル変数は， HEditor.pas で宣言されています。

MailChars は， toMail として判別される文字集合を表現します。

UrlChars は toUrl として判別される文字集合を表現します。

新しい文字をこれらの文字集合に含める必要が発生した場合は，自由に変更することが出来ます。変更をレジストリ等に保存する必要がある場合は， HEditor.pas 内にある， CharSetToStr, StrToCharSet 関数をご利用下さい。

1.1. TEditor 独自のマウスカーソル

1.1.1. TEditor 独自のマウスカーソルについて

TEditor は， HEditor.res ファイルに格納された以下のカーソルを LoadCursor しています。

: RIGHTARROW
  レフトマージン内のマウスカーソルとして利用
: DRAGSELCOPY
  選択領域をドラッグ中にコントロールキーが押された時に表示するマウスカーソルとして利用

TEditor では，これらのマウスカーソルを利用するために crRightArrow, crDragSelCopy 識別子を宣言しています。

crRightArrow, crDragSelCopy は， Caret.Cursors.LeftMarginCursor 及び DragSelCopyCursor プロパティのデフォルト値として指定されています。

HEditor.pas 内の initialization 部では以下のように初期化と LoadCursor が実行されています。
--code
initialization
  crRightArrow := GetUnUsedCursorIndex;
  Screen.Cursors[crRightArrow] := LoadCursor(HInstance, PChar(RightArrowCursorResourceIdent));
  crDragSelCopy := GetUnUsedCursorIndex;
  Screen.Cursors[crDragSelCopy] := LoadCursor(HInstance, PChar(DragSelCopyCursorResourceIdent));
end.
--
RightArrowCursorResourceIdent, DragSelCopyCursorResourceIdent の 2 定数及び， GetUnUsedCursorIndex 関数も HEditor.pas 内で宣言されています。

1.1.1. CursorState, Caret.AutoCursor, Caret.Cursors プロパティ

TEditor は，マウスカーソルの現在の位置を状態として扱い， CursorState プロパティに保持しています。 Caret.AutoCursor プロパティが True に設定されている場合は，マウスカーソルがこの状態に応じたものに自動的に変化します。各状態に応じて表示されるマウスカーソルは， Caret.Cursors プロパティに保持されています。

OnMouseMove イベントハンドラで， url やメールアドレス上のマウスカーソルを crHandPoint などに変更する処理を行う場合は，これらの状態に対応する必要があります。 CursorState プロパティのトピックにサンプルコードがありますので，参照して下さい。

1.1.1. オブジェクトインスペクタへの対応

TEditorCursors の各プロパティを設定する際は，オブジェクトインスペクタや，コンポーネントエディタにも 'crRightArrow', 'crDragSelCopy' の文字列が表示されます。

1.1.1. ユーザーによる LoadCursor

アプリケーションで独自のマウスカーソルを利用するために LoadCursor する場合は， crRightArrow, crDragSelCopy に設定されている値と重複しないインデックスを取得する必要がありますので，上記 GetUnUsedCursorIndex 関数をご利用下さい。

1.1. 選択領域のマウスドラッグ

1.1.1. 選択領域のマウスドラッグによる移動・複写について

TEditor ver 1.50 から選択領域文字列のマウスでの移動が実装されました。 ver 1.54 では，コントロールキーや，エスケープキーへ対応するための機能が追加されています。

Caret.SelMove プロパティが True に設定されていて， SelDragMode プロパティが dmAutomatic に設定されている場合，選択領域の文字列をマウスドラッグで移動することが出来ます。

ドラッグ終了時にコントロールキー (CTRL) を押していると移動ではなく，コピーすることが出来ます。

ドラッグ中にエスケープキー (ESC) を押すと，ドラッグが解除されます。

また， Caret.AutoCursor プロパティが True に設定されている場合は，マウスカーソルがそれぞれの状況に応じて自動的に変化します。

TEditor が行う選択領域文字列のマウスドラッグは，該当 TEditor 内でだけ有効です。同一アプリケーション内の他のコントロールへ選択文字列を渡したり， 2 画面分割状態や，別窓編集している TEditor 同士でもドラッグ＆ドロップを有効にするためには， Delphi 標準の TDragObject を利用したドラッグ＆ドロップを実装する必要があります。サンプルアプリケーションの unit2.pas に実装例がありますので参照して下さい。

1.1. properties

: caret

: col

: col_count

: col_width

: curosr_state

: delimiters

: editor_undo_obj

: font_height

: leftbar

: left_scroll_width

: lines

: list_bracket

: list_count

: list_string

: margin

: marks

: modified

: over_write

: reserve_word_list

: row

: row_count

: row_height

: ruler

: sel_draw_position

: selection_mode

: selected

: sel_length

: sel_start

: sel_str_position

: sel_text

: top_col

: top_row

: undo_list_max

: view

: word_wrap

: wrap_option

1.1. methods

: can_redo

: can_undo

: cancel_sel_drag

: can_sel_drag

: char_from_pos

: clear

: clean_selection

: clear_selection

: col_to_char

: copy_selection

: copy_to_clipboard

: cut_to_clip_board

: delete_row

: draw_text_rect

: exchange_list

: expand_tab

: get_text_len

: is_selected_area

: left_margin

: list_to_file

: list_to_stream

: move_selection

: paste_from_clipboard

: pos_to_row_col

: redo

: row_to_lines

: select_all

: select_token_bracket_from_caret

: select_token_bracket_from_pos

: select_token_from_caret

: select_token_from_pos

: select_word_from_caret

: select_word_from_pos

: sel_indent

: sel_un_indent

: sel_tab_indent

: sel_tab_un_indent

: set_row_col

: set_sel_text_box

: set_sel_text_buf

: str_info_from_pos

: token_bracket_from_caret

: token_bracket_from_pos

: token_from_caret

: token_from_pos

: token_string_bracket_from_caret

: token_string_bracket_from_pos

: token_string_from_caret

: token_string_from_pos

: top_margin

: undo

: word_from_caret

: word_from_pos

1.1. event handlers

: on_caret_moved

: on_change

: on_draw_line

: on_selection_change

: on_selection_mode_change

: on_top_col_change

: on_top_row_change
