1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #ifdef HAVE_CONFIG_H
31 #include "../config.h"
32 #endif
33
34 #include "highlight.h"
35 #include "textBuf.h"
36 #include "textDisp.h"
37 #include "text.h"
38 #include "textP.h"
39 #include "nedit.h"
40 #include "regularExp.h"
41 #include "highlightData.h"
42 #include "preferences.h"
43 #include "window.h"
44 #include "../util/misc.h"
45 #include "../util/DialogF.h"
46 #include "../util/nedit_malloc.h"
47
48 #include <stdio.h>
49 #include <limits.h>
50 #include <math.h>
51 #include <stdlib.h>
52 #include <string.h>
53
54 #ifndef __MVS__
55 #include <sys/param.h>
56 #endif
57
58 #include <inttypes.h>
59
60 #include <Xm/Xm.h>
61 #include <Xm/XmP.h>
62 #if XmVersion >=
1002
63 #include <Xm/PrimitiveP.h>
64 #endif
65
66 #ifdef HAVE_DEBUG_H
67 #include "../debug.h"
68 #endif
69
70
71 #define PASS_2_REPARSE_CHUNK_SIZE 1000
72
73
74
75
76 #define REPARSE_CHUNK_SIZE 80
77
78
79
80
81 #define UNFINISHED_STYLE ASCII_A
82 #define PLAIN_STYLE (
ASCII_A+
1)
83 #define IS_PLAIN(style) (style ==
PLAIN_STYLE || style ==
UNFINISHED_STYLE)
84 #define IS_STYLED(style) (style !=
PLAIN_STYLE && style !=
UNFINISHED_STYLE)
85
86
87
88 #define EQUIVALENT_STYLE(style1, style2, firstPass2Style) (style1 == style2 || \
89 (style1 ==
UNFINISHED_STYLE && \
90 (style2 ==
PLAIN_STYLE || (
unsigned char)style2 >= firstPass2Style)) || \
91 (style2 ==
UNFINISHED_STYLE && \
92 (style1 ==
PLAIN_STYLE || (
unsigned char)style1 >= firstPass2Style)))
93
94
95
96
97 #define CAN_CROSS_LINE_BOUNDARIES(contextRequirements) \
98 (contextRequirements->nLines !=
1 || contextRequirements->nChars !=
0)
99
100
101 typedef struct _highlightDataRec {
102 regexp *startRE;
103 regexp *endRE;
104 regexp *errorRE;
105 regexp *subPatternRE;
106 char style;
107 int colorOnly;
108 signed char startSubexprs[
NSUBEXP+
1];
109 signed char endSubexprs[
NSUBEXP+
1];
110 int flags;
111 int nSubPatterns;
112 int nSubBranches;
113 int userStyleIndex;
114 struct _highlightDataRec **subPatterns;
115 } highlightDataRec;
116
117
118 typedef struct {
119 int nLines;
120 int nChars;
121 } reparseContext;
122
123
124
125 typedef struct {
126 highlightDataRec *pass1Patterns;
127 highlightDataRec *pass2Patterns;
128 char *parentStyles;
129 reparseContext contextRequirements;
130 styleTableEntry *styleTable;
131 int nStyles;
132 textBuffer *styleBuffer;
133 patternSet *patternSetForWindow;
134 } windowHighlightData;
135
136 static windowHighlightData *createHighlightData(WindowInfo *window,
137 patternSet *patSet);
138 static void freeHighlightData(windowHighlightData *hd);
139 static patternSet *findPatternsForWindow(WindowInfo *window,
int warn);
140 static highlightDataRec *compilePatterns(ColorProfile *colorProfile, Widget dialogParent,
141 highlightPattern *patternSrc,
int nPatterns);
142 static void freePatterns(highlightDataRec *patterns);
143 static void handleUnparsedRegion(
const WindowInfo* win, textBuffer* styleBuf,
144 int pos);
145 static void handleUnparsedRegionCB(
const textDisp* textD,
int pos,
146 const void* cbArg);
147 static void incrementalReparse(windowHighlightData *highlightData,
148 textBuffer *buf,
int pos,
int nInserted,
const char *delimiters);
149 static int parseBufferRange(highlightDataRec *pass1Patterns,
150 highlightDataRec *pass2Patterns, textBuffer *buf, textBuffer *styleBuf,
151 reparseContext *contextRequirements,
int beginParse,
int endParse,
152 const char *delimiters);
153 static int parseString(highlightDataRec *pattern,
const char **string,
154 char **styleString,
int length,
char *prevChar,
int anchored,
155 const char *delimiters,
const char* lookBehindTo,
const char* match_till);
156 static void passTwoParseString(highlightDataRec *pattern,
char *string,
157 char *styleString,
int length,
char *prevChar,
const char *delimiters,
158 const char* lookBehindTo,
const char* match_till);
159 static void fillStyleString(
const char **stringPtr,
char **stylePtr,
160 const char *toPtr,
char style,
char *prevChar);
161 static void modifyStyleBuf(textBuffer *styleBuf,
char *styleString,
162 int startPos,
int endPos,
int firstPass2Style);
163 static int lastModified(textBuffer *styleBuf);
164 static int max(
int i1,
int i2);
165 static int min(
int i1,
int i2);
166 static char getPrevChar(textBuffer *buf,
int pos);
167 static regexp *compileREAndWarn(Widget parent,
const char *re);
168 static int parentStyleOf(
const char *parentStyles,
int style);
169 static int isParentStyle(
const char *parentStyles,
int style1,
int style2);
170 static int findSafeParseRestartPos(textBuffer *buf,
171 windowHighlightData *highlightData,
int *pos);
172 static int backwardOneContext(textBuffer *buf, reparseContext *context,
173 int fromPos);
174 static int forwardOneContext(textBuffer *buf, reparseContext *context,
175 int fromPos);
176 static void recolorSubexpr(regexp *re,
int subexpr,
int style,
177 const char *string,
char *styleString);
178 static int indexOfNamedPattern(highlightPattern *patList,
int nPats,
179 const char *patName);
180 static int findTopLevelParentIndex(highlightPattern *patList,
int nPats,
181 int index);
182 static highlightDataRec *patternOfStyle(highlightDataRec *patterns,
int style);
183 static void updateWindowHeight(WindowInfo *window,
int oldFontHeight);
184 static int getFontHeight(WindowInfo *window);
185 static styleTableEntry *styleTableEntryOfCode(WindowInfo *window,
int hCode);
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207 void SyntaxHighlightModifyCB(
int pos,
int nInserted,
int nDeleted,
208 int nRestyled,
const char *deletedText,
void *cbArg)
209 {
210 WindowInfo *window = (WindowInfo *)cbArg;
211 windowHighlightData
212 *highlightData = (windowHighlightData *)window->highlightData;
213
214 if(window->ansiColors) {
215 BufParseEscSeq(window->buffer, pos, nInserted, nDeleted);
216 }
217
218 if (highlightData ==
NULL)
219 return;
220
221
222
223
224 if (nInserted ==
0 && nDeleted ==
0) {
225 BufUnselect(highlightData->styleBuffer);
226 return;
227 }
228
229
230
231 if (nInserted >
0) {
232 char *insStyle;
233 int i;
234
235 insStyle = (
char*)NEditMalloc(nInserted +
1);
236 for (i=
0; i<nInserted; i++)
237 insStyle[i] =
UNFINISHED_STYLE;
238 insStyle[i] =
'\0';
239 BufReplace(highlightData->styleBuffer, pos, pos+nDeleted, insStyle);
240 NEditFree(insStyle);
241 }
else {
242 BufRemove(highlightData->styleBuffer, pos, pos+nDeleted);
243 }
244
245
246
247
248
249
250 BufSelect(highlightData->styleBuffer, pos, pos+nInserted);
251
252
253 if (highlightData->pass1Patterns)
254 incrementalReparse(highlightData, window->buffer, pos, nInserted,
255 GetWindowDelimiters(window));
256 }
257
258
259
260
261
262 void StartHighlighting(WindowInfo *window,
int warn)
263 {
264 patternSet *patterns;
265 windowHighlightData *highlightData;
266 char *stylePtr, *styleString;
267 const char *stringPtr, *bufString;
268 char prevChar =
'\0';
269 int i, oldFontHeight;
270
271
272
273 patterns = findPatternsForWindow(window, warn);
274 if (patterns ==
NULL)
275 return;
276
277
278 highlightData = createHighlightData(window, patterns);
279 if (highlightData ==
NULL)
280 return;
281
282
283 BeginWait(window->shell);
284 XmUpdateDisplay(window->shell);
285
286
287
288 stylePtr = styleString = (
char*)NEditMalloc(window->buffer->length +
1);
289 if (highlightData->pass1Patterns ==
NULL) {
290 for (i=
0; i<window->buffer->length; i++)
291 *stylePtr++ =
UNFINISHED_STYLE;
292 }
else {
293 stringPtr = bufString = BufAsString(window->buffer);
294 parseString(highlightData->pass1Patterns, &stringPtr, &stylePtr,
295 window->buffer->length, &prevChar, False,
296 GetWindowDelimiters(window), bufString,
NULL);
297 }
298 *stylePtr =
'\0';
299 BufSetAll(highlightData->styleBuffer, styleString);
300 NEditFree(styleString);
301
302
303 window->highlightData = highlightData;
304
305
306
307
308 oldFontHeight = getFontHeight(window);
309
310
311 AttachHighlightToWidget(window->textArea, window);
312 for (i=
0; i<window->nPanes; i++)
313 AttachHighlightToWidget(window->textPanes[i], window);
314
315
316
317 updateWindowHeight(window, oldFontHeight);
318 UpdateWMSizeHints(window);
319 UpdateMinPaneHeights(window);
320
321
322
323
324
325 XmUpdateDisplay(window->shell);
326 EndWait(window->shell);
327 }
328
329
330
331
332
333 void StopHighlighting(WindowInfo *window)
334 {
335 int i, oldFontHeight;
336
337 if (window->highlightData==
NULL)
338 return;
339
340
341
342
343 oldFontHeight = getFontHeight(window);
344
345
346 freeHighlightData((windowHighlightData *)window->highlightData);
347 window->highlightData =
NULL;
348
349
350
351 RemoveWidgetHighlight(window->textArea);
352 for (i=
0; i<window->nPanes; i++)
353 RemoveWidgetHighlight(window->textPanes[i]);
354
355
356
357 updateWindowHeight(window, oldFontHeight);
358 UpdateWMSizeHints(window);
359 UpdateMinPaneHeights(window);
360 }
361
362
363
364
365
366 void FreeHighlightingData(WindowInfo *window)
367 {
368 int i;
369
370 if (window->highlightData ==
NULL)
371 return;
372
373
374 freeHighlightData((windowHighlightData *)window->highlightData);
375 window->highlightData =
NULL;
376
377
378
379 ((TextWidget)window->textArea)->text.textD->styleBuffer =
NULL;
380 for (i=
0; i<window->nPanes; i++)
381 ((TextWidget)window->textPanes[i])->text.textD->styleBuffer =
NULL;
382 }
383
384
385
386
387
388 void AttachHighlightToWidget(Widget widget, WindowInfo *window)
389 {
390 windowHighlightData *highlightData =
391 (windowHighlightData *)window->highlightData;
392
393 TextDAttachHighlightData(((TextWidget)widget)->text.textD,
394 highlightData->styleBuffer, highlightData->styleTable,
395 highlightData->nStyles,
UNFINISHED_STYLE, handleUnparsedRegionCB,
396 window);
397 }
398
399
400
401
402 void RemoveWidgetHighlight(Widget widget)
403 {
404 TextDAttachHighlightData(((TextWidget)widget)->text.textD,
405 NULL,
NULL,
0,
UNFINISHED_STYLE,
NULL,
NULL);
406 }
407
408
409
410
411
412 void UpdateHighlightStyles(WindowInfo *window, Boolean redisplay)
413 {
414 patternSet *patterns;
415 windowHighlightData *highlightData;
416 windowHighlightData *oldHighlightData =
417 (windowHighlightData *)window->highlightData;
418 textBuffer *styleBuffer;
419 int i;
420
421
422 if (window->highlightData ==
NULL)
423 return;
424
425
426 patterns = findPatternsForWindow(window, False);
427 if (patterns ==
NULL) {
428 StopHighlighting(window);
429 return;
430 }
431
432
433 highlightData = createHighlightData(window, patterns);
434 if (highlightData ==
NULL) {
435 StopHighlighting(window);
436 return;
437 }
438
439
440
441
442
443 styleBuffer = oldHighlightData->styleBuffer;
444 oldHighlightData->styleBuffer = highlightData->styleBuffer;
445 freeHighlightData(oldHighlightData);
446 highlightData->styleBuffer = styleBuffer;
447 window->highlightData = highlightData;
448
449
450
451 ((TextWidget)window->textArea)->text.textD->disableRedisplay = !redisplay;
452 AttachHighlightToWidget(window->textArea, window);
453 ((TextWidget)window->textArea)->text.textD->disableRedisplay =
0;
454 for (i=
0; i<window->nPanes; i++) {
455 ((TextWidget)window->textPanes[i])->text.textD->disableRedisplay = !redisplay;
456 AttachHighlightToWidget(window->textPanes[i], window);
457 ((TextWidget)window->textPanes[i])->text.textD->disableRedisplay =
0;
458 }
459 }
460
461
462
463
464
465
466
467
468
469
470
471 int TestHighlightPatterns(patternSet *patSet)
472 {
473 windowHighlightData *highlightData;
474
475
476
477 highlightData = createHighlightData(WindowList, patSet);
478 if (highlightData ==
NULL)
479 return False;
480 freeHighlightData(highlightData);
481 return True;
482 }
483
484
485
486
487
488
489
490
491
492
493
494 void* GetHighlightInfo(WindowInfo *window,
int pos)
495 {
496 int style;
497 highlightDataRec *pattern =
NULL;
498 windowHighlightData *highlightData =
499 (windowHighlightData *)window->highlightData;
500 if (!highlightData)
501 return NULL;
502
503
504 style = (
int)BufGetCharacter(highlightData->styleBuffer, pos);
505
506
507 if (style ==
UNFINISHED_STYLE) {
508 handleUnparsedRegion(window, highlightData->styleBuffer, pos);
509 style = (
int)BufGetCharacter(highlightData->styleBuffer, pos);
510 }
511
512 if (highlightData->pass1Patterns) {
513 pattern = patternOfStyle(highlightData->pass1Patterns, style);
514 }
515
516 if (!pattern && highlightData->pass2Patterns) {
517 pattern = patternOfStyle(highlightData->pass2Patterns, style);
518 }
519
520 if (!pattern) {
521 return NULL;
522 }
523 return (
void*)(
intptr_t)pattern->userStyleIndex;
524 }
525
526
527
528
529
530
531
532
533 static void freeHighlightData(windowHighlightData *hd)
534 {
535 if (hd ==
NULL)
536 return;
537 if (hd->pass1Patterns !=
NULL)
538 freePatterns(hd->pass1Patterns);
539 if (hd->pass2Patterns !=
NULL)
540 freePatterns(hd->pass2Patterns);
541 NEditFree(hd->parentStyles);
542 BufFree(hd->styleBuffer);
543 NEditFree(hd->styleTable);
544 NEditFree(hd);
545 }
546
547
548
549
550
551 static patternSet *findPatternsForWindow(WindowInfo *window,
int warn)
552 {
553 patternSet *patterns;
554 char *modeName;
555
556
557 modeName = LanguageModeName(window->languageMode);
558 if (modeName ==
NULL) {
559 if (warn)
560 DialogF(
DF_WARN, window->shell,
1,
"Language Mode",
561 "No language-specific mode has been set for this file.\n\n"
562 "To use syntax highlighting in this window, please select a\n"
563 "language from the Preferences -> Language Modes menu.\n\n"
564 "New language modes and syntax highlighting patterns can be\n"
565 "added via Preferences -> Default Settings -> Language Modes,\n"
566 "and Preferences -> Default Settings -> Syntax Highlighting.",
567 "OK");
568 return NULL;
569 }
570
571
572 patterns = FindPatternSet(modeName);
573 if (patterns ==
NULL)
574 {
575 if (warn)
576 {
577 DialogF(
DF_WARN, window->shell,
1,
"Language Mode",
578 "Syntax highlighting is not available in language\n"
579 "mode %s.\n\n"
580 "You can create new syntax highlight patterns in the\n"
581 "Preferences -> Default Settings -> Syntax Highlighting\n"
582 "dialog, or choose a different language mode from:\n"
583 "Preferences -> Language Mode.",
"OK", modeName);
584 return NULL;
585 }
586 }
587
588 return patterns;
589 }
590
591
592
593
594
595
596
597 static windowHighlightData *createHighlightData(WindowInfo *window,
598 patternSet *patSet)
599 {
600 highlightPattern *patternSrc = patSet->patterns;
601 int nPatterns = patSet->nPatterns;
602 int contextLines = patSet->lineContext;
603 int contextChars = patSet->charContext;
604 int i, nPass1Patterns, nPass2Patterns;
605 int noPass1, noPass2;
606 char *parentStyles, *parentStylesPtr, *parentName;
607 highlightPattern *pass1PatternSrc, *pass2PatternSrc, *p1Ptr, *p2Ptr;
608 styleTableEntry *styleTable, *styleTablePtr;
609 textBuffer *styleBuf;
610 highlightDataRec *pass1Pats, *pass2Pats;
611 windowHighlightData *highlightData;
612 ColorProfile *colorprofile = window->colorProfile;
613
614
615 if (nPatterns ==
0)
616 {
617 return NULL;
618 }
619
620
621 if (!NamedStyleExists(colorprofile,
"Plain"))
622 {
623 DialogF(
DF_WARN, window->shell,
1,
"Highlight Style",
624 "Highlight style \"Plain\" is missing",
"OK");
625 return NULL;
626 }
627
628 for (i=
0; i<nPatterns; i++)
629 {
630 if (patternSrc[i].subPatternOf !=
NULL
631 && indexOfNamedPattern(patternSrc, nPatterns,
632 patternSrc[i].subPatternOf) == -
1)
633 {
634 DialogF(
DF_WARN, window->shell,
1,
"Parent Pattern",
635 "Parent field \"%s\" in pattern \"%s\"\n"
636 "does not match any highlight patterns in this set",
637 "OK", patternSrc[i].subPatternOf, patternSrc[i].name);
638 return NULL;
639 }
640 }
641
642 for (i=
0; i<nPatterns; i++)
643 {
644 if (!NamedStyleExists(colorprofile, patternSrc[i].style))
645 {
646 DialogF(
DF_WARN, window->shell,
1,
"Highlight Style",
647 "Style \"%s\" named in pattern \"%s\"\n"
648 "does not match any existing style",
"OK",
649 patternSrc[i].style, patternSrc[i].name);
650 return NULL;
651 }
652 }
653
654
655
656
657 for (i =
0; i < nPatterns; i++)
658 {
659 if (patternSrc[i].subPatternOf !=
NULL)
660 {
661 int parentindex;
662
663 parentindex=findTopLevelParentIndex(patternSrc, nPatterns, i);
664 if (parentindex==-
1)
665 {
666 DialogF(
DF_WARN, window->shell,
1,
"Parent Pattern",
667 "Pattern \"%s\" does not have valid parent",
"OK",
668 patternSrc[i].name);
669 return NULL;
670 }
671
672 if (patternSrc[parentindex].flags &
DEFER_PARSING)
673 {
674 patternSrc[i].flags |=
DEFER_PARSING;
675 }
else
676 {
677 patternSrc[i].flags &= ~
DEFER_PARSING;
678 }
679 }
680 }
681
682
683
684 nPass1Patterns =
1;
685 nPass2Patterns =
1;
686 for (i=
0; i<nPatterns; i++)
687 if (patternSrc[i].flags &
DEFER_PARSING)
688 nPass2Patterns++;
689 else
690 nPass1Patterns++;
691 p1Ptr = pass1PatternSrc = (highlightPattern *)NEditMalloc(
692 sizeof(highlightPattern) * nPass1Patterns);
693 p2Ptr = pass2PatternSrc = (highlightPattern *)NEditMalloc(
694 sizeof(highlightPattern) * nPass2Patterns);
695 p1Ptr->name = p2Ptr->name =
"";
696 p1Ptr->startRE = p2Ptr->startRE =
NULL;
697 p1Ptr->endRE = p2Ptr->endRE =
NULL;
698 p1Ptr->errorRE = p2Ptr->errorRE =
NULL;
699 p1Ptr->style = p2Ptr->style =
"Plain";
700 p1Ptr->subPatternOf = p2Ptr->subPatternOf =
NULL;
701 p1Ptr->flags = p2Ptr->flags =
0;
702 p1Ptr++; p2Ptr++;
703 for (i=
0; i<nPatterns; i++) {
704 if (patternSrc[i].flags &
DEFER_PARSING)
705 *p2Ptr++ = patternSrc[i];
706 else
707 *p1Ptr++ = patternSrc[i];
708 }
709
710
711
712 if (nPass1Patterns ==
1)
713 nPass1Patterns =
0;
714 if (nPass2Patterns ==
1)
715 nPass2Patterns =
0;
716
717
718 if (nPass1Patterns ==
0)
719 pass1Pats =
NULL;
720 else {
721 pass1Pats = compilePatterns(window->colorProfile, window->shell, pass1PatternSrc,
722 nPass1Patterns);
723 if (pass1Pats ==
NULL)
724 return NULL;
725 }
726 if (nPass2Patterns ==
0)
727 pass2Pats =
NULL;
728 else {
729 pass2Pats = compilePatterns(window->colorProfile, window->shell, pass2PatternSrc,
730 nPass2Patterns);
731 if (pass2Pats ==
NULL)
732 return NULL;
733 }
734
735
736
737
738
739 noPass1 = nPass1Patterns ==
0;
740 noPass2 = nPass2Patterns ==
0;
741 if (noPass2)
742 pass1Pats[
0].style =
PLAIN_STYLE;
743 else if (noPass1)
744 pass2Pats[
0].style =
PLAIN_STYLE;
745 else {
746 pass1Pats[
0].style =
UNFINISHED_STYLE;
747 pass2Pats[
0].style =
PLAIN_STYLE;
748 }
749 for (i=
1; i<nPass1Patterns; i++)
750 pass1Pats[i].style =
PLAIN_STYLE + i;
751 for (i=
1; i<nPass2Patterns; i++)
752 pass2Pats[i].style =
PLAIN_STYLE + (noPass1 ?
0 : nPass1Patterns-
1) + i;
753
754
755 parentStylesPtr = parentStyles = (
char*)NEditMalloc(nPass1Patterns+nPass2Patterns+
2);
756 *parentStylesPtr++ =
'\0';
757 *parentStylesPtr++ =
'\0';
758 for (i=
1; i<nPass1Patterns; i++) {
759 parentName = pass1PatternSrc[i].subPatternOf;
760 *parentStylesPtr++ = parentName ==
NULL ?
PLAIN_STYLE :
761 pass1Pats[indexOfNamedPattern(pass1PatternSrc,
762 nPass1Patterns, parentName)].style;
763 }
764 for (i=
1; i<nPass2Patterns; i++) {
765 parentName = pass2PatternSrc[i].subPatternOf;
766 *parentStylesPtr++ = parentName ==
NULL ?
PLAIN_STYLE :
767 pass2Pats[indexOfNamedPattern(pass2PatternSrc,
768 nPass2Patterns, parentName)].style;
769 }
770
771
772 styleTablePtr = styleTable = (styleTableEntry *)NEditMalloc(
773 sizeof(styleTableEntry) * (nPass1Patterns + nPass2Patterns +
1));
774 #define setStyleTablePtr(colorProfile, styleTablePtr, patternSrc) \
775 do { \
776 styleTableEntry *p = styleTablePtr; \
777 highlightPattern *pat = patternSrc; \
778 int r, g, b; \
779 \
780 p->highlightName = pat->name; \
781 p->styleName = pat->style; \
782 p->colorName = ColorOfNamedStyle(colorProfile, pat->style); \
783 p->bgColorName = BgColorOfNamedStyle(colorProfile, pat->style); \
784 p->isBold = FontOfNamedStyleIsBold(colorProfile, pat->style); \
785 p->isItalic = FontOfNamedStyleIsItalic(colorProfile, pat->style); \
786 \
787 p->color.pixel = AllocColor(window->textArea, p->colorName, &r, &g, &b); \
788 p->color.color.red = r; \
789 p->color.color.green = g; \
790 p->color.color.blue = b; \
791 p->color.color.alpha = 0xFFFF; \
792 \
793 if (p->bgColorName) { \
794 p->bgColor = PixelToColor(window->textArea, AllocColor(window->textArea, p->bgColorName, &r, &g, &b)); \
795 p->bgColor.pixel = AllocColor(window->textArea, p->colorName, &r, &g, &b); \
796 p->bgColor.color.red = r; \
797 p->bgColor.color.green = g; \
798 p->bgColor.color.blue = b; \
799 p->bgColor.color.alpha = 0xFFFF; \
800 } \
801 else { \
802 p->bgColor = p->color; \
803 if(colorProfile->styleType ==
1) \
804 p->color = LightenColor(p->color); \
805 } \
806 p->font = FontOfNamedStyle(colorProfile, window, pat->style); \
807 }
while (
0)
808
809
810 styleTablePtr->underline =
FALSE;
811 setStyleTablePtr(colorprofile, styleTablePtr++,
812 noPass1 ? &pass2PatternSrc[
0] : &pass1PatternSrc[
0]);
813
814 styleTablePtr->underline =
FALSE;
815 setStyleTablePtr(colorprofile, styleTablePtr++,
816 noPass2 ? &pass1PatternSrc[
0] : &pass2PatternSrc[
0]);
817
818 for (i=
1; i<nPass1Patterns; i++) {
819 styleTablePtr->underline =
FALSE;
820 setStyleTablePtr(colorprofile, styleTablePtr++, &pass1PatternSrc[i]);
821 }
822
823 for (i=
1; i<nPass2Patterns; i++) {
824 styleTablePtr->underline =
FALSE;
825 setStyleTablePtr(colorprofile, styleTablePtr++, &pass2PatternSrc[i]);
826 }
827
828
829 NEditFree(pass1PatternSrc);
830 NEditFree(pass2PatternSrc);
831
832
833 styleBuf = BufCreate();
834
835
836 highlightData =(windowHighlightData *)NEditMalloc(
sizeof(windowHighlightData));
837 highlightData->pass1Patterns = pass1Pats;
838 highlightData->pass2Patterns = pass2Pats;
839 highlightData->parentStyles = parentStyles;
840 highlightData->styleTable = styleTable;
841 highlightData->nStyles = styleTablePtr - styleTable;
842 highlightData->styleBuffer = styleBuf;
843 highlightData->contextRequirements.nLines = contextLines;
844 highlightData->contextRequirements.nChars = contextChars;
845 highlightData->patternSetForWindow = patSet;
846
847 return highlightData;
848 }
849
850
851
852
853
854
855 static highlightDataRec *compilePatterns(ColorProfile *colorProfile, Widget dialogParent,
856 highlightPattern *patternSrc,
int nPatterns)
857 {
858 int i, nSubExprs, patternNum, length, subPatIndex, subExprNum, charsRead;
859 int parentIndex;
860 char *ptr, *bigPattern, *compileMsg;
861 highlightDataRec *compiledPats;
862
863
864
865 compiledPats = (highlightDataRec *)NEditMalloc(
sizeof(highlightDataRec) *
866 (nPatterns +
1));
867 compiledPats[nPatterns].style =
0;
868
869
870 for (i=
0; i<nPatterns; i++) {
871 compiledPats[i].nSubPatterns =
0;
872 compiledPats[i].nSubBranches =
0;
873 }
874 for (i=
1; i<nPatterns; i++)
875 if (patternSrc[i].subPatternOf ==
NULL)
876 compiledPats[
0].nSubPatterns++;
877 else
878 compiledPats[indexOfNamedPattern(patternSrc, nPatterns,
879 patternSrc[i].subPatternOf)].nSubPatterns++;
880 for (i=
0; i<nPatterns; i++)
881 compiledPats[i].subPatterns = compiledPats[i].nSubPatterns ==
0 ?
882 NULL : (highlightDataRec **)NEditMalloc(
883 sizeof(highlightDataRec *) * compiledPats[i].nSubPatterns);
884 for (i=
0; i<nPatterns; i++)
885 compiledPats[i].nSubPatterns =
0;
886 for (i=
1; i<nPatterns; i++) {
887 if (patternSrc[i].subPatternOf ==
NULL) {
888 compiledPats[
0].subPatterns[compiledPats[
0].nSubPatterns++] =
889 &compiledPats[i];
890 }
else {
891 parentIndex = indexOfNamedPattern(patternSrc,
892 nPatterns, patternSrc[i].subPatternOf);
893 compiledPats[parentIndex].subPatterns[compiledPats[parentIndex].
894 nSubPatterns++] = &compiledPats[i];
895 }
896 }
897
898
899
900 for (i=
0; i<nPatterns; i++) {
901 compiledPats[i].colorOnly = patternSrc[i].flags &
COLOR_ONLY;
902 compiledPats[i].userStyleIndex = IndexOfNamedStyle(colorProfile, patternSrc[i].style);
903 if (compiledPats[i].colorOnly && compiledPats[i].nSubPatterns !=
0)
904 {
905 DialogF(
DF_WARN, dialogParent,
1,
"Color-only Pattern",
906 "Color-only pattern \"%s\" may not have subpatterns",
907 "OK", patternSrc[i].name);
908 return NULL;
909 }
910 nSubExprs =
0;
911 if (patternSrc[i].startRE !=
NULL) {
912 ptr = patternSrc[i].startRE;
913 while(
TRUE) {
914 if (*ptr ==
'&') {
915 compiledPats[i].startSubexprs[nSubExprs++] =
0;
916 ptr++;
917 }
else if (sscanf(ptr,
"\\%d%n", &subExprNum, &charsRead)==
1) {
918 compiledPats[i].startSubexprs[nSubExprs++] = subExprNum;
919 ptr += charsRead;
920 }
else
921 break;
922 }
923 }
924 compiledPats[i].startSubexprs[nSubExprs] = -
1;
925 nSubExprs =
0;
926 if (patternSrc[i].endRE !=
NULL) {
927 ptr = patternSrc[i].endRE;
928 while(
TRUE) {
929 if (*ptr ==
'&') {
930 compiledPats[i].endSubexprs[nSubExprs++] =
0;
931 ptr++;
932 }
else if (sscanf(ptr,
"\\%d%n", &subExprNum, &charsRead)==
1) {
933 compiledPats[i].endSubexprs[nSubExprs++] = subExprNum;
934 ptr += charsRead;
935 }
else
936 break;
937 }
938 }
939 compiledPats[i].endSubexprs[nSubExprs] = -
1;
940 }
941
942
943 for (i=
0; i<nPatterns; i++) {
944 if (patternSrc[i].startRE ==
NULL || compiledPats[i].colorOnly)
945 compiledPats[i].startRE =
NULL;
946 else {
947 if ((compiledPats[i].startRE = compileREAndWarn(dialogParent,
948 patternSrc[i].startRE)) ==
NULL)
949 return NULL;
950 }
951 if (patternSrc[i].endRE ==
NULL || compiledPats[i].colorOnly)
952 compiledPats[i].endRE =
NULL;
953 else {
954 if ((compiledPats[i].endRE = compileREAndWarn(dialogParent,
955 patternSrc[i].endRE)) ==
NULL)
956 return NULL;
957 }
958 if (patternSrc[i].errorRE ==
NULL)
959 compiledPats[i].errorRE =
NULL;
960 else {
961 if ((compiledPats[i].errorRE = compileREAndWarn(dialogParent,
962 patternSrc[i].errorRE)) ==
NULL)
963 return NULL;
964 }
965 }
966
967
968
969
970 for (patternNum=
0; patternNum<nPatterns; patternNum++) {
971 if (patternSrc[patternNum].endRE ==
NULL &&
972 patternSrc[patternNum].errorRE ==
NULL &&
973 compiledPats[patternNum].nSubPatterns ==
0) {
974 compiledPats[patternNum].subPatternRE =
NULL;
975 continue;
976 }
977 length = (compiledPats[patternNum].colorOnly ||
978 patternSrc[patternNum].endRE ==
NULL) ?
0 :
979 strlen(patternSrc[patternNum].endRE) +
5;
980 length += (compiledPats[patternNum].colorOnly ||
981 patternSrc[patternNum].errorRE ==
NULL) ?
0 :
982 strlen(patternSrc[patternNum].errorRE) +
5;
983 for (i=
0; i<compiledPats[patternNum].nSubPatterns; i++) {
984 subPatIndex = compiledPats[patternNum].subPatterns[i]-compiledPats;
985 length += compiledPats[subPatIndex].colorOnly ?
0 :
986 strlen(patternSrc[subPatIndex].startRE) +
5;
987 }
988 if (length ==
0) {
989 compiledPats[patternNum].subPatternRE =
NULL;
990 continue;
991 }
992 bigPattern = (
char*)NEditMalloc(length+
1);
993 ptr=bigPattern;
994 if (patternSrc[patternNum].endRE !=
NULL) {
995 *ptr++ =
'('; *ptr++ =
'?'; *ptr++ =
':';
996 strcpy(ptr, patternSrc[patternNum].endRE);
997 ptr += strlen(patternSrc[patternNum].endRE);
998 *ptr++ =
')';
999 *ptr++ =
'|';
1000 compiledPats[patternNum].nSubBranches++;
1001 }
1002 if (patternSrc[patternNum].errorRE !=
NULL) {
1003 *ptr++ =
'('; *ptr++ =
'?'; *ptr++ =
':';
1004 strcpy(ptr, patternSrc[patternNum].errorRE);
1005 ptr += strlen(patternSrc[patternNum].errorRE);
1006 *ptr++ =
')';
1007 *ptr++ =
'|';
1008 compiledPats[patternNum].nSubBranches++;
1009 }
1010 for (i=
0; i<compiledPats[patternNum].nSubPatterns; i++) {
1011 subPatIndex = compiledPats[patternNum].subPatterns[i]-compiledPats;
1012 if (compiledPats[subPatIndex].colorOnly)
1013 continue;
1014 *ptr++ =
'('; *ptr++ =
'?'; *ptr++ =
':';
1015 strcpy(ptr, patternSrc[subPatIndex].startRE);
1016 ptr += strlen(patternSrc[subPatIndex].startRE);
1017 *ptr++ =
')';
1018 *ptr++ =
'|';
1019 compiledPats[patternNum].nSubBranches++;
1020 }
1021 *(ptr-
1) =
'\0';
1022 compiledPats[patternNum].subPatternRE = CompileRE(bigPattern,
1023 &compileMsg,
REDFLT_STANDARD);
1024 if (compiledPats[patternNum].subPatternRE ==
NULL) {
1025 fprintf(stderr,
"Error compiling syntax highlight patterns:\n%s",
1026 compileMsg);
1027 return NULL;
1028 }
1029 NEditFree(bigPattern);
1030 }
1031
1032
1033 for (i=
0; i<nPatterns; i++)
1034 compiledPats[i].flags = patternSrc[i].flags;
1035
1036 return compiledPats;
1037 }
1038
1039
1040
1041
1042 static void freePatterns(highlightDataRec *patterns)
1043 {
1044 int i;
1045
1046 for (i=
0; patterns[i].style!=
0; i++) {
1047 if (patterns[i].startRE !=
NULL)
1048 free((
char *)patterns[i].startRE);
1049 if (patterns[i].endRE !=
NULL)
1050 free((
char *)patterns[i].endRE);
1051 if (patterns[i].errorRE !=
NULL)
1052 free((
char *)patterns[i].errorRE);
1053 if (patterns[i].subPatternRE !=
NULL)
1054 free((
char *)patterns[i].subPatternRE);
1055 }
1056
1057 for (i=
0; patterns[i].style!=
0; i++) {
1058 NEditFree(patterns[i].subPatterns);
1059 }
1060
1061 NEditFree(patterns);
1062 }
1063
1064
1065
1066
1067 highlightPattern *FindPatternOfWindow(WindowInfo *window,
char *name)
1068 {
1069 windowHighlightData *hData = (windowHighlightData *)window->highlightData;
1070 patternSet *set;
1071 int i;
1072
1073 if (hData && (set = hData->patternSetForWindow)) {
1074 for (i =
0; i < set->nPatterns; i++)
1075 if (strcmp(set->patterns[i].name, name) ==
0)
1076 return &set->patterns[i];
1077 }
1078 return NULL;
1079 }
1080
1081
1082
1083
1084
1085 int HighlightCodeOfPos(WindowInfo *window,
int pos)
1086 {
1087 windowHighlightData *highlightData =
1088 (windowHighlightData *)window->highlightData;
1089 textBuffer *styleBuf =
1090 highlightData ? highlightData->styleBuffer :
NULL;
1091 int hCode =
0;
1092
1093 if (styleBuf !=
NULL) {
1094 hCode = (
unsigned char)BufGetCharacter(styleBuf, pos);
1095 if (hCode ==
UNFINISHED_STYLE) {
1096
1097 handleUnparsedRegion(window, highlightData->styleBuffer, pos);
1098 hCode = (
unsigned char)BufGetCharacter(styleBuf, pos);
1099 }
1100 }
1101 return hCode;
1102 }
1103
1104
1105
1106
1107
1108
1109
1110
1111 int HighlightLengthOfCodeFromPos(WindowInfo *window,
int pos,
int *checkCode)
1112 {
1113 windowHighlightData *highlightData =
1114 (windowHighlightData *)window->highlightData;
1115 textBuffer *styleBuf =
1116 highlightData ? highlightData->styleBuffer :
NULL;
1117 int hCode;
1118 int oldPos = pos;
1119
1120 if (styleBuf !=
NULL) {
1121 hCode = (
unsigned char)BufGetCharacter(styleBuf, pos);
1122 if (!hCode)
1123 return 0;
1124 if (hCode ==
UNFINISHED_STYLE) {
1125
1126 handleUnparsedRegion(window, highlightData->styleBuffer, pos);
1127 hCode = (
unsigned char)BufGetCharacter(styleBuf, pos);
1128 }
1129 if (*checkCode ==
0)
1130 *checkCode = hCode;
1131 while (hCode == *checkCode || hCode ==
UNFINISHED_STYLE) {
1132 if (hCode ==
UNFINISHED_STYLE) {
1133
1134 handleUnparsedRegion(window, highlightData->styleBuffer, pos);
1135 hCode = (
unsigned char)BufGetCharacter(styleBuf, pos);
1136 }
1137 else {
1138
1139 hCode = (
unsigned char)BufGetCharacter(styleBuf, ++pos);
1140 }
1141 }
1142 }
1143 return pos - oldPos;
1144 }
1145
1146
1147
1148
1149
1150
1151 int StyleLengthOfCodeFromPos(WindowInfo *window,
int pos,
1152 const char **checkStyleName)
1153 {
1154 windowHighlightData *highlightData =
1155 (windowHighlightData *)window->highlightData;
1156 textBuffer *styleBuf =
1157 highlightData ? highlightData->styleBuffer :
NULL;
1158 int hCode;
1159 int oldPos = pos;
1160 styleTableEntry *entry;
1161
1162 if (styleBuf !=
NULL) {
1163 hCode = (
unsigned char)BufGetCharacter(styleBuf, pos);
1164 if (!hCode)
1165 return 0;
1166 if (hCode ==
UNFINISHED_STYLE) {
1167
1168 handleUnparsedRegion(window, highlightData->styleBuffer, pos);
1169 hCode = (
unsigned char)BufGetCharacter(styleBuf, pos);
1170 }
1171 entry = styleTableEntryOfCode(window, hCode);
1172 if (entry ==
NULL)
1173 return 0;
1174 if ((*checkStyleName) ==
NULL)
1175 (*checkStyleName) = entry->styleName;
1176 while (hCode ==
UNFINISHED_STYLE ||
1177 ((entry = styleTableEntryOfCode(window, hCode)) &&
1178 strcmp(entry->styleName, (*checkStyleName)) ==
0)) {
1179 if (hCode ==
UNFINISHED_STYLE) {
1180
1181 handleUnparsedRegion(window, highlightData->styleBuffer, pos);
1182 hCode = (
unsigned char)BufGetCharacter(styleBuf, pos);
1183 }
1184 else {
1185
1186 hCode = (
unsigned char)BufGetCharacter(styleBuf, ++pos);
1187 }
1188 }
1189 }
1190 return pos - oldPos;
1191 }
1192
1193
1194
1195
1196
1197 static styleTableEntry *styleTableEntryOfCode(WindowInfo *window,
int hCode)
1198 {
1199 windowHighlightData *highlightData =
1200 (windowHighlightData *)window->highlightData;
1201
1202 hCode -=
UNFINISHED_STYLE;
1203 if (!highlightData || hCode <
0 || hCode >= highlightData->nStyles)
1204 return NULL;
1205 return &highlightData->styleTable[hCode];
1206 }
1207
1208
1209
1210
1211
1212 char *HighlightNameOfCode(WindowInfo *window,
int hCode)
1213 {
1214 styleTableEntry *entry = styleTableEntryOfCode(window, hCode);
1215 return entry ? entry->highlightName :
"";
1216 }
1217
1218 char *HighlightStyleOfCode(WindowInfo *window,
int hCode)
1219 {
1220 styleTableEntry *entry = styleTableEntryOfCode(window, hCode);
1221 return entry ? entry->styleName :
"";
1222 }
1223
1224
1225 XftColor HighlightColorValueOfCode(WindowInfo *window,
int hCode,
1226 int *r,
int *g,
int *b)
1227 {
1228 styleTableEntry *entry = styleTableEntryOfCode(window, hCode);
1229 if (entry) {
1230 *r = entry->color.color.red;
1231 *g = entry->color.color.green;
1232 *b = entry->color.color.blue;
1233 return entry->color;
1234 }
1235 else
1236 {
1237
1238 XftColor color = TextGetFGColor(window->textArea);
1239 *r = color.color.red;
1240 *g = color.color.green;
1241 *b = color.color.blue;
1242 return color;
1243 }
1244 }
1245
1246 XftColor GetHighlightBGColorOfCode(WindowInfo *window,
int hCode,
1247 int *r,
int *g,
int *b)
1248 {
1249 styleTableEntry *entry = styleTableEntryOfCode(window, hCode);
1250 if (entry && entry->bgColorName) {
1251 *r = entry->bgColor.color.red;
1252 *g = entry->bgColor.color.green;
1253 *b = entry->bgColor.color.blue;
1254 return entry->bgColor;
1255 }
1256 else
1257 {
1258
1259 XftColor color = TextGetBGColor(window->textArea);
1260 *r = color.color.red;
1261 *g = color.color.green;
1262 *b = color.color.blue;
1263 return color;
1264 }
1265 }
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276 static void handleUnparsedRegion(
const WindowInfo* window, textBuffer* styleBuf,
1277 int pos)
1278 {
1279 textBuffer *buf = window->buffer;
1280 int beginParse, endParse, beginSafety, endSafety, p;
1281 windowHighlightData *highlightData =
1282 (windowHighlightData *)window->highlightData;
1283
1284 reparseContext *context = &highlightData->contextRequirements;
1285 highlightDataRec *pass2Patterns = highlightData->pass2Patterns;
1286 char *string, *styleString, *stylePtr, c, prevChar;
1287 const char *stringPtr;
1288
1289
1290
1291 if (pass2Patterns ==
NULL)
1292 return;
1293
1294 int firstPass2Style = (
unsigned char)pass2Patterns[
1].style;
1295
1296
1297
1298
1299 beginParse = pos;
1300 beginSafety = backwardOneContext(buf, context, beginParse);
1301 for (p=beginParse; p>=beginSafety; p--) {
1302 c = BufGetCharacter(styleBuf, p);
1303 if (c !=
UNFINISHED_STYLE && c !=
PLAIN_STYLE &&
1304 (
unsigned char)c < firstPass2Style) {
1305 beginSafety = p +
1;
1306 break;
1307 }
1308 }
1309
1310
1311
1312
1313
1314 endParse = min(buf->length, pos +
PASS_2_REPARSE_CHUNK_SIZE);
1315 endSafety = forwardOneContext(buf, context, endParse);
1316 for (p=pos; p<endSafety; p++) {
1317 c = BufGetCharacter(styleBuf, p);
1318 if (c !=
UNFINISHED_STYLE && c !=
PLAIN_STYLE &&
1319 (
unsigned char)c < firstPass2Style) {
1320 endParse = min(endParse, p);
1321 endSafety = p;
1322 break;
1323 }
else if (c !=
UNFINISHED_STYLE && p < endParse) {
1324 endParse = p;
1325 if ((
unsigned char)c < firstPass2Style)
1326 endSafety = p;
1327 else
1328 endSafety = forwardOneContext(buf, context, endParse);
1329 break;
1330 }
1331 }
1332
1333
1334
1335
1336 stringPtr = string = BufGetRange(buf, beginSafety, endSafety);
1337 styleString = stylePtr = BufGetRange(styleBuf, beginSafety, endSafety);
1338
1339
1340 prevChar = getPrevChar(buf, beginSafety);
1341 parseString(pass2Patterns, &stringPtr, &stylePtr, endParse - beginSafety,
1342 &prevChar, False, GetWindowDelimiters(window), string,
NULL);
1343
1344
1345
1346 styleString[endParse-beginSafety] =
'\0';
1347 BufReplace(styleBuf, beginParse, endParse,
1348 &styleString[beginParse-beginSafety]);
1349 NEditFree(styleString);
1350 NEditFree(string);
1351 }
1352
1353
1354
1355
1356 static void handleUnparsedRegionCB(
const textDisp* textD,
int pos,
1357 const void* cbArg)
1358 {
1359 handleUnparsedRegion((WindowInfo*) cbArg, textD->styleBuffer, pos);
1360 }
1361
1362
1363
1364
1365
1366
1367
1368 static void incrementalReparse(windowHighlightData *highlightData,
1369 textBuffer *buf,
int pos,
int nInserted,
const char *delimiters)
1370 {
1371 int beginParse, endParse, endAt, lastMod, parseInStyle, nPasses;
1372 textBuffer *styleBuf = highlightData->styleBuffer;
1373 highlightDataRec *pass1Patterns = highlightData->pass1Patterns;
1374 highlightDataRec *pass2Patterns = highlightData->pass2Patterns;
1375 highlightDataRec *startPattern;
1376 reparseContext *context = &highlightData->contextRequirements;
1377 char *parentStyles = highlightData->parentStyles;
1378
1379
1380
1381
1382 beginParse = pos;
1383 parseInStyle = findSafeParseRestartPos(buf, highlightData, &beginParse);
1384
1385
1386
1387
1388 lastMod = pos + nInserted;
1389 endParse = forwardOneContext(buf, context, lastMod);
1390
1391
1392
1393
1394
1395
1396
1397
1398 for (nPasses=
0; ; nPasses++) {
1399
1400
1401
1402 startPattern = patternOfStyle(pass1Patterns, parseInStyle);
1403
1404
1405
1406
1407
1408
1409 if (!startPattern) {
1410 startPattern = pass1Patterns;
1411 }
1412 endAt = parseBufferRange(startPattern,
1413 pass2Patterns, buf, styleBuf, context, beginParse, endParse,
1414 delimiters);
1415
1416
1417
1418 if (endAt < endParse) {
1419 beginParse = endAt;
1420 endParse = forwardOneContext(buf, context,
1421 max(endAt, max(lastModified(styleBuf), lastMod)));
1422 if (
IS_PLAIN(parseInStyle)) {
1423 fprintf(stderr,
1424 "XNEdit internal error: incr. reparse fell short\n");
1425 return;
1426 }
1427 parseInStyle = parentStyleOf(parentStyles, parseInStyle);
1428
1429
1430 }
else if (lastModified(styleBuf) <= lastMod) {
1431 return;
1432
1433
1434
1435
1436 }
else {
1437 lastMod = lastModified(styleBuf);
1438 endParse = min(buf->length, forwardOneContext(buf, context, lastMod)
1439 + (
REPARSE_CHUNK_SIZE << nPasses));
1440 }
1441 }
1442 }
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459 static int parseBufferRange(highlightDataRec *pass1Patterns,
1460 highlightDataRec *pass2Patterns, textBuffer *buf, textBuffer *styleBuf,
1461 reparseContext *contextRequirements,
int beginParse,
int endParse,
1462 const char *delimiters)
1463 {
1464 char *string, *styleString, *stylePtr, *temp, prevChar;
1465 const char *stringPtr;
1466 int endSafety, endPass2Safety, startPass2Safety, tempLen;
1467 int modStart, modEnd, beginSafety, beginStyle, p, style;
1468 int firstPass2Style = pass2Patterns ==
NULL ?
INT_MAX :
1469 (
unsigned char)pass2Patterns[
1].style;
1470
1471
1472 beginStyle = pass1Patterns->style;
1473 if (
CAN_CROSS_LINE_BOUNDARIES(contextRequirements)) {
1474 beginSafety = backwardOneContext(buf, contextRequirements, beginParse);
1475 for (p=beginParse; p>=beginSafety; p--) {
1476 style = BufGetCharacter(styleBuf, p-
1);
1477 if (!
EQUIVALENT_STYLE(style, beginStyle, firstPass2Style)) {
1478 beginSafety = p;
1479 break;
1480 }
1481 }
1482 }
else {
1483 for (beginSafety=max(
0,beginParse-
1); beginSafety>
0; beginSafety--) {
1484 style = BufGetCharacter(styleBuf, beginSafety);
1485 if (!
EQUIVALENT_STYLE(style, beginStyle, firstPass2Style) ||
1486 BufGetCharacter(buf, beginSafety) ==
'\n') {
1487 beginSafety++;
1488 break;
1489 }
1490 }
1491 }
1492
1493
1494
1495
1496 if (endParse ==
0)
1497 return 0;
1498 if (
CAN_CROSS_LINE_BOUNDARIES(contextRequirements))
1499 endSafety = forwardOneContext(buf, contextRequirements, endParse);
1500 else if (endParse>=buf->length || (BufGetCharacter(buf,endParse-
1)==
'\n'))
1501 endSafety = endParse;
1502 else
1503 endSafety = min(buf->length, BufEndOfLine(buf, endParse) +
1);
1504
1505
1506 string = BufGetRange(buf, beginSafety, endSafety);
1507 styleString = BufGetRange(styleBuf, beginSafety, endSafety);
1508
1509
1510
1511 prevChar = getPrevChar(buf, beginParse);
1512 stringPtr = &string[beginParse-beginSafety];
1513 stylePtr = &styleString[beginParse-beginSafety];
1514 parseString(pass1Patterns, &stringPtr, &stylePtr, endParse-beginParse,
1515 &prevChar, False, delimiters, string,
NULL);
1516
1517
1518 endParse = min(endParse, stringPtr-string + beginSafety);
1519
1520
1521 if (pass2Patterns ==
NULL)
1522 goto parseDone;
1523
1524
1525
1526
1527 if (styleBuf->primary.selected) {
1528 modStart = styleBuf->primary.start;
1529 modEnd = styleBuf->primary.end;
1530 }
else
1531 modStart = modEnd =
0;
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541 if (beginSafety < modStart) {
1542 if (endSafety > modStart) {
1543 endPass2Safety = forwardOneContext(buf, contextRequirements,
1544 modStart);
1545 if (endPass2Safety +
PASS_2_REPARSE_CHUNK_SIZE >= modEnd)
1546 endPass2Safety = endSafety;
1547 }
else
1548 endPass2Safety = endSafety;
1549 prevChar = getPrevChar(buf, beginSafety);
1550 if (endPass2Safety == endSafety) {
1551 passTwoParseString(pass2Patterns, string, styleString,
1552 endParse - beginSafety, &prevChar, delimiters, string,
NULL);
1553 goto parseDone;
1554 }
else {
1555 tempLen = endPass2Safety - modStart;
1556 temp = (
char*)NEditMalloc(tempLen);
1557 strncpy(temp, &styleString[modStart-beginSafety], tempLen);
1558 passTwoParseString(pass2Patterns, string, styleString,
1559 modStart - beginSafety, &prevChar, delimiters, string,
NULL);
1560 strncpy(&styleString[modStart-beginSafety], temp, tempLen);
1561 NEditFree(temp);
1562 }
1563 }
1564
1565
1566
1567
1568 if (endParse > modEnd) {
1569 if (beginSafety > modEnd) {
1570 prevChar = getPrevChar(buf, beginSafety);
1571 passTwoParseString(pass2Patterns, string, styleString,
1572 endParse - beginSafety, &prevChar, delimiters, string,
NULL);
1573 }
else {
1574 startPass2Safety = max(beginSafety,
1575 backwardOneContext(buf, contextRequirements, modEnd));
1576 tempLen = modEnd - startPass2Safety;
1577 temp = (
char*)NEditMalloc(tempLen);
1578 strncpy(temp, &styleString[startPass2Safety-beginSafety], tempLen);
1579 prevChar = getPrevChar(buf, startPass2Safety);
1580 passTwoParseString(pass2Patterns,
1581 &string[startPass2Safety-beginSafety],
1582 &styleString[startPass2Safety-beginSafety],
1583 endParse-startPass2Safety, &prevChar, delimiters, string,
1584 NULL);
1585 strncpy(&styleString[startPass2Safety-beginSafety], temp, tempLen);
1586 NEditFree(temp);
1587 }
1588 }
1589
1590 parseDone:
1591
1592
1593
1594 styleString[endParse-beginSafety] =
'\0';
1595 modifyStyleBuf(styleBuf, &styleString[beginParse-beginSafety],
1596 beginParse, endParse, firstPass2Style);
1597 NEditFree(styleString);
1598 NEditFree(string);
1599
1600 return endParse;
1601 }
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626 static int parseString(highlightDataRec *pattern,
const char **string,
1627 char **styleString,
int length,
char *prevChar,
int anchored,
1628 const char *delimiters,
const char* lookBehindTo,
1629 const char* match_till)
1630 {
1631 int i, subExecuted, subIndex;
1632 char *stylePtr;
1633 const char *stringPtr, *savedStartPtr, *startingStringPtr;
1634 signed char *subExpr;
1635 char savedPrevChar;
1636 char succChar = match_till ? (*match_till) :
'\0';
1637 highlightDataRec *subPat =
NULL, *subSubPat;
1638
1639 if (length <=
0)
1640 return False;
1641
1642 stringPtr = *string;
1643 stylePtr = *styleString;
1644
1645 while (ExecRE(pattern->subPatternRE, stringPtr, anchored ? *string+
1 :
1646 *string+length+
1, False, *prevChar, succChar, delimiters,
1647 lookBehindTo, match_till)) {
1648
1649
1650
1651 subIndex = (pattern->nSubBranches >
1) ?
1652 pattern->subPatternRE->top_branch :
0;
1653
1654
1655
1656 startingStringPtr = stringPtr;
1657
1658
1659
1660 fillStyleString(&stringPtr, &stylePtr, pattern->subPatternRE->startp[
0],
1661 pattern->style, prevChar);
1662
1663
1664
1665
1666 savedStartPtr = stringPtr;
1667 savedPrevChar = *prevChar;
1668 if (pattern->endRE !=
NULL) {
1669 if (subIndex ==
0) {
1670 fillStyleString(&stringPtr, &stylePtr,
1671 pattern->subPatternRE->endp[
0], pattern->style, prevChar);
1672 subExecuted = False;
1673 for (i=
0;i<pattern->nSubPatterns; i++) {
1674 subPat = pattern->subPatterns[i];
1675 if (subPat->colorOnly) {
1676 if (!subExecuted) {
1677 if (!ExecRE(pattern->endRE, savedStartPtr,
1678 savedStartPtr+
1, False, savedPrevChar,
1679 succChar, delimiters, lookBehindTo, match_till)) {
1680 fprintf(stderr,
"Internal error, failed to "
1681 "recover end match in parseString\n");
1682 return False;
1683 }
1684 subExecuted = True;
1685 }
1686 for (subExpr=subPat->endSubexprs; *subExpr!=-
1; subExpr++)
1687 recolorSubexpr(pattern->endRE, *subExpr,
1688 subPat->style, *string, *styleString);
1689 }
1690 }
1691 *string = stringPtr;
1692 *styleString = stylePtr;
1693 return True;
1694 }
1695 --subIndex;
1696 }
1697
1698
1699
1700 if (pattern->errorRE !=
NULL) {
1701 if (subIndex ==
0) {
1702 fillStyleString(&stringPtr, &stylePtr,
1703 pattern->subPatternRE->startp[
0], pattern->style, prevChar);
1704 *string = stringPtr;
1705 *styleString = stylePtr;
1706 return False;
1707 }
1708 --subIndex;
1709 }
1710
1711
1712 for (i=
0; i<pattern->nSubPatterns; i++) {
1713 subPat = pattern->subPatterns[i];
1714 if (subPat->colorOnly) ++subIndex;
1715 else if (i == subIndex)
break;
1716 }
1717 if (i == pattern->nSubPatterns) {
1718 fprintf(stderr,
"Internal error, failed to match in parseString\n");
1719 return False;
1720 }
1721
1722
1723 if (subPat->subPatternRE ==
NULL) {
1724 fillStyleString(&stringPtr, &stylePtr, pattern->subPatternRE->endp[
0],
1725 subPat->style, prevChar);
1726
1727
1728 }
else if (subPat->endRE !=
NULL) {
1729
1730
1731
1732
1733
1734 if (!(subPat->flags &
PARSE_SUBPATS_FROM_START))
1735 fillStyleString(&stringPtr, &stylePtr, pattern->subPatternRE->endp[
0],
1736 subPat->style, prevChar);
1737
1738
1739 parseString(subPat, &stringPtr, &stylePtr, length -
1740 (stringPtr - *string), prevChar, False, delimiters,
1741 lookBehindTo, match_till);
1742 }
else {
1743
1744
1745
1746
1747
1748
1749
1750 parseString(subPat, &stringPtr, &stylePtr,
1751 pattern->subPatternRE->endp[
0]-stringPtr, prevChar, False,
1752 delimiters, lookBehindTo, pattern->subPatternRE->endp[
0]);
1753 }
1754
1755
1756
1757 subExecuted = False;
1758 for (i=
0; i<subPat->nSubPatterns; i++) {
1759 subSubPat = subPat->subPatterns[i];
1760 if (subSubPat->colorOnly) {
1761 if (!subExecuted) {
1762 if (!ExecRE(subPat->startRE, savedStartPtr,
1763 savedStartPtr+
1, False, savedPrevChar, succChar,
1764 delimiters, lookBehindTo, match_till)) {
1765 fprintf(stderr,
"Internal error, failed to recover "
1766 "start match in parseString\n");
1767 return False;
1768 }
1769 subExecuted = True;
1770 }
1771 for (subExpr=subSubPat->startSubexprs; *subExpr!=-
1; subExpr++)
1772 recolorSubexpr(subPat->startRE, *subExpr, subSubPat->style,
1773 *string, *styleString);
1774 }
1775 }
1776
1777
1778
1779 if (stringPtr == startingStringPtr) {
1780
1781
1782 if (*stringPtr ==
'\0')
1783 break;
1784 fillStyleString(&stringPtr, &stylePtr, stringPtr+
1,
1785 pattern->style, prevChar);
1786 }
1787 }
1788
1789
1790
1791 if (anchored && stringPtr == *string)
1792 return False;
1793
1794
1795
1796 if (!anchored)
1797 fillStyleString(&stringPtr, &stylePtr, *string+length, pattern->style,
1798 prevChar);
1799
1800
1801 *string = stringPtr;
1802 *styleString = stylePtr;
1803 return pattern->endRE ==
NULL;
1804 }
1805
1806
1807
1808
1809
1810
1811
1812 static void passTwoParseString(highlightDataRec *pattern,
char *string,
1813 char *styleString,
int length,
char *prevChar,
const char *delimiters,
1814 const char *lookBehindTo,
const char *match_till)
1815 {
1816 int inParseRegion = False;
1817 char *stylePtr, temp, *parseStart =
NULL, *parseEnd, *s, *c;
1818 const char *stringPtr;
1819 int firstPass2Style = (
unsigned char)pattern[
1].style;
1820
1821 for (c = string, s = styleString; ; c++, s++) {
1822 if (!inParseRegion && *c !=
'\0' && (*s ==
UNFINISHED_STYLE ||
1823 *s ==
PLAIN_STYLE || (
unsigned char)*s >= firstPass2Style)) {
1824 parseStart = c;
1825 inParseRegion = True;
1826 }
1827 if (inParseRegion && (*c ==
'\0' || !(*s ==
UNFINISHED_STYLE ||
1828 *s ==
PLAIN_STYLE || (
unsigned char)*s >= firstPass2Style))) {
1829 parseEnd = c;
1830 if (parseStart != string)
1831 *prevChar = *(parseStart-
1);
1832 stringPtr = parseStart;
1833 stylePtr = &styleString[parseStart - string];
1834 temp = *parseEnd;
1835 *parseEnd =
'\0';
1836
1837 parseString(pattern, &stringPtr, &stylePtr,
1838 min(parseEnd - parseStart, length - (parseStart - string)),
1839 prevChar, False, delimiters, lookBehindTo, match_till);
1840 *parseEnd = temp;
1841 inParseRegion = False;
1842 }
1843 if (*c ==
'\0' || (!inParseRegion && c - string >= length))
1844 break;
1845 }
1846 }
1847
1848
1849
1850
1851
1852
1853
1854 static void fillStyleString(
const char **stringPtr,
char **stylePtr,
1855 const char *toPtr,
char style,
char *prevChar)
1856 {
1857 int i, len = toPtr-*stringPtr;
1858
1859 if (*stringPtr >= toPtr)
1860 return;
1861
1862 for (i=
0; i<len; i++)
1863 *(*stylePtr)++ = style;
1864 if (prevChar !=
NULL) *prevChar = *(toPtr-
1);
1865 *stringPtr = toPtr;
1866 }
1867
1868
1869
1870
1871
1872
1873
1874
1875 static void modifyStyleBuf(textBuffer *styleBuf,
char *styleString,
1876 int startPos,
int endPos,
int firstPass2Style)
1877 {
1878 char *c, bufChar;
1879 int pos, modStart, modEnd, minPos =
INT_MAX, maxPos =
0;
1880 selection *sel = &styleBuf->primary;
1881
1882
1883 if (sel->selected) {
1884 modStart = sel->start;
1885 modEnd = sel->end;
1886 }
else
1887 modStart = modEnd = startPos;
1888
1889
1890
1891
1892
1893 for (c=styleString, pos=startPos; pos<modStart && pos<endPos; c++, pos++) {
1894 bufChar = BufGetCharacter(styleBuf, pos);
1895 if (*c != bufChar && !(bufChar ==
UNFINISHED_STYLE &&
1896 (*c ==
PLAIN_STYLE || (
unsigned char)*c >= firstPass2Style))) {
1897 if (pos < minPos) minPos = pos;
1898 if (pos > maxPos) maxPos = pos;
1899 }
1900 }
1901 for (c=&styleString[max(
0, modEnd-startPos)], pos=max(modEnd, startPos);
1902 pos<endPos; c++, pos++) {
1903 bufChar = BufGetCharacter(styleBuf, pos);
1904 if (*c != bufChar && !(bufChar ==
UNFINISHED_STYLE &&
1905 (*c ==
PLAIN_STYLE || (
unsigned char)*c >= firstPass2Style))) {
1906 if (pos < minPos) minPos = pos;
1907 if (pos+
1 > maxPos) maxPos = pos+
1;
1908 }
1909 }
1910
1911
1912 BufReplace(styleBuf, startPos, endPos, styleString);
1913
1914
1915
1916
1917 BufSelect(styleBuf, min(modStart, minPos), max(modEnd, maxPos));
1918 }
1919
1920
1921
1922
1923
1924
1925 static int lastModified(textBuffer *styleBuf)
1926 {
1927 if (styleBuf->primary.selected)
1928 return max(
0, styleBuf->primary.end);
1929 return 0;
1930 }
1931
1932
1933
1934
1935
1936 static double colorDistance(
const XColor *c1,
const XColor *c2)
1937 {
1938
1939
1940
1941
1942
1943
1944 static const double scale =
65535;
1945
1946 double tred = c1->red / scale - c2->red / scale;
1947 double tgreen = c1->green / scale - c2->green / scale;
1948 double tblue = c1->blue / scale - c2->blue / scale;
1949
1950
1951 return tred * tred + tgreen * tgreen + tblue * tblue;
1952 }
1953
1954
1955
1956
1957
1958
1959 Pixel AllocateColor(Widget w,
const char *colorName)
1960 {
1961 int dummy;
1962
1963 return AllocColor(w, colorName, &dummy, &dummy, &dummy);
1964 }
1965
1966
1967 static int printParseColorError =
1;
1968
1969 void SetParseColorError(
int value)
1970 {
1971 printParseColorError = value;
1972 }
1973
1974 XftColor ParseXftColor(Display *display, Colormap colormap, Pixel foreground,
int depth,
const char *colorName)
1975 {
1976 XftColor xftColor;
1977 memset(&xftColor,
0,
sizeof(XftColor));
1978 xftColor.color.alpha = 0xFFFF;
1979
1980 XColor colorDef;
1981 if (XParseColor(display, colormap, colorName, &colorDef)) {
1982 xftColor.color.red = colorDef.red;
1983 xftColor.color.green = colorDef.green;
1984 xftColor.color.blue = colorDef.blue;
1985 }
else if(printParseColorError) {
1986 fprintf(stderr,
"XNEdit: Color name %s not in database\n", colorName);
1987 }
1988
1989 return xftColor;
1990 }
1991
1992
1993
1994
1995
1996
1997
1998 Pixel AllocColor(Widget w,
const char *colorName,
int *r,
int *g,
int *b)
1999 {
2000 XColor colorDef;
2001 XColor *allColorDefs;
2002 Display *display = XtDisplay(w);
2003 Colormap cMap;
2004 Pixel foreground, bestPixel;
2005 double small =
1.0e9;
2006 int depth;
2007 unsigned int ncolors;
2008 unsigned long i, best =
0;
2009
2010
2011
2012
2013 XtVaGetValues(w,
2014 XtNcolormap, &cMap,
2015 XtNdepth, &depth,
2016 XtNforeground, &foreground,
2017 NULL);
2018
2019 bestPixel = foreground;
2020
2021
2022 if (! XParseColor(display, cMap, colorName, &colorDef)) {
2023 if(printParseColorError) {
2024 fprintf(stderr,
"NEdit: Color name %s not in database\n", colorName);
2025 }
2026 colorDef.pixel = foreground;
2027 if (XQueryColor(display, cMap, &colorDef)) {
2028 *r = colorDef.red;
2029 *g = colorDef.green;
2030 *b = colorDef.blue;
2031 }
2032 return foreground;
2033 }
2034
2035
2036 if (XAllocColor(display, cMap, &colorDef)) {
2037 *r = colorDef.red;
2038 *g = colorDef.green;
2039 *b = colorDef.blue;
2040 return colorDef.pixel;
2041 }
2042
2043
2044
2045 #if 0
2046 printf(
"Couldn''t allocate %d %d %d\n", colorDef.red, colorDef.green, colorDef.blue);
2047 #endif
2048
2049
2050
2051
2052 if (depth >
8) {
2053 colorDef.pixel = foreground;
2054 if (XQueryColor(display, cMap, &colorDef)) {
2055 *r = colorDef.red;
2056 *g = colorDef.green;
2057 *b = colorDef.blue;
2058 }
2059 return foreground;
2060 }
2061
2062
2063 ncolors = (
1 << depth);
2064 allColorDefs = malloc(ncolors *
sizeof(XColor));
2065 memset(allColorDefs,
0, ncolors *
sizeof(XColor));
2066
2067 for (i =
0; i < ncolors; i++)
2068 allColorDefs[i].pixel = i;
2069
2070 XQueryColors(display, cMap, allColorDefs, ncolors);
2071
2072
2073 for (i =
0; i < ncolors; i++)
2074 {
2075 double dist = colorDistance(&allColorDefs[i], &colorDef);
2076
2077 if (dist < small)
2078 {
2079 best = i;
2080 small = dist;
2081 }
2082 }
2083
2084
2085
2086
2087
2088 if (XAllocColor(display, cMap, &allColorDefs[best]))
2089 bestPixel = allColorDefs[best].pixel;
2090
2091 #if 0
2092 printf(
"Got %d %d %d, ", allColorDefs[best].red,
2093 allColorDefs[best].green,
2094 allColorDefs[best].blue);
2095 printf(
"That''s %f off\n", small);
2096 #endif
2097
2098 *r = allColorDefs[best].red;
2099 *g = allColorDefs[best].green;
2100 *b = allColorDefs[best].blue;
2101 free(allColorDefs);
2102 return bestPixel;
2103 }
2104
2105 XftColor AllocXftColor(Widget w,
const char *colorName)
2106 {
2107 int r, g, b;
2108 XftColor c;
2109 c.pixel = AllocColor(w, colorName, &r, &g, &b);
2110 c.color.red = r;
2111 c.color.green = g;
2112 c.color.blue = b;
2113 c.color.alpha = 0xFFFF;
2114 return c;
2115 }
2116
2117
2118
2119
2120 static char getPrevChar(textBuffer *buf,
int pos)
2121 {
2122 return pos ==
0 ?
'\0' : BufGetCharacter(buf, pos-
1);
2123 }
2124
2125
2126
2127
2128 static regexp *compileREAndWarn(Widget parent,
const char *re)
2129 {
2130 regexp *compiledRE;
2131 char *compileMsg;
2132
2133 compiledRE = CompileRE(re, &compileMsg,
REDFLT_STANDARD);
2134 if (compiledRE ==
NULL)
2135 {
2136 char *boundedRe = NEditStrdup(re);
2137 size_t maxLength =
DF_MAX_MSG_LENGTH - strlen(compileMsg) -
60;
2138
2139
2140
2141 if (strlen(boundedRe) > maxLength)
2142 {
2143 strcpy(&boundedRe[maxLength-
3],
"...");
2144 }
2145
2146 DialogF(
DF_WARN, parent,
1,
"Error in Regex",
2147 "Error in syntax highlighting regular expression:\n%s\n%s",
2148 "OK", boundedRe, compileMsg);
2149 NEditFree(boundedRe);
2150 return NULL;
2151 }
2152 return compiledRE;
2153 }
2154
2155 static int parentStyleOf(
const char *parentStyles,
int style)
2156 {
2157 return parentStyles[(
unsigned char)style-
UNFINISHED_STYLE];
2158 }
2159
2160 static int isParentStyle(
const char *parentStyles,
int style1,
int style2)
2161 {
2162 int p;
2163
2164 for (p = parentStyleOf(parentStyles, style2); p !=
'\0';
2165 p = parentStyleOf(parentStyles, p))
2166 if (style1 == p)
2167 return TRUE;
2168 return FALSE;
2169 }
2170
2171
2172
2173
2174
2175
2176
2177
2178 static int patternIsParsable(highlightDataRec *pattern)
2179 {
2180 return pattern !=
NULL && pattern->subPatternRE !=
NULL;
2181 }
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197 static int findSafeParseRestartPos(textBuffer *buf,
2198 windowHighlightData *highlightData,
int *pos)
2199 {
2200 int style, startStyle, runningStyle, checkBackTo, safeParseStart, i;
2201 char *parentStyles = highlightData->parentStyles;
2202 highlightDataRec *pass1Patterns = highlightData->pass1Patterns;
2203 reparseContext *context = &highlightData->contextRequirements;
2204
2205
2206 *pos = backwardOneContext(buf, context, *pos);
2207
2208
2209
2210 if (*pos ==
0)
2211 return PLAIN_STYLE;
2212 startStyle = BufGetCharacter(highlightData->styleBuffer, *pos);
2213 if (
IS_PLAIN(startStyle))
2214 return PLAIN_STYLE;
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230 if (patternIsParsable(patternOfStyle(pass1Patterns, startStyle))) {
2231 safeParseStart = backwardOneContext(buf, context, *pos);
2232 checkBackTo = backwardOneContext(buf, context, safeParseStart);
2233 }
else {
2234 safeParseStart =
0;
2235 checkBackTo =
0;
2236 }
2237 runningStyle = startStyle;
2238 for (i = *pos-
1; ; i--) {
2239
2240
2241 if (i ==
0) {
2242 *pos =
0;
2243 return PLAIN_STYLE;
2244 }
2245
2246
2247
2248 style = BufGetCharacter(highlightData->styleBuffer, i);
2249 if (isParentStyle(parentStyles, style, runningStyle)) {
2250 if (patternIsParsable(patternOfStyle(pass1Patterns, style))) {
2251 *pos = i +
1;
2252 return style;
2253 }
else {
2254
2255
2256 runningStyle = style;
2257 }
2258 }
2259
2260
2261
2262
2263 else if (isParentStyle(parentStyles, runningStyle, style)) {
2264 if (patternIsParsable
2265 (patternOfStyle(pass1Patterns, runningStyle))) {
2266 *pos = i +
1;
2267 return runningStyle;
2268 }
2269
2270
2271 }
2272
2273
2274
2275
2276
2277
2278 else if (runningStyle != style &&
2279 isParentStyle(parentStyles,
2280 parentStyleOf(parentStyles, runningStyle), style)) {
2281 int parentStyle = parentStyleOf(parentStyles, runningStyle);
2282 if (patternIsParsable(patternOfStyle(pass1Patterns, parentStyle))) {
2283 *pos = i +
1;
2284 return parentStyle;
2285 }
else {
2286
2287 runningStyle = style;
2288 }
2289 }
2290
2291
2292
2293
2294
2295 else if (runningStyle != style) {
2296 *pos = i +
1;
2297 return PLAIN_STYLE;
2298 }
2299
2300
2301
2302
2303
2304
2305 if (i == checkBackTo) {
2306 *pos = safeParseStart;
2307
2308
2309
2310
2311
2312
2313
2314
2315 while (!patternIsParsable
2316 (patternOfStyle(pass1Patterns, runningStyle)))
2317 runningStyle = parentStyleOf(parentStyles, runningStyle);
2318
2319 return runningStyle;
2320 }
2321 }
2322 }
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336 static int backwardOneContext(textBuffer *buf, reparseContext *context,
2337 int fromPos)
2338 {
2339 if (context->nLines ==
0)
2340 return max(
0, fromPos - context->nChars);
2341 else if (context->nChars ==
0)
2342 return max(
0,
2343 BufCountBackwardNLines(buf, fromPos, context->nLines-
1) -
1);
2344 else
2345 return max(
0, min(max(
0, BufCountBackwardNLines(buf, fromPos,
2346 context->nLines-
1) -
1), fromPos - context->nChars));
2347 }
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357 static int forwardOneContext(textBuffer *buf, reparseContext *context,
2358 int fromPos)
2359 {
2360 if (context->nLines ==
0)
2361 return min(buf->length, fromPos + context->nChars);
2362 else if (context->nChars ==
0)
2363 return min(buf->length,
2364 BufCountForwardNLines(buf, fromPos, context->nLines));
2365 else
2366 return min(buf->length, max(BufCountForwardNLines(buf, fromPos,
2367 context->nLines), fromPos + context->nChars));
2368 }
2369
2370
2371
2372
2373
2374
2375 static void recolorSubexpr(regexp *re,
int subexpr,
int style,
2376 const char *string,
char *styleString)
2377 {
2378 const char *stringPtr;
2379 char *stylePtr;
2380
2381 stringPtr = re->startp[subexpr];
2382 stylePtr = &styleString[stringPtr - string];
2383 fillStyleString(&stringPtr, &stylePtr, re->endp[subexpr], style,
NULL);
2384 }
2385
2386
2387
2388
2389 static highlightDataRec *patternOfStyle(highlightDataRec *patterns,
int style)
2390 {
2391 int i;
2392 for (i=
0; patterns[i].style!=
0; i++)
2393 if (patterns[i].style == style)
2394 return &patterns[i];
2395 if (style ==
PLAIN_STYLE || style ==
UNFINISHED_STYLE)
2396 return &patterns[
0];
2397 return NULL;
2398 }
2399
2400 static int max(
int i1,
int i2)
2401 {
2402 return i1 >= i2 ? i1 : i2;
2403 }
2404
2405 static int min(
int i1,
int i2)
2406 {
2407 return i1 <= i2 ? i1 : i2;
2408 }
2409
2410 static int indexOfNamedPattern(highlightPattern *patList,
int nPats,
2411 const char *patName)
2412 {
2413 int i;
2414
2415 if (patName ==
NULL)
2416 return -
1;
2417 for (i=
0; i<nPats; i++)
2418 if (!strcmp(patList[i].name, patName))
2419 return i;
2420 return -
1;
2421 }
2422
2423 static int findTopLevelParentIndex(highlightPattern *patList,
int nPats,
2424 int index)
2425 {
2426 int topIndex;
2427
2428 topIndex = index;
2429 while (patList[topIndex].subPatternOf !=
NULL) {
2430 topIndex = indexOfNamedPattern(patList, nPats,
2431 patList[topIndex].subPatternOf);
2432 if (index==topIndex)
2433 return -
1;
2434 }
2435 return topIndex;
2436 }
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446 static void updateWindowHeight(WindowInfo *window,
int oldFontHeight)
2447 {
2448 int i, borderHeight, marginHeight;
2449 Dimension windowHeight, textAreaHeight, textHeight, newWindowHeight;
2450
2451
2452
2453 if (NDocuments(window) >
1)
2454 return;
2455
2456
2457
2458 XtVaGetValues(window->shell, XmNheight, &windowHeight,
NULL);
2459 XtVaGetValues(window->textArea, XmNheight, &textAreaHeight,
2460 textNmarginHeight, &marginHeight,
NULL);
2461 textHeight = textAreaHeight -
2*marginHeight;
2462 for (i=
0; i<window->nPanes; i++) {
2463 XtVaGetValues(window->textPanes[i], XmNheight, &textAreaHeight,
NULL);
2464 textHeight += textAreaHeight -
2*marginHeight;
2465 }
2466 borderHeight = windowHeight - textHeight;
2467
2468
2469 newWindowHeight = (textHeight*getFontHeight(window)) / oldFontHeight +
2470 borderHeight;
2471
2472
2473
2474
2475
2476 XtVaSetValues(window->shell, XmNheightInc, getFontHeight(window),
NULL);
2477
2478
2479 XtVaSetValues(window->shell, XmNheight, newWindowHeight,
NULL);
2480 }
2481
2482
2483
2484
2485
2486
2487 static int getFontHeight(WindowInfo *window)
2488 {
2489 textDisp *textD = ((TextWidget)window->textArea)->text.textD;
2490
2491 return textD->ascent + textD->descent;
2492 }
2493
2494 XftColor LightenColor(XftColor color)
2495 {
2496 int r = color.color.red;
2497 int g = color.color.green;
2498 int b = color.color.blue;
2499
2500
2501
2502 if(abs(r-g) <
5 && abs(g-b) <
5) {
2503 r = 0xFFFF - r;
2504 g = 0xFFFF - g;
2505 b = 0xFFFF - b;
2506 }
else {
2507
2508 r = r + 0x8000;
2509 g = g + 0x8000;
2510 b = b + 0x8000;
2511 if(r > 0xFFFF) r = 0xFFFF;
2512 if(g > 0xFFFF) g = 0xFFFF;
2513 if(b > 0xFFFF) b = 0xFFFF;
2514 }
2515
2516 color.color.red = r;
2517 color.color.green = g;
2518 color.color.blue = b;
2519 return color;
2520 }
2521