OSDN Git Service

TSF Wrapperで複数の選択領域を返せるようにした
[fooeditengine/FooEditEngine.git] / DotNetTextStore / TextStoreBase.cs
1 // TSF のデバッグ表示を行うかどうか?
2 //#define TSF_DEBUG_OUTPUT
3 //#define TSF_DEBUG_OUTPUT_DISPLAY_ATTR
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Text;
8 using System.Diagnostics;
9 using System.Reflection;
10 using System.Runtime.CompilerServices;
11 using System.Runtime.InteropServices;
12 using System.Globalization;
13
14 using DotNetTextStore.UnmanagedAPI.TSF;
15 using DotNetTextStore.UnmanagedAPI.TSF.TextStore;
16 using DotNetTextStore.UnmanagedAPI.WinDef;
17 using DotNetTextStore.UnmanagedAPI.WinError;
18
19 namespace DotNetTextStore
20 {
21 #if TSF_DEBUG_OUTPUT
22     /// <summary>コールスタックの階層にあわせてインデントしてデバッグ表示するクラス。</summary>
23     public class DebugOut : IDisposable
24     {
25         public DebugOut(string i_string, params object[] i_params)
26         {
27             _text = string.Format(i_string, i_params);
28
29             s_callCount++;
30             Debug.WriteLine("");
31             Debug.WriteLine(string.Format("{0, 4} : ↓↓↓ ", s_callCount) + _text);
32         }
33
34         public static void Print(string i_string, params object[] i_params)
35         {
36             Debug.WriteLine(i_string, i_params);
37         }
38
39         public void Dispose()
40         {
41             s_callCount++;
42             Debug.WriteLine(string.Format("{0, 4} : ↑↑↑ ", s_callCount) + _text);
43         }
44
45         public static string GetCaller([CallerMemberName] string caller="")
46         {
47             return caller;
48         }
49
50         string      _text;
51         static int  s_callCount = 0;
52     }
53 #endif
54
55     //=============================================================================================
56
57
58     public struct TextDisplayAttribute
59     {
60         public int startIndex;
61         public int endIndex;
62         public TF_DISPLAYATTRIBUTE attribute;
63     }
64
65     //========================================================================================
66
67     public struct TextSelection
68     {
69         public int start;
70         public int end;
71         public TextSelection(int start = 0,int end = 0)
72         {
73             this.start = start;
74             this.end = end;
75         }
76     }
77     
78
79     /// <summary>Dispose() で TextStore のロック解除を行うクラス。</summary>
80     public class Unlocker : IDisposable
81     {
82         /// <summary>コンストラクタ</summary>
83         public Unlocker(TextStoreBase io_textStore)
84         {
85             _textStore = io_textStore;
86         }
87         /// <summary>ロックが成功したかどうか調べる。</summary>
88         public bool IsLocked
89         {
90             get { return _textStore != null; }
91         }
92         /// <summary>アンロックを行う。</summary>
93         void IDisposable.Dispose()
94         {
95             if (_textStore != null)
96             {
97                 _textStore.UnlockDocument();
98                 _textStore = null;
99             }
100         }
101
102         /// <summary>アンロックを行うテキストストア</summary>
103         TextStoreBase _textStore;
104     }
105
106     public abstract class TextStoreBase
107     {
108         public delegate bool IsReadOnlyHandler();
109         public event IsReadOnlyHandler IsReadOnly;
110
111         public delegate bool IsLoadingHandler();
112         public event IsLoadingHandler IsLoading;
113
114         public event Func<int> GetSelectionCount;
115
116         public delegate int GetStringLengthHandler();
117         public event GetStringLengthHandler GetStringLength;
118
119         public delegate void GetSelectionIndexHandler(int start_index, int max_count, out TextSelection[] sel);
120         public event GetSelectionIndexHandler GetSelectionIndex;
121
122         public delegate void SetSelectionIndexHandler(TextSelection[] sel);
123         public event SetSelectionIndexHandler SetSelectionIndex;
124
125         public delegate string GetStringHandler(int start, int length);
126         public event GetStringHandler GetString;
127
128         public delegate void InsertAtSelectionHandler(string i_value,ref int o_startIndex,ref int o_endIndex);
129         public event InsertAtSelectionHandler InsertAtSelection;
130
131         public delegate void GetScreenExtentHandler(
132             out POINT o_pointTopLeft,
133             out POINT o_pointBottomRight
134         );
135         public event GetScreenExtentHandler GetScreenExtent;
136
137         public delegate void GetStringExtentHandler(
138             int i_startIndex,
139             int i_endIndex,
140             out POINT o_pointTopLeft,
141             out POINT o_pointBottomRight
142         );
143         public event GetStringExtentHandler GetStringExtent;
144
145         public delegate bool CompositionStartedHandler();
146         public event CompositionStartedHandler CompositionStarted;
147
148         public delegate void CompostionUpdateHandler(int start, int end);
149         public event CompostionUpdateHandler CompositionUpdated;
150
151         public delegate void CompositionEndedHandler();
152         public event CompositionEndedHandler CompositionEnded;
153
154         bool _allow_multi_sel = false;
155
156         #region "生成と破棄"
157         public TextStoreBase(bool allow_multi_sel = false)
158         {
159 #if TSF_DEBUG_OUTPUT
160             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
161 #endif
162             {
163                 this._allow_multi_sel = allow_multi_sel;
164                 try
165                 {
166                     // スレッドマネージャ-の生成
167                     CreateThreadMgr();
168                     // カテゴリマネージャーの生成
169                     CreateCategoryMgr();
170                     // 表示属性マネージャーの生成
171                     CreateDisplayAttributeMgr();
172
173                     // ドキュメントマネージャーの生成
174                     _threadMgr.CreateDocumentMgr(out _documentMgr);
175
176                     // スレッドマネージャのアクティブ化
177                     int clientId = 0;
178                     _threadMgr.Activate(out clientId);
179
180                     // コンテキストの生成
181                     _documentMgr.CreateContext(clientId, 0, this, out _context, out _editCookie);
182
183                     // コンテキストの push
184                     _documentMgr.Push(_context);
185
186                     // ファンクションプロバイダーを取得する。
187                     Guid guid = TfDeclarations.GUID_SYSTEM_FUNCTIONPROVIDER;
188                     _threadMgr.GetFunctionProvider(ref guid, out _functionProvider);
189
190                     // ITfReconversion オブジェクトを取得する。
191                     var guidNull = new Guid();
192                     var guidReconversion = new Guid("4cea93c0-0a58-11d3-8df0-00105a2799b5");    //ITfFnReconversionの定義から
193                     object reconversion = null;
194                     _functionProvider.GetFunction(
195                         ref guidNull,
196                         ref guidReconversion,
197                         out reconversion
198                     );
199                     _reconversion = reconversion as ITfFnReconversion;
200
201                     // MODEBIAS の初期化
202                     uint guidAtom = 0;
203                     Guid guidModebiasNone = TfDeclarations.GUID_MODEBIAS_NONE;
204                     _categoryMgr.RegisterGUID(ref guidModebiasNone, out guidAtom);
205                     _attributeInfo[0].attrID = TfDeclarations.GUID_PROP_MODEBIAS;
206                     _attributeInfo[0].flags = AttributeInfoFlags.None;
207                     _attributeInfo[0].currentValue.vt = (short)VarEnum.VT_EMPTY;
208                     _attributeInfo[0].defaultValue.vt = (short)VarEnum.VT_I4;
209                     _attributeInfo[0].defaultValue.data1 = (IntPtr)guidAtom;
210                 }
211                 catch (Exception exception)
212                 {
213                     Debug.WriteLine(exception.Message);
214                     Dispose(false);
215                 }
216             }
217         }
218
219         /// <summary>
220         /// オブジェクトの破棄を行う。このメソッドは必ず呼び出す必要があります
221         /// </summary>
222         /// <param name="flag"></param>
223         protected void Dispose(bool flag)
224         {
225             if (flag)
226                 return;
227 #if TSF_DEBUG_OUTPUT
228             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
229 #endif
230             {
231                 ReleaseComObject("_reconversion", ref _reconversion);
232                 ReleaseComObject("_functionProvider", ref _functionProvider);
233                 ReleaseComObject("_context", ref _context);
234                 DestroyDocumentMgr();
235                 DestroyDisplayAttributeMgr();
236                 DestroyCategoryMgr();
237                 DestroyThreadMgr();
238
239                 GC.SuppressFinalize(this);
240             }
241         }
242
243         /// <summary>
244         /// スレッドマネージャの生成。このメソッドの実装は必須です
245         /// </summary>
246         /// 
247         /// <exception cref="COMException">
248         /// スレッドマネージャーの生成に失敗した場合。
249         /// </exception>
250         protected virtual void CreateThreadMgr()
251         {
252             throw new NotImplementedException();
253         }
254
255         /// <summary>
256         /// スレッドマネージャーの解放。
257         /// </summary>
258         void DestroyThreadMgr()
259         {
260             if (_threadMgr != null)
261             {
262                 try { _threadMgr.Deactivate(); }
263                 catch (Exception) { }
264
265                 ReleaseComObject("_threadMgr", ref _threadMgr);
266             }
267         }
268
269         /// <summary>
270         /// カテゴリマネージャーの生成。
271         /// </summary>
272         /// 
273         /// <exception cref="COMException">
274         /// カテゴリマネージャーの生成に失敗した場合。
275         /// </exception>
276         void CreateCategoryMgr()
277         {
278             if (_categoryMgr == null)
279             {
280                 var clsid = Marshal.GetTypeFromCLSID(TfDeclarations.CLSID_TF_CategoryMgr);
281                 _categoryMgr = Activator.CreateInstance(clsid) as ITfCategoryMgr;
282
283                 if (_categoryMgr == null)
284                 {
285                     const string message = "カテゴリマネージャーの生成に失敗しました。";
286                     Debug.WriteLine(message);
287                     throw new COMException(message, HRESULT.E_NOTIMPL);
288                 }
289             }
290         }
291
292         /// <summary>
293         /// カテゴリマネージャーの解放。
294         /// </summary>
295         void DestroyCategoryMgr()
296         {
297             ReleaseComObject("_categoryMgr", ref _categoryMgr);
298         }
299
300         /// <summary>
301         /// 表示属性マネージャーの生成。
302         /// </summary>
303         /// 
304         /// <exception cref="COMException">
305         /// 表示属性マネージャーの生成に失敗した場合。
306         /// </exception>
307         void CreateDisplayAttributeMgr()
308         {
309             if (_displayAttributeMgr == null)
310             {
311                 var clsid = Marshal.GetTypeFromCLSID(TfDeclarations.CLSID_TF_DisplayAttributeMgr);
312                 _displayAttributeMgr = Activator.CreateInstance(clsid) as ITfDisplayAttributeMgr;
313
314                 if (_displayAttributeMgr == null)
315                 {
316                     const string message = "表示属性マネージャーの生成に失敗しました。";
317                     Debug.WriteLine(message);
318                     throw new COMException(message, HRESULT.E_NOTIMPL);
319                 }
320             }
321         }
322
323         /// <summary>
324         /// 表示属性マネージャーの解放。
325         /// </summary>
326         void DestroyDisplayAttributeMgr()
327         {
328             ReleaseComObject("_displayAttributeMgr", ref _displayAttributeMgr);
329         }
330
331         /// <summary>
332         /// ドキュメントマネージャーの解放
333         /// </summary>
334         void DestroyDocumentMgr()
335         {
336             if (_documentMgr != null)
337             {
338                 try { _documentMgr.Pop(PopFlags.TF_POPF_ALL); }
339                 catch (Exception) { }
340
341                 ReleaseComObject("_documentMgr", ref _documentMgr);
342             }
343         }
344
345         /// <summary>
346         /// COM オブジェクトのリリースとデバッグメッセージ出力。
347         /// </summary>
348         protected static void ReleaseComObject<ComObject>(
349             string i_objectName,
350             ref ComObject io_comObject
351         )
352         {
353             if (io_comObject != null)
354             {
355                 var refCount = Marshal.ReleaseComObject(io_comObject);
356 #if TSF_DEBUG_OUTPUT
357                     Debug.WriteLine(
358                         "Marshal.ReleaseComObject({0}) returns {1}.",
359                         i_objectName,
360                         refCount
361                     );
362 #endif
363
364                 io_comObject = default(ComObject);
365             }
366         }
367         #endregion
368
369         #region "コントロール側が状況に応じて呼び出さなければいけない TSF に通知を送るメソッド"
370         /// <summary>
371         /// 選択領域が変更されたことをTSFに伝える。各種ハンドラ内からコールしてはいけない。
372         /// </summary>
373         public void NotifySelectionChanged()
374         {
375             if( _sink != null )
376             {
377 #if TSF_DEBUG_OUTPUT
378                 DebugOut.Print(DebugOut.GetCaller());
379 #endif
380                 if ((_adviseFlags & AdviseFlags.TS_AS_SEL_CHANGE) != 0)
381                     _sink.OnSelectionChange();
382             }
383         }
384
385         
386         //=========================================================================================
387
388
389         /// <summary>
390         /// テキストが変更されたことをTSFに伝える。各種ハンドラ内からコールしてはいけない。
391         /// </summary>
392         void NotifyTextChanged(TS_TEXTCHANGE textChange)
393         {
394             if( _sink != null )
395             {
396 #if TSF_DEBUG_OUTPUT
397                 DebugOut.Print(DebugOut.GetCaller());
398 #endif
399                 if ((_adviseFlags & AdviseFlags.TS_AS_TEXT_CHANGE) != 0)
400                     _sink.OnTextChange(0, ref textChange);
401                 _sink.OnLayoutChange(TsLayoutCode.TS_LC_CHANGE, 1);
402             }
403         }
404
405         
406         //=========================================================================================
407
408         /// <summary>
409         /// テキストが変更されたことをTSFに伝える。各種ハンドラ内からコールしてはいけない。
410         /// </summary>
411         /// <param name="start">開始位置</param>
412         /// <param name="oldend">更新前の終了位置</param>
413         /// <param name="newend">更新後の終了位置</param>
414         /// <remarks>
415         /// 詳しいことはITextStoreACPSink::OnTextChangeを参照してください
416         /// </remarks>
417         public void NotifyTextChanged(int start,int oldend,int newend)
418         {
419             if (_sink != null)
420             {
421 #if TSF_DEBUG_OUTPUT
422                 DebugOut.Print(DebugOut.GetCaller());
423 #endif
424                 if ((_adviseFlags & AdviseFlags.TS_AS_TEXT_CHANGE) != 0)
425                 {
426                     var textChange = new TS_TEXTCHANGE();
427                     textChange.start = start;
428                     textChange.oldEnd = oldend;
429                     textChange.newEnd = newend;
430
431                     _sink.OnTextChange(0, ref textChange);
432                 }
433                 _sink.OnLayoutChange(TsLayoutCode.TS_LC_CHANGE, 1);
434             }
435         }
436
437         /// <summary>
438         /// テキストが変更されたことをTSFに伝える。各種ハンドラ内からコールしてはいけない。
439         /// </summary>
440         /// <param name="i_oldLength"></param>
441         /// <param name="i_newLength"></param>
442         public void NotifyTextChanged(int i_oldLength, int i_newLength)
443         {
444             if( _sink != null )
445             {
446 #if TSF_DEBUG_OUTPUT
447                 DebugOut.Print(DebugOut.GetCaller());
448 #endif
449                 if ((_adviseFlags & AdviseFlags.TS_AS_TEXT_CHANGE) != 0)
450                 {
451                     var textChange = new TS_TEXTCHANGE();
452                     textChange.start = 0;
453                     textChange.oldEnd = i_oldLength;
454                     textChange.newEnd = i_newLength;
455
456                     _sink.OnTextChange(0, ref textChange);
457                 }
458                 _sink.OnLayoutChange(TsLayoutCode.TS_LC_CHANGE, 1);
459             }
460         }
461
462         
463         
464         //=========================================================================================
465
466
467         /// <summary>コントロールがフォーカスを取得した時に呼び出さなければいけない。</summary>
468         public void SetFocus()
469         {
470 #if TSF_DEBUG_OUTPUT
471             DebugOut.Print(DebugOut.GetCaller());
472 #endif
473             if (_threadMgr != null)
474                 _threadMgr.SetFocus(_documentMgr);
475         }
476         #endregion "コントロール側が状況に応じて呼び出さなければいけない TSF に通知を送るメソッド"
477
478         #region ロック関連
479         /// <summary>
480         /// ドキュメントのロックを行う。
481         /// </summary>
482         /// <param name="i_writable">読み書き両用ロックか?false の場合、読み取り専用。</param>
483         /// <returns>Unlocker のインスタンスを返す。失敗した場合 null を返す。</returns>
484         public Unlocker LockDocument(bool i_writable)
485         {
486             #if TSF_DEBUG_OUTPUT
487             using(var dbgout = new DebugOut("{0}({1})", DebugOut.GetCaller(),
488                                                         i_writable) )
489             #endif
490             {
491                 lock(this)
492                 {
493                     if( this._lockFlags == 0 )
494                     {
495                         if( i_writable )
496                             this._lockFlags = LockFlags.TS_LF_READWRITE;
497                         else
498                             this._lockFlags = LockFlags.TS_LF_READ;
499
500                         #if TSF_DEBUG_OUTPUT
501                             Debug.WriteLine("LockDocument is succeeded.");
502                         #endif
503
504                         return new Unlocker(this);
505                     }
506                     else
507                     {
508                         #if TSF_DEBUG_OUTPUT
509                             Debug.WriteLine("LockDocument is failed. {0}", _lockFlags);
510                         #endif
511
512                         return null;
513                     }
514                 }
515             }
516         }
517
518
519         //========================================================================================
520
521         
522         /// <summary>
523         /// ドキュメントのロックを行う。
524         /// </summary>
525         /// <param name="i_writable">読み書き両用ロックか?false の場合、読み取り専用。</param>
526         /// <returns>Unlocker のインスタンスを返す。失敗した場合 null を返す。</returns>
527         public Unlocker LockDocument(LockFlags i_flags)
528         {
529             #if TSF_DEBUG_OUTPUT
530             using(var dbgout = new DebugOut("{0}({1})", DebugOut.GetCaller(),
531                                                         i_flags) )
532             #endif
533             {
534                 lock(this)
535                 {
536                     if( this._lockFlags == 0 )
537                     {
538                         this._lockFlags = i_flags;
539
540                         #if TSF_DEBUG_OUTPUT
541                             Debug.WriteLine("LockDocument is succeeded.");
542                         #endif
543
544                         return new Unlocker(this);
545                     }
546                     else
547                     {
548                         #if TSF_DEBUG_OUTPUT
549                             Debug.WriteLine("LockDocument is failed. {0}", _lockFlags);
550                         #endif
551
552                         return null;
553                     }
554                 }
555             }
556         }
557
558
559         //========================================================================================
560
561         
562         /// <summary>
563         /// ドキュメントのアンロックを行う。
564         /// </summary>
565         public void UnlockDocument()
566         {
567             #if TSF_DEBUG_OUTPUT
568             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
569             #endif
570             {
571                 lock(this)
572                 {
573                     _lockFlags = 0;
574                 }
575
576                 if( _pendingLockUpgrade )
577                 {
578                     _pendingLockUpgrade = false;
579                     int sessionResult;
580                     RequestLock(LockFlags.TS_LF_READWRITE, out sessionResult);
581                 }
582             }
583         }
584
585
586         //========================================================================================
587
588         
589         /// <summary>
590         /// 指定されたフラグでロックしている状態かどうか調べる。
591         /// </summary>
592         /// <param name="i_lockFlags"></param>
593         /// <returns>ロックされている場合は true, されていない場合は false を返す。</returns>
594         public bool IsLocked(LockFlags i_lockFlags)
595         {
596             #if TSF_DEBUG_OUTPUT
597             using(var dbgout = new DebugOut("{0}({1})",
598                                             DebugOut.GetCaller(), i_lockFlags) )
599             #endif
600             {
601                 #if TSF_DEBUG_OUTPUT
602                     Debug.WriteLine(
603                         "IsLocked() returns " + ((this._lockFlags & i_lockFlags) == i_lockFlags)
604                     );
605                 #endif
606                 return (this._lockFlags & i_lockFlags) == i_lockFlags;
607             }
608         }
609
610         /// <summary>
611         /// ロックされているか調べる
612         /// </summary>
613         /// <returns>ロックされているなら真、そうでなければ偽を返す</returns>
614         public bool IsLocked()
615         {
616 #if TSF_DEBUG_OUTPUT
617             using(var dbgout = new DebugOut("{0}",
618                                             DebugOut.GetCaller()) )
619 #endif
620             {
621                 bool retval = this._lockFlags != 0;
622 #if TSF_DEBUG_OUTPUT
623                     Debug.WriteLine(
624                         "IsLocked() returns " + retval
625                     );
626 #endif
627                 return retval;
628             }
629         }
630         #endregion
631
632         #region ITextStroeACP,ITextStoreACP2の共通部分
633
634         /// <summary>
635         /// 文字列を挿入する。
636         /// </summary>
637         public void InsertTextAtSelection(string s)
638         {
639             TS_TEXTCHANGE textChange = new TS_TEXTCHANGE();
640
641             using (var unlocker = LockDocument(true))
642             {
643                 if (unlocker != null)
644                 {
645                     int startIndex, endIndex;
646
647                     InsertTextAtSelection(
648                         UnmanagedAPI.TSF.TextStore.InsertAtSelectionFlags.TF_IAS_NOQUERY,
649                         s.ToCharArray(),
650                         s.Length,
651                         out startIndex,
652                         out endIndex,
653                         out textChange
654                     );
655                 }
656             }
657
658             // シンクの OnSelectionChange() をコール。
659             NotifySelectionChanged();
660             NotifyTextChanged(textChange);
661         }
662
663         public void InsertEmbeddedAtSelection(
664             InsertAtSelectionFlags flags,
665             object obj,
666             out int start,
667             out int end,
668             out TS_TEXTCHANGE change
669         )
670         {
671 #if TSF_DEBUG_OUTPUT
672             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
673 #endif
674             {
675                 throw new NotImplementedException();
676             }
677         }
678
679         public void AdviseSink(ref Guid i_riid, object i_unknown, AdviseFlags i_mask)
680         {
681 #if TSF_DEBUG_OUTPUT
682             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
683 #endif
684             {
685                 if (i_riid != new Guid("22d44c94-a419-4542-a272-ae26093ececf")) //ITextStoreACPSinkの定義より
686                 {
687                     throw new COMException(
688                         "ITextStoreACPSink 以外のIIDが渡されました。",
689                         UnmanagedAPI.WinError.HRESULT.E_INVALIDARG
690                     );
691                 }
692
693                 // 既存のシンクのマスクのみを更新
694                 if (_sink == i_unknown)
695                 {
696                     _adviseFlags = i_mask;
697                 }
698                 // シンクを複数登録しようとした
699                 else if (_sink != null)
700                 {
701                     throw new COMException(
702                         "既にシンクを登録済みです。",
703                         UnmanagedAPI.TSF.TextStore.TsResult.CONNECT_E_ADVISELIMIT
704                     );
705                 }
706                 else
707                 {
708                     // 各種値を保存
709                     _services = (ITextStoreACPServices)i_unknown;
710                     _sink = (ITextStoreACPSink)i_unknown;
711                     _adviseFlags = i_mask;
712                 }
713             }
714         }
715
716         public void UnadviseSink(object i_unknown)
717         {
718 #if TSF_DEBUG_OUTPUT
719             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
720 #endif
721             {
722                 if (_sink == null || _sink != i_unknown)
723                 {
724                     throw new COMException(
725                         "シンクは登録されていません。",
726                         UnmanagedAPI.TSF.TextStore.TsResult.CONNECT_E_NOCONNECTION
727                     );
728                 }
729
730                 _services = null;
731                 _sink = null;
732                 _adviseFlags = 0;
733             }
734         }
735
736         public void RequestLock(LockFlags i_lockFlags, out int o_sessionResult)
737         {
738 #if TSF_DEBUG_OUTPUT
739             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
740 #endif
741             {
742                 o_sessionResult = UnmanagedAPI.WinError.HRESULT.E_FAIL;
743
744                 if (_sink == null)
745                 {
746                     throw new COMException(
747                         "シンクが登録されていません。",
748                         UnmanagedAPI.TSF.TextStore.TsResult.CONNECT_E_NOCONNECTION
749                     );
750                 }
751
752                 if (_lockFlags != 0)   // すでにロックされた状態の場合。
753                 {
754                     if ((i_lockFlags & LockFlags.TS_LF_SYNC) != 0)
755                     {
756                         o_sessionResult = TsResult.TS_E_SYNCHRONOUS;
757                         return;
758                     }
759                     else
760                         if ((_lockFlags & LockFlags.TS_LF_READWRITE) == LockFlags.TS_LF_READ
761                         && (i_lockFlags & LockFlags.TS_LF_READWRITE) == LockFlags.TS_LF_READWRITE)
762                         {
763                             _pendingLockUpgrade = true;
764                             o_sessionResult = TsResult.TS_S_ASYNC;
765                             return;
766                         }
767
768                     throw new COMException();
769                 }
770
771                 using (var unlocker = LockDocument(i_lockFlags))
772                 {
773                     // ロックに失敗した場合は TS_E_SYNCHRONOUS をセットして S_OK を返す。
774                     if (unlocker == null)
775                     {
776                         o_sessionResult = TsResult.TS_E_SYNCHRONOUS;
777                     }
778                     // ロックに成功した場合は OnLockGranted() を呼び出す。
779                     else
780                     {
781                         try
782                         {
783                             o_sessionResult = _sink.OnLockGranted(i_lockFlags);
784                         }
785                         catch (COMException comException)
786                         {
787                             Debug.WriteLine("OnLockGranted() 呼び出し中に例外が発生。");
788                             Debug.WriteLine("  " + comException.Message);
789                             o_sessionResult = comException.HResult;
790                         }
791                         catch (Exception exception)
792                         {
793                             Debug.WriteLine("OnLockGranted() 呼び出し中に例外が発生。");
794                             Debug.WriteLine("  " + exception.Message);
795                         }
796                     }
797                 }
798             }
799         }
800
801         public void GetStatus(out TS_STATUS o_documentStatus)
802         {
803 #if TSF_DEBUG_OUTPUT
804             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
805 #endif
806             {
807                 if (IsReadOnly != null && IsReadOnly())
808                     o_documentStatus.dynamicFlags = DynamicStatusFlags.TS_SD_READONLY;
809                 if (IsLoading != null && IsLoading())
810                     o_documentStatus.dynamicFlags = DynamicStatusFlags.TS_SD_LOADING;
811                 else
812                     o_documentStatus.dynamicFlags = 0;
813                 o_documentStatus.staticFlags = StaticStatusFlags.TS_SS_REGIONS;
814                 if (this._allow_multi_sel)
815                     o_documentStatus.staticFlags |= StaticStatusFlags.TS_SS_DISJOINTSEL;
816             }
817         }
818
819         public void QueryInsert(
820             int i_startIndex,
821             int i_endIndex,
822             int i_length,
823             out int o_startIndex,
824             out int o_endIndex
825         )
826         {
827 #if TSF_DEBUG_OUTPUT
828             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
829 #endif
830             {
831                 if (GetStringLength == null)
832                     throw new NotImplementedException();
833
834                 int documentLength = GetStringLength();
835
836                 if (i_startIndex < 0
837                 || i_startIndex > i_endIndex
838                 || i_endIndex > documentLength)
839                 {
840                     throw new COMException(
841                         "インデックスが無効です。",
842                         UnmanagedAPI.WinError.HRESULT.E_INVALIDARG
843                     );
844                 }
845                 o_startIndex = i_startIndex;
846                 o_endIndex = i_endIndex;
847
848 #if TSF_DEBUG_OUTPUT
849                 DebugOut.Print("o_startIndex:{0} o_endIndex:{1}", i_startIndex, i_endIndex);
850 #endif
851             }
852         }
853
854         public void GetSelection(
855             int i_index,
856             int i_selectionBufferLength,
857             TS_SELECTION_ACP[] o_selections,
858             out int o_fetchedLength
859         )
860         {
861 #if TSF_DEBUG_OUTPUT
862             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
863 #endif
864             {
865                 if (GetSelectionIndex == null)
866                     throw new NotImplementedException();
867
868                 o_fetchedLength = 0;
869
870                 if (IsLocked(LockFlags.TS_LF_READ) == false)
871                 {
872                     throw new COMException(
873                         "読取用ロックがされていません。",
874                         TsResult.TS_E_NOLOCK
875                     );
876                 }
877
878                 // -1 は TF_DEFAULT_SELECTION。選択は1つだけしかサポートしないので、
879                 // TF_DEFAULT_SELECTION でもなく、0 を超える数値が指定された場合はエラー。
880                 if (i_index != -1 && i_index > 0 && !this._allow_multi_sel)
881                 {
882                     throw new COMException(
883                         "選択は1つだけしかサポートしていません。",
884                         UnmanagedAPI.WinError.HRESULT.E_INVALIDARG
885                     );
886                 }
887
888                 if (i_selectionBufferLength > 0)
889                 {
890                     TextSelection[] sels;
891                     GetSelectionIndex(i_index,i_selectionBufferLength,out sels);
892                     if (sels == null)
893                         throw new InvalidOperationException("selsはnull以外の値を返す必要があります");
894                     for(int i = 0; i < sels.Length; i++)
895                     {
896                         int start = sels[i].start, end = sels[i].end;
897
898                         if (start <= end)
899                         {
900                             o_selections[0].start = start;
901                             o_selections[0].end = end;
902                             o_selections[0].style.ase = TsActiveSelEnd.TS_AE_END;
903                             o_selections[0].style.interimChar = false;
904                         }
905                         else
906                         {
907                             o_selections[0].start = end;
908                             o_selections[0].end = start;
909                             o_selections[0].style.ase = TsActiveSelEnd.TS_AE_START;
910                             o_selections[0].style.interimChar = false;
911                         }
912                     }
913
914                     o_fetchedLength = sels.Length;
915
916 #if TSF_DEBUG_OUTPUT
917                     DebugOut.Print("sel start:{0} end:{1}", start, end);
918 #endif
919                 }
920             }
921         }
922
923         public void SetSelection(int i_count, TS_SELECTION_ACP[] i_selections)
924         {
925 #if TSF_DEBUG_OUTPUT
926             using(var dbgout = new DebugOut("{0}({1}, {2})",
927                                             DebugOut.GetCaller(),
928                                             i_selections[0].start,
929                                             i_selections[0].end))
930 #endif
931             {
932                 if (SetSelectionIndex == null)
933                     throw new NotImplementedException();
934
935                 if (i_count != 1 && !this._allow_multi_sel)
936                 {
937                     throw new COMException(
938                         "選択は1つだけしかサポートしていません。",
939                         UnmanagedAPI.WinError.HRESULT.E_INVALIDARG
940                     );
941                 }
942
943                 if (IsLocked(LockFlags.TS_LF_READWRITE) == false)
944                 {
945                     throw new COMException(
946                         "ロックされていません。",
947                         TsResult.TS_E_NOLOCK
948                     );
949                 }
950
951                 TextSelection[] sels = new TextSelection[i_count];
952                 for(int i = 0; i < i_count; i++)
953                 {
954                     sels[i] = new TextSelection(i_selections[i].start, i_selections[i].end);
955                 }
956
957                 SetSelectionIndex(sels);
958
959 #if TSF_DEBUG_OUTPUT
960                 DebugOut.Print("set selection startIndex:{0} endIndex:{1}", i_selections[0].start, i_selections[0].end);
961 #endif
962             }
963         }
964
965         public void GetText(
966             int i_startIndex,
967             int i_endIndex,
968             char[] o_plainText,
969             int i_plainTextLength,
970             out int o_plainTextLength,
971             TS_RUNINFO[] o_runInfos,
972             int i_runInfoLength,
973             out int o_runInfoLength,
974             out int o_nextUnreadCharPos
975         )
976         {
977 #if TSF_DEBUG_OUTPUT
978             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
979 #endif
980             {
981                 if (GetStringLength == null || GetString == null)
982                     throw new NotImplementedException();
983
984                 if (IsLocked(LockFlags.TS_LF_READ) == false)
985                 {
986                     throw new COMException(
987                         "読取用ロックがされていません。",
988                         TsResult.TS_E_NOLOCK
989                     );
990                 }
991
992                 if ((i_endIndex != -1 && i_startIndex > i_endIndex)
993                 || i_startIndex < 0 || i_startIndex > GetStringLength()
994                 || i_endIndex > GetStringLength())
995                 {
996                     throw new COMException(
997                         "インデックスが無効です。",
998                         UnmanagedAPI.WinError.HRESULT.E_INVALIDARG
999                     );
1000                 }
1001
1002                 var textLength = 0;
1003                 var copyLength = 0;
1004
1005                 if (i_endIndex == -1)
1006                     textLength = GetStringLength() - i_startIndex;
1007                 else
1008                     textLength = i_endIndex - i_startIndex;
1009                 copyLength = Math.Min(i_plainTextLength, textLength);
1010
1011                 // 文字列を格納。
1012                 var text = GetString(i_startIndex, copyLength);
1013 #if TSF_DEBUG_OUTPUT
1014                 DebugOut.Print("got text:{0} from {1} length {2}", text,i_startIndex,copyLength);
1015 #endif
1016                 for (int i = 0; i < copyLength; i++)
1017                 {
1018                     o_plainText[i] = text[i];
1019                 }
1020
1021                 // 文字数を格納。
1022                 o_plainTextLength = copyLength;
1023                 // RUNINFO を格納。
1024                 if (i_runInfoLength > 0)
1025                 {
1026                     o_runInfos[0].type = TsRunType.TS_RT_PLAIN;
1027                     o_runInfos[0].length = copyLength;
1028                 }
1029                 o_runInfoLength = 1;
1030
1031                 // 次の文字の位置を格納。
1032                 o_nextUnreadCharPos = i_startIndex + copyLength;
1033             }
1034         }
1035
1036         public void SetText(
1037             SetTextFlags i_flags,
1038             int i_startIndex,
1039             int i_endIndex,
1040             char[] i_text,
1041             int i_length,
1042             out TS_TEXTCHANGE o_textChange
1043         )
1044         {
1045 #if TSF_DEBUG_OUTPUT
1046             using(var dbgout = new DebugOut("{0}({1}, {2})",
1047                                             DebugOut.GetCaller(),
1048                                             i_startIndex, i_endIndex) )
1049 #endif
1050             {
1051                 var selections = new TS_SELECTION_ACP[]
1052                 {
1053                     new TS_SELECTION_ACP
1054                     {
1055                         start = i_startIndex,
1056                         end   = i_endIndex,
1057                         style = new TS_SELECTIONSTYLE
1058                         {
1059                             ase = TsActiveSelEnd.TS_AE_END,
1060                             interimChar = false
1061                         }
1062                     }
1063                 };
1064
1065                 int startIndex = 0, endIndex = 0;
1066                 SetSelection(1, selections);
1067                 InsertTextAtSelection(
1068                     InsertAtSelectionFlags.TF_IAS_NOQUERY,
1069                     i_text,
1070                     i_length,
1071                     out startIndex,
1072                     out endIndex,
1073                     out o_textChange
1074                 );
1075             }
1076         }
1077
1078         public void GetFormattedText(int i_start, int i_end, out object o_obj)
1079         {
1080 #if TSF_DEBUG_OUTPUT
1081             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1082 #endif
1083             {
1084                 throw new NotImplementedException();
1085             }
1086         }
1087
1088         public void GetEmbedded(
1089             int i_position,
1090             ref Guid i_guidService,
1091             ref Guid i_riid,
1092             out object o_obj
1093         )
1094         {
1095 #if TSF_DEBUG_OUTPUT
1096             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1097 #endif
1098             {
1099                 throw new NotImplementedException();
1100             }
1101         }
1102
1103         public void QueryInsertEmbedded(
1104             ref Guid i_guidService,
1105             int i_formatEtc,
1106             out bool o_insertable
1107         )
1108         {
1109 #if TSF_DEBUG_OUTPUT
1110             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1111 #endif
1112             {
1113                 throw new NotImplementedException();
1114             }
1115         }
1116
1117         public void InsertEmbedded(
1118             InsertEmbeddedFlags i_flags,
1119             int i_start,
1120             int i_end,
1121             object i_obj,
1122             out TS_TEXTCHANGE o_textChange
1123         )
1124         {
1125 #if TSF_DEBUG_OUTPUT
1126             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1127 #endif
1128             {
1129                 throw new NotImplementedException();
1130             }
1131         }
1132
1133         public void InsertTextAtSelection(
1134             InsertAtSelectionFlags i_flags,
1135             char[] i_text,
1136             int i_length,
1137             out int o_startIndex,
1138             out int o_endIndex,
1139             out TS_TEXTCHANGE o_textChange
1140         )
1141         {
1142 #if TSF_DEBUG_OUTPUT
1143             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1144 #endif
1145             {
1146                 if (GetSelectionIndex == null || InsertAtSelection == null)
1147                     throw new NotImplementedException();
1148
1149                 int sel_count = 1;
1150                 if(this.GetSelectionCount != null)
1151                     sel_count = this.GetSelectionCount();
1152
1153                 if (sel_count == 0)
1154                     throw new InvalidOperationException("sel_countは1以上の値でなければなりません");
1155
1156                 //エラーになるので適当な値で埋めておく
1157                 o_startIndex = 0;
1158                 o_endIndex = 0;
1159                 o_textChange.start = 0;
1160                 o_textChange.oldEnd = 0;
1161                 o_textChange.newEnd = 0;
1162
1163                 TextSelection[] sels;
1164                 GetSelectionIndex(0, sel_count, out sels);
1165
1166                 for(int i = 0; i < sel_count; i++)
1167                 {
1168                     // 問い合わせのみで実際には操作を行わない
1169                     if ((i_flags & InsertAtSelectionFlags.TF_IAS_QUERYONLY) != 0)
1170                     {
1171                         o_startIndex = Math.Min(sels[i].start, sels[i].end);
1172                         o_endIndex = Math.Max(sels[i].start, sels[i].end);//o_startIndex + i_length;
1173
1174                         o_textChange.start = o_startIndex;
1175                         o_textChange.oldEnd = o_endIndex;
1176                         o_textChange.newEnd = o_startIndex + i_length;
1177                     }
1178                     else
1179                     {
1180                         var start = Math.Min(sels[i].start, sels[i].end);
1181                         var end = Math.Max(sels[i].start, sels[i].end);
1182
1183 #if TSF_DEBUG_OUTPUT
1184                     DebugOut.Print("start: {0}, end: {1}, text: {2}", start, end, new string(i_text));
1185 #endif
1186
1187                         o_startIndex = start;
1188                         o_endIndex = start + i_length;
1189
1190                         InsertAtSelection(new string(i_text), ref o_startIndex, ref o_endIndex);
1191
1192                         o_textChange.start = start;
1193                         o_textChange.oldEnd = end;
1194                         o_textChange.newEnd = o_endIndex;
1195                         // InsertAtSelection() 内でカーソル位置を更新しているため、ここでは不要。
1196                         // 改行した時に位置が狂う。
1197                         // SetSelectionIndex(start, start + i_length);
1198                     }
1199                 }
1200             }
1201         }
1202
1203         public void GetEndACP(out int o_length)
1204         {
1205 #if TSF_DEBUG_OUTPUT
1206             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1207 #endif
1208             {
1209                 if (GetStringLength == null)
1210                     throw new NotImplementedException();
1211
1212                 if (IsLocked(LockFlags.TS_LF_READ) == false)
1213                 {
1214                     throw new COMException(
1215                         "読取用ロックがされていません。",
1216                         TsResult.TS_E_NOLOCK
1217                     );
1218                 }
1219
1220                 o_length = GetStringLength();
1221             }
1222         }
1223
1224         public void GetActiveView(out int o_viewCookie)
1225         {
1226 #if TSF_DEBUG_OUTPUT
1227             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1228 #endif
1229             {
1230                 o_viewCookie = 1;
1231             }
1232         }
1233
1234         public void GetACPFromPoint(
1235             int i_viewCookie,
1236             ref POINT i_point,
1237             GetPositionFromPointFlags i_flags,
1238             out int o_index
1239         )
1240         {
1241 #if TSF_DEBUG_OUTPUT
1242             using (var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()))
1243 #endif
1244             {
1245                 throw new NotImplementedException();
1246             }
1247         }
1248
1249         public void GetTextExt(
1250             int i_viewCookie,
1251             int i_startIndex,
1252             int i_endIndex,
1253             out RECT o_rect,
1254             out bool o_isClipped
1255         )
1256         {
1257 #if TSF_DEBUG_OUTPUT
1258             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1259 #endif
1260             {
1261                 if (GetStringLength == null)
1262                     throw new NotImplementedException();
1263
1264                 // 読取用ロックの確認。
1265                 if (IsLocked(LockFlags.TS_LF_READ) == false)
1266                 {
1267                     throw new COMException(
1268                         "読取用ロックがされていません。",
1269                         TsResult.TS_E_NOLOCK
1270                     );
1271                 }
1272
1273                 if ((i_endIndex != -1 && i_startIndex > i_endIndex)
1274                 || i_startIndex < 0 || i_startIndex > GetStringLength()
1275                 || i_endIndex > GetStringLength())
1276                 {
1277                     throw new COMException(
1278                         "インデックスが無効です。",
1279                         UnmanagedAPI.WinError.HRESULT.E_INVALIDARG
1280                     );
1281                 }
1282
1283                 if (i_endIndex == -1)
1284                     i_endIndex = GetStringLength();
1285
1286                 var pointTopLeft = new POINT();
1287                 var pointBotttomRight = new POINT();
1288                 GetStringExtent(i_startIndex, i_endIndex, out pointTopLeft, out pointBotttomRight);
1289
1290                 o_rect.left = (int)(pointTopLeft.x);
1291                 o_rect.top = (int)(pointTopLeft.y);
1292                 o_rect.bottom = (int)(pointBotttomRight.y);
1293                 o_rect.right = (int)(pointBotttomRight.x);
1294                 o_isClipped = false;
1295 #if TSF_DEBUG_OUTPUT
1296                 DebugOut.Print("rect left:{0} top:{1} bottom:{2} right:{3}", o_rect.left, o_rect.top, o_rect.bottom, o_rect.right);
1297 #endif
1298             }
1299         }
1300
1301         public void GetScreenExt(int i_viewCookie, out RECT o_rect)
1302         {
1303 #if TSF_DEBUG_OUTPUT
1304             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1305 #endif
1306             {
1307                 if (GetScreenExtent == null)
1308                     throw new NotImplementedException();
1309
1310                 POINT pointTopLeft, pointBottomRight;
1311
1312                 GetScreenExtent(out pointTopLeft, out pointBottomRight);
1313
1314                 o_rect.left = (int)(pointTopLeft.x);
1315                 o_rect.top = (int)(pointTopLeft.y);
1316                 o_rect.bottom = (int)(pointBottomRight.y);
1317                 o_rect.right = (int)(pointBottomRight.x);
1318 #if TSF_DEBUG_OUTPUT
1319                 DebugOut.Print("rect left:{0} top:{1} bottom:{2} right:{3}", o_rect.left, o_rect.top, o_rect.bottom, o_rect.right);
1320 #endif
1321             }
1322         }
1323
1324         public void RequestSupportedAttrs(
1325             AttributeFlags i_flags,
1326             int i_length,
1327             Guid[] i_filterAttributes
1328         )
1329         {
1330 #if TSF_DEBUG_OUTPUT
1331             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1332 #endif
1333             {
1334                 for (int i = 0; i < i_length; i++)
1335                 {
1336                     if (i_filterAttributes[i].Equals(_attributeInfo[0].attrID))
1337                     {
1338                         _attributeInfo[0].flags = AttributeInfoFlags.Requested;
1339                         if ((i_flags & AttributeFlags.TS_ATTR_FIND_WANT_VALUE) != 0)
1340                         {
1341                             _attributeInfo[0].flags |= AttributeInfoFlags.Default;
1342                         }
1343                         else
1344                         {
1345                             _attributeInfo[0].currentValue = _attributeInfo[0].defaultValue;
1346                         }
1347                     }
1348                 }
1349             }
1350         }
1351
1352         public void RequestAttrsAtPosition(
1353             int i_position,
1354             int i_length,
1355             Guid[] i_filterAttributes,
1356             AttributeFlags i_flags
1357         )
1358         {
1359 #if TSF_DEBUG_OUTPUT
1360             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1361 #endif
1362             {
1363                 for (int i = 0; i < i_length; i++)
1364                 {
1365                     if (i_filterAttributes[i].Equals(_attributeInfo[0].attrID))
1366                     {
1367                         _attributeInfo[0].flags = AttributeInfoFlags.Requested;
1368                         if ((i_flags & AttributeFlags.TS_ATTR_FIND_WANT_VALUE) != 0)
1369                         {
1370                             _attributeInfo[0].flags |= AttributeInfoFlags.Default;
1371                         }
1372                         else
1373                         {
1374                             _attributeInfo[0].currentValue = _attributeInfo[0].defaultValue;
1375                         }
1376                     }
1377                 }
1378             }
1379         }
1380
1381         public void RequestAttrsTransitioningAtPosition(
1382             int i_position,
1383             int i_length,
1384             Guid[] i_filterAttributes,
1385             AttributeFlags i_flags
1386         )
1387         {
1388 #if TSF_DEBUG_OUTPUT
1389             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()))
1390 #endif
1391             {
1392                 // 何もしない。
1393             }
1394         }
1395
1396         public void FindNextAttrTransition(
1397             int i_start,
1398             int i_halt,
1399             int i_length,
1400             Guid[] i_filterAttributes,
1401             AttributeFlags i_flags,
1402             out int o_nextIndex,
1403             out bool o_found,
1404             out int o_foundOffset
1405         )
1406         {
1407 #if TSF_DEBUG_OUTPUT
1408             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1409 #endif
1410             {
1411                 throw new NotImplementedException();
1412             }
1413         }
1414
1415         public void RetrieveRequestedAttrs(
1416             int i_length,
1417             TS_ATTRVAL[] o_attributeVals,
1418             out int o_fetchedLength
1419         )
1420         {
1421 #if TSF_DEBUG_OUTPUT
1422             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1423 #endif
1424             {
1425                 o_fetchedLength = 0;
1426                 for (int i = 0; i < _attributeInfo.Length && o_fetchedLength < i_length; i++)
1427                 {
1428                     if ((_attributeInfo[i].flags & AttributeInfoFlags.Requested) != 0)
1429                     {
1430                         o_attributeVals[o_fetchedLength].overlappedId = 0;
1431                         o_attributeVals[o_fetchedLength].attributeId = _attributeInfo[i].attrID;
1432                         o_attributeVals[o_fetchedLength].val = _attributeInfo[i].currentValue;
1433
1434                         if ((_attributeInfo[i].flags & AttributeInfoFlags.Default) != 0)
1435                             _attributeInfo[i].currentValue = _attributeInfo[i].defaultValue;
1436
1437                         o_fetchedLength++;
1438                         _attributeInfo[i].flags = AttributeInfoFlags.None;
1439                     }
1440                 }
1441             }
1442         }
1443         #endregion
1444
1445         #region "ITfContextOwnerCompositionSink インターフェイスの実装"
1446         /// <summary>コンポジション入力が開始された時の処理。</summary>
1447         public void OnStartComposition(ITfCompositionView view, out bool ok)
1448         {
1449             #if TSF_DEBUG_OUTPUT
1450             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1451             #endif
1452             {
1453                 if( CompositionStarted != null )
1454                     ok = CompositionStarted();
1455                 else
1456                     ok = true;
1457             }
1458         }
1459
1460
1461         //========================================================================================
1462
1463
1464         /// <summary>コンポジションが変更された時の処理。</summary>
1465         public void OnUpdateComposition(ITfCompositionView view, ITfRange rangeNew)
1466         {
1467             #if TSF_DEBUG_OUTPUT
1468             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1469             #endif
1470             {
1471                 if (rangeNew == null)
1472                     return;
1473
1474                 int start, count;
1475                 
1476                 ITfRangeACP rangeAcp = (ITfRangeACP)rangeNew;
1477                 
1478                 rangeAcp.GetExtent(out start, out count);
1479                 
1480                 if (this.CompositionUpdated != null)
1481                     this.CompositionUpdated(start, start + count);
1482             }
1483         }
1484
1485         
1486         //========================================================================================
1487
1488
1489         /// <summary>コンポジション入力が終了した時の処理。</summary>
1490         public void OnEndComposition(ITfCompositionView view)
1491         {
1492             #if TSF_DEBUG_OUTPUT
1493             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()) )
1494             #endif
1495             {
1496                 if( CompositionEnded != null )
1497                     CompositionEnded();
1498             }
1499         }
1500         #endregion "ITfContextOwnerCompositionSink インターフェイスの実装"
1501
1502         #region 表示属性
1503         /// <summary>表示属性の取得</summary>
1504         public IEnumerable<TextDisplayAttribute> EnumAttributes(int start, int end)
1505         {
1506             ITfRangeACP allRange;
1507             _services.CreateRange(start, end, out allRange);
1508
1509             foreach (TextDisplayAttribute attr in this.EnumAttributes((ITfRange)allRange))
1510                 yield return attr;
1511
1512             ReleaseComObject("allRange", ref allRange);
1513         }
1514
1515         IEnumerable<TextDisplayAttribute> EnumAttributes(ITfRange range)
1516         {
1517 #if TSF_DEBUG_OUTPUT
1518             using(var dbgout = new DebugOut("{0}()", DebugOut.GetCaller()))
1519 #endif
1520             {
1521                 ITfProperty property = null;    // プロパティインターフェイス
1522                 IEnumTfRanges enumRanges;         // 範囲の列挙子
1523                 Guid guidPropAttribute = TfDeclarations.GUID_PROP_ATTRIBUTE;
1524
1525                 if (_context == null || _services == null)
1526                     yield break;
1527
1528                 // GUID_PROP_ATTRIBUTE プロパティを取得。
1529                 _context.GetProperty(ref guidPropAttribute, out property);
1530                 if (property == null)
1531                     yield break;
1532
1533                 // 全範囲の中で表示属性プロパティをもつ範囲を列挙する。
1534                 property.EnumRanges((int)_editCookie, out enumRanges, range);
1535
1536                 ITfRange[] ranges = new ITfRange[1];
1537                 int fetchedLength = 0;
1538                 while (HRESULT.Succeeded(enumRanges.Next(1, ranges, out fetchedLength))
1539                     && fetchedLength > 0)
1540                 {
1541                     // ItfRange から ItfRangeACP を取得。
1542                     ITfRangeACP rangeACP = ranges[0] as ITfRangeACP;
1543                     if (rangeACP == null)
1544                         continue;   // 普通はあり得ない
1545
1546                     // 範囲の開始位置と文字数を取得。
1547                     int start, count;
1548                     rangeACP.GetExtent(out start, out count);
1549
1550                     // VARIANT 値としてプロパティ値を取得。VT_I4 の GUID ATOM がとれる。
1551                     VARIANT value = new VARIANT();
1552                     property.GetValue((int)_editCookie, ranges[0], ref value);
1553                     if (value.vt == (short)VarEnum.VT_I4)
1554                     {
1555                         Guid guid, clsid;
1556                         ITfDisplayAttributeInfo info;
1557                         TF_DISPLAYATTRIBUTE attribute;
1558
1559                         // GUID ATOM から GUID を取得する。
1560                         _categoryMgr.GetGUID((int)value.data1, out guid);
1561                         // その GUID から IDisplayAttributeInfo インターフェイスを取得。
1562                         _displayAttributeMgr.GetDisplayAttributeInfo(
1563                             ref guid,
1564                             out info,
1565                             out clsid
1566                         );
1567                         // さらに IDisplayAttributeInfo インターフェイスから表示属性を取得する。
1568                         info.GetAttributeInfo(out attribute);
1569                         ReleaseComObject("info", ref info);
1570
1571                         yield return new TextDisplayAttribute
1572                         {
1573                             startIndex = start,
1574                             endIndex = start + count,
1575                             attribute = attribute
1576                         };
1577
1578 #if TSF_DEBUG_OUTPUT_DISPLAY_ATTR
1579                             Debug.WriteLine(
1580                                 "*******:::: DisplayAttribute: {0} ~ {1} :::::: *********",
1581                                 start, start + count
1582                             );
1583                             Debug.WriteLine(attribute.bAttr);
1584                             Debug.WriteLine(
1585                                 "LineColorType: {0}, {1}",
1586                                 attribute.crLine.type, attribute.crLine.indexOrColorRef
1587                             );
1588                             Debug.WriteLine(
1589                                 "TextColorType: {0}, {1}",
1590                                 attribute.crText.type, attribute.crText.indexOrColorRef
1591                             );
1592                             Debug.WriteLine(
1593                                 "BackColorType: {0}, {1}",
1594                                 attribute.crBk.type, attribute.crBk.indexOrColorRef
1595                             );
1596                             Debug.WriteLine(
1597                                 "Bold, Style  : {0}, {1}",
1598                                 attribute.fBoldLine, attribute.lsStyle
1599                             );
1600 #endif
1601                     }
1602
1603                     ReleaseComObject("rangeACP", ref rangeACP);
1604                 }
1605
1606                 ReleaseComObject("ranges[0]", ref ranges[0]);
1607                 ReleaseComObject("enumRanges", ref enumRanges);
1608                 ReleaseComObject("property", ref property);
1609             }
1610         }
1611         #endregion
1612
1613 #if METRO
1614         protected ITfThreadMgr2 _threadMgr;
1615 #else
1616         protected ITfThreadMgr _threadMgr;
1617 #endif
1618         protected ITfDocumentMgr _documentMgr;
1619         protected ITfFunctionProvider _functionProvider;
1620         protected ITfFnReconversion _reconversion;
1621         protected ITfContext _context;
1622         protected ITfCategoryMgr _categoryMgr;
1623         protected ITfDisplayAttributeMgr _displayAttributeMgr;
1624         protected ITextStoreACPSink _sink;
1625         protected uint _editCookie = 0;
1626         protected ITextStoreACPServices _services;
1627         protected AdviseFlags               _adviseFlags = 0;
1628         protected LockFlags                 _lockFlags = 0;
1629         protected bool                      _pendingLockUpgrade = false;
1630
1631         /// <summary>
1632         /// AttributeInfo で使用されるフラグ。各属性の状態を示す。
1633         /// </summary>
1634         protected enum AttributeInfoFlags
1635         {
1636             /// <summary>何もない。</summary>
1637             None        = 0,
1638             /// <summary>デフォルト値の要求。</summary>
1639             Default     = 1 << 0,
1640             /// <summary>要求された。</summary>
1641             Requested   = 1 << 1
1642         }
1643
1644         protected struct AttributeInfo
1645         {
1646             public Guid                 attrID;
1647             public AttributeInfoFlags   flags;
1648             public VARIANT              currentValue;
1649             public VARIANT              defaultValue;
1650         }
1651
1652         protected AttributeInfo[]       _attributeInfo = new AttributeInfo[1];
1653
1654     }
1655 }