@@ -125,54 +125,64 @@ private void AIGeneratedNBPMLError_SystemColorsChanged(object sender, EventArgs
125125 /// character will be highlighted.</param>
126126 private void WriteToRichTextBoxAndHighlightError ( string brokenXML )
127127 {
128- // Collect parts of the XML with error info
129128 List < ( string text , bool isError ) > parts = new ( ) ;
130129 string xml = brokenXML ;
131130
132131 try
133132 {
134- // Try to parse the entire XML
135133 var doc = new XmlDocument ( ) ;
136134 doc . LoadXml ( xml ) ;
137- // If successful, add the entire string as normal
138135 parts . Add ( ( xml , false ) ) ;
139136 }
140137 catch ( XmlException ex )
141138 {
142- // Find error position
143139 int line = ex . LineNumber ;
144140 int pos = ex . LinePosition ;
145141
146- // Find character index in the string
147142 int charIndex = 0 ;
148143 string [ ] lines = xml . Split ( '\n ' ) ;
149144 for ( int i = 0 ; i < line - 1 && i < lines . Length ; i ++ )
150145 charIndex += lines [ i ] . Length + 1 ;
151146 charIndex += pos - 1 ;
152147
153- // Find the start of the tag (last '<' before error)
154- int tagStart = xml . LastIndexOf ( '<' , charIndex ) ;
155- if ( tagStart == - 1 ) tagStart = 0 ;
148+ // Boundary checks
149+ if ( charIndex < 0 ) charIndex = 0 ;
150+ if ( charIndex > xml . Length ) charIndex = xml . Length ;
156151
157- // Find the end of the tag (next '>' after error)
158- int tagEnd = xml . IndexOf ( '>' , charIndex ) ;
159- if ( tagEnd == - 1 ) tagEnd = xml . Length ;
160- else tagEnd += 1 ; // Include the '>'
152+ int tagStart = xml . LastIndexOf ( '<' , Math . Min ( charIndex , xml . Length - 1 ) ) ;
153+ if ( tagStart < 0 || tagStart > xml . Length - 1 ) tagStart = 0 ;
161154
162- // Separate the string into parts: before tag (normal), tag (highlighted), after tag (normal)
163- string before = xml . Substring ( 0 , tagStart ) ;
164- string errorTag = xml . Substring ( tagStart , tagEnd - tagStart ) ;
155+ int tagEnd = xml . IndexOf ( '>' , charIndex ) ;
156+ if ( tagEnd < 0 || tagEnd > xml . Length ) tagEnd = xml . Length ;
157+ else tagEnd += 1 ;
158+ if ( tagEnd < tagStart ) tagEnd = xml . Length ;
159+
160+ // Last sanity checks
161+ if ( tagStart < 0 ) tagStart = 0 ;
162+ if ( tagStart > xml . Length ) tagStart = xml . Length ;
163+ if ( tagEnd < tagStart ) tagEnd = tagStart ;
164+ if ( tagEnd > xml . Length ) tagEnd = xml . Length ;
165+
166+ string before = tagStart > 0 ? xml . Substring ( 0 , tagStart ) : "" ;
167+ string errorTag = ( tagEnd > tagStart && tagStart < xml . Length ) ? xml . Substring ( tagStart , tagEnd - tagStart ) : "" ;
165168 string after = ( tagEnd < xml . Length ) ? xml . Substring ( tagEnd ) : "" ;
166169
167- if ( ! string . IsNullOrEmpty ( before ) )
168- parts . Add ( ( before , false ) ) ;
169- if ( ! string . IsNullOrEmpty ( errorTag ) )
170- parts . Add ( ( errorTag , true ) ) ;
171- if ( ! string . IsNullOrEmpty ( after ) )
172- parts . Add ( ( after , false ) ) ;
170+ // If no valid tag found, treat entire NBPML (XML) as error
171+ if ( string . IsNullOrEmpty ( errorTag ) )
172+ {
173+ parts . Add ( ( xml , true ) ) ;
174+ }
175+ else
176+ {
177+ if ( ! string . IsNullOrEmpty ( before ) )
178+ parts . Add ( ( before , false ) ) ;
179+ if ( ! string . IsNullOrEmpty ( errorTag ) )
180+ parts . Add ( ( errorTag , true ) ) ;
181+ if ( ! string . IsNullOrEmpty ( after ) )
182+ parts . Add ( ( after , false ) ) ;
183+ }
173184 }
174185
175- // Create RTF content with highlights and proper newline handling
176186 string EscapeRtf ( string s ) => s . Replace ( @"\" , @"\\" ) . Replace ( "{" , @"\{" ) . Replace ( "}" , @"\}" ) . Replace ( "\n " , "\\ line " ) ;
177187 var rtf = @"{\rtf1\ansi{\colortbl ;\red255\green255\blue255;\red255\green0\blue0;}" ;
178188 foreach ( var part in parts )
0 commit comments