0:   //  TextLine.cs
1:   //  Copyright (c) 2000 Mike Krueger
2:   //
3:   //  This program is free software; you can redistribute it and/or modify
4:   //  it under the terms of the GNU General Public License as published by
5:   //  the Free Software Foundation; either version 2 of the License, or
6:   //  (at your option) any later version.
7:   //
8:   //  This program is distributed in the hope that it will be useful,
9:   //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10:   //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11:   //  GNU General Public License for more details.
12:   //
13:   //  You should have received a copy of the GNU General Public License
14:   //  along with this program; if not, write to the Free Software
15:   //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16:  
17:   using System;
18:   using System.Drawing;
19:   using System.Text;
20:   using System.Collections;
21:  
22:   namespace SharpDevelop.Internal.Text {
23:       
24:       /// <summary>
25:       /// In this class are single lines saved, it colorizes the line.
26:       /// (It devides it up into single words, when you set the Text property)
27:       /// </summary>
28:       public class TextLine
29:       {
30:           string      line;
31:           TextWord[]  word;
32:           TextBuffer  buffer;
33:           
34:           public bool Selected  false;
35:           public bool foldon    false;
36:           public bool foldoff   false;
37:           public bool Visible   true;
38:           
39:           public TextLine(TextBuffer bufferint linenumberstring line)
40:           {
41:               this.buffer buffer;
42:               SetText(linenumber 1line);
43:           }
44:           
45:           public TextWord this[int i] {
46:               get {
47:                   return word[i];    
48:               }
49:               set {
50:                   word[i] = value;
51:               }
52:           }
53:           
54:           public TextBuffer TextBuffer {
55:               get {
56:                   return buffer;
57:               }
58:               set {
59:                   buffer value;
60:               }
61:           }
62:           
63:           public int Length {
64:               get {
65:                   return word.Length;
66:               }
67:           }
68:           
69:           public bool BlockSpanOn false;
70:           public bool Span        false;
71:           public Span CurSpan     null;
72:           
73:           
74:           SyntaxColor markNext null;
75:           ArrayList words new ArrayList();
76:           int       curoffset;
77:           int       curlength;
78:           
79:           /// <summary>
80:           /// pushes the curWord string on the word list, with the
81:           /// correct color.
82:           /// </summary>
83:           void PushCurWord()
84:           {
85:               if (curlength > 0) {
86:                   RuleSet ruleset TextBuffer.Syntax.GetRuleSet(Span CurSpan.Rule : null);
87:                   
88:                   if (words.Count > && ruleset != null) {
89:                       TextWord prevword = ((TextWord)words[words.Count 1]);
90:                       if (prevword.NotMarked) {
91:                           PrevMarker marker = (PrevMarker)ruleset.PrevMarkers[linecuroffsetcurlength];
92:                           if (marker != null) {
93:                               prevword.SyntaxColor marker.Color;
94:                           }
95:                       }
96:                   }
97:                   
98:                   if (Span) {
99:                       SyntaxColor c null;
100:                       if (CurSpan.Rule == null
101:                           c CurSpan.Color;
102:                       else
103:                           c TextBuffer.Syntax.GetColor(CurSpan.Rulelinecuroffsetcurlength);
104:                       
105:                       if (== null) {
106:                           c CurSpan.Color;
107:                           if (c.Color == Color.Transparent) {
108:                               c TextBuffer.Syntax.defaultColor;
109:                           }
110:                       }
111:                       
112:                       words.Add(new TextWord(linecuroffsetcurlengthTextBuffer.SyntaxmarkNext != null markNext : c));
113:                   else {
114:                       words.Add(new TextWord(linecuroffsetcurlengthTextBuffer.SyntaxmarkNext != null markNext : TextBuffer.Syntax.GetColor(linecuroffsetcurlength)));
115:                   }
116:                   
117:                   if (ruleset != null) {
118:                       NextMarker nextMarker = (NextMarker)ruleset.NextMarkers[linecuroffsetcurlength];
119:                       if (nextMarker != null) {
120:                           if (nextMarker.MarkMarker && words.Count > 0) {
121:                               TextWord prevword = ((TextWord)words[words.Count 1]);
122:                               prevword.SyntaxColor nextMarker.Color;
123:                           }
124:                           markNext nextMarker.Color;
125:                       else {
126:                           markNext null;
127:                       }
128:                   }
129:                   curoffset += curlength;
130:                   curlength 0;
131:                                   
132:               }
133:           }
134:           
135:           /// <summary>
136:           /// get the string, which matches the regular expression expr,
137:           /// in string s2 at index
138:           /// </summary>
139:           string GetRegString(string exprstring s2int index)
140:           {
141:               int 0;
142:               StringBuilder regexpr new StringBuilder();;
143:               
144:               for (int 0< expr.Length; ++i, ++j) {
145:                   if (index >= s2.Length
146:                       break;
147:                   
148:                   switch (expr[i]) {
149:                       case '@'// "special" meaning
150:                           ++i;
151:                           switch (expr[i]) {
152:                               case '!'// don't match the following expression
153:                                   StringBuilder whatmatch new StringBuilder();
154:                                   ++i;
155:                                   while (< expr.Length && expr[i] != '@')
156:                                       whatmatch.Append(expr[i++]);
157:                                   break;
158:                               case '@'// matches @
159:                                   regexpr.Append(s2[index j]);
160:                                   break;
161:                           }
162:                           break;
163:                       default:
164:                           if (expr[i] != s2[index j])
165:                               return regexpr.ToString();
166:                       regexpr.Append(s2[index j]);
167:                       break;
168:                   }
169:               }
170:               return regexpr.ToString();
171:           }
172:           
173:           /// <summary>
174:           /// returns true, if the get the string s2 at index matches the expression expr
175:           /// </summary>
176:           bool MatchExpr(string exprstring s2int index)
177:           {
178:               for (int 00< expr.Length; ++i, ++j) {
179:                   switch (expr[i]) {
180:                       case '@'// "special" meaning
181:                       ++i;
182:                       switch (expr[i]) {
183:                           case '!'// don't match the following expression
184:                               StringBuilder whatmatch new StringBuilder();
185:                               ++i;
186:                               while (< expr.Length && expr[i] != '@')
187:                                   whatmatch.Append(expr[i++]);
188:                               ++i;
189:                           
190:                               if (whatmatch.Length < expr.Length) {
191:                                   int 0;
192:                                   for (; < whatmatch.Length; ++k)
193:                                       if (s2[index k] != whatmatch[k])
194:                                           break;
195:                                   if (>= whatmatch.Length) {
196:                                       return false;
197:                                   }
198:                               }
199:                               break;
200:                           case '@'// matches @
201:                               if (index >= s2.Length || '@' != s2[index j]) {
202:                                   return false;
203:                               }
204:                               break;
205:                       }
206:                       
207:                       break;
208:                       default:
209:                           if (index >= s2.Length || expr[i] != s2[index j]) 
210:                               return false;
211:                       break;
212:                   }
213:               }
214:               return true;
215:           }
216:           
217:           Stack  spanstack new Stack();
218:           
219:           public string Text {
220:               get {
221:                   return line;
222:               
223:           }
224:           
225:           public void SetText(int myNumberstring text)
226:           {
227:               words.Clear();
228:               line text;
229:               
230:               ParseLine(myNumber);
231:           }
232:           
233:           void ParseLine(int myNumber)
234:           {
235:               foldoff foldon false;
236:               bool obo         BlockSpanOn;
237:               Span OldSpan     CurSpan;
238:               
239:               curoffset 0;
240:               curlength 0;
241:               
242:               if (myNumber > && TextBuffer[myNumber 1].BlockSpanOn) {
243:                   CurSpan     TextBuffer[myNumber 1].CurSpan;
244:                   BlockSpanOn Span true;
245:               else {
246:                   CurSpan     null;
247:                   BlockSpanOn Span false;
248:               }
249:               
250:               for (int 0< line.Length; ++i) {
251:                   char ch line[i];
252:                   
253:                   switch (ch) {
254:                       case '{':
255:                           foldon true;
256:                           goto default;
257:                       case '}':
258:                           if (foldon) {
259:                               foldon false;
260:                           }
261:                           foldoff true;
262:                           goto default;
263:                       case ' ':
264:                           PushCurWord();
265:                           words.Add(new TextWord(TextWordType.Space));
266:                           ++curoffset;
267:                           break;
268:                       case '\t':
269:                           PushCurWord();
270:                           words.Add(new TextWord(TextWordType.Tab));
271:                           ++curoffset;
272:                           break;
273:                       case '\\'// handle escape chars
274:                           RuleSet curruleset TextBuffer.Syntax.GetRuleSet(Span CurSpan.Rule : null);
275:                           
276:                           if (curruleset.NoEscapeSequences || (Span && CurSpan.NoEscapeSequences)) {
277:                               goto default;
278:                           }
279:                           ++curlength;
280:                           if (< line.Length) {
281:                               ++curlength;
282:                           }
283:                           PushCurWord();
284:                           ++i;
285:                           continue;
286:                       default{
287:                           // highlight digits
288:                           if (!Span && (Char.IsDigit(ch) || (ch == '.' && i < line.Length && Char.IsDigit(line[1]))) && curlength == 0) {
289:                               bool ishex false;
290:                               bool isfloatingpoint false;
291:                               
292:                               if (ch == '0' && i < line.Length && Char.ToUpper(line[1]) == 'X') { // hex digits
293:                                   const string hex "0123456789ABCDEF";
294:                                   ++curlength;
295:                                   ++i// skip 'x'
296:                                   ++curlength
297:                                   ishex true;
298:                                   while (< line.Length && hex.IndexOf(Char.ToUpper(line[1])) != -1) {
299:                                       ++i;
300:                                       ++curlength;
301:                                   }
302:                               else {
303:                                   ++curlength
304:                                   while (< line.Length && Char.IsDigit(line[1])) {
305:                                       ++i;
306:                                       ++curlength;
307:                                   }
308:                               }
309:                               if (!ishex && i < line.Length && line[1] == '.') {
310:                                   isfloatingpoint true;
311:                                   ++i;
312:                                   ++curlength;
313:                                   while (< line.Length && Char.IsDigit(line[1])) {
314:                                       ++i;
315:                                       ++curlength;
316:                                   }
317:                               
318:                                   
319:                               if (< line.Length && Char.ToUpper(line[1]) == 'E') {
320:                                   isfloatingpoint true;
321:                                   ++i;
322:                                   ++curlength;
323:                                   if (< line.Length && (line[1] == '+' || line[1] == '-')) {
324:                                       ++i;
325: