/* 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