1 // Scintilla source code edit control
2 /** @file LexFortran.cxx
4 ** Written by Chuan-jian Shen, Last changed Sep. 2003
6 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
7 // The License.txt file describes the conditions under which this software may be distributed.
8 /***************************************/
15 /***************************************/
17 #include "Scintilla.h"
21 #include "LexAccessor.h"
23 #include "StyleContext.h"
24 #include "CharacterSet.h"
25 #include "LexerModule.h"
26 /***************************************/
29 using namespace Scintilla
;
32 /***********************************************/
33 static inline bool IsAWordChar(const int ch
) {
34 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_' || ch
== '%');
36 /**********************************************/
37 static inline bool IsAWordStart(const int ch
) {
38 return (ch
< 0x80) && (isalnum(ch
));
40 /***************************************/
41 static inline bool IsABlank(unsigned int ch
) {
42 return (ch
== ' ') || (ch
== 0x09) || (ch
== 0x0b) ;
44 /***************************************/
45 static inline bool IsALineEnd(char ch
) {
46 return ((ch
== '\n') || (ch
== '\r')) ;
48 /***************************************/
49 static Sci_PositionU
GetContinuedPos(Sci_PositionU pos
, Accessor
&styler
) {
50 while (!IsALineEnd(styler
.SafeGetCharAt(pos
++))) continue;
51 if (styler
.SafeGetCharAt(pos
) == '\n') pos
++;
52 while (IsABlank(styler
.SafeGetCharAt(pos
++))) continue;
53 char chCur
= styler
.SafeGetCharAt(pos
);
55 while (IsABlank(styler
.SafeGetCharAt(++pos
))) continue;
61 /***************************************/
62 static void ColouriseFortranDoc(Sci_PositionU startPos
, Sci_Position length
, int initStyle
,
63 WordList
*keywordlists
[], Accessor
&styler
, bool isFixFormat
) {
64 WordList
&keywords
= *keywordlists
[0];
65 WordList
&keywords2
= *keywordlists
[1];
66 WordList
&keywords3
= *keywordlists
[2];
67 /***************************************/
68 Sci_Position posLineStart
= 0;
69 int numNonBlank
= 0, prevState
= 0;
70 Sci_Position endPos
= startPos
+ length
;
71 /***************************************/
72 // backtrack to the nearest keyword
73 while ((startPos
> 1) && (styler
.StyleAt(startPos
) != SCE_F_WORD
)) {
76 startPos
= styler
.LineStart(styler
.GetLine(startPos
));
77 initStyle
= styler
.StyleAt(startPos
- 1);
78 StyleContext
sc(startPos
, endPos
-startPos
, initStyle
, styler
);
79 /***************************************/
80 for (; sc
.More(); sc
.Forward()) {
81 // remember the start position of the line
83 posLineStart
= sc
.currentPos
;
85 sc
.SetState(SCE_F_DEFAULT
);
87 if (!IsASpaceOrTab(sc
.ch
)) numNonBlank
++;
88 /***********************************************/
89 // Handle the fix format generically
90 Sci_Position toLineStart
= sc
.currentPos
- posLineStart
;
91 if (isFixFormat
&& (toLineStart
< 6 || toLineStart
>= 72)) {
92 if ((toLineStart
== 0 && (tolower(sc
.ch
) == 'c' || sc
.ch
== '*')) || sc
.ch
== '!') {
93 if (sc
.MatchIgnoreCase("cdec$") || sc
.MatchIgnoreCase("*dec$") || sc
.MatchIgnoreCase("!dec$") ||
94 sc
.MatchIgnoreCase("cdir$") || sc
.MatchIgnoreCase("*dir$") || sc
.MatchIgnoreCase("!dir$") ||
95 sc
.MatchIgnoreCase("cms$") || sc
.MatchIgnoreCase("*ms$") || sc
.MatchIgnoreCase("!ms$") ||
97 sc
.SetState(SCE_F_PREPROCESSOR
);
99 sc
.SetState(SCE_F_COMMENT
);
102 while (!sc
.atLineEnd
&& sc
.More()) sc
.Forward(); // Until line end
103 } else if (toLineStart
>= 72) {
104 sc
.SetState(SCE_F_COMMENT
);
105 while (!sc
.atLineEnd
&& sc
.More()) sc
.Forward(); // Until line end
106 } else if (toLineStart
< 5) {
108 sc
.SetState(SCE_F_LABEL
);
110 sc
.SetState(SCE_F_DEFAULT
);
111 } else if (toLineStart
== 5) {
112 //if (!IsASpace(sc.ch) && sc.ch != '0') {
113 if (sc
.ch
!= '\r' && sc
.ch
!= '\n') {
114 sc
.SetState(SCE_F_CONTINUATION
);
115 if (!IsASpace(sc
.ch
) && sc
.ch
!= '0')
116 sc
.ForwardSetState(prevState
);
118 sc
.SetState(SCE_F_DEFAULT
);
122 /***************************************/
123 // Handle line continuation generically.
124 if (!isFixFormat
&& sc
.ch
== '&' && sc
.state
!= SCE_F_COMMENT
) {
127 while (IsABlank(chTemp
) && j
<132) {
128 chTemp
= static_cast<char>(sc
.GetRelative(j
));
132 sc
.SetState(SCE_F_CONTINUATION
);
133 if (sc
.chNext
== '!') sc
.ForwardSetState(SCE_F_COMMENT
);
134 } else if (chTemp
== '\r' || chTemp
== '\n') {
135 int currentState
= sc
.state
;
136 sc
.SetState(SCE_F_CONTINUATION
);
137 sc
.ForwardSetState(SCE_F_DEFAULT
);
138 while (IsASpace(sc
.ch
) && sc
.More()) {
140 if (sc
.atLineStart
) numNonBlank
= 0;
141 if (!IsASpaceOrTab(sc
.ch
)) numNonBlank
++;
144 sc
.SetState(SCE_F_CONTINUATION
);
147 sc
.SetState(currentState
);
150 /***************************************/
151 // Hanndle preprocessor directives
152 if (sc
.ch
== '#' && numNonBlank
== 1)
154 sc
.SetState(SCE_F_PREPROCESSOR
);
155 while (!sc
.atLineEnd
&& sc
.More())
156 sc
.Forward(); // Until line end
158 /***************************************/
159 // Determine if the current state should terminate.
160 if (sc
.state
== SCE_F_OPERATOR
) {
161 sc
.SetState(SCE_F_DEFAULT
);
162 } else if (sc
.state
== SCE_F_NUMBER
) {
163 if (!(IsAWordChar(sc
.ch
) || sc
.ch
=='\'' || sc
.ch
=='\"' || sc
.ch
=='.')) {
164 sc
.SetState(SCE_F_DEFAULT
);
166 } else if (sc
.state
== SCE_F_IDENTIFIER
) {
167 if (!IsAWordChar(sc
.ch
) || (sc
.ch
== '%')) {
169 sc
.GetCurrentLowered(s
, sizeof(s
));
170 if (keywords
.InList(s
)) {
171 sc
.ChangeState(SCE_F_WORD
);
172 } else if (keywords2
.InList(s
)) {
173 sc
.ChangeState(SCE_F_WORD2
);
174 } else if (keywords3
.InList(s
)) {
175 sc
.ChangeState(SCE_F_WORD3
);
177 sc
.SetState(SCE_F_DEFAULT
);
179 } else if (sc
.state
== SCE_F_COMMENT
|| sc
.state
== SCE_F_PREPROCESSOR
) {
180 if (sc
.ch
== '\r' || sc
.ch
== '\n') {
181 sc
.SetState(SCE_F_DEFAULT
);
183 } else if (sc
.state
== SCE_F_STRING1
) {
184 prevState
= sc
.state
;
186 if (sc
.chNext
== '\'') {
189 sc
.ForwardSetState(SCE_F_DEFAULT
);
190 prevState
= SCE_F_DEFAULT
;
192 } else if (sc
.atLineEnd
) {
193 sc
.ChangeState(SCE_F_STRINGEOL
);
194 sc
.ForwardSetState(SCE_F_DEFAULT
);
196 } else if (sc
.state
== SCE_F_STRING2
) {
197 prevState
= sc
.state
;
199 sc
.ChangeState(SCE_F_STRINGEOL
);
200 sc
.ForwardSetState(SCE_F_DEFAULT
);
201 } else if (sc
.ch
== '\"') {
202 if (sc
.chNext
== '\"') {
205 sc
.ForwardSetState(SCE_F_DEFAULT
);
206 prevState
= SCE_F_DEFAULT
;
209 } else if (sc
.state
== SCE_F_OPERATOR2
) {
211 sc
.ForwardSetState(SCE_F_DEFAULT
);
213 } else if (sc
.state
== SCE_F_CONTINUATION
) {
214 sc
.SetState(SCE_F_DEFAULT
);
215 } else if (sc
.state
== SCE_F_LABEL
) {
216 if (!IsADigit(sc
.ch
)) {
217 sc
.SetState(SCE_F_DEFAULT
);
219 if (isFixFormat
&& sc
.currentPos
-posLineStart
> 4)
220 sc
.SetState(SCE_F_DEFAULT
);
221 else if (numNonBlank
> 5)
222 sc
.SetState(SCE_F_DEFAULT
);
225 /***************************************/
226 // Determine if a new state should be entered.
227 if (sc
.state
== SCE_F_DEFAULT
) {
229 if (sc
.MatchIgnoreCase("!dec$") || sc
.MatchIgnoreCase("!dir$") ||
230 sc
.MatchIgnoreCase("!ms$") || sc
.chNext
== '$') {
231 sc
.SetState(SCE_F_PREPROCESSOR
);
233 sc
.SetState(SCE_F_COMMENT
);
235 } else if ((!isFixFormat
) && IsADigit(sc
.ch
) && numNonBlank
== 1) {
236 sc
.SetState(SCE_F_LABEL
);
237 } else if (IsADigit(sc
.ch
) || (sc
.ch
== '.' && IsADigit(sc
.chNext
))) {
238 sc
.SetState(SCE_F_NUMBER
);
239 } else if ((tolower(sc
.ch
) == 'b' || tolower(sc
.ch
) == 'o' ||
240 tolower(sc
.ch
) == 'z') && (sc
.chNext
== '\"' || sc
.chNext
== '\'')) {
241 sc
.SetState(SCE_F_NUMBER
);
243 } else if (sc
.ch
== '.' && isalpha(sc
.chNext
)) {
244 sc
.SetState(SCE_F_OPERATOR2
);
245 } else if (IsAWordStart(sc
.ch
)) {
246 sc
.SetState(SCE_F_IDENTIFIER
);
247 } else if (sc
.ch
== '\"') {
248 sc
.SetState(SCE_F_STRING2
);
249 } else if (sc
.ch
== '\'') {
250 sc
.SetState(SCE_F_STRING1
);
251 } else if (isoperator(static_cast<char>(sc
.ch
))) {
252 sc
.SetState(SCE_F_OPERATOR
);
258 /***************************************/
259 static void CheckLevelCommentLine(const unsigned int nComL
,
260 int nComColB
[], int nComColF
[], int &nComCur
,
261 bool comLineB
[], bool comLineF
[], bool &comLineCur
,
262 int &levelDeltaNext
) {
268 if (!comLineF
[0] || nComColF
[0] != nComCur
) {
270 for (; i
<nComL
; i
++) {
271 if (!comLineB
[i
] || nComColB
[i
] != nComCur
) {
279 else if (!comLineB
[0] || nComColB
[0] != nComCur
) {
281 for (; i
<nComL
; i
++) {
282 if (!comLineF
[i
] || nComColF
[i
] != nComCur
) {
291 /***************************************/
292 static void GetIfLineComment(Accessor
&styler
, bool isFixFormat
, const Sci_Position line
, bool &isComLine
, Sci_Position
&comCol
) {
293 Sci_Position col
= 0;
295 Sci_Position pos
= styler
.LineStart(line
);
296 Sci_Position len
= styler
.Length();
298 char ch
= styler
.SafeGetCharAt(pos
);
299 if (ch
== '!' || (isFixFormat
&& col
== 0 && (tolower(ch
) == 'c' || ch
== '*'))) {
304 else if (!IsABlank(ch
) || IsALineEnd(ch
)) {
311 /***************************************/
312 static void StepCommentLine(Accessor
&styler
, bool isFixFormat
, Sci_Position lineCurrent
, const unsigned int nComL
,
313 Sci_Position nComColB
[], Sci_Position nComColF
[], Sci_Position
&nComCur
,
314 bool comLineB
[], bool comLineF
[], bool &comLineCur
) {
315 Sci_Position nLineTotal
= styler
.GetLine(styler
.Length()-1) + 1;
316 if (lineCurrent
>= nLineTotal
) {
320 for (int i
=nComL
-2; i
>=0; i
--) {
321 nComColB
[i
+1] = nComColB
[i
];
322 comLineB
[i
+1] = comLineB
[i
];
324 nComColB
[0] = nComCur
;
325 comLineB
[0] = comLineCur
;
326 nComCur
= nComColF
[0];
327 comLineCur
= comLineF
[0];
328 for (unsigned int i
=0; i
+1<nComL
; i
++) {
329 nComColF
[i
] = nComColF
[i
+1];
330 comLineF
[i
] = comLineF
[i
+1];
332 Sci_Position chL
= lineCurrent
+ nComL
;
333 if (chL
< nLineTotal
) {
334 GetIfLineComment(styler
, isFixFormat
, chL
, comLineF
[nComL
-1], nComColF
[nComL
-1]);
337 comLineF
[nComL
-1] = false;
340 /***************************************/
341 static void CheckBackComLines(Accessor
&styler
, bool isFixFormat
, Sci_Position lineCurrent
, const unsigned int nComL
,
342 Sci_Position nComColB
[], Sci_Position nComColF
[], Sci_Position nComCur
,
343 bool comLineB
[], bool comLineF
[], bool &comLineCur
) {
344 unsigned int nLines
= nComL
+ nComL
+ 1;
345 bool* comL
= new bool[nLines
];
346 Sci_Position
* nComCol
= new Sci_Position
[nLines
];
348 Sci_Position nComCol0
;
349 GetIfLineComment(styler
, isFixFormat
, lineCurrent
-nComL
-1, comL0
, nComCol0
);
350 for (unsigned int i
=0; i
<nComL
; i
++) {
351 unsigned copyTo
= nComL
- i
- 1;
352 comL
[copyTo
] = comLineB
[i
];
353 nComCol
[copyTo
] = nComColB
[i
];
355 assert(nComL
< nLines
);
356 comL
[nComL
] = comLineCur
;
357 nComCol
[nComL
] = nComCur
;
358 for (unsigned int i
=0; i
<nComL
; i
++) {
359 unsigned copyTo
= i
+ nComL
+ 1;
360 comL
[copyTo
] = comLineF
[i
];
361 nComCol
[copyTo
] = nComColF
[i
];
364 Sci_Position lineC
= lineCurrent
- nComL
+ 1;
368 iStart
= nComL
- lineCurrent
;
373 bool levChanged
= false;
374 int lev
= styler
.LevelAt(lineC
) & SC_FOLDLEVELNUMBERMASK
;
376 for (unsigned int i
=iStart
; i
<=nComL
; i
++) {
377 if (comL
[i
] && (!comL
[i
-1] || nComCol
[i
] != nComCol
[i
-1])) {
378 bool increase
= true;
379 unsigned int until
= i
+ nComL
;
380 for (unsigned int j
=i
+1; j
<=until
; j
++) {
381 if (!comL
[j
] || nComCol
[j
] != nComCol
[i
]) {
386 lev
= styler
.LevelAt(lineC
) & SC_FOLDLEVELNUMBERMASK
;
388 int levH
= lev
| SC_FOLDLEVELHEADERFLAG
;
390 if (levH
!= styler
.LevelAt(lineC
)) {
391 styler
.SetLevel(lineC
, levH
);
393 for (Sci_Position j
=lineC
+1; j
<=lineCurrent
; j
++) {
394 if (lev
!= styler
.LevelAt(j
)) {
395 styler
.SetLevel(j
, lev
);
401 if (lev
!= styler
.LevelAt(lineC
)) {
402 styler
.SetLevel(lineC
, lev
);
407 else if (levChanged
&& comL
[i
]) {
408 if (lev
!= styler
.LevelAt(lineC
)) {
409 styler
.SetLevel(lineC
, lev
);
417 /***************************************/
418 // To determine the folding level depending on keywords
419 static int classifyFoldPointFortran(const char* s
, const char* prevWord
, const char chNextNonBlank
) {
422 if ((strcmp(prevWord
, "module") == 0 && strcmp(s
, "subroutine") == 0)
423 || (strcmp(prevWord
, "module") == 0 && strcmp(s
, "function") == 0)) {
425 } else if (strcmp(s
, "associate") == 0 || strcmp(s
, "block") == 0
426 || strcmp(s
, "blockdata") == 0 || strcmp(s
, "select") == 0
427 || strcmp(s
, "selecttype") == 0 || strcmp(s
, "selectcase") == 0
428 || strcmp(s
, "do") == 0 || strcmp(s
, "enum") ==0
429 || strcmp(s
, "function") == 0 || strcmp(s
, "interface") == 0
430 || strcmp(s
, "module") == 0 || strcmp(s
, "program") == 0
431 || strcmp(s
, "subroutine") == 0 || strcmp(s
, "then") == 0
432 || (strcmp(s
, "type") == 0 && chNextNonBlank
!= '(')
433 || strcmp(s
, "critical") == 0 || strcmp(s
, "submodule") == 0){
434 if (strcmp(prevWord
, "end") == 0)
438 } else if ((strcmp(s
, "end") == 0 && chNextNonBlank
!= '=')
439 || strcmp(s
, "endassociate") == 0 || strcmp(s
, "endblock") == 0
440 || strcmp(s
, "endblockdata") == 0 || strcmp(s
, "endselect") == 0
441 || strcmp(s
, "enddo") == 0 || strcmp(s
, "endenum") ==0
442 || strcmp(s
, "endif") == 0 || strcmp(s
, "endforall") == 0
443 || strcmp(s
, "endfunction") == 0 || strcmp(s
, "endinterface") == 0
444 || strcmp(s
, "endmodule") == 0 || strcmp(s
, "endprogram") == 0
445 || strcmp(s
, "endsubroutine") == 0 || strcmp(s
, "endtype") == 0
446 || strcmp(s
, "endwhere") == 0 || strcmp(s
, "endcritical") == 0
447 || (strcmp(prevWord
, "module") == 0 && strcmp(s
, "procedure") == 0) // Take care of the "module procedure" statement
448 || strcmp(s
, "endsubmodule") == 0) {
450 } else if (strcmp(prevWord
, "end") == 0 && strcmp(s
, "if") == 0){ // end if
452 } else if (strcmp(prevWord
, "type") == 0 && strcmp(s
, "is") == 0){ // type is
454 } else if ((strcmp(prevWord
, "end") == 0 && strcmp(s
, "procedure") == 0)
455 || strcmp(s
, "endprocedure") == 0) {
456 lev
= 1; // level back to 0, because no folding support for "module procedure" in submodule
460 /***************************************/
462 static void FoldFortranDoc(Sci_PositionU startPos
, Sci_Position length
, int initStyle
,
463 Accessor
&styler
, bool isFixFormat
) {
465 bool foldComment
= styler
.GetPropertyInt("fold.comment", 1) != 0;
466 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
467 Sci_PositionU endPos
= startPos
+ length
;
468 int visibleChars
= 0;
469 Sci_Position lineCurrent
= styler
.GetLine(startPos
);
471 if (lineCurrent
> 0) {
473 startPos
= styler
.LineStart(lineCurrent
);
478 char chNext
= styler
[startPos
];
479 int styleNext
= styler
.StyleAt(startPos
);
480 int style
= initStyle
;
481 int levelDeltaNext
= 0;
483 const unsigned int nComL
= 3; // defines how many comment lines should be before they are folded
484 Sci_Position nComColB
[nComL
];
485 Sci_Position nComColF
[nComL
] = {};
486 Sci_Position nComCur
;
487 bool comLineB
[nComL
];
488 bool comLineF
[nComL
];
490 Sci_Position nLineTotal
= styler
.GetLine(styler
.Length()-1) + 1;
492 for (unsigned int i
=0; i
<nComL
; i
++) {
493 Sci_Position chL
= lineCurrent
-(i
+1);
498 GetIfLineComment(styler
, isFixFormat
, chL
, comLineB
[i
], nComColB
[i
]);
500 for (unsigned int j
=i
+1; j
<nComL
; j
++) {
506 for (unsigned int i
=0; i
<nComL
; i
++) {
507 Sci_Position chL
= lineCurrent
+i
+1;
508 if (chL
>= nLineTotal
) {
512 GetIfLineComment(styler
, isFixFormat
, chL
, comLineF
[i
], nComColF
[i
]);
514 GetIfLineComment(styler
, isFixFormat
, lineCurrent
, comLineCur
, nComCur
);
515 CheckBackComLines(styler
, isFixFormat
, lineCurrent
, nComL
, nComColB
, nComColF
, nComCur
,
516 comLineB
, comLineF
, comLineCur
);
518 int levelCurrent
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
520 /***************************************/
521 Sci_Position lastStart
= 0;
522 char prevWord
[32] = "";
523 /***************************************/
524 for (Sci_PositionU i
= startPos
; i
< endPos
; i
++) {
526 chNext
= styler
.SafeGetCharAt(i
+ 1);
527 char chNextNonBlank
= chNext
;
528 bool nextEOL
= false;
529 if (IsALineEnd(chNextNonBlank
)) {
533 while(IsABlank(chNextNonBlank
) && j
<endPos
) {
535 chNextNonBlank
= styler
.SafeGetCharAt(j
);
536 if (IsALineEnd(chNextNonBlank
)) {
540 if (!nextEOL
&& j
== endPos
) {
543 int stylePrev
= style
;
545 styleNext
= styler
.StyleAt(i
+ 1);
546 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
548 if (((isFixFormat
&& stylePrev
== SCE_F_CONTINUATION
) || stylePrev
== SCE_F_DEFAULT
549 || stylePrev
== SCE_F_OPERATOR
) && (style
== SCE_F_WORD
|| style
== SCE_F_LABEL
)) {
550 // Store last word and label start point.
553 /***************************************/
554 if (style
== SCE_F_WORD
) {
555 if(iswordchar(ch
) && !iswordchar(chNext
)) {
558 for(k
=0; (k
<31 ) && (k
<i
-lastStart
+1 ); k
++) {
559 s
[k
] = static_cast<char>(tolower(styler
[lastStart
+k
]));
562 // Handle the forall and where statement and structure.
563 if (strcmp(s
, "forall") == 0 || (strcmp(s
, "where") == 0 && strcmp(prevWord
, "else") != 0)) {
564 if (strcmp(prevWord
, "end") != 0) {
566 char chBrace
= '(', chSeek
= ')', ch1
= styler
.SafeGetCharAt(j
);
567 // Find the position of the first (
568 while (ch1
!= chBrace
&& j
<endPos
) {
570 ch1
= styler
.SafeGetCharAt(j
);
572 char styBrace
= styler
.StyleAt(j
);
578 chAtPos
= styler
.SafeGetCharAt(j
);
579 styAtPos
= styler
.StyleAt(j
);
580 if (styAtPos
== styBrace
) {
581 if (chAtPos
== chBrace
) depth
++;
582 if (chAtPos
== chSeek
) depth
--;
583 if (depth
== 0) break;
586 Sci_Position tmpLineCurrent
= lineCurrent
;
589 chAtPos
= styler
.SafeGetCharAt(j
);
590 styAtPos
= styler
.StyleAt(j
);
591 if (!IsALineEnd(chAtPos
) && (styAtPos
== SCE_F_COMMENT
|| IsABlank(chAtPos
))) continue;
593 if (!IsALineEnd(chAtPos
)) {
596 if (tmpLineCurrent
< styler
.GetLine(styler
.Length()-1)) {
598 j
= styler
.LineStart(tmpLineCurrent
);
599 if (styler
.StyleAt(j
+5) == SCE_F_CONTINUATION
600 && !IsABlank(styler
.SafeGetCharAt(j
+5)) && styler
.SafeGetCharAt(j
+5) != '0') {
610 if (chAtPos
== '&' && styler
.StyleAt(j
) == SCE_F_CONTINUATION
) {
611 j
= GetContinuedPos(j
+1, styler
);
613 } else if (IsALineEnd(chAtPos
)) {
623 int wordLevelDelta
= classifyFoldPointFortran(s
, prevWord
, chNextNonBlank
);
624 levelDeltaNext
+= wordLevelDelta
;
625 if (((strcmp(s
, "else") == 0) && (nextEOL
|| chNextNonBlank
== '!')) ||
626 (strcmp(prevWord
, "else") == 0 && strcmp(s
, "where") == 0) || strcmp(s
, "elsewhere") == 0) {
631 } else if ((strcmp(prevWord
, "else") == 0 && strcmp(s
, "if") == 0) || strcmp(s
, "elseif") == 0) {
635 } else if ((strcmp(prevWord
, "select") == 0 && strcmp(s
, "case") == 0) || strcmp(s
, "selectcase") == 0 ||
636 (strcmp(prevWord
, "select") == 0 && strcmp(s
, "type") == 0) || strcmp(s
, "selecttype") == 0) {
638 } else if ((strcmp(s
, "case") == 0 && chNextNonBlank
== '(') || (strcmp(prevWord
, "case") == 0 && strcmp(s
, "default") == 0) ||
639 (strcmp(prevWord
, "type") == 0 && strcmp(s
, "is") == 0) ||
640 (strcmp(prevWord
, "class") == 0 && strcmp(s
, "is") == 0) ||
641 (strcmp(prevWord
, "class") == 0 && strcmp(s
, "default") == 0) ) {
646 } else if ((strcmp(prevWord
, "end") == 0 && strcmp(s
, "select") == 0) || strcmp(s
, "endselect") == 0) {
650 // There are multiple forms of "do" loop. The older form with a label "do 100 i=1,10" would require matching
651 // labels to ensure the folding level does not decrease too far when labels are used for other purposes.
652 // Since this is difficult, do-label constructs are not folded.
653 if (strcmp(s
, "do") == 0 && IsADigit(chNextNonBlank
)) {
654 // Remove delta for do-label
655 levelDeltaNext
-= wordLevelDelta
;
664 CheckLevelCommentLine(nComL
, nComColB
, nComColF
, nComCur
, comLineB
, comLineF
, comLineCur
, ldNext
);
665 levelDeltaNext
+= ldNext
;
667 int lev
= levelCurrent
;
668 if (visibleChars
== 0 && foldCompact
)
669 lev
|= SC_FOLDLEVELWHITEFLAG
;
670 if ((levelDeltaNext
> 0) && (visibleChars
> 0))
671 lev
|= SC_FOLDLEVELHEADERFLAG
;
672 if (lev
!= styler
.LevelAt(lineCurrent
))
673 styler
.SetLevel(lineCurrent
, lev
);
676 levelCurrent
+= levelDeltaNext
;
679 strcpy(prevWord
, "");
683 StepCommentLine(styler
, isFixFormat
, lineCurrent
, nComL
, nComColB
, nComColF
, nComCur
,
684 comLineB
, comLineF
, comLineCur
);
687 /***************************************/
688 if (!isspacechar(ch
)) visibleChars
++;
690 /***************************************/
692 /***************************************/
693 static const char * const FortranWordLists
[] = {
694 "Primary keywords and identifiers",
695 "Intrinsic functions",
696 "Extended and user defined functions",
699 /***************************************/
700 static void ColouriseFortranDocFreeFormat(Sci_PositionU startPos
, Sci_Position length
, int initStyle
, WordList
*keywordlists
[],
702 ColouriseFortranDoc(startPos
, length
, initStyle
, keywordlists
, styler
, false);
704 /***************************************/
705 static void ColouriseFortranDocFixFormat(Sci_PositionU startPos
, Sci_Position length
, int initStyle
, WordList
*keywordlists
[],
707 ColouriseFortranDoc(startPos
, length
, initStyle
, keywordlists
, styler
, true);
709 /***************************************/
710 static void FoldFortranDocFreeFormat(Sci_PositionU startPos
, Sci_Position length
, int initStyle
,
711 WordList
*[], Accessor
&styler
) {
712 FoldFortranDoc(startPos
, length
, initStyle
,styler
, false);
714 /***************************************/
715 static void FoldFortranDocFixFormat(Sci_PositionU startPos
, Sci_Position length
, int initStyle
,
716 WordList
*[], Accessor
&styler
) {
717 FoldFortranDoc(startPos
, length
, initStyle
,styler
, true);
719 /***************************************/
720 LexerModule
lmFortran(SCLEX_FORTRAN
, ColouriseFortranDocFreeFormat
, "fortran", FoldFortranDocFreeFormat
, FortranWordLists
);
721 LexerModule
lmF77(SCLEX_F77
, ColouriseFortranDocFixFormat
, "f77", FoldFortranDocFixFormat
, FortranWordLists
);