11using System ;
2+ using System . Collections ;
23using System . Collections . Generic ;
34using System . Linq ;
45using System . Management . Automation . Language ;
@@ -53,9 +54,8 @@ public EditableText ApplyEdit1(TextEdit textEdit)
5354 {
5455 ValidateTextEdit ( textEdit ) ;
5556
56- // Break up the change lines
57- var changeLines = textEdit . Lines ;
58- var Lines = new List < String > ( this . Lines ) ;
57+ var editLines = textEdit . Lines ;
58+ var Lines = new TextLines ( this . Lines ) ;
5959
6060 // Get the first fragment of the first line
6161 string firstLineFragment =
@@ -77,19 +77,19 @@ public EditableText ApplyEdit1(TextEdit textEdit)
7777
7878 // Build and insert the new lines
7979 int currentLineNumber = textEdit . StartLineNumber ;
80- for ( int changeIndex = 0 ; changeIndex < changeLines . Length ; changeIndex ++ )
80+ for ( int changeIndex = 0 ; changeIndex < editLines . Length ; changeIndex ++ )
8181 {
8282 // Since we split the lines above using \n, make sure to
8383 // trim the ending \r's off as well.
84- string finalLine = changeLines [ changeIndex ] . TrimEnd ( '\r ' ) ;
84+ string finalLine = editLines [ changeIndex ] . TrimEnd ( '\r ' ) ;
8585
8686 // Should we add first or last line fragments?
8787 if ( changeIndex == 0 )
8888 {
8989 // Append the first line fragment
9090 finalLine = firstLineFragment + finalLine ;
9191 }
92- if ( changeIndex == changeLines . Length - 1 )
92+ if ( changeIndex == editLines . Length - 1 )
9393 {
9494 // Append the last line fragment
9595 finalLine = finalLine + lastLineFragment ;
@@ -182,5 +182,171 @@ private int GetNumNewLineCharacters()
182182
183183 return numCharDiff / ( Lines . Length - 1 ) ;
184184 }
185+
186+ private class TextLines : IList < String >
187+ {
188+ private LinkedList < String > lines ;
189+
190+ private void ValidateIndex ( int index )
191+ {
192+ if ( index >= Count || index < 0 )
193+ {
194+ throw new ArgumentOutOfRangeException ( nameof ( index ) ) ;
195+ }
196+ }
197+
198+ private LinkedListNode < String > GetNodeAt ( int index )
199+ {
200+ var node = lines . First ;
201+ int count = 0 ;
202+ while ( node != null )
203+ {
204+ if ( count ++ == index )
205+ {
206+ return node ;
207+ }
208+
209+ node = node . Next ;
210+ }
211+
212+ throw new InvalidOperationException ( ) ;
213+ }
214+
215+ public string this [ int index ]
216+ {
217+ get
218+ {
219+ ValidateIndex ( index ) ;
220+ return GetNodeAt ( index ) . Value ;
221+ }
222+ set
223+ {
224+ ValidateIndex ( index ) ;
225+ Insert ( index , value ) ;
226+ RemoveAt ( index ) ;
227+ }
228+ }
229+
230+ public int Count { get ; private set ; }
231+
232+ public bool IsReadOnly => false ;
233+
234+ public TextLines ( )
235+ {
236+ lines = new LinkedList < String > ( ) ;
237+ Count = 0 ;
238+ }
239+
240+ public TextLines ( IEnumerable < String > inputLines )
241+ {
242+ if ( inputLines == null )
243+ {
244+ throw new ArgumentNullException ( nameof ( inputLines ) ) ;
245+ }
246+
247+ if ( inputLines . Any ( line => line == null ) )
248+ {
249+ // todo localize
250+ throw new ArgumentException ( "Line element cannot be null." ) ;
251+ }
252+
253+ lines = new LinkedList < String > ( inputLines ) ;
254+ Count = lines . Count ;
255+ }
256+
257+ public void Add ( string item )
258+ {
259+ if ( item == null )
260+ {
261+ throw new ArgumentNullException ( nameof ( item ) ) ;
262+ }
263+
264+ Insert ( Count - 1 , item ) ;
265+ }
266+
267+ public void Clear ( )
268+ {
269+ lines . Clear ( ) ;
270+ }
271+
272+ public bool Contains ( string item )
273+ {
274+ return lines . Contains ( item ) ;
275+ }
276+
277+ public void CopyTo ( string [ ] array , int arrayIndex )
278+ {
279+ lines . CopyTo ( array , arrayIndex ) ;
280+ }
281+
282+ public IEnumerator < string > GetEnumerator ( )
283+ {
284+ return lines . GetEnumerator ( ) ;
285+ }
286+
287+ public int IndexOf ( string item )
288+ {
289+ var llNode = lines . First ;
290+ int count = 0 ;
291+ while ( llNode != null )
292+ {
293+ if ( llNode . Value . Equals ( item ) )
294+ {
295+ return count ;
296+ }
297+
298+ llNode = llNode . Next ;
299+ count ++ ;
300+ }
301+
302+ return - 1 ;
303+ }
304+
305+ public void Insert ( int index , string item )
306+ {
307+ ValidateIndex ( index ) ;
308+ if ( index == 0 )
309+ {
310+ lines . AddFirst ( item ) ;
311+ }
312+ else if ( index == Count - 1 )
313+ {
314+ lines . AddBefore ( lines . Last , item ) ;
315+ }
316+ else
317+ {
318+ lines . AddBefore ( GetNodeAt ( index ) , item ) ;
319+ }
320+
321+ Count ++ ;
322+ }
323+
324+ public bool Remove ( string item )
325+ {
326+ if ( lines . Remove ( item ) )
327+ {
328+ Count -- ;
329+ return true ;
330+ }
331+
332+ return false ;
333+ }
334+
335+ public void RemoveAt ( int index )
336+ {
337+ lines . Remove ( GetNodeAt ( index ) ) ;
338+ Count -- ;
339+ }
340+
341+ IEnumerator IEnumerable . GetEnumerator ( )
342+ {
343+ return lines . GetEnumerator ( ) ;
344+ }
345+
346+ public override string ToString ( )
347+ {
348+ return String . Join ( Environment . NewLine , lines ) ;
349+ }
350+ }
185351 }
186352}
0 commit comments