@@ -71,15 +71,15 @@ internal bool FindAndReplace(long startPos)
7171 // track the caret position resulting from the FIRST '\i' replacement
7272 long firstIndentCaret = - 1 ;
7373
74- Dictionary < string , Action > replacements = new ( )
74+ Dictionary < string , Func < int > > replacements = new ( )
7575 {
7676 { "\\ f" , PasteFileContents } ,
77- { "\\ c" , sci . Paste } ,
77+ { "\\ c" , PasteClipboard } ,
7878 { "\\ u" , PasteUserName } ,
7979 { "\\ x" , PasteFileName } ,
8080 { "\\ p" , PasteFilePath } ,
8181 { "\\ d" , PasteDateTime } ,
82- { "\\ i" , sci . Tab } // must come last as the caret will be restored here!
82+ { "\\ i" , PasteTab } // must come last as the caret will be restored here!
8383 } ;
8484
8585 foreach ( ( string seq , var replaceFunc ) in replacements )
@@ -91,6 +91,7 @@ internal bool FindAndReplace(long startPos)
9191
9292 while ( seqStart > - 1 )
9393 {
94+ var newSeqLength = - 1 ; // seq.Length
9495 var tmpTargetText = sci . GetTargetText ( ) . Substring ( 0 , seqStart ) ;
9596 int tmpByteDiff = sci . CodePage . GetByteCount ( tmpTargetText ) - tmpTargetText . Length ;
9697 if ( tmpByteDiff > 0 )
@@ -99,7 +100,7 @@ internal bool FindAndReplace(long startPos)
99100 sci . SetSelection ( selStart , selStart + seq . Length ) ; // sci.CodePage.GetByteCount(seq)
100101 if ( seqStart == 0 || sci . GetCharAt ( selStart - 1 ) != 92 ) // Backspace (\)
101102 {
102- replaceFunc ( ) ;
103+ newSeqLength = replaceFunc ( ) ;
103104 }
104105 else
105106 {
@@ -108,11 +109,7 @@ internal bool FindAndReplace(long startPos)
108109 rangeEnd -- ;
109110 }
110111 sci . SetCurrentPos ( sci . GetSelectionEnd ( ) ) ;
111- rangeEnd += ( sci . GetSelectionEnd ( ) - selStart ) - seq . Length ; // sci.CodePage.GetByteCount(seq)
112-
113- // Capture the first date only!
114- if ( seq == "\\ d" )
115- break ; // TODO: replacing the first occurrence (Unicode issue?) -- rangeEnd may be wrong as using `seq.Length`!
112+ rangeEnd += ( sci . GetSelectionEnd ( ) - selStart ) - ( newSeqLength > - 1 ? newSeqLength : seq . Length ) ; // sci.CodePage.GetByteCount(seq)
116113
117114 // capture the caret position produced by the first '\i' replacement
118115 if ( seq == "\\ i" && firstIndentCaret == - 1 )
@@ -142,13 +139,13 @@ internal bool FindAndReplace(long startPos)
142139 /// <remarks>
143140 /// Adapted from <see href="https://github.com/alex-ilin/WebEdit/blob/7bb4243/Legacy-v2.1/Src/Tags.ob2#L223"/>
144141 /// </remarks>
145- private void PasteFileContents ( )
142+ private int PasteFileContents ( )
146143 {
147144 ScintillaGateway sci = new ( Utils . GetCurrentScintilla ( ) ) ;
148145 long tagStart = sci . GetSelectionEnd ( ) ;
149146
150147 if ( '[' != sci . GetCharAt ( tagStart ) )
151- return ;
148+ return - 1 ;
152149
153150 long selectionEnd = tagStart ;
154151 while ( ']' != sci . GetCharAt ( selectionEnd ) && selectionEnd ++ < sci . GetLineEndPosition ( tagStart ) ) ;
@@ -164,7 +161,7 @@ private void PasteFileContents()
164161 if ( ! File . Exists ( filePath ) ||
165162 /* do not paste the contents of our own INI file */
166163 ( string . IsNullOrEmpty ( section ) && string . Compare ( filePath , Main . iniFilePath , StringComparison . InvariantCultureIgnoreCase ) == 0 ) )
167- return ;
164+ return - 1 ;
168165
169166 StringBuilder buffer = new ( ) ;
170167 if ( ! string . IsNullOrEmpty ( section ) )
@@ -180,11 +177,25 @@ private void PasteFileContents()
180177 }
181178
182179 string replacementText = buffer . ToString ( ) . TrimEnd ( ) ;
180+ var newSeqLength = - 1 ;
183181 if ( ! string . IsNullOrWhiteSpace ( replacementText ) )
184- {
182+ {
185183 sci . SetSelection ( sci . GetSelectionStart ( ) , selectionEnd + sci . CodePage . GetByteCount ( "]" ) ) ;
184+ newSeqLength = ( int ) ( sci . GetSelectionEnd ( ) - sci . GetSelectionStart ( ) ) ;
186185 sci . ReplaceSel ( replacementText ) ;
187186 }
187+ return newSeqLength ;
188+ }
189+
190+
191+ /// <summary>
192+ /// Paste the Windows clipboard content for the '\c' tag.
193+ /// </summary>
194+ private int PasteClipboard ( )
195+ {
196+ ScintillaGateway sci = new ( Utils . GetCurrentScintilla ( ) ) ;
197+ sci . Paste ( ) ;
198+ return - 1 ;
188199 }
189200
190201 /// <summary>
@@ -193,7 +204,7 @@ private void PasteFileContents()
193204 /// <remarks>
194205 /// For custom date/time format strings see: <see href="https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings"/>
195206 /// </remarks>
196- private void PasteDateTime ( )
207+ private int PasteDateTime ( )
197208 {
198209 ScintillaGateway sci = new ( Utils . GetCurrentScintilla ( ) ) ;
199210 long startPos = sci . GetSelectionStart ( ) ;
@@ -217,41 +228,55 @@ private void PasteDateTime()
217228 int matchStart = match . Index + offset ;
218229 int matchEnd = matchStart + match . Length ;
219230 sci . SetSelection ( sci . GetTargetStart ( ) + matchStart , sci . GetTargetStart ( ) + matchEnd ) ;
231+ int newSeqLength = ( int ) ( sci . GetSelectionEnd ( ) - sci . GetSelectionStart ( ) ) ;
220232 sci . ReplaceSel ( formattedDate ) ;
221- return ; // Hotfix: only replace the first occurrence (Unicode issue?)
233+ return newSeqLength ; // Hotfix: only replace the first occurrence (Unicode issue?)
222234 // offset += (formattedDate.Length - match.Length);
223235 }
224-
236+ return - 1 ;
225237 }
226238
227239 /// <summary>
228240 /// Paste the short Windows username for the '\u' tag.
229241 /// </summary>
230- private void PasteUserName ( )
242+ private int PasteUserName ( )
231243 {
232244 ScintillaGateway sci = new ( Utils . GetCurrentScintilla ( ) ) ;
233245 string user = Environment . UserName ?? string . Empty ;
234246 sci . ReplaceSel ( user ) ;
247+ return - 1 ;
235248 }
236249
237250 /// <summary>
238251 /// Paste the current file name for the '\x' tag e.g. 'example.txt'
239252 /// </summary>
240- private void PasteFileName ( )
253+ private int PasteFileName ( )
241254 {
242255 ScintillaGateway sci = new ( Utils . GetCurrentScintilla ( ) ) ;
243256 string fileName = Path . GetFileName ( PluginData . Notepad . GetCurrentFilePath ( ) ) ; // `PluginData.Notepad.GetCurrentFile()` or similar function (for `NppMsg.NPPM_GETFILENAME`) is not available...
244257 sci . ReplaceSel ( fileName ) ;
258+ return - 1 ;
245259 }
246260
247261 /// <summary>
248262 /// Paste the current file name for the '\p' tag e.g. 'C:\path\to\example.txt'
249263 /// </summary>
250- private void PasteFilePath ( )
264+ private int PasteFilePath ( )
251265 {
252266 ScintillaGateway sci = new ( Utils . GetCurrentScintilla ( ) ) ;
253- string fileName = PluginData . Notepad . GetCurrentFilePath ( ) ;
254- sci . ReplaceSel ( fileName ) ;
267+ string filePath = PluginData . Notepad . GetCurrentFilePath ( ) ;
268+ sci . ReplaceSel ( filePath ) ;
269+ return - 1 ;
270+ }
271+
272+ /// <summary>
273+ /// Paste tab for the '\t' tag
274+ /// </summary>
275+ private int PasteTab ( )
276+ {
277+ ScintillaGateway sci = new ( Utils . GetCurrentScintilla ( ) ) ;
278+ sci . Tab ( ) ;
279+ return - 1 ;
255280 }
256281
257282 /// <summary>
0 commit comments