1 /*    c_config.cpp
2  *
3  *    Copyright (c) 1994-1996, Marko Macek
4  *
5  *    You may distribute under the terms of either the GNU General Public
6  *    License or the Artistic License, as specified in the README file.
7  *
8  */
9 
10 #include "c_config.h"
11 
12 #include "c_bind.h"
13 #include "c_color.h"
14 #include "c_fconfig.h"
15 #include "ftever.h"
16 #include "log.h"
17 #include "o_buflist.h"
18 #include "o_cvsbase.h"
19 #include "o_svnbase.h"
20 #include "s_string.h"
21 
22 #include <fcntl.h>
23 #include <stdio.h>
24 
25 struct GUICharactersEntry {
26     struct GUICharactersEntry *next;
27     char *name;
28     char *chars;
29 };
30 
31 struct CurPos {
32     off_t sz;
33     const char *a;
34     const char *c;
35     const char *z;
36     int line;
37     const char *name; // filename
38 };
39 
40 #ifdef CONFIG_INDENT_C
41 extern int C_Indent;
42 extern int C_BraceOfs;
43 extern int C_CaseOfs;
44 extern int C_CaseDelta;
45 extern int C_ClassOfs;
46 extern int C_ClassDelta;
47 extern int C_ColonOfs;
48 extern int C_CommentOfs;
49 extern int C_CommentDelta;
50 extern int C_FirstLevelWidth;
51 extern int C_FirstLevelIndent;
52 extern int C_Continuation;
53 extern int C_ParenDelta;
54 extern int FunctionUsesContinuation;
55 #endif
56 
57 #ifdef CONFIG_INDENT_REXX
58 extern int REXX_Base_Indent;
59 extern int REXX_Do_Offset;
60 #endif
61 
62 extern int ShowVScroll;
63 extern int ShowHScroll;
64 extern int ShowMenuBar;
65 
66 int SystemClipboard = 0;
67 int ScreenSizeX = -1, ScreenSizeY = -1;
68 int ScrollBarWidth = 1;
69 int CursorInsSize[2] = { 90, 100 };
70 int CursorOverSize[2] = { 0, 100 };
71 bool CursorBlink = 0; // default is "no" (same as before)
72 int OpenAfterClose = 1;
73 int SelectPathname = 0;
74 char DefaultModeName[32] = "";
75 RxNode *CompletionFilter = NULL;
76 #if defined(DOS) || defined(DOSP32)
77 char PrintDevice[MAXPATH] = "PRN";
78 #else
79 char PrintDevice[MAXPATH] = "\\DEV\\PRN";
80 #endif
81 char CompileCommand[256] = "make";
82 int KeepHistory = 0;
83 int LoadDesktopOnEntry = 0;
84 int SaveDesktopOnExit = 0;
85 char WindowFont[64] = "";
86 // Custom RGB colors (if console driver supports them)
87 TRGBColor RGBColor[16];
88 // true if corresponding triplet in RGBColor is valid
89 bool RGBColorValid [16];
90 int KeepMessages = 0;
91 int ScrollBorderX = 0;
92 int ScrollBorderY = 0;
93 int ScrollJumpX = 8;
94 int ScrollJumpY = 1;
95 int GUIDialogs = 1;
96 int PMDisableAccel = 0;
97 int SevenBit = 0;
98 int WeirdScroll = 0;
99 int LoadDesktopMode = 0;
100 char HelpCommand[128] = "man -a";
101 char *ConfigSourcePath = 0;
102 int IgnoreBufferList = 0;
103 static GUICharactersEntry *GUICharacters = NULL;
104 #ifdef CONFIG_OBJ_CVS
105 char CvsCommand[256] = "cvs";
106 char CvsLogMode[32] = "PLAIN";
107 #endif
108 #ifdef CONFIG_OBJ_SVN
109 char SvnCommand[256] = "svn";
110 char SvnLogMode[32] = "PLAIN";
111 #endif
112 int ReassignModelIds = 0;
113 int RecheckReadOnly = 0;
114 char XShellCommand[256] = "xterm";
115 int ShowTildeFilesInDirList = 1;
116 
117 // Which characters to get. defaultCharacters if not set, rest filled
118 // with defaultCharacters if too short
119 // List of GUICharacters is freed, only one item remains
GetGUICharacters(const char * which,const char * defChars)120 const char *GetGUICharacters(const char *which, const char *defChars) {
121     GUICharactersEntry *g, *gg, *found = NULL;
122     char *s;
123     size_t i;
124 
125     for (g = GUICharacters; g; g=gg) {
126         gg = g->next;
127         if (strcmp(g->name, which) == 0) {
128             if ((i = strlen(g->chars)) < strlen(defChars)) {
129                 s = new char [strlen(defChars) + 1];
130                 assert(s != NULL);
131                 strcpy(s, g->chars);
132                 strcpy(s + i, defChars + i);
133                 delete g->chars;
134                 g->chars = s;
135             }
136             if (found) {
137                 free(found->chars); free(found->name); free(found);
138             }
139             found = g;
140         } else {
141             free(g->name); free(g->chars); free(g);
142         }
143     }
144     GUICharacters = found;
145     return found ? found->chars : defChars;
146 }
147 
AppendGUICharacters(const char * string)148 static void AppendGUICharacters(const char *string) {
149     const char *s;
150     GUICharactersEntry *g;
151 
152     s = strchr(string, ':');
153     if (s) {
154         g = new GUICharactersEntry;
155         assert(g != NULL);
156 
157         // allocate memory for name  +1 for strncat
158         g->name = (char *)malloc((s-string) + 1);
159         assert(g->name != NULL);
160 
161         // make sure we have zero at start of string
162         *(g->name) = 0;
163 
164         // strncat makes sure that we have zero at the end...
165         strncat(g->name, string, (s-string));
166 
167         // copy text after ':' to chars...
168         g->chars = strdup(s+1);
169         assert(g->chars != NULL);
170 
171         g->next = GUICharacters;
172         GUICharacters = g;
173     }
174 }
175 
176 #ifdef CONFIG_SYNTAX_HILIT
AddKeyword(ColorKeywords * tab,char color,const char * keyword)177 static int AddKeyword(ColorKeywords *tab, char color, const char *keyword) {
178     size_t len = strlen(keyword);
179     if (len < 1 || len >= CK_MAXLEN) return 0;
180 
181     if (tab->key[len]) {
182         size_t lx = strlen(tab->key[len]);
183         char *key;
184 
185         key = (char *)realloc(tab->key[len], lx + len + 1 + 1);
186         assert(key != NULL);
187 
188         tab->key[len] = key;
189         assert(tab->key[len] != 0);
190         strcpy(tab->key[len] + lx, keyword);
191         tab->key[len][lx + len] = color;
192         tab->key[len][lx + len + 1] = 0;
193     } else {
194         tab->key[len] = (char *)malloc(len + 2);
195         assert(tab->key[len] != 0);
196         strcpy(tab->key[len], keyword);
197         tab->key[len][len] = color;
198         tab->key[len][len + 1] = 0;
199     }
200     tab->count[len]++;
201     tab->TotalCount++;
202     return 1;
203 }
204 #endif
205 
SetModeNumber(EMode * mode,int what,int number)206 static int SetModeNumber(EMode *mode, int what, int number) {
207     int j = what;
208 
209     if (j == BFI_LeftMargin || j == BFI_RightMargin) number--;
210     mode->Flags.num[j] = number;
211     return 0;
212 }
213 
SetModeString(EMode * mode,int what,const char * string)214 static int SetModeString(EMode *mode, int what, const char *string) {
215     int j = what;
216 
217 #ifdef CONFIG_SYNTAX_HILIT
218     if (j == BFI_Colorizer) {
219         mode->fColorize = FindColorizer(string);
220     } else
221 #endif
222         if (j == BFI_EventMap) {
223             mode->fEventMap = FindEventMap(string);
224 #ifdef CONFIG_INDENT
225         } else if (j == BFI_IndentMode) {
226             mode->Flags.num[j] = GetIndentMode(string);
227 #endif
228         } else if (j == BFS_WordChars) {
229             SetWordChars(mode->Flags.WordChars, string);
230         } else if (j == BFS_CapitalChars) {
231             SetWordChars(mode->Flags.CapitalChars, string);
232         } else if (j == BFS_FileNameRx) {
233             if (mode->MatchName)
234                 free(mode->MatchName);
235             if (mode->MatchNameRx)
236                 RxFree(mode->MatchNameRx);
237             mode->MatchName = strdup(string);
238             mode->MatchNameRx = RxCompile(string);
239         } else if (j == BFS_FirstLineRx) {
240             if (mode->MatchLine)
241                 free(mode->MatchLine);
242             if (mode->MatchLineRx)
243                 RxFree(mode->MatchLineRx);
244             mode->MatchLine = strdup(string);
245             mode->MatchLineRx = RxCompile(string);
246         } else {
247             if (mode->Flags.str[j & 0xFF])
248                 free(mode->Flags.str[j & 0xFF]);
249             mode->Flags.str[j & 0xFF] = strdup(string);
250         }
251     return 0;
252 }
253 
254 // *INDENT-OFF*
SetGlobalNumber(int what,int number)255 static int SetGlobalNumber(int what, int number)
256 {
257     STARTFUNC("SetGlobalNumber");
258     LOG << "What: " << what << " Number: " << number << ENDLINE;
259     switch (what) {
260 #ifdef CONFIG_INDENT_C
261     case FLAG_C_Indent:          C_Indent = number; break;
262     case FLAG_C_BraceOfs:        C_BraceOfs = number; break;
263     case FLAG_C_CaseOfs:         C_CaseOfs = number; break;
264     case FLAG_C_CaseDelta:       C_CaseDelta = number; break;
265     case FLAG_C_ClassOfs:        C_ClassOfs = number; break;
266     case FLAG_C_ClassDelta:      C_ClassDelta = number; break;
267     case FLAG_C_ColonOfs:        C_ColonOfs = number; break;
268     case FLAG_C_CommentOfs:      C_CommentOfs = number; break;
269     case FLAG_C_CommentDelta:    C_CommentDelta = number; break;
270     case FLAG_C_FirstLevelIndent: C_FirstLevelIndent = number; break;
271     case FLAG_C_FirstLevelWidth: C_FirstLevelWidth = number; break;
272     case FLAG_C_Continuation:    C_Continuation = number; break;
273     case FLAG_C_ParenDelta:      C_ParenDelta = number; break;
274     case FLAG_FunctionUsesContinuation: FunctionUsesContinuation = number; break;
275 #endif
276 #ifdef CONFIG_INDENT_REXX
277     case FLAG_REXX_Indent:       REXX_Base_Indent = number; break;
278     case FLAG_REXX_Do_Offset:    REXX_Do_Offset = number; break;
279 #endif
280     case FLAG_ScreenSizeX:       ScreenSizeX = number; break;
281     case FLAG_ScreenSizeY:       ScreenSizeY = number; break;
282     case FLAG_CursorInsertStart: CursorInsSize[0] = number; break;
283     case FLAG_CursorInsertEnd:   CursorInsSize[1] = number; break;
284     case FLAG_CursorOverStart:   CursorOverSize[0] = number; break;
285     case FLAG_CursorOverEnd:     CursorOverSize[1] = number; break;
286     case FLAG_CursorBlink:       CursorBlink = number; break;
287     case FLAG_SysClipboard:      SystemClipboard = number; break;
288     case FLAG_OpenAfterClose:    OpenAfterClose = number; break;
289     case FLAG_ShowVScroll:       ShowVScroll = number; break;
290     case FLAG_ShowHScroll:       ShowHScroll = number; break;
291     case FLAG_ScrollBarWidth:    ScrollBarWidth = number; break;
292     case FLAG_SelectPathname:    SelectPathname = number; break;
293     case FLAG_ShowMenuBar:       ShowMenuBar = number; break;
294     case FLAG_ShowToolBar:       ShowToolBar = number; break;
295     case FLAG_KeepHistory:       KeepHistory = number; break;
296     case FLAG_LoadDesktopOnEntry: LoadDesktopOnEntry = number; break;
297     case FLAG_SaveDesktopOnExit: SaveDesktopOnExit = number; break;
298     case FLAG_KeepMessages:      KeepMessages = number; break;
299     case FLAG_ScrollBorderX:     ScrollBorderX = number; break;
300     case FLAG_ScrollBorderY:     ScrollBorderY = number; break;
301     case FLAG_ScrollJumpX:       ScrollJumpX = number; break;
302     case FLAG_ScrollJumpY:       ScrollJumpY = number; break;
303     case FLAG_GUIDialogs:        GUIDialogs = number; break;
304     case FLAG_PMDisableAccel:    PMDisableAccel = number; break;
305     case FLAG_SevenBit:          SevenBit = number; break;
306     case FLAG_WeirdScroll:       WeirdScroll = number; break;
307     case FLAG_LoadDesktopMode:   LoadDesktopMode = number; break;
308     case FLAG_IgnoreBufferList:  IgnoreBufferList = number; break;
309     case FLAG_ReassignModelIds:  ReassignModelIds = number; break;
310     case FLAG_RecheckReadOnly:   RecheckReadOnly = number; break;
311     case FLAG_ShowTildeFilesInDirList: ShowTildeFilesInDirList = number; break;
312     default:
313         //printf("Unknown global number: %d\n", what);
314         ENDFUNCRC(-1);
315     }
316     ENDFUNCRC(0);
317 }
318 // *INDENT-ON*
319 
SetRGBColor(const char * string)320 static void SetRGBColor(const char *string) {
321     int idx,r,g,b;
322     if (sscanf (string, "%x:%x,%x,%x", &idx, &r, &g, &b) != 4) {
323         fprintf(stderr, "Invalid RGB Definition: %s\n", string);
324         return;
325     }
326     if (idx < 0 || idx > 15) {
327         fprintf(stderr, "Invalid RGB index: (0-f only) (%s)\n", string);
328         return;
329     }
330     if (r < 0 || r > 255 ||
331         g < 0 || g > 255 ||
332         b < 0 || b > 255) {
333         fprintf(stderr, "Invalid RGB palette values (00-ff only): %s\n", string);
334         return;
335     }
336     RGBColorValid[idx] = true;
337     RGBColor[idx].r = (unsigned char) r;
338     RGBColor[idx].g = (unsigned char) g;
339     RGBColor[idx].b = (unsigned char) b;
340 }
341 
SetGlobalString(long what,const char * string)342 static int SetGlobalString(long what, const char *string) {
343     STARTFUNC("SetGlobalString");
344     LOG << "What: " << what << " String: " << string << ENDLINE;
345 
346     switch (what) {
347     case FLAG_DefaultModeName: strlcpy(DefaultModeName, string, sizeof(DefaultModeName)); break;
348     case FLAG_CompletionFilter: if ((CompletionFilter = RxCompile(string)) == NULL) return -1; break;
349     case FLAG_PrintDevice: strlcpy(PrintDevice, string, sizeof(PrintDevice)); break;
350     case FLAG_CompileCommand: strlcpy(CompileCommand, string, sizeof(CompileCommand)); break;
351     case FLAG_WindowFont: strlcpy(WindowFont, string, sizeof(WindowFont)); break;
352     case FLAG_HelpCommand: strlcpy(HelpCommand, string, sizeof(HelpCommand)); break;
353     case FLAG_GUICharacters: AppendGUICharacters (string); break;
354 #ifdef CONFIG_OBJ_CVS
355     case FLAG_CvsCommand: strlcpy(CvsCommand, string, sizeof(CvsCommand)); break;
356     case FLAG_CvsLogMode: strlcpy(CvsLogMode, string, sizeof(CvsLogMode)); break;
357 #endif
358 #ifdef CONFIG_OBJ_SVN
359     case FLAG_SvnCommand: strlcpy(SvnCommand, string, sizeof(SvnCommand)); break;
360     case FLAG_SvnLogMode: strlcpy(SvnLogMode, string, sizeof(SvnLogMode)); break;
361 #endif
362     case FLAG_RGBColor: SetRGBColor(string); break;
363     case FLAG_XShellCommand: strlcpy(XShellCommand, string, sizeof(XShellCommand)); break;
364     default:
365         //printf("Unknown global string: %ld\n", what);
366         ENDFUNCRC(-1);
367     }
368     ENDFUNCRC(0);
369 }
370 
SetEventString(EEventMap * Map,int what,const char * string)371 static int SetEventString(EEventMap *Map, int what, const char *string) {
372     STARTFUNC("SetEventString");
373     LOG << "What: " << what << " String: " << string << ENDLINE;
374     switch (what) {
375     case EM_MainMenu:
376     case EM_LocalMenu:
377         Map->SetMenu(what, string);
378         break;
379     default:
380         ENDFUNCRC(-1);
381     }
382     ENDFUNCRC(0);
383 }
384 
385 #ifdef CONFIG_SYNTAX_HILIT
SetColorizeString(EColorize * Colorize,long what,const char * string)386 static int SetColorizeString(EColorize *Colorize, long what, const char *string) {
387     STARTFUNC("SetColorizeString");
388     LOG << "What: " << what << " String: " << string << ENDLINE;
389     switch (what) {
390     case COL_SyntaxParser:
391         Colorize->SyntaxParser = GetHilitMode(string);
392         break;
393     default:
394         ENDFUNCRC(-1);
395     }
396     ENDFUNCRC(0);
397 }
398 #endif
399 
GetObj(CurPos & cp,unsigned short & len)400 static unsigned char GetObj(CurPos &cp, unsigned short &len) {
401     len = 0;
402     if (cp.c + 3 <= cp.z) {
403         unsigned char c;
404         unsigned char l[2];
405         c = *cp.c++;
406         memcpy(l, cp.c, 2);
407         len = (l[1] << 8) + l[0];
408         cp.c += 2;
409         return c;
410     }
411     return 0xFF;
412 }
413 
GetCharStr(CurPos & cp,unsigned short len)414 static const char *GetCharStr(CurPos &cp, unsigned short len) {
415     STARTFUNC("GetCharStr");
416     LOG << "Length: " << len << ENDLINE;
417 
418     const char *p = cp.c;
419     if (cp.c + len > cp.z)
420     {
421         LOG << "End of config file in GetCharStr" << ENDLINE;
422         ENDFUNCRC(0);
423     }
424     cp.c += len;
425     ENDFUNCRC(p);
426 }
427 
GetNum(CurPos & cp,long & num)428 static int GetNum(CurPos &cp, long &num) {
429     unsigned char n[4];
430     if (cp.c + 4 > cp.z) return 0;
431     memcpy(n, cp.c, 4);
432     num =
433         (n[3] << 24) +
434         (n[2] << 16) +
435         (n[1] << 8) +
436         n[0];
437 
438     if ((n[3] > 127) && sizeof(long) > 4)
439         num = num | (~0xFFFFFFFFUL);
440     cp.c += 4;
441     return 1;
442 }
443 
ReadCommands(CurPos & cp,const char * Name)444 static int ReadCommands(CurPos &cp, const char *Name) {
445     STARTFUNC("ReadCommands");
446     LOG << "Name = " << (Name != NULL ? Name : "(null)") << ENDLINE;
447 
448     unsigned char obj;
449     unsigned short len;
450     long Cmd = NewCommand(Name);
451     long cmdno;
452 
453     if (GetObj(cp, len) != CF_INT) ENDFUNCRC(-1);
454     if (GetNum(cp, cmdno) == 0) ENDFUNCRC(-1);
455     if (cmdno != (Cmd | CMD_EXT)) {
456         fprintf(stderr, "Bad Command map %s -> %ld != %ld\n", Name, Cmd, cmdno);
457         ENDFUNCRC(-1);
458     }
459 
460     while ((obj = GetObj(cp, len)) != 0xFF) {
461         switch (obj) {
462         case CF_COMMAND:
463             {
464                 //              char *s;
465                 long cnt;
466                 long ign;
467                 long cmd;
468 
469                 //                if ((s = GetCharStr(cp, len)) == 0) return -1;
470                 if (GetNum(cp, cmd) == 0) ENDFUNCRC(-1);
471                 if (GetObj(cp, len) != CF_INT) ENDFUNCRC(-1);
472                 if (GetNum(cp, cnt) == 0) ENDFUNCRC(-1);
473                 if (GetObj(cp, len) != CF_INT) ENDFUNCRC(-1);
474                 if (GetNum(cp, ign) == 0) ENDFUNCRC(-1);
475 
476                 //                if (cmd != CmdNum(s)) {
477                 //                    fprintf(stderr, "Bad Command Id: %s -> %d\n", s, cmd);
478                 //                    return -1;
479                 //                }
480 
481                 if (AddCommand(Cmd, cmd, cnt, ign) == 0) {
482                     if (Name == 0 || strcmp(Name, "xx") != 0) {
483                         fprintf(stderr, "Bad Command Id: %ld\n", cmd);
484                         ENDFUNCRC(-1);
485                     }
486                 }
487             }
488             break;
489         case CF_STRING:
490             {
491                 const char *s = GetCharStr(cp, len);
492 
493                 if (s == 0) ENDFUNCRC(-1);
494                 if (AddString(Cmd, s) == 0) ENDFUNCRC(-1);
495             }
496             break;
497         case CF_INT:
498             {
499                 long num;
500 
501                 if (GetNum(cp, num) == 0) ENDFUNCRC(-1);
502                 if (AddNumber(Cmd, num) == 0) ENDFUNCRC(-1);
503             }
504             break;
505         case CF_VARIABLE:
506             {
507                 long num;
508 
509                 if (GetNum(cp, num) == 0) ENDFUNCRC(-1);
510                 if (AddVariable(Cmd, num) == 0) ENDFUNCRC(-1);
511             }
512             break;
513         case CF_CONCAT:
514             if (AddConcat(Cmd) == 0) ENDFUNCRC(-1);
515             break;
516         case CF_END:
517             ENDFUNCRC(Cmd);
518         default:
519             ENDFUNCRC(-1);
520         }
521     }
522     ENDFUNCRC(-1);
523 }
524 
ReadMenu(CurPos & cp,const char * MenuName)525 static int ReadMenu(CurPos &cp, const char *MenuName) {
526     unsigned char obj;
527     unsigned short len;
528 
529     int menu = -1, item = -1;
530 
531     menu = NewMenu(MenuName);
532 
533     while ((obj = GetObj(cp, len)) != 0xFF) {
534         switch (obj) {
535         case CF_ITEM:
536             {
537                 if (len == 0) {
538                     item = NewItem(menu, 0);
539                 } else {
540                     const char *s = GetCharStr(cp, len);
541                     int Cmd;
542                     if (s == 0) return -1;
543                     item = NewItem(menu, s);
544                     if ((obj = GetObj(cp, len)) != CF_MENUSUB) return -1;
545                     if ((Cmd = ReadCommands(cp, 0)) == -1) return -1;
546                     Menus[menu].Items[item].Cmd = Cmd + 65536;
547                 }
548             }
549             break;
550         case CF_SUBMENU:
551             {
552                 const char *s = GetCharStr(cp, len);
553                 const char *w;
554 
555                 if ((obj = GetObj(cp, len)) != CF_STRING) return -1;
556                 if ((w = GetCharStr(cp, len)) == 0) return -1;
557                 item = NewSubMenu(menu, s, GetMenuId(w), SUBMENU_NORMAL);
558             }
559             break;
560 
561         case CF_SUBMENUCOND:
562             {
563                 const char *s = GetCharStr(cp, len);
564                 const char *w;
565 
566                 if ((obj = GetObj(cp, len)) != CF_STRING) return -1;
567                 if ((w = GetCharStr(cp, len)) == 0) return -1;
568                 item = NewSubMenu(menu, s, GetMenuId(w), SUBMENU_CONDITIONAL);
569             }
570             break;
571 
572         case CF_END:
573             return 0;
574         default:
575             return -1;
576         }
577     }
578     return -1;
579 }
580 
ReadColors(CurPos & cp,const char * ObjName)581 static int ReadColors(CurPos &cp, const char *ObjName) {
582     unsigned char obj;
583     unsigned short len;
584 
585     while ((obj = GetObj(cp, len)) != 0xFF) {
586         switch (obj) {
587         case CF_STRING:
588             {
589                 const char *sname = GetCharStr(cp, len);
590                 const char *svalue;
591                 if (sname == 0) return -1;
592                 if ((obj = GetObj(cp, len)) != CF_STRING) return -1;
593                 if ((svalue = GetCharStr(cp, len)) == 0) return -1;
594 
595                 StlString cl(ObjName);
596 
597                 cl += '.';
598                 cl += sname;
599 
600                 if (SetColor(cl.c_str(), svalue) == 0)
601                    return -1;
602             }
603             break;
604         case CF_END:
605             return 0;
606         default:
607             return -1;
608         }
609     }
610     return -1;
611 }
612 
613 #ifdef CONFIG_SYNTAX_HILIT
ReadHilitColors(CurPos & cp,EColorize * Colorize,const char *)614 static int ReadHilitColors(CurPos &cp, EColorize *Colorize, const char * /*ObjName*/) {
615     unsigned char obj;
616     unsigned short len;
617 
618     while ((obj = GetObj(cp, len)) != 0xFF) {
619         switch (obj) {
620         case CF_INT:
621             {
622                 long cidx;
623                 const char *svalue;
624 
625                 if (GetNum(cp, cidx) == 0) return -1;
626                 if ((obj = GetObj(cp, len)) != CF_STRING)
627                     return -1;
628                 if ((svalue = GetCharStr(cp, len)) == 0)
629                     return -1;
630                 if (Colorize->SetColor(cidx, svalue) == 0)
631                     return -1;
632             }
633             break;
634         case CF_END:
635             return 0;
636         default:
637             return -1;
638         }
639     }
640     return -1;
641 }
642 
ReadKeywords(CurPos & cp,ColorKeywords * keywords,int color)643 static int ReadKeywords(CurPos &cp, ColorKeywords *keywords, int color) {
644     unsigned char obj;
645     unsigned short len;
646 
647     while ((obj = GetObj(cp, len)) != 0xFF) {
648         switch (obj) {
649         case CF_STRING:
650             {
651                 const char *kname = GetCharStr(cp, len);
652                 if (kname == 0) return -1;
653                 if (AddKeyword(keywords, (char) color, kname) != 1) return -1;
654             }
655             break;
656         case CF_END:
657             return 0;
658         default:
659             return -1;
660         }
661     }
662     return -1;
663 }
664 #endif
665 
ReadEventMap(CurPos & cp,EEventMap * Map,const char *)666 static int ReadEventMap(CurPos &cp, EEventMap *Map, const char * /*MapName*/) {
667     unsigned char obj;
668     unsigned short len;
669 
670     while ((obj = GetObj(cp, len)) != 0xFF) {
671         switch (obj) {
672         case CF_KEY:
673             {
674                 EKey *Key;
675                 const char *s;
676                 int Cmd;
677 
678                 if ((s = GetCharStr(cp, len)) == 0) return -1;
679                 if ((Key = SetKey(Map, s)) == 0) return -1;
680                 if ((obj = GetObj(cp, len)) != CF_KEYSUB) return -1;
681                 if ((Cmd = ReadCommands(cp, 0)) == -1) return -1;
682                 Key->Cmd = Cmd;
683             }
684             break;
685 
686 #ifdef CONFIG_ABBREV
687         case CF_ABBREV:
688             {
689                 EAbbrev *Ab;
690                 const char *s;
691                 const char *x;
692                 int Cmd;
693 
694                 if ((s = GetCharStr(cp, len)) == 0) return -1;
695                 obj = GetObj(cp, len);
696                 if (obj == CF_KEYSUB) {
697                     if ((Cmd = ReadCommands(cp, 0)) == -1) return -1;
698                     Ab = new EAbbrev(s, Cmd);
699                 } else if (obj == CF_STRING) {
700                     x = GetCharStr(cp, len);
701                     Ab = new EAbbrev(s, x);
702                 } else
703                     return -1;
704                 if (Ab) {
705                     Map->AddAbbrev(Ab);
706                 }
707             }
708             break;
709 #endif
710 
711         case CF_SETVAR:
712             {
713                 long what;
714 
715                 if (GetNum(cp, what) == 0) return -1;
716                 switch (GetObj(cp, len)) {
717                 case CF_STRING:
718                     {
719                         const char *val = GetCharStr(cp, len);
720                         if (len == 0) return -1;
721                         if (SetEventString(Map, what, val) != 0) return -1;
722                     }
723                     break;
724                     /*                case CF_INT:
725                      {
726                      long num;
727 
728                      if (GetNum(cp, num) == 0) return -1;
729                      if (SetModeNumber(Mode, what, num) != 0) return -1;
730                      }
731                      break;*/
732                 default:
733                     return -1;
734                 }
735             }
736             break;
737         case CF_END:
738             return 0;
739         default:
740             return -1;
741         }
742     }
743     return -1;
744 }
745 
746 #ifdef CONFIG_SYNTAX_HILIT
ReadColorize(CurPos & cp,EColorize * Colorize,const char * ModeName)747 static int ReadColorize(CurPos &cp, EColorize *Colorize, const char *ModeName) {
748     unsigned char obj;
749     unsigned short len;
750 
751     long LastState = -1;
752 
753     while ((obj = GetObj(cp, len)) != 0xFF) {
754         switch (obj) {
755         case CF_COLOR:
756             if (ReadHilitColors(cp, Colorize, ModeName) == -1) return -1;
757             break;
758 
759         case CF_KEYWORD:
760             {
761                 const char *colorstr;
762 
763                 if ((colorstr = GetCharStr(cp, len)) == 0) return -1;
764 
765                 unsigned int Col;
766                 unsigned int ColBg, ColFg;
767 
768                 if (sscanf(colorstr, "%1X %1X", &ColFg, &ColBg) != 2)
769                     return 0;
770 
771                 Col = ColFg | (ColBg << 4);
772 
773                 int color = ChColor(Col);
774                 if (ReadKeywords(cp, &Colorize->Keywords, color) == -1) return -1;
775             }
776             break;
777 
778         case CF_HSTATE:
779             {
780                 long stateno;
781                 long color;
782 
783                 if (Colorize->hm == 0)
784                     Colorize->hm = new HMachine();
785 
786                 assert(Colorize->hm != 0);
787 
788                 if (GetNum(cp, stateno) == 0)
789                     return -1;
790 
791                 assert(stateno == LastState + 1);
792 
793                 obj = GetObj(cp, len);
794                 assert(obj == CF_INT);
795 
796                 if (GetNum(cp, color) == 0)
797                     return -1;
798 
799                 HState newState;
800 
801                 newState.InitState();
802 
803                 newState.color = color;
804 
805                 Colorize->hm->AddState(newState);
806                 LastState = stateno;
807             }
808             break;
809 
810         case CF_HTRANS:
811             {
812                 HTrans newTrans;
813                 long nextState;
814                 long matchFlags;
815                 const char *match;
816                 long color;
817 
818                 if (GetNum(cp, nextState) == 0)
819                     return -1;
820                 obj = GetObj(cp, len);
821                 assert(obj == CF_INT);
822                 if (GetNum(cp, matchFlags) == 0)
823                     return -1;
824                 obj = GetObj(cp, len);
825                 assert(obj == CF_INT);
826                 if (GetNum(cp, color) == 0)
827                     return -1;
828                 obj = GetObj(cp, len);
829                 assert(matchFlags & MATCH_REGEXP ? obj == CF_REGEXP : obj == CF_STRING);
830                 if ((match = GetCharStr(cp, len)) == 0)
831                     return -1;
832 
833                 newTrans.InitTrans();
834 
835                 newTrans.matchFlags = matchFlags;
836                 newTrans.nextState = nextState;
837                 newTrans.color = color;
838 
839                 if (newTrans.matchFlags & MATCH_REGEXP) {
840                     newTrans.regexp = RxCompile(match);
841                     newTrans.matchLen = 0;
842                 } else if ((newTrans.matchFlags & MATCH_SET) ||
843                            (newTrans.matchFlags & MATCH_NOTSET))
844                 {
845                     newTrans.matchLen = 1;
846                     newTrans.match = (char *)malloc(256/8);
847                     assert(newTrans.match != NULL);
848                     SetWordChars(newTrans.match, match);
849                 } else {
850                     newTrans.match = strdup(match);
851                     newTrans.matchLen = strlen(match);
852                 }
853 
854                 Colorize->hm->AddTrans(newTrans);
855             }
856             break;
857 
858         case CF_HWTYPE:
859             {
860                 long nextKwdMatchedState;
861                 long nextKwdNotMatchedState;
862                 long nextKwdNoCharState;
863                 long options;
864                 const char *wordChars;
865 
866                 obj = GetObj(cp, len);
867                 assert(obj == CF_INT);
868                 if (GetNum(cp, nextKwdMatchedState) == 0)
869                     return -1;
870 
871                 obj = GetObj(cp, len);
872                 assert(obj == CF_INT);
873                 if (GetNum(cp, nextKwdNotMatchedState) == 0)
874                     return -1;
875 
876                 obj = GetObj(cp, len);
877                 assert(obj == CF_INT);
878                 if (GetNum(cp, nextKwdNoCharState) == 0)
879                     return -1;
880 
881                 obj = GetObj(cp, len);
882                 assert(obj == CF_INT);
883                 if (GetNum(cp, options) == 0)
884                     return -1;
885 
886                 obj = GetObj(cp, len);
887                 assert(obj == CF_STRING);
888                 if ((wordChars = GetCharStr(cp, len)) == 0)
889                     return -1;
890 
891                 Colorize->hm->LastState()->options = options;
892                 Colorize->hm->LastState()->nextKwdMatchedState = nextKwdMatchedState;
893                 Colorize->hm->LastState()->nextKwdNotMatchedState = nextKwdNotMatchedState;
894                 Colorize->hm->LastState()->nextKwdNoCharState = nextKwdNoCharState;
895 
896                 if (wordChars && *wordChars) {
897                     Colorize->hm->LastState()->wordChars = (char *)malloc(256/8);
898                     assert(Colorize->hm->LastState()->wordChars != NULL);
899                     SetWordChars(Colorize->hm->LastState()->wordChars, wordChars);
900                 }
901             }
902             break;
903 
904         case CF_HWORDS:
905             {
906                 const char *colorstr;
907                 int color;
908 
909                 if ((colorstr = GetCharStr(cp, len)) == 0) return -1;
910 
911                 color = hcPlain_Keyword;
912 
913                 if (strcmp(colorstr, "-") != 0) {
914                     const char *Value = colorstr;
915                     int Col;
916 
917                     if (*Value == '-') {
918                         Value++;
919                         if (sscanf(Value, "%1X", &Col) != 1) return -1;
920                         Col |= (hcPlain_Background & 0xF0);
921                     } else if (Value[1] == '-') {
922                         if (sscanf(Value, "%1X", &Col) != 1) return -1;
923                         Col <<= 4;
924                         Col |= (hcPlain_Background & 0x0F);
925                     } else {
926                         unsigned int ColBg, ColFg;
927 
928                         if (sscanf(colorstr, "%1X %1X", &ColFg, &ColBg) != 2)
929                             return 0;
930 
931                         Col = ColFg | (ColBg << 4);
932                     }
933                     color = Col;
934                 }
935                 if (ReadKeywords(cp, &Colorize->hm->LastState()->keywords, color) == -1) return -1;
936             }
937             break;
938 
939         case CF_SETVAR:
940             {
941                 long what;
942 
943                 if (GetNum(cp, what) == 0) return -1;
944                 switch (GetObj(cp, len)) {
945                 case CF_STRING:
946                     {
947                         const char *val = GetCharStr(cp, len);
948                         if (len == 0) return -1;
949                         if (SetColorizeString(Colorize, what, val) != 0) return -1;
950                     }
951                     break;
952                     /*                case CF_INT:
953                      {
954                      long num;
955 
956                      if (GetNum(cp, num) == 0) return -1;
957                      if (SetModeNumber(Mode, what, num) != 0) return -1;
958                      }
959                      break;*/
960                 default:
961                     return -1;
962                 }
963             }
964             break;
965         case CF_END:
966             return 0;
967         default:
968             return -1;
969         }
970     }
971     return -1;
972 }
973 #endif
974 
ReadMode(CurPos & cp,EMode * Mode,const char *)975 static int ReadMode(CurPos &cp, EMode *Mode, const char * /*ModeName*/) {
976     unsigned char obj;
977     unsigned short len;
978 
979     while ((obj = GetObj(cp, len)) != 0xFF) {
980         switch (obj) {
981         case CF_SETVAR:
982             {
983                 long what;
984 
985                 if (GetNum(cp, what) == 0) return -1;
986                 switch (GetObj(cp, len)) {
987                 case CF_STRING:
988                     {
989                         const char *val = GetCharStr(cp, len);
990                         if (len == 0) return -1;
991                         if (SetModeString(Mode, what, val) != 0) return -1;
992                     }
993                     break;
994                 case CF_INT:
995                     {
996                         long num;
997 
998                         if (GetNum(cp, num) == 0) return -1;
999                         if (SetModeNumber(Mode, what, num) != 0) return -1;
1000                     }
1001                     break;
1002                 default:
1003                     return -1;
1004                 }
1005             }
1006             break;
1007         case CF_END:
1008             return 0;
1009         default:
1010             return -1;
1011         }
1012     }
1013     return -1;
1014 }
1015 
ReadObject(CurPos & cp,const char * ObjName)1016 static int ReadObject(CurPos &cp, const char *ObjName) {
1017     unsigned char obj;
1018     unsigned short len;
1019 
1020     while ((obj = GetObj(cp, len)) != 0xFF) {
1021         switch (obj) {
1022         case CF_COLOR:
1023             if (ReadColors(cp, ObjName) == -1) return -1;
1024             break;
1025 #ifdef CONFIG_OBJ_MESSAGES
1026         case CF_COMPRX:
1027             {
1028                 long file, line, msg;
1029                 const char *regexp;
1030 
1031                 if (GetObj(cp, len) != CF_INT) return -1;
1032                 if (GetNum(cp, file) == 0) return -1;
1033                 if (GetObj(cp, len) != CF_INT) return -1;
1034                 if (GetNum(cp, line) == 0) return -1;
1035                 if (GetObj(cp, len) != CF_INT) return -1;
1036                 if (GetNum(cp, msg) == 0) return -1;
1037                 if (GetObj(cp, len) != CF_REGEXP) return -1;
1038                 if ((regexp = GetCharStr(cp, len)) == 0) return -1;
1039 
1040                 if (AddCRegexp(file, line, msg, regexp) == 0) return -1;
1041             }
1042             break;
1043 #endif
1044 #ifdef CONFIG_OBJ_CVS
1045         case CF_CVSIGNRX:
1046             {
1047                 const char *regexp;
1048 
1049                 if (GetObj(cp, len) != CF_REGEXP) return -1;
1050                 if ((regexp = GetCharStr(cp, len)) == 0) return -1;
1051 
1052                 if (AddCvsIgnoreRegexp(regexp) == 0) return -1;
1053             }
1054             break;
1055 #endif
1056 
1057 #ifdef CONFIG_OBJ_SVN
1058         case CF_SVNIGNRX:
1059             {
1060                 const char *regexp;
1061 
1062                 if (GetObj(cp, len) != CF_REGEXP) return -1;
1063                 if ((regexp = GetCharStr(cp, len)) == 0) return -1;
1064 
1065                 if (AddSvnIgnoreRegexp(regexp) == 0) return -1;
1066             }
1067             break;
1068 #endif
1069         case CF_SETVAR:
1070             {
1071                 long what;
1072                 if (GetNum(cp, what) == 0) return -1;
1073 
1074                 switch (GetObj(cp, len)) {
1075                 case CF_STRING:
1076                     {
1077                         const char *val = GetCharStr(cp, len);
1078                         if (len == 0) return -1;
1079                         if (SetGlobalString(what, val) != 0) return -1;
1080                     }
1081                     break;
1082                 case CF_INT:
1083                     {
1084                         long num;
1085 
1086                         if (GetNum(cp, num) == 0) return -1;
1087                         if (SetGlobalNumber(what, num) != 0) return -1;
1088                     }
1089                     break;
1090                 default:
1091                     return -1;
1092                 }
1093             }
1094             break;
1095         case CF_END:
1096             return 0;
1097         default:
1098             return -1;
1099         }
1100     }
1101     return -1;
1102 }
1103 
ReadConfigFile(CurPos & cp)1104 static int ReadConfigFile(CurPos &cp) {
1105     unsigned char obj;
1106     unsigned short len;
1107 
1108     {
1109         const char *p;
1110 
1111         obj = GetObj(cp, len);
1112         assert(obj == CF_STRING);
1113         if ((p = GetCharStr(cp, len)) == 0)
1114             return -1;
1115 
1116         if (ConfigSourcePath)
1117             free(ConfigSourcePath);
1118 
1119         ConfigSourcePath = strdup(p);
1120     }
1121 
1122     while ((obj = GetObj(cp, len)) != 0xFF) {
1123         switch (obj) {
1124         case CF_SUB:
1125             {
1126                 const char *CmdName = GetCharStr(cp, len);
1127 
1128                 if (ReadCommands(cp, CmdName) == -1) return -1;
1129             }
1130             break;
1131         case CF_MENU:
1132             {
1133                 const char *MenuName = GetCharStr(cp, len);
1134 
1135                 if (ReadMenu(cp, MenuName) == -1) return -1;
1136             }
1137             break;
1138         case CF_EVENTMAP:
1139             {
1140                 EEventMap *EventMap = 0;
1141                 const char *MapName = GetCharStr(cp, len);
1142                 const char *UpMap = 0;
1143 
1144                 if ((obj = GetObj(cp, len)) != CF_PARENT) return -1;
1145                 if (len > 0)
1146                     if ((UpMap = GetCharStr(cp, len)) == 0) return -1;
1147 
1148                 // add new mode
1149                 if ((EventMap = FindEventMap(MapName)) == 0) {
1150                     EEventMap *OrgMap = 0;
1151 
1152                     if (strcmp(UpMap, "") != 0)
1153                         OrgMap = FindEventMap(UpMap);
1154                     EventMap = new EEventMap(MapName, OrgMap);
1155                 } else {
1156                     if (EventMap->Parent == 0)
1157                         EventMap->Parent = FindEventMap(UpMap);
1158                 }
1159                 if (ReadEventMap(cp, EventMap, MapName) == -1) return -1;
1160             }
1161             break;
1162 #ifdef CONFIG_SYNTAX_HILIT
1163         case CF_COLORIZE:
1164             {
1165                 EColorize *Mode = 0;
1166                 const char *ModeName = GetCharStr(cp, len);
1167                 const char *UpMode = 0;
1168 
1169                 if ((obj = GetObj(cp, len)) != CF_PARENT) return -1;
1170                 if (len > 0)
1171                     if ((UpMode = GetCharStr(cp, len)) == 0) return -1;
1172 
1173                 // add new mode
1174                 if ((Mode = FindColorizer(ModeName)) == 0)
1175                     Mode = new EColorize(ModeName, UpMode);
1176                 else {
1177                     if (Mode->Parent == 0)
1178                         Mode->Parent = FindColorizer(UpMode);
1179                 }
1180                 if (ReadColorize(cp, Mode, ModeName) == -1)
1181                     return -1;
1182             }
1183             break;
1184 #endif
1185         case CF_MODE:
1186             {
1187                 EMode *Mode = 0;
1188                 const char *ModeName = GetCharStr(cp, len);
1189                 const char *UpMode = 0;
1190 
1191                 if ((obj = GetObj(cp, len)) != CF_PARENT) return -1;
1192                 if (len > 0)
1193                     if ((UpMode = GetCharStr(cp, len)) == 0) return -1;
1194 
1195                 // add new mode
1196                 if ((Mode = FindMode(ModeName)) == 0) {
1197                     EMode *OrgMode = 0;
1198                     EEventMap *Map;
1199 
1200                     if (strcmp(UpMode, "") != 0)
1201                         OrgMode = FindMode(UpMode);
1202                     Map = FindEventMap(ModeName);
1203                     if (Map == 0) {
1204                         EEventMap *OrgMap = 0;
1205 
1206                         if (strcmp(UpMode, "") != 0)
1207                             OrgMap = FindEventMap(UpMode);
1208                         Map = new EEventMap(ModeName, OrgMap);
1209                     }
1210                     Mode = new EMode(OrgMode, Map, ModeName);
1211                     Mode->fNext = Modes;
1212                     Modes = Mode;
1213                 } else {
1214                     if (Mode->fParent == 0)
1215                         Mode->fParent = FindMode(UpMode);
1216                 }
1217                 if (ReadMode(cp, Mode, ModeName) == -1)
1218                     return -1;
1219             }
1220             break;
1221         case CF_OBJECT:
1222             {
1223                 const char *ObjName;
1224 
1225                 if ((ObjName = GetCharStr(cp, len)) == 0)
1226                     return -1;
1227                 if (ReadObject(cp, ObjName) == -1)
1228                     return -1;
1229             }
1230             break;
1231         case CF_EOF:
1232             return 0;
1233         default:
1234             return -1;
1235         }
1236     }
1237     return -1;
1238 }
1239 
LoadConfig(int,char **,char * CfgFileName)1240 int LoadConfig(int /*argc*/, char ** /*argv*/, char *CfgFileName) {
1241     STARTFUNC("LoadConfig");
1242     LOG << "Config file: " << CfgFileName << ENDLINE;
1243 
1244     int fd, rc;
1245     char *buffer = 0;
1246     struct stat statbuf;
1247     CurPos cp;
1248 
1249     if ((fd = open(CfgFileName, O_RDONLY | O_BINARY)) == -1)
1250         ENDFUNCRC(-1);
1251     if (fstat(fd, &statbuf) != 0) {
1252         close(fd);
1253         ENDFUNCRC(-1);
1254     }
1255 
1256     // check that we have enough room for signature (CONFIG_ID + VERNUM)
1257     if (statbuf.st_size < (4+4)) {
1258         close(fd);
1259         DieError(0, "Bad .CNF signature");
1260         ENDFUNCRC(-1);
1261     }
1262 
1263     buffer = (char *) malloc((size_t)statbuf.st_size);
1264     if (buffer == 0) {
1265         close(fd);
1266         ENDFUNCRC(-1);
1267     }
1268     if (read(fd, buffer, (size_t)statbuf.st_size) != statbuf.st_size) {
1269         close(fd);
1270         free(buffer);
1271         ENDFUNCRC(-1);
1272     }
1273     close(fd);
1274 
1275     unsigned char l[4];
1276     unsigned long ln;
1277 
1278     memcpy(l, buffer, 4);
1279     ln = (l[3] << 24) + (l[2] << 16) + (l[1] << 8) + l[0];
1280 
1281     if (ln != CONFIG_ID) {
1282         free(buffer);
1283         DieError(0, "Bad .CNF signature");
1284         ENDFUNCRC(-1);
1285     }
1286 
1287     memcpy(l, buffer + 4, 4);
1288     ln = (l[3] << 24) + (l[2] << 16) + (l[1] << 8) + l[0];
1289 
1290     if (ln != VERNUM) {
1291         LOG << std::hex << ln << " != " << VERNUM << ENDLINE;
1292         free(buffer);
1293         DieError(0, "Bad .CNF version.");
1294         ENDFUNCRC(-1);
1295     }
1296 
1297     cp.name = CfgFileName;
1298     cp.sz = statbuf.st_size;
1299     cp.a = buffer;
1300     cp.c = cp.a + 2 * 4;
1301     cp.z = cp.a + cp.sz;
1302     cp.line = 1;
1303 
1304     rc = ReadConfigFile(cp);
1305 
1306     free(buffer);
1307 
1308     if (rc == -1) {
1309         DieError(1, "Error %s offset %d\n", CfgFileName, cp.c - cp.a);
1310     }
1311     ENDFUNCRC(rc);
1312 }
1313 
1314 #include "defcfg.h"
1315 
UseDefaultConfig()1316 int UseDefaultConfig() {
1317     CurPos cp;
1318     int rc;
1319 
1320     cp.name = "Internal Configuration";
1321     cp.sz = sizeof(DefaultConfig);
1322     cp.a = (char *)DefaultConfig;
1323     cp.c = (char *)DefaultConfig + 2 * 4;
1324     cp.z = cp.a + cp.sz;
1325     cp.line = 1;
1326 
1327     rc = ReadConfigFile(cp);
1328 
1329     if (rc == -1)
1330         DieError(1, "Error %s offset %d\n", cp.name, cp.c - cp.a);
1331     return rc;
1332 }
1333