392 lines
12 KiB
C++
392 lines
12 KiB
C++
|
/* h_rexx.cpp
|
||
|
*
|
||
|
* Copyright (c) 1994-1996, Marko Macek
|
||
|
*
|
||
|
* You may distribute under the terms of either the GNU General Public
|
||
|
* License or the Artistic License, as specified in the README file.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include "fte.h"
|
||
|
|
||
|
#ifdef CONFIG_HILIT_REXX
|
||
|
|
||
|
#define hsREXX_Normal 0
|
||
|
#define hsREXX_Comment 1
|
||
|
#define hsREXX_String1 3
|
||
|
#define hsREXX_String2 4
|
||
|
#define hsREXX_Keyword 5
|
||
|
|
||
|
int Hilit_REXX(EBuffer *BF, int /*LN*/, PCell B, int Pos, int Width, ELine *Line, hlState &State, hsState *StateMap, int *ECol) {
|
||
|
ChColor *Colors = BF->Mode->fColorize->Colors;
|
||
|
int j = 0;
|
||
|
int firstnw = 0;
|
||
|
HILIT_VARS(Colors[CLR_Normal], Line);
|
||
|
int wascall = 0;
|
||
|
|
||
|
C = 0;
|
||
|
NC = 0;
|
||
|
for(i = 0; i < Line->Count;) {
|
||
|
if (*p != ' ' && *p != 9) firstnw++;
|
||
|
IF_TAB() else {
|
||
|
switch(State) {
|
||
|
case hsREXX_Comment:
|
||
|
Color = Colors[CLR_Comment];
|
||
|
if ((len >= 2) && (*p == '*') && (*(p+1) == '/')) {
|
||
|
ColorNext();
|
||
|
set_normal:
|
||
|
ColorNext();
|
||
|
State = hsREXX_Normal;
|
||
|
continue;
|
||
|
}
|
||
|
goto hilit;
|
||
|
case hsREXX_String1:
|
||
|
Color = Colors[CLR_String];
|
||
|
if (*p == '\'') {
|
||
|
goto set_normal;
|
||
|
}
|
||
|
goto hilit;
|
||
|
case hsREXX_String2:
|
||
|
Color = Colors[CLR_String];
|
||
|
if (*p == '"') {
|
||
|
goto set_normal;
|
||
|
}
|
||
|
goto hilit;
|
||
|
default:
|
||
|
case hsREXX_Normal:
|
||
|
if (isalpha(*p) || (*p == '_')) {
|
||
|
|
||
|
j = 0;
|
||
|
while (((i + j) < Line->Count) &&
|
||
|
(isalnum(Line->Chars[i+j]) ||
|
||
|
(Line->Chars[i + j] == '_'))
|
||
|
) j++;
|
||
|
if (wascall) {
|
||
|
State = hsREXX_Normal;
|
||
|
Color = Colors[CLR_Function];
|
||
|
wascall = 0;
|
||
|
} else {
|
||
|
if (BF->GetHilitWord(j, Line->Chars + i, Color, 1))
|
||
|
State = hsREXX_Keyword;
|
||
|
else {
|
||
|
int x;
|
||
|
x = i + j;
|
||
|
if ((x < Line->Count) && (Line->Chars[x] == '(')) {
|
||
|
Color = Colors[CLR_Function];
|
||
|
} else {
|
||
|
Color = Colors[CLR_Normal];
|
||
|
}
|
||
|
State = hsREXX_Normal;
|
||
|
}
|
||
|
}
|
||
|
if (StateMap)
|
||
|
memset(StateMap + i, State, j);
|
||
|
if (B)
|
||
|
MoveMem(B, C - Pos, Width, Line->Chars + i, Color, j);
|
||
|
if (State == hsREXX_Keyword)
|
||
|
if (strnicmp(Line->Chars + i, "CALL", 4) == 0)
|
||
|
wascall = 1;
|
||
|
i += j;
|
||
|
len -= j;
|
||
|
p += j;
|
||
|
C += j;
|
||
|
State = hsREXX_Normal;
|
||
|
continue;
|
||
|
} else if ((len >= 2) && (*p == '/') && (*(p+1) == '*')) {
|
||
|
State = hsREXX_Comment;
|
||
|
Color = Colors[CLR_Comment];
|
||
|
//hilit2:
|
||
|
ColorNext();
|
||
|
hilit:
|
||
|
ColorNext();
|
||
|
continue;
|
||
|
} else if (isdigit(*p)) {
|
||
|
Color = Colors[CLR_Number];
|
||
|
ColorNext();
|
||
|
while(len && isdigit(*p)) ColorNext();
|
||
|
continue;
|
||
|
} else if (*p == '\'') {
|
||
|
State = hsREXX_String1;
|
||
|
Color = Colors[CLR_String];
|
||
|
goto hilit;
|
||
|
} else if (*p == '"') {
|
||
|
State = hsREXX_String2;
|
||
|
Color = Colors[CLR_String];
|
||
|
goto hilit;
|
||
|
} else if (ispunct(*p) && *p != '_') {
|
||
|
Color = Colors[CLR_Punctuation];
|
||
|
goto hilit;
|
||
|
}
|
||
|
Color = Colors[CLR_Normal];
|
||
|
goto hilit;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
switch (State) {
|
||
|
case hsREXX_String1:
|
||
|
case hsREXX_String2:
|
||
|
State = hsREXX_Normal;
|
||
|
break;
|
||
|
}
|
||
|
*ECol = C;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#ifdef CONFIG_INDENT_REXX
|
||
|
|
||
|
static int Match(int Len, int Pos, hsState *StateMap, const char *Text, const char *String, hsState State) {
|
||
|
int L = strlen(String);
|
||
|
|
||
|
if (Pos + L <= Len)
|
||
|
if (StateMap == NULL || IsState(StateMap + Pos, State, L))
|
||
|
if (strnicmp(String, Text + Pos, L) == 0)
|
||
|
return 1;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int SearchMatch(int Count, EBuffer *B, int Row, int Ctx) {
|
||
|
char *P;
|
||
|
int L;
|
||
|
int Pos;
|
||
|
int StateLen;
|
||
|
hsState *StateMap;
|
||
|
int ICount = (Ctx == 2) ? Count : 0;
|
||
|
|
||
|
Count = (Ctx == 2) ? 0 : Count;
|
||
|
|
||
|
|
||
|
while (Row >= 0) {
|
||
|
P = B->RLine(Row)->Chars;
|
||
|
L = B->RLine(Row)->Count;
|
||
|
StateMap = NULL;
|
||
|
if (B->GetMap(Row, &StateLen, &StateMap) == 0) return -1;
|
||
|
Pos = L - 1;
|
||
|
if (L > 0) while (Pos >= 0) {
|
||
|
if (isalpha(P[Pos])) {
|
||
|
if (Match(L, Pos, StateMap, P, "do", hsREXX_Keyword) ||
|
||
|
Match(L, Pos, StateMap, P, "select", hsREXX_Keyword ))
|
||
|
{
|
||
|
Count++;
|
||
|
if (Count == 0 && Ctx != 2) {
|
||
|
if (StateMap)
|
||
|
free(StateMap);
|
||
|
return B->LineIndented(Row);
|
||
|
}
|
||
|
} else if (Match(L, Pos, StateMap, P, "end", hsREXX_Keyword)) {
|
||
|
Count--;
|
||
|
}
|
||
|
if (Ctx == 2 && Count == 0) {
|
||
|
if (Match(L, Pos, StateMap, P, "if", hsREXX_Keyword)) {
|
||
|
ICount++;
|
||
|
if (ICount == 0) {
|
||
|
if (StateMap)
|
||
|
free(StateMap);
|
||
|
return B->LineIndented(Row);
|
||
|
}
|
||
|
} else if (Match(L, Pos, StateMap, P, "else", hsREXX_Keyword)) {
|
||
|
ICount--;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Pos--;
|
||
|
}
|
||
|
if (StateMap) free(StateMap);
|
||
|
Row--;
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
static int CheckLabel(EBuffer *B, int Line) {
|
||
|
PELine L = B->RLine(Line);
|
||
|
int P = B->CharOffset(L, B->LineIndented(Line));
|
||
|
int Cnt = 0;
|
||
|
|
||
|
if (Line > 0 && B->RLine(Line - 1)->StateE != hsREXX_Normal)
|
||
|
return 0;
|
||
|
|
||
|
while ((P < L->Count) &&
|
||
|
(L->Chars[P] == ' ' || L->Chars[P] == 9)) P++;
|
||
|
while (P < L->Count) {
|
||
|
if (Cnt > 0)
|
||
|
if (L->Chars[P] == ':') return 1;
|
||
|
if (!(isalnum(L->Chars[P]) || (L->Chars[P] == '_'))) return 0;
|
||
|
Cnt++;
|
||
|
P++;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int SearchBackContext(EBuffer *B, int Row, char &ChFind) {
|
||
|
char *P;
|
||
|
int L;
|
||
|
int Pos;
|
||
|
int Count = -1;
|
||
|
int StateLen;
|
||
|
hsState *StateMap;
|
||
|
int isblank = 0;
|
||
|
|
||
|
ChFind = '0';
|
||
|
while (Row >= 0) {
|
||
|
P = B->RLine(Row)->Chars;
|
||
|
L = B->RLine(Row)->Count;
|
||
|
StateMap = NULL;
|
||
|
if (B->GetMap(Row, &StateLen, &StateMap) == 0) return 0;
|
||
|
Pos = L - 1;
|
||
|
if (L > 0) while (Pos >= 0) {
|
||
|
if (CheckLabel(B, Row) == 1) {
|
||
|
Count++;
|
||
|
ChFind = 'p';
|
||
|
if (Count == 0) {
|
||
|
if (StateMap)
|
||
|
free(StateMap);
|
||
|
return B->LineIndented(Row);
|
||
|
}
|
||
|
}
|
||
|
if (isalpha(P[Pos]) && (Pos == 0 || !isalpha(P[Pos - 1]))) {
|
||
|
if (Match(L, Pos, StateMap, P, "do", hsREXX_Keyword)) {
|
||
|
Count++;
|
||
|
ChFind = 'd';
|
||
|
//} else if (Match(L, Pos, StateMap, P, "procedure", hsREXX_Keyword)) {
|
||
|
//Count++;
|
||
|
//ChFind = 'p';
|
||
|
} else if (Match(L, Pos, StateMap, P, "select", hsREXX_Keyword)) {
|
||
|
Count++;
|
||
|
ChFind = 's';
|
||
|
} else if (Match(L, Pos, StateMap, P, "otherwise", hsREXX_Keyword) && Count == 0) {
|
||
|
//Count++;
|
||
|
ChFind = 'o';
|
||
|
if (StateMap)
|
||
|
free(StateMap);
|
||
|
return B->LineIndented(Row);
|
||
|
} else if (Match(L, Pos, StateMap, P, "end", hsREXX_Keyword)) {
|
||
|
Count--;
|
||
|
ChFind = 'e';
|
||
|
} else if (isblank < 5 && Match(L, Pos, StateMap, P, "then", hsREXX_Keyword)) {
|
||
|
ChFind = 't';
|
||
|
if (StateMap)
|
||
|
free(StateMap);
|
||
|
return B->LineIndented(Row);
|
||
|
} else if (isblank < 5 && Match(L, Pos, StateMap, P, "else", hsREXX_Keyword)) {
|
||
|
ChFind = 'e';
|
||
|
if (StateMap)
|
||
|
free(StateMap);
|
||
|
return B->LineIndented(Row);
|
||
|
} else {
|
||
|
isblank++;
|
||
|
Pos--;
|
||
|
continue;
|
||
|
}
|
||
|
if (Count == 0) {
|
||
|
if (StateMap)
|
||
|
free(StateMap);
|
||
|
return B->LineIndented(Row);
|
||
|
}
|
||
|
}
|
||
|
if (P[Pos] != ' ' && P[Pos] != 9) isblank++;
|
||
|
Pos--;
|
||
|
}
|
||
|
if (StateMap) free(StateMap);
|
||
|
Row--;
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
int REXX_Base_Indent = 4;
|
||
|
int REXX_Do_Offset = 0;
|
||
|
|
||
|
#define REXX_BASE_INDENT REXX_Base_Indent
|
||
|
#define REXX_DO_OFFSET REXX_Do_Offset
|
||
|
|
||
|
static int IndentComment(EBuffer *B, int Row, int /*StateLen*/, hsState * /*StateMap*/) {
|
||
|
int I = 0;
|
||
|
|
||
|
if (Row > 0) {
|
||
|
I = B->LineIndented(Row - 1);
|
||
|
if (B->RLine(Row - 1)->StateE == hsREXX_Comment)
|
||
|
if (LookAt(B, Row - 1, I, "/*", hsREXX_Comment, 0)) I+= 1;
|
||
|
}
|
||
|
return I;
|
||
|
}
|
||
|
|
||
|
|
||
|
static int IndentNormal(EBuffer *B, int Line, int /*StateLen*/, hsState * /*StateMap*/) {
|
||
|
int I = 0;
|
||
|
|
||
|
if (CheckLabel(B, Line)) {
|
||
|
return 0;
|
||
|
} else if (LookAtNoCase(B, Line, 0, "end", hsREXX_Keyword)) {
|
||
|
return SearchMatch(-1, B, Line - 1, 1);
|
||
|
} else if (LookAtNoCase(B, Line, 0, "else", hsREXX_Keyword)) {
|
||
|
return SearchMatch(-1, B, Line - 1, 2);
|
||
|
} else {
|
||
|
char ChFind;
|
||
|
|
||
|
I = SearchBackContext(B, Line - 1, ChFind);
|
||
|
if (I == -1)
|
||
|
return 0;
|
||
|
switch (ChFind) {
|
||
|
case 'p':
|
||
|
if (LookAtNoCase(B, Line, 0, "return", hsREXX_Keyword))
|
||
|
return I;
|
||
|
else
|
||
|
return I + REXX_BASE_INDENT;
|
||
|
case 's':
|
||
|
case 'd':
|
||
|
return I + REXX_BASE_INDENT;
|
||
|
case 't':
|
||
|
case 'e':
|
||
|
case 'o':
|
||
|
if (LookAtNoCase(B, Line, 0, "do", hsREXX_Keyword))
|
||
|
return I + REXX_DO_OFFSET;
|
||
|
else
|
||
|
return I + REXX_BASE_INDENT;
|
||
|
default:
|
||
|
return I;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int Indent_REXX(EBuffer *B, int Line, int PosCursor) {
|
||
|
int I;
|
||
|
hsState *StateMap = NULL;
|
||
|
int StateLen = 0;
|
||
|
int OI;
|
||
|
|
||
|
OI = I = B->LineIndented(Line);
|
||
|
if (I != 0) B->IndentLine(Line, 0);
|
||
|
if (B->GetMap(Line, &StateLen, &StateMap) == 0) return 0;
|
||
|
|
||
|
if (StateLen > 0) { // line is not empty
|
||
|
if (StateMap[0] == hsREXX_Comment) {
|
||
|
I = IndentComment(B, Line, StateLen, StateMap);
|
||
|
} else {
|
||
|
I = IndentNormal(B, Line, StateLen, StateMap);
|
||
|
}
|
||
|
} else {
|
||
|
I = IndentNormal(B, Line, 0, NULL);
|
||
|
}
|
||
|
if (StateMap)
|
||
|
free(StateMap);
|
||
|
if (I >= 0)
|
||
|
B->IndentLine(Line, I);
|
||
|
else
|
||
|
I = 0;
|
||
|
if (PosCursor == 1) {
|
||
|
int X = B->CP.Col;
|
||
|
|
||
|
X = X - OI + I;
|
||
|
if (X < I) X = I;
|
||
|
if (X < 0) X = 0;
|
||
|
if (X > B->LineLen(Line)) {
|
||
|
X = B->LineLen(Line);
|
||
|
if (X < I) X = I;
|
||
|
}
|
||
|
if (B->SetPosR(X, Line) == 0) return 0;
|
||
|
} else if (PosCursor == 2) {
|
||
|
if (B->SetPosR(I, Line) == 0) return 0;
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
#endif
|
||
|
#endif
|