This repository has been archived on 2023-07-11. You can view files and clone it, but cannot push or open issues or pull requests.
fte/h_c.cpp

1341 lines
47 KiB
C++
Raw Normal View History

/* h_c.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.
*
*/
#define NEED_LOG_H
#include "fte.h"
#ifdef CONFIG_HILIT_C
#define PRINTF(x) //printf x
#define ISNAME(x) (isalnum(x) || (x == '_'))
#define hsC_Normal 0
#define hsC_Comment 1
#define hsC_CommentL 2
#define hsC_Keyword 4
#define hsC_String1 10
#define hsC_String2 11
#define hsC_CPP 12
#define hsC_CPP_Comm 13
#define hsC_CPP_String1 14
#define hsC_CPP_String2 15
#define hsC_CPP_ABrace 16
int Hilit_C(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 len1 = len;
char *last = p + len1 - 1;
int was_include = 0;
for(i = 0; i < Line->Count;) {
if (*p != ' ' && *p != 9) firstnw++;
IF_TAB() else {
switch(State) {
default:
case hsC_Normal:
if (toupper(*p) == 'L' && p[1] == '"') {
State = hsC_String2;
Color = Colors[CLR_String];
goto hilit2;
} else if (toupper(*p) == 'L' && p[1] == '\'') {
State = hsC_String1;
Color = Colors[CLR_String];
goto hilit2;
} else if (isalpha(*p) || *p == '_') {
j = 0;
while (((i + j) < Line->Count)
&& ISNAME(Line->Chars[i + j]))
j++;
if (BF->GetHilitWord(j, &Line->Chars[i], Color)) {
// Color = hcC_Keyword;
State = hsC_Keyword;
} else {
int x;
x = i + j;
while (x < Line->Count && isspace(Line->Chars[x]))
x++;
if (x < Line->Count && Line->Chars[x] == '(') {
Color = Colors[CLR_Function];
} else if ((x < Line->Count)
&& (Line->Chars[x] == ':'
&& (x == Line->Count - 1
|| Line->Chars[x + 1] != ':'))
&& firstnw == 1) {
Color = Colors[CLR_Label];
} else {
Color = Colors[CLR_Normal];
}
State = hsC_Normal;
}
if (StateMap)
memset(StateMap + i, State, j);
if (B)
MoveMem(B, C - Pos, Width, Line->Chars + i, Color, j);
i += j;
len -= j;
p += j;
C += j;
State = hsC_Normal;
continue;
} else if ((len >= 2) && (*p == '/') && (*(p+1) == '*')) {
State = hsC_Comment;
Color = Colors[CLR_Comment];
goto hilit2;
} else if ((len >= 2) && (*p == '/') && (p[1] == '/')) {
State = hsC_CommentL;
Color = Colors[CLR_Comment];
goto hilit2;
} else if (isdigit(*p)) {
// check if it is not floating point number 0.08!
if ((len >= 2) && (*p == '0') && p[1] != '.') {
if (toupper(*(p+1)) == 'X') {
Color = Colors[CLR_HexNumber];
ColorNext();
ColorNext();
while (len && isxdigit(*p)) ColorNext();
} else /* assume it's octal */ {
Color = Colors[CLR_Number];
ColorNext();
while (len && ('0' <= *p && *p <= '7')) ColorNext();
// if we hit a non-octal, stop hilighting it.
if (len && ('8' <= *p && *p <= '9'))
{
Color = Colors[CLR_Normal];
while (len && !isspace(*p)) ColorNext();
continue;
}
}
} else /* assume it's decimal/floating */ {
Color = Colors[CLR_Number];
ColorNext();
while (len && (isdigit(*p) || *p == 'e' || *p == 'E' || *p == '.')) ColorNext();
// if it ends with 'f', the number can't have more extras.
if (len && (toupper(*p) == 'F')) {
ColorNext();
continue;
}
}
// allowed extras: u, l, ll, ul, ull, lu, llu
int colored_u = 0;
if (len && (toupper(*p) == 'U')) {
ColorNext();
colored_u = 1;
}
if (len && (toupper(*p) == 'L')) {
ColorNext();
if (len && (toupper(*p) == 'L')) ColorNext();
if (! colored_u && len && (toupper(*p) == 'U')) ColorNext();
}
continue;
} else if (*p == '\'') {
State = hsC_String1;
Color = Colors[CLR_String];
goto hilit;
} else if (*p == '"') {
State = hsC_String2;
Color = Colors[CLR_String];
goto hilit;
} else if (firstnw == 1 && *p == '#') {
State = hsC_CPP;
Color = Colors[CLR_CPreprocessor];
goto hilit;
} else if (ispunct(*p) && *p != '_') {
Color = Colors[CLR_Punctuation];
goto hilit;
}
Color = Colors[CLR_Normal];
goto hilit;
case hsC_Comment:
Color = Colors[CLR_Comment];
if ((len >= 2) && (*p == '*') && (*(p+1) == '/')) {
ColorNext();
ColorNext();
State = hsC_Normal;
continue;
}
goto hilit;
case hsC_CPP_Comm:
Color = Colors[CLR_Comment];
if ((len >= 2) && (*p == '*') && (*(p+1) == '/')) {
ColorNext();
ColorNext();
State = hsC_CPP;
continue;
}
goto hilit;
case hsC_CPP_ABrace:
Color = Colors[CLR_String];
if (*p == '>') {
Color = Colors[CLR_CPreprocessor];
State = hsC_CPP;
}
goto hilit;
case hsC_CommentL:
Color = Colors[CLR_Comment];
goto hilit;
case hsC_String1:
Color = Colors[CLR_String];
if ((len >= 2) && (*p == '\\')) {
goto hilit2;
} else if (*p == '\'') {
ColorNext();
State = hsC_Normal;
continue;
}
goto hilit;
case hsC_String2:
Color = Colors[CLR_String];
if ((len >= 2) && (*p == '\\')) {
goto hilit2;
} else if (*p == '"') {
ColorNext();
State = hsC_Normal;
continue;
}
goto hilit;
case hsC_CPP_String1:
Color = Colors[CLR_String];
if ((len >= 2) && (*p == '\\')) {
goto hilit2;
} else if (*p == '\'') {
ColorNext();
State = hsC_CPP;
continue;
}
goto hilit;
case hsC_CPP_String2:
Color = Colors[CLR_String];
if ((len >= 2) && (*p == '\\')) {
goto hilit2;
} else if (*p == '"') {
ColorNext();
State = hsC_CPP;
continue;
}
goto hilit;
case hsC_CPP:
if (ISNAME(*p)) {
j = 0;
Color = Colors[CLR_CPreprocessor];
while (((i + j) < Line->Count) &&
(isalnum(Line->Chars[i+j]) ||
(Line->Chars[i + j] == '_'))
) j++;
if (j == 7 && memcmp(Line->Chars + i, "include", 7) == 0)
was_include = 1;
if (StateMap)
memset(StateMap + i, State, j);
if (B)
MoveMem(B, C - Pos, Width, Line->Chars + i, Color, j);
i += j;
len -= j;
p += j;
C += j;
continue;
} else if ((len >= 2) && (*p == '/') && (*(p+1) == '*')) {
State = hsC_CPP_Comm;
Color = Colors[CLR_Comment];
goto hilit2;
} else if ((len >= 2) && (*p == '/') && (*(p+1) == '/')) {
State = hsC_CommentL;
Color = Colors[CLR_Comment];
hilit2:
ColorNext();
hilit:
ColorNext();
continue;
} else if (isdigit(*p)) {
if ((len >= 2) && (*p == '0')) {
if (toupper(*(p+1)) == 'X') {
Color = Colors[CLR_HexNumber];
ColorNext();
ColorNext();
while (len && isxdigit(*p)) ColorNext();
} else /* assume it's octal */ {
Color = Colors[CLR_Number];
ColorNext();
while (len && ('0' <= *p && *p <= '7')) ColorNext();
// if we hit a non-octal, stop hilighting it.
if (len && ('8' <= *p && *p <= '9'))
{
Color = Colors[CLR_Normal];
while (len && !isspace(*p)) ColorNext();
continue;
}
}
} else /* assume it's decimal/floating */ {
Color = Colors[CLR_Number];
ColorNext();
while (len && (isdigit(*p) || *p == 'e' || *p == 'E' || *p == '.')) ColorNext();
// if it ends with 'f', the number can't have more extras.
if (len && (toupper(*p) == 'F')) {
ColorNext();
continue;
}
}
// allowed extras: u, l, ll, ul, ull, lu, llu
int colored_u = 0;
if (len && (toupper(*p) == 'U')) {
ColorNext();
colored_u = 1;
}
if (len && (toupper(*p) == 'L')) {
ColorNext();
if (len && (toupper(*p) == 'L')) ColorNext();
if (! colored_u && len && (toupper(*p) == 'U')) ColorNext();
}
continue;
} else if (*p == '\'') {
State = hsC_CPP_String1;
Color = Colors[CLR_String];
goto hilit;
} else if (*p == '"') {
State = hsC_CPP_String2;
Color = Colors[CLR_String];
goto hilit;
} else if (*p == '<' && was_include) {
ColorNext();
State = hsC_CPP_ABrace;
continue;
} else {
Color = Colors[CLR_CPreprocessor];
goto hilit;
}
}
}
}
if (State == hsC_CommentL)
State = hsC_Normal;
if ((len1 == 0) || (*last != '\\')) {
switch(State) {
case hsC_String1:
case hsC_String2:
case hsC_CPP:
case hsC_CPP_String1:
case hsC_CPP_String2:
State = hsC_Normal;
break;
}
}
*ECol = C;
return 0;
}
int IsState(hsState *Buf, hsState State, int Len) {
int I;
for(I = 0; I < Len; I++)
if (Buf[I] != State) return 0;
return 1;
}
int LookAt(EBuffer *B, int Row, unsigned int Pos, const char *What, hsState State, int NoWord, int CaseInsensitive) {
STARTFUNC("LookAt{h_c.cpp}");
int Len = strlen(What);
if (Row < 0 || Row >= B->RCount) {
LOG << "Row out of range: " << Row << " vs " << B->RCount << ENDLINE;
ENDFUNCRC(0);
}
char* pLine = B->RLine(Row)->Chars;
unsigned int uLineLength = B->RLine(Row)->Count;
Pos = B->CharOffset(B->RLine(Row), Pos);
if (Pos + strlen(What) > uLineLength) { ENDFUNCRC(0); }
if (NoWord && uLineLength > Pos + Len && ISNAME(pLine[Pos + Len]))
{
ENDFUNCRC(0);
}
LOG << "Check against [" << What << ']' << ENDLINE;
if (
(CaseInsensitive && memicmp(pLine + Pos, (char *)What, Len) == 0) ||
(!CaseInsensitive && memcmp(pLine + Pos, (char *)What, Len) == 0)
)
{
ENDFUNCRC(1);
}
else
{
ENDFUNCRC(0);
}
}
#ifdef CONFIG_INDENT_C
int C_Indent = 4;
int C_BraceOfs = 0;
int C_ParenDelta = -1;
int C_CaseOfs = 0;
int C_CaseDelta = 4;
int C_ClassOfs = 0;
int C_ClassDelta = 4;
int C_ColonOfs = 0;//-4;
int C_CommentOfs = 0;
int C_CommentDelta = 1;
int C_FirstLevelWidth = -1;
int C_FirstLevelIndent = 4;
int C_Continuation = 4;
// this is global, unfortunately -- FIX !!!
int EBuffer::SetCIndentStyle(ExState &State) {
if (State.GetIntParam(View, &C_Indent) == 0)
return 0;
if (State.GetIntParam(View, &C_BraceOfs) == 0)
return 0;
if (State.GetIntParam(View, &C_ParenDelta) == 0)
return 0;
if (State.GetIntParam(View, &C_CaseOfs) == 0)
return 0;
if (State.GetIntParam(View, &C_CaseDelta) == 0)
return 0;
if (State.GetIntParam(View, &C_ClassOfs) == 0)
return 0;
if (State.GetIntParam(View, &C_ClassDelta) == 0)
return 0;
if (State.GetIntParam(View, &C_ColonOfs) == 0)
return 0;
if (State.GetIntParam(View, &C_CommentOfs) == 0)
return 0;
if (State.GetIntParam(View, &C_CommentDelta) == 0)
return 0;
if (State.GetIntParam(View, &C_FirstLevelWidth) == 0)
return 0;
if (State.GetIntParam(View, &C_FirstLevelIndent) == 0)
return 0;
if (State.GetIntParam(View, &C_Continuation) == 0)
return 0;
return 1;
}
#define C_INDENT C_Indent
#define C_BRACE_OFS C_BraceOfs
#define C_PAREN_DELTA C_ParenDelta
#define C_CASE_OFS C_CaseOfs
#define C_CASE_DELTA C_CaseDelta
#define C_CLASS_OFS C_ClassOfs
#define C_CLASS_DELTA C_ClassDelta
#define C_COLON_OFS C_ColonOfs
#define C_COMMENT_OFS C_CommentOfs
#define C_COMMENT_DELTA C_CommentDelta
#define C_CONTINUATION C_Continuation
#define C_FIRST_INDENT C_FirstLevelIndent
#define C_FIRST_WIDTH C_FirstLevelWidth
#define FIND_IF 0x0001
#define FIND_SEMICOLON 0x0002
#define FIND_COMMA 0x0004
#define FIND_COLON 0x0008
#define FIND_ELSE 0x0010
#define FIND_FOR 0x0020
#define FIND_WHILE 0x0040
#define FIND_ENDBLOCK 0x0080
//#define FIND_BEGINBLOCK 0x0100
#define FIND_CLASS 0x0200
#define FIND_CASE 0x0400
#define FIND_SWITCH 0x0800
#define FIND_QUESTION 0x1000
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 != hsC_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] == ':' && (Cnt == 1 || L->Chars[P + 1] != ':')) return 1;
if (!isalnum(L->Chars[P]) && L->Chars[P] != '_') return 0;
Cnt++;
P++;
}
return 0;
}
static int SearchBackMatch(int Count, EBuffer *B, int Row, hsState State, const char *Open, const char *Close, int *OPos, int *OLine, int matchparens = 0, int bolOnly = 0) {
char *P;
int L;
int Pos;
int LOpen = strlen(Open);
int LClose = strlen(Close);
int StateLen;
hsState *StateMap;
int CountX[3] = { 0, 0, 0 };
int didMatch = 0;
*OLine = Row;
*OPos = 0;
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 (P[Pos] != ' ' && P[Pos] != 9) {
if (StateMap[Pos] == hsC_Normal) {
switch (P[Pos]) {
case '{': CountX[0]--; break;
case '}': CountX[0]++; break;
case '(': CountX[1]--; break;
case ')': CountX[1]++; break;
case '[': CountX[2]--; break;
case ']': CountX[2]++; break;
}
}
if (!matchparens ||
(CountX[0] == 0 && CountX[1] == 0 && CountX[2] == 0))
{
if (LOpen + Pos <= L) {
if (IsState(StateMap + Pos, State, LOpen)) {
if (memcmp(P + Pos, Open, LOpen) == 0) Count++;
if (Count == 0) {
if (bolOnly)
didMatch = 1;
else {
*OPos = B->ScreenPos(B->RLine(Row), Pos);
*OLine = Row;
free(StateMap);
return B->LineIndented(Row);
}
}
}
if (LClose + Pos <= L) {
if (IsState(StateMap + Pos, State, LClose)) {
if (memcmp(P + Pos, Close, LClose) == 0) Count--;
}
}
}
}
}
Pos--;
}
if (bolOnly && didMatch && CountX[1] == 0 && CountX[2] == 0) {
*OPos = 0;
*OLine = Row;
free(StateMap);
return B->LineIndented(Row);
}
if (StateMap) free(StateMap);
Row--;
}
return -1;
}
static int FindPrevIndent(EBuffer *B, int &RowP, int &ColP, char &CharP, int Flags) {
STARTFUNC("FindPrevIndent{h_c.cpp}");
LOG << "Flags: " << hex << Flags << dec << ENDLINE;
int StateLen;
hsState *StateMap = 0;
char *P;
int L;
int Count[4] = {
0, // { }
0, // ( )
0, // [ ]
0, // if/else (one if for each else)
};
#define TEST_ZERO (Count[0] == 0 && Count[1] == 0 && Count[2] == 0\
&& Count[3] == 0)
assert(RowP >= 0 && RowP < B->RCount);
L = B->RLine(RowP)->Count;
if (ColP >= L)
ColP = L - 1;
assert(ColP >= -1 && ColP <= L);
char BolChar = ' ';
int BolCol = -1;
int BolRow = -1;
while (RowP >= 0) {
P = B->RLine(RowP)->Chars;
L = B->RLine(RowP)->Count;
StateMap = NULL;
if (B->GetMap(RowP, &StateLen, &StateMap) == 0)
{
LOG << "Can't get state maps" << ENDLINE;
ENDFUNCRC(0);
}
if (L > 0) while (ColP >= 0) {
LOG << "ColP: " << ColP << " State: " << (int)StateMap[ColP] << ENDLINE;
if (StateMap[ColP] == hsC_Normal) {
LOG << "CharP: " << BinChar(P[ColP]) << " BolChar: " << BinChar(BolChar) <<
" BolRow: " << BolRow <<
" BolCol: " << BolCol <<
ENDLINE;
switch (CharP = P[ColP]) {
case '{':
if (BolChar == ':' || BolChar == ',') {
CharP = BolChar;
ColP = BolCol;
RowP = BolRow;
free(StateMap);
ENDFUNCRC(1);
}
if (TEST_ZERO) {
free(StateMap);
ENDFUNCRC(1);
}
Count[0]--;
break;
case '}':
if (BolChar == ':' || BolChar == ',') {
CharP = BolChar;
ColP = BolCol;
RowP = BolRow;
free(StateMap);
ENDFUNCRC(1);
}
if (BolChar == ';') {
CharP = BolChar;
ColP = BolCol;
RowP = BolRow;
free(StateMap);
ENDFUNCRC(1);
}
if (ColP == 0) { /* speed optimization */
free(StateMap);
ENDFUNCRC(1);
}
if (TEST_ZERO && (Flags & FIND_ENDBLOCK)) {
free(StateMap);
ENDFUNCRC(1);
}
Count[0]++;
break;
case '(':
if (TEST_ZERO) {
free(StateMap);
ENDFUNCRC(1);
}
Count[1]--;
break;
case ')':
Count[1]++;
break;
case '[':
if (TEST_ZERO) {
free(StateMap);
ENDFUNCRC(1);
}
Count[2]--;
break;
case ']':
Count[2]++;
break;
case ':':
if (ColP >= 1 && P[ColP - 1] == ':') { // skip ::
ColP -= 2;
continue;
}
case ',':
case ';':
if (TEST_ZERO && BolChar == ' ') {
if ((CharP == ';' && (Flags & FIND_SEMICOLON))
|| (CharP == ',' && (Flags & FIND_COMMA))
|| (CharP == ':' && (Flags & FIND_COLON))) {
BolChar = CharP;
BolCol = ColP;
BolRow = RowP;
// this should be here
// if not say why ???
//free(StateMap);
//return 1;
}
}
if (BolChar == ',' && CharP == ':') {
BolChar = ' ';
BolCol = -1;
BolRow = -1;
break;
}
if ((BolChar == ':' || BolChar == ',')
&& (CharP == ';'/* || CharP == ','*/)) {
CharP = ':';
ColP = BolCol;
RowP = BolRow;
free(StateMap);
ENDFUNCRC(1);
}
break;
case '?':
//if ((Flags & FIND_QUESTION)) {
if (BolChar == ':' || BolChar == ',') {
BolChar = ' ';
BolCol = -1;
BolRow = -1;
}
//}
break;
}
} else if (StateMap[ColP] == hsC_Keyword && (BolChar == ' ' || BolChar == ':')) {
if (L - ColP >= 2 &&
IsState(StateMap + ColP, hsC_Keyword, 2) &&
memcmp(P + ColP, "if", 2) == 0)
{
//puts("\nif");
if (Count[3] > 0)
Count[3]--;
if (Flags & FIND_IF) {
if (TEST_ZERO) {
CharP = 'i';
free(StateMap);
ENDFUNCRC(1);
}
}
}
if (L - ColP >= 4 &&
IsState(StateMap + ColP, hsC_Keyword, 4) &&
memcmp(P + ColP, "else", 4) == 0)
{
//puts("\nelse\x7");
if (Flags & FIND_ELSE) {
if (TEST_ZERO) {
CharP = 'e';
free(StateMap);
ENDFUNCRC(1);
}
}
Count[3]++;
}
if (TEST_ZERO) {
if ((Flags & FIND_FOR) &&
L - ColP >= 3 &&
IsState(StateMap + ColP, hsC_Keyword, 3) &&
memcmp(P + ColP, "for", 3) == 0)
{
CharP = 'f';
free(StateMap);
ENDFUNCRC(1);
}
if ((Flags & FIND_WHILE) &&
L - ColP >= 5 &&
IsState(StateMap + ColP, hsC_Keyword, 5) &&
memcmp(P + ColP, "while", 5) == 0)
{
CharP = 'w';
free(StateMap);
ENDFUNCRC(1);
}
if ((Flags & FIND_SWITCH) &&
L - ColP >= 6 &&
IsState(StateMap + ColP, hsC_Keyword, 6) &&
memcmp(P + ColP, "switch", 6) == 0)
{
CharP = 's';
free(StateMap);
ENDFUNCRC(1);
}
if (((Flags & FIND_CASE) || (BolChar == ':')) &&
(L - ColP >= 4 &&
IsState(StateMap + ColP, hsC_Keyword, 4) &&
memcmp(P + ColP, "case", 4) == 0) ||
((L - ColP >= 7) &&
IsState(StateMap + ColP, hsC_Keyword, 7) &&
memcmp(P + ColP, "default", 7) == 0))
{
CharP = 'c';
if (BolChar == ':') {
CharP = BolChar;
ColP = BolCol;
RowP = BolRow;
}
free(StateMap);
ENDFUNCRC(1);
}
if (((Flags & FIND_CLASS) || (BolChar == ':')) &&
(L - ColP >= 5 &&
IsState(StateMap + ColP, hsC_Keyword, 5) &&
memcmp(P + ColP, "class", 5) == 0))
{
CharP = 'l';
if (BolChar == ':') {
CharP = BolChar;
ColP = BolCol;
RowP = BolRow;
}
free(StateMap);
ENDFUNCRC(1);
}
if (((Flags & FIND_CLASS) || (BolChar == ':')) &&
((L - ColP >= 6 &&
IsState(StateMap + ColP, hsC_Keyword, 6) &&
memcmp(P + ColP, "public", 6) == 0) ||
((L - ColP >= 7) &&
IsState(StateMap + ColP, hsC_Keyword, 7) &&
memcmp(P + ColP, "private", 7) == 0) ||
((L - ColP >= 9) &&
IsState(StateMap + ColP, hsC_Keyword, 9) &&
memcmp(P + ColP, "protected", 9) == 0)))
{
CharP = 'p';
if (BolChar == ':') {
CharP = BolChar;
ColP = BolCol;
RowP = BolRow;
}
free(StateMap);
ENDFUNCRC(1);
}
}
}
ColP--;
}
free(StateMap);
if (BolChar != ' ' && BolChar != ':' && BolChar != ',') {
CharP = BolChar;
ColP = BolCol;
ENDFUNCRC(1);
}
RowP--;
if (RowP >= 0) {
L = B->RLine(RowP)->Count;
ColP = L - 1;
}
}
#undef TEST_ZERO
ENDFUNCRC(0);
}
#define SKIP_FORWARD 0
#define SKIP_BACK 1
#define SKIP_MATCH 2
#define SKIP_LINE 4
#define SKIP_TOBOL 8
static int SkipWhite(EBuffer *B, int Bottom, int &Row, int &Col, int Flags) {
char *P;
int L;
int StateLen;
hsState *StateMap;
int Count[3] = { 0, 0, 0 };
assert (Row >= 0 && Row < B->RCount);
L = B->RLine(Row)->Count;
if (Col >= L)
Col = L;
assert (Col >= -1 && Col <= L) ;
while (Row >= 0 && Row < B->RCount) {
P = B->RLine(Row)->Chars;
L = B->RLine(Row)->Count;
StateMap = NULL;
if (B->GetMap(Row, &StateLen, &StateMap) == 0)
return 0;
if (L > 0)
for ( ; Col >= 0 && Col < L;
Col += ((Flags & SKIP_BACK) ? -1 : +1)) {
if (P[Col] == ' ' || P[Col] == '\t')
continue;
if (StateMap[Col] != hsC_Normal &&
StateMap[Col] != hsC_Keyword &&
StateMap[Col] != hsC_String1 &&
StateMap[Col] != hsC_String2)
continue;
if (StateMap[Col] == hsC_Normal && (Flags & SKIP_MATCH)) {
switch (P[Col]) {
case '{': Count[0]--; continue;
case '}': Count[0]++; continue;
case '(': Count[1]--; continue;
case ')': Count[1]++; continue;
case '[': Count[2]--; continue;
case ']': Count[2]++; continue;
}
}
if (Count[0] == 0 && Count[1] == 0 && Count[2] == 0
&& !(Flags & SKIP_TOBOL)) {
free(StateMap);
return 1;
}
}
free(StateMap);
if (Count[0] == 0 && Count[1] == 0 && Count[2] == 0 && (Flags & SKIP_TOBOL))
return 1;
if (Flags & SKIP_LINE) {
return 1;
}
if (Flags & SKIP_BACK) {
Row--;
if (Row >= 0) {
L = B->RLine(Row)->Count;
Col = L - 1;
}
} else {
if (Row + 1 >= Bottom)
return 1;
Row++;
Col = 0;
}
}
return 0;
}
static int IndentNormal(EBuffer *B, int Line, int /*StateLen*/, hsState * /*StateMap*/) {
STARTFUNC("IndentNormal{h_c.cpp}");
int I = 0;
int Pos, L;
if (LookAt(B, Line, 0, "case", hsC_Keyword) ||
LookAt(B, Line, 0, "default", hsC_Keyword))
{
I = SearchBackMatch(-1, B, Line - 1, hsC_Normal, "{", "}", &Pos, &L) + C_CASE_OFS;
return I;
} else if (LookAt(B, Line, 0, "public:", hsC_Keyword, 0) ||
LookAt(B, Line, 0, "private:", hsC_Keyword, 0) ||
LookAt(B, Line, 0, "protected:", hsC_Keyword, 0))
{
I = SearchBackMatch(-1, B, Line - 1, hsC_Normal, "{", "}", &Pos, &L) + C_CLASS_OFS;
return I;
} else if (LookAt(B, Line, 0, "else", hsC_Keyword)) {
I = SearchBackMatch(-1, B, Line - 1, hsC_Keyword, "if", "else", &Pos, &L, 1);
return I;
} else if (LookAt(B, Line, 0, "}", hsC_Normal, 0)) {
I = SearchBackMatch(-1, B, Line - 1, hsC_Normal, "{", "}", &Pos, &L, 0, 1);
return I;
} else if (LookAt(B, Line, 0, ")", hsC_Normal, 0)) {
I = SearchBackMatch(-1, B, Line - 1, hsC_Normal, "(", ")", &Pos, &L);
if (C_PAREN_DELTA >= 0)
return I + C_PAREN_DELTA;
else
return Pos;
} else if (LookAt(B, Line, 0, "]", hsC_Normal, 0)) {
I = SearchBackMatch(-1, B, Line - 1, hsC_Normal, "[", "]", &Pos, &L);
if (C_PAREN_DELTA >= 0)
return I + C_PAREN_DELTA;
else
return Pos;
} else {
char CharP = ' ';
// char FirstCharP = ' ';
int RowP = Line;
int ColP = -1;
int PrevRowP = RowP;
int PrevColP = ColP;
int FirstRowP;
int FirstColP;
int ContinuationIndent = 0;
if (SkipWhite(B, Line, PrevRowP, PrevColP, SKIP_BACK) != 1)
return 0;
PrevColP++;
LOG << "PrevRowP=" << PrevRowP << ", PrevColP=" << PrevColP << ENDLINE;
if (FindPrevIndent(B, RowP, ColP, CharP,
FIND_IF |
FIND_ELSE |
FIND_FOR |
FIND_WHILE |
FIND_SWITCH |
FIND_CASE |
//FIND_CLASS |
FIND_COLON |
FIND_SEMICOLON |
FIND_COMMA |
FIND_ENDBLOCK) != 1)
{
if (RowP != PrevRowP)
ContinuationIndent = C_CONTINUATION;
I = 0;
if (LookAt(B, Line, 0, "{", hsC_Normal, 0)) {
I += C_BRACE_OFS;
ContinuationIndent = 0;
}
return I + ContinuationIndent;
}
FirstRowP = RowP;
FirstColP = ColP;
// FirstCharP = CharP;
LOG << "FirstRowP=" << FirstRowP << ", FirstColP=" << FirstColP <<
", CharP=" << BinChar(CharP) << ENDLINE;
switch (CharP) {
case 'c':
I = B->LineIndented(RowP) + C_CONTINUATION;
return I;
case '(':
case '[':
if (C_PAREN_DELTA >= 0) {
I = B->LineIndented(FirstRowP) + C_PAREN_DELTA;
} else {
ColP++;
if (SkipWhite(B, Line, RowP, ColP, SKIP_FORWARD | SKIP_LINE) != 1)
return 0;
I = B->ScreenPos(B->RLine(RowP), ColP);
}
return I;
case '{':
ColP++;
if (((PrevRowP != RowP) ||
((PrevRowP == RowP) && (PrevColP != ColP)))
&& FirstRowP != PrevRowP)
ContinuationIndent = C_CONTINUATION;
ColP--; ColP--;
if (SkipWhite(B, Line, RowP, ColP, SKIP_BACK | SKIP_TOBOL | SKIP_MATCH) != 1)
return 0;
I = B->LineIndented(RowP);
if (B->LineIndented(FirstRowP) <= C_FIRST_WIDTH)
I += C_FIRST_INDENT;
else
I += C_INDENT;
PRINTF(("'{' indent : Line=%d, RowP=%d, ColP=%d, CharP=%c\n", Line, RowP, ColP, CharP));
if (LookAt(B, Line, 0, "{", hsC_Normal, 0))
I -= C_BRACE_OFS;
else
I += ContinuationIndent;
return I;
case ',':
I = B->LineIndented(FirstRowP);
return I;
case '}':
ColP++;
ColP++;
/*---nobreak---*/
case ';':
ColP--;
if (FindPrevIndent(B, RowP, ColP, CharP,
((CharP == ',') ? FIND_COMMA | FIND_COLON :
//(CharP == ';') ? FIND_SEMICOLON | FIND_COLON :
FIND_SEMICOLON | FIND_COLON)) != 1)
{
if (FirstRowP != PrevRowP)
ContinuationIndent = C_CONTINUATION;
I = 0;
if (LookAt(B, Line, 0, "{", hsC_Normal, 0)) {
I += C_BRACE_OFS;
ContinuationIndent = 0;
}
return I + ContinuationIndent;
}
PRINTF(("';' Line=%d, RowP=%d, ColP=%d, CharP=%c\n", Line, RowP, ColP, CharP));
LOG << " CharP now: " << BinChar(CharP) << ENDLINE;
switch (CharP) {
case ',':
case ';':
case '{':
case ':':
ColP++;
if (SkipWhite(B, Line, RowP, ColP, SKIP_FORWARD) != 1)
return 0;
//ColP--;
//if (SkipWhite(B, RowP, ColP, SKIP_BACK) != 1)
//if (CharP == ':') {
// I -= C_COLON_OFS;
//}
PRINTF(("';' indent : Line=%d, RowP=%d, ColP=%d, CharP=%c\n", Line, RowP, ColP, CharP));
I = B->LineIndented(RowP);
if (((PrevRowP != RowP) ||
((PrevRowP == RowP) && (PrevColP != ColP)))
&& FirstRowP != PrevRowP)
ContinuationIndent = C_CONTINUATION;
if (LookAt(B, Line, 0, "{", hsC_Normal, 0)) {
//I -= C_BRACE_OFS;
ContinuationIndent = 0;
}
if (LookAt(B, Line, 0, "{", hsC_Normal, 0)
&& LookAt(B, RowP, ColP, "{", hsC_Normal, 0))
I -= 0; //C_BRACE_OFS;
else if (LookAt(B, Line, 0, "{", hsC_Normal, 0)
&& !LookAt(B, RowP, ColP, "{", hsC_Normal, 0))
I += C_BRACE_OFS;
else if (!LookAt(B, Line, 0, "{", hsC_Normal, 0)
&& LookAt(B, RowP, ColP, "{", hsC_Normal, 0))
I -= C_BRACE_OFS;
break;
case '(':
ColP++;
if (SkipWhite(B, Line, RowP, ColP, SKIP_FORWARD | SKIP_LINE) != 1)
return 0;
I = B->ScreenPos(B->RLine(RowP), ColP);
break;
default:
I = B->LineIndented(RowP);
break;
}
PRINTF(("';' -- indent : Line=%d, RowP=%d, ColP=%d, CharP=%c\n", Line, RowP, ColP, CharP));
// else
// if (LookAt(B, Line, 0, "{", hsC_Normal, 0))
// I += C_INDENT - C_BRACE_OFS;
return I + ContinuationIndent;
case ':':
ColP--;
if (FindPrevIndent(B, RowP, ColP, CharP, FIND_SEMICOLON | FIND_COLON | FIND_QUESTION | FIND_CLASS | FIND_CASE) != 1) {
if (FirstRowP != PrevRowP)
ContinuationIndent = C_CONTINUATION;
return 0 + ContinuationIndent;
}
PRINTF(("':' Line=%d, RowP=%d, ColP=%d, CharP=%c\n", Line, RowP, ColP, CharP));
switch (CharP) {
case ':':
//ColP++;
/*if (SkipWhite(B, Line, RowP, ColP, SKIP_FORWARD) != 1)
return 0;
I = B->LineIndented(RowP);// - C_COLON_OFS;
PRINTF(("':' 0 indent : Line=%d, RowP=%d, ColP=%d, CharP=%c\n", Line, RowP, ColP, CharP));
break;*/
case '{':
case ';':
ColP++;
if (SkipWhite(B, Line, RowP, ColP, SKIP_FORWARD) != 1)
return 0;
I = B->LineIndented(RowP);
PRINTF(("!!! FirstRowP=%d, PrevRowP=%d, RowP=%d, I=%d\n", FirstRowP, PrevRowP, RowP, I));
PRINTF(("!!! FirstColP=%d, PrevColP=%d, ColP=%d\n", FirstColP, PrevColP, ColP));
if (CheckLabel(B, RowP))
I -= C_COLON_OFS;
else if (PrevRowP == RowP && FirstRowP == PrevRowP && FirstColP + 1 == PrevColP)
I += C_CONTINUATION;
if (LookAt(B, Line, 0, "{", hsC_Normal, 0)
&& LookAt(B, RowP, ColP, "{", hsC_Normal, 0))
I -= 0;//C_BRACE_OFS;
else if (LookAt(B, Line, 0, "{", hsC_Normal, 0)
&& !LookAt(B, RowP, ColP, "{", hsC_Normal, 0))
I += C_BRACE_OFS;
else if (!LookAt(B, Line, 0, "{", hsC_Normal, 0)
&& LookAt(B, RowP, ColP, "{", hsC_Normal, 0))
I -= C_BRACE_OFS;
PRINTF(("':' 1 indent : Line=%d, RowP=%d, ColP=%d, CharP=%c\n", Line, RowP, ColP, CharP));
break;
case 'p':
ColP++;
//if (SkipWhite(B, Line, RowP, ColP, SKIP_FORWARD) != 1)
// return 0;
I = B->LineIndented(RowP) + C_CLASS_DELTA;
// if (FirstRowP == RowP) {
// I += C_CLASS_DELTA;
/// if (LookAt(B, Line, 0, "{", hsC_Normal, 0)) {
/// I += C_INDENT - C_BRACE_OFS;
/// }
// }
PRINTF(("':' 2 indent : Line=%d, RowP=%d, ColP=%d, CharP=%c\n", Line, RowP, ColP, CharP));
break;
case 'l':
ColP++;
I = B->LineIndented(RowP) + C_BRACE_OFS;
//C_CLASS_OFS + C_CLASS_DELTA;
break;
case 'c':
ColP++;
// if (SkipWhite(B, Line, RowP, ColP, SKIP_FORWARD) != 1)
// return 0;
I = B->LineIndented(RowP) + C_CASE_DELTA;
// if (FirstRowP == RowP) {
// I += C_CASE_DELTA;
/// if (LookAt(B, Line, 0, "{", hsC_Normal, 0)) {
/// I += C_INDENT - C_BRACE_OFS;
/// }
// }
PRINTF(("':' 3 indent : Line=%d, RowP=%d, ColP=%d, CharP=%c\n", Line, RowP, ColP, CharP));
break;
default:
I = B->LineIndented(RowP);
break;
}
if (((PrevRowP != RowP) ||
((PrevRowP == RowP) && (PrevColP != ColP)))
&& FirstRowP != PrevRowP)
ContinuationIndent = C_CONTINUATION;
if (LookAt(B, Line, 0, "{", hsC_Normal, 0)) {
//I -= C_INDENT - C_BRACE_OFS;
ContinuationIndent = 0;
}
PRINTF(("':' -- indent : Line=%d, RowP=%d, ColP=%d, CharP=%c\n", Line, RowP, ColP, CharP));
return I + ContinuationIndent;
case 'i':
case 's':
case 'f':
case 'e':
case 'w':
I = B->LineIndented(RowP);
switch (CharP) {
case 'i': ColP += 2; break; // if
case 'f': ColP += 3; break; // for
case 'e': ColP += 4; break; // else
case 'w': ColP += 5; break; // while
case 's': ColP += 6; break;
}
PRINTF(("'ifews' -- indent 1: Line=%d, RowP=%d, ColP=%d, CharP=%c\n", Line, RowP, ColP, CharP));
if (SkipWhite(B, Line, RowP, ColP,
SKIP_FORWARD | (CharP != 'e' ? SKIP_MATCH : 0)) != 1)
return 0;
if (RowP >= Line) {
RowP = Line;
ColP = -1;
} else
ColP--;
if (SkipWhite(B, Line, RowP, ColP, SKIP_BACK) != 1)
return 0;
ColP++;
PRINTF(("'ifews' -- indent 2: Line=%d, RowP=%d, ColP=%d, CharP=%c\n", Line, RowP, ColP, CharP));
if (((PrevRowP != RowP) ||
((PrevRowP == RowP) && (PrevColP != ColP)))
&& FirstRowP != PrevRowP)
ContinuationIndent = C_CONTINUATION;
I += C_INDENT;
if (LookAt(B, Line, 0, "{", hsC_Normal, 0)) {
I -= C_INDENT - C_BRACE_OFS;
ContinuationIndent = 0;
}
return I + ContinuationIndent;
// default: return 0;
}
}
return 0;
}
static int IndentComment(EBuffer *B, int Row, int /*StateLen*/, hsState * /*StateMap*/) {
int I = 0, R;
//puts("Comment");
if (Row > 0) {
R = Row - 1;
while (R >= 0) {
if (B->RLine(R)->Count == 0) R--;
else {
I = B->LineIndented(R);
break;
}
}
if (B->RLine(Row - 1)->StateE == hsC_Comment)
if (LookAt(B, Row - 1, I, "/*", hsC_Comment, 0)) I += C_COMMENT_DELTA;
if (B->RLine(Row - 1)->StateE == hsC_CPP_Comm)
if (LookAt(B, Row - 1, I, "/*", hsC_CPP_Comm, 0)) I += C_COMMENT_DELTA;
}
return I;
}
static int IndentCPP(EBuffer *B, int Line, int /*StateLen*/, hsState * /*StateMap*/) {
if (LookAt(B, Line, 0, "#", hsC_CPP, 0))
return 0;
else
return C_INDENT;
}
int Indent_C(EBuffer *B, int Line, int PosCursor) {
int I;
hsState *StateMap = NULL;
int StateLen = 0;
int OI;
OI = I = B->LineIndented(Line);
if (Line == 0) {
I = 0;
} else {
if (I != 0) B->IndentLine(Line, 0);
if (B->GetMap(Line, &StateLen, &StateMap) == 0) return 0;
switch (B->RLine(Line - 1)->StateE) {
case hsC_Comment:
case hsC_CPP_Comm:
I = IndentComment(B, Line, StateLen, StateMap);
break;
case hsC_CPP:
/*case hsC_CPP_Comm:*/
case hsC_CPP_String1:
case hsC_CPP_String2:
case hsC_CPP_ABrace:
I = C_INDENT;
break;
default:
if (StateLen > 0) { // line is not empty
if (StateMap[0] == hsC_CPP || StateMap[0] == hsC_CPP_Comm ||
StateMap[0] == hsC_CPP_String1 || StateMap[0] == hsC_CPP_String2 ||
StateMap[0] == hsC_CPP_ABrace)
{
I = IndentCPP(B, Line, StateLen, 0);
} else {
I = IndentNormal(B, Line, StateLen, StateMap);
if ((StateMap[0] == hsC_Comment
|| StateMap[0] == hsC_CommentL
|| StateMap[0] == hsC_CPP_Comm)
&& ((LookAt(B, Line, 0, "/*", hsC_Comment, 0)
|| LookAt(B, Line, 0, "/*", hsC_CPP_Comm, 0)
|| LookAt(B, Line, 0, "//", hsC_CommentL, 0))))
{
I += C_COMMENT_OFS;
} else if (CheckLabel(B, Line)) {
if (LookAt(B, Line, 0, "case", hsC_Keyword) ||
LookAt(B, Line, 0, "default", hsC_Keyword) ||
LookAt(B, Line, 0, "public:", hsC_Keyword, 0) ||
LookAt(B, Line, 0, "private:", hsC_Keyword, 0) ||
LookAt(B, Line, 0, "protected:", hsC_Keyword, 0))
;
else
I += C_COLON_OFS;
} //else if (LookAt(B, Line, 0, "{", hsC_Normal, 0)) {
// I -= C_INDENT - C_BRACE_OFS;
//}
}
} else {
I = IndentNormal(B, Line, 0, NULL);
}
break;
}
}
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