/* c_bind.cpp * * Copyright (c) 1994-1996, Marko Macek * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. * */ #include "fte.h" ////////////////////////////////////////////////////////////////////////////// EMode *Modes = 0; EEventMap *EventMaps = 0; int CMacros = 0; ExMacro *Macros = 0; ////////////////////////////////////////////////////////////////////////////// #include "c_cmdtab.h" ////////////////////////////////////////////////////////////////////////////// const char *GetCommandName(int Command) { if (Command & CMD_EXT) { Command &= ~CMD_EXT; if ((Command < 0) || (Command >= CMacros)) return "?INVALID?"; if (Macros[Command].Name) return Macros[Command].Name; else return "?NONE?"; } for (int i = 0; i < int(sizeof(Command_Table) / sizeof(Command_Table[0])); i++) if (Command_Table[i].CmdId == Command) return Command_Table[i].Name; return "?invalid?"; } int CmdNum(char *Cmd) { int i; for (i = 0; i < int(sizeof(Command_Table) / sizeof(Command_Table[0])); i++) if (strcmp(Cmd, Command_Table[i].Name) == 0) return Command_Table[i].CmdId; for (i = 0; i < CMacros; i++) if (Macros[i].Name && (strcmp(Cmd, Macros[i].Name)) == 0) return i | CMD_EXT; return 0; // Nop } EMode *FindMode(const char *Name) { EMode *m = Modes; //fprintf(stderr, "Searching mode %s\n", Name); while (m) { if (strcmp(Name, m->fName) == 0) return m; m = m->fNext; } return 0; } EEventMap *FindEventMap(const char *Name) { EEventMap *m = EventMaps; //fprintf(stderr, "Searching map %s\n", Name); while (m) { if (strcmp(Name, m->Name) == 0) return m; m = m->Next; } return 0; } EEventMap *FindActiveMap(EMode *Mode) { while (Mode) { if (Mode->fEventMap) return Mode->fEventMap; Mode = Mode->fParent; } return 0; } EKey *SetKey(EEventMap *aMap, const char *aKey) { EKeyMap **map = &aMap->KeyMap, *pm, *parent = 0; EKey *k; char Key[256]; char *p, *d; EEventMap *xm = aMap; // printf("Setting key %s\n", Key); strcpy(Key, aKey); // if mode has parent, get parent keymap while (xm && xm->Parent && (parent == 0)) { parent = xm->Parent->KeyMap; // printf("%s : %s : %d\n", xm->fName, xm->fParent->fName, parent); xm = xm->Parent; } d = p = Key; while (d) { // parse key combination p = d; d = strchr(p, '_'); if (d) { if (d[1] == 0 || d[1] == '_') d++; if (*d == 0) d = 0; else { *d = 0; d++; } } // if lastkey if (d == 0) { k = new EKey(p); if (*map) { (*map)->AddKey(k); } else { *map = new EKeyMap(); (*map)->fParent = parent; (*map)->AddKey(k); } return k; } else { // if introductory key if (*map == 0) { // first key in mode, create map // printf("new map key = %s, parent %d\n", p, parent); k = new EKey(p, 0); *map = new EKeyMap(); (*map)->fParent = parent; (*map)->AddKey(k); } else { KeySel ks; ParseKey(p, ks); if ((k = (*map)->FindKey(ks.Key)) == 0) { // check if key exists // add it if not k = new EKey(p, 0); (*map)->AddKey(k); } } map = &k->fKeyMap; // set current map to key's map // get parent keymap pm = parent; parent = 0; // printf("Searching %s\n", p); while (pm) { // while exists KeySel ks; EKey *pk; ParseKey(p, ks); if ((pk = pm->FindKey(ks.Key)) != 0) { // if key exists, find parent of it parent = pk->fKeyMap; // printf("Key found %d\n", parent); break; } pm = pm->fParent; // otherwise find parent of current keymap } } } return 0; } void InitWordChars() { static int init = 0; if (init == 0) { for (int i = 0; i < 256; i++) // isalnum??? if (isdigit(i) || (i >= 'A' && i <= 'Z') || (i >= 'a' && i <= 'z') || (i == '_')) { WSETBIT(DefaultBufferFlags.WordChars, i, 1); if ((i >= 'A' && i <= 'Z')) WSETBIT(DefaultBufferFlags.CapitalChars, i, 1); } init = 1; } } void SetWordChars(char *w, const char *s) { const char *p; memset((void *)w, 0, 32); p = s; while (p && *p) { if (*p == '\\') { p++; if (*p == 0) return; } else if (p[1] == '-') { if (p[2] == 0) return ; for (int i = p[0]; i < p[2]; i++) WSETBIT(w, i, 1); p += 2; } WSETBIT(w, *p, 1); p++; } } EMode::EMode(EMode *aMode, EEventMap *Map, const char *aName) { fNext = 0; fName = strdup(aName); fEventMap = Map; fParent = aMode; InitWordChars(); if (aMode) { #ifdef CONFIG_SYNTAX_HILIT fColorize = aMode->fColorize; #endif Flags = aMode->Flags; // duplicate strings in flags to allow them be freed for (int i=0; iFlags.str[i] != 0) Flags.str[i] = strdup(aMode->Flags.str[i]); } MatchName = 0; MatchLine = 0; MatchNameRx = 0; MatchLineRx = 0; if (aMode->MatchName) { MatchName = strdup(aMode->MatchName); MatchNameRx = RxCompile(MatchName); } if (aMode->MatchLine) { MatchLine = strdup(aMode->MatchLine); MatchLineRx = RxCompile(MatchLine); } } else { MatchName = 0; MatchLine = 0; MatchNameRx = 0; MatchLineRx = 0; #ifdef CONFIG_SYNTAX_HILIT fColorize = 0; #endif Flags = DefaultBufferFlags; // there is no strings in default settings... } } EMode::~EMode() { // fEventMap is just pointer to EventMaps list, so do not destroy it // fColorize is also just a pointer free(fName); free(MatchName); RxFree(MatchNameRx); free(MatchLine); RxFree(MatchLineRx); // free strings from flags for (int i=0; ifNext; delete e; } } } void EKeyMap::AddKey(EKey *aKey) { aKey->fNext = fKeys; fKeys = aKey; } int MatchKey(TKeyCode aKey, KeySel aSel) { long flags = aKey & ~ 0xFFFF; long key = aKey & 0xFFFF; flags &= ~kfAltXXX; if (flags & kfShift) { if (key < 256) if (flags == kfShift) flags &= ~kfShift; else if (isascii(key)) key = toupper(key); } if ((flags & kfCtrl) && !(flags & kfSpecial)) if (key < 32) key += 64; flags &= ~aSel.Mask; if (aSel.Mask & kfShift) { if (key < 256) if (isascii(key)) key = toupper(key); } aKey = key | flags; if (aKey == aSel.Key) return 1; return 0; } EKey *EKeyMap::FindKey(TKeyCode aKey) { EKey *p = fKeys; while (p) { if (MatchKey(aKey, p->fKey)) return p; p = p->fNext; } return 0; } EEventMap::EEventMap(const char *AName, EEventMap *AParent) { Name = strdup(AName); Parent = AParent; KeyMap = 0; Next = EventMaps; EventMaps = this; memset(Menu, 0, sizeof(Menu)); memset(abbrev, 0, sizeof(abbrev)); } EEventMap::~EEventMap() { free(Name); // free menu[] { for (int i = 0; i < EM_MENUS; i++) { free(Menu[i]); } } // free Abbrev's { EAbbrev *ab; for (int i = 0; i < ABBREV_HASH; i++) { while((ab = abbrev[i]) != NULL) { abbrev[i] = abbrev[i]->next; delete ab; } } } // free keymap's { delete KeyMap; } } void EEventMap::SetMenu(int which, const char *What) { if (which < 0 || which >= EM_MENUS) return; if (Menu[which] != 0) free(Menu[which]); Menu[which] = strdup(What); } char *EEventMap::GetMenu(int which) { if (which < 0 || which >= EM_MENUS) return 0; if (Menu[which] || Parent == 0) return Menu[which]; else return Parent->GetMenu(which); } #ifdef CONFIG_ABBREV int EEventMap::AddAbbrev(EAbbrev *ab) { int i = HashStr(ab->Match, ABBREV_HASH); ab->next = abbrev[i]; abbrev[i] = ab; return 1; } EAbbrev *EMode::FindAbbrev(const char *string) { EEventMap *Map = fEventMap; EAbbrev *ab; int i; if (string == 0) return 0; i = HashStr(string, ABBREV_HASH); while (Map) { ab = Map->abbrev[i]; while (ab != 0) { if (ab->Match && (strcmp(string, ab->Match) == 0)) return ab; ab = ab->next; } Map = Map->Parent; } return 0; } #endif static const struct { const char *Name; TKeyCode Key; } KeyList[] = { { "Esc", kbEsc }, { "Tab", kbTab }, { "Space", kbSpace }, { "Enter", kbEnter }, { "BackSp", kbBackSp }, { "F1", kbF1 }, { "F2", kbF2 }, { "F3", kbF3 }, { "F4", kbF4 }, { "F5", kbF5 }, { "F6", kbF6 }, { "F7", kbF7 }, { "F8", kbF8 }, { "F9", kbF9 }, { "F10", kbF10 }, { "F11", kbF11 }, { "F12", kbF12 }, { "Left", kbLeft }, { "Right", kbRight }, { "Up", kbUp }, { "Down", kbDown }, { "Home", kbHome }, { "End", kbEnd }, { "PgUp", kbPgUp }, { "PgDn", kbPgDn }, { "Ins", kbIns }, { "Del", kbDel }, { "Center", kbCenter }, { "Break", kbBreak }, { "Pause", kbPause }, { "PrtScr", kbPrtScr }, { "SysReq", kbSysReq }, }; int ParseKey(const char *Key, KeySel &ks) { unsigned char *p = (unsigned char *)Key; TKeyCode KeyFlags = 0; int i; ks.Mask = 0; ks.Key = 0; while ((*p) && ((p[1] == '+') || (p[1] == '-'))) { if (p[1] == '-') { switch (p[0]) { case 'A': ks.Mask |= kfAlt; break; case 'C': ks.Mask |= kfCtrl; break; case 'S': ks.Mask |= kfShift; break; case 'G': ks.Mask |= kfGray; break; case 'X': ks.Mask |= kfSpecial; break; } } else if (p[1] == '+') { switch (p[0]) { case 'A': KeyFlags |= kfAlt; break; case 'C': KeyFlags |= kfCtrl; break; case 'S': KeyFlags |= kfShift; break; case 'G': KeyFlags |= kfGray; break; case 'X': KeyFlags |= kfSpecial; break; } } p += 2; } for (i = 0; i < int(sizeof(KeyList)/sizeof(KeyList[0])); i++) if (strcmp((char *)p, KeyList[i].Name) == 0) { ks.Key = KeyList[i].Key; break; } if (ks.Key == 0) ks.Key = *p; if ((KeyFlags & kfCtrl) && !(KeyFlags & kfSpecial)) { if (ks.Key < 256) { if (ks.Key < 32) ks.Key += 64; else ks.Key = toupper(ks.Key); } } ks.Key |= KeyFlags; return 0; } int GetKeyName(char *Key, KeySel &ks) { *Key = 0; if (ks.Key & kfAlt) strcat(Key, "A+"); if (ks.Mask & kfAlt) strcat(Key, "A-"); if (ks.Key & kfCtrl) strcat(Key, "C+"); if (ks.Mask & kfCtrl) strcat(Key, "C-"); if (ks.Key & kfGray) strcat(Key, "G+"); if (ks.Mask & kfGray) strcat(Key, "G-"); if (ks.Key & kfShift) strcat(Key, "S+"); if (ks.Mask & kfShift) strcat(Key, "S-"); if (keyCode(ks.Key) < 256) { char c[2]; c[0] = (char)(ks.Key & 0xFF); c[1] = 0; //if (ks.Key & kfCtrl) // if (c[0] < ' ') // c[0] += '@'; if (c[0] == 32) strcat(Key, "Space"); else strcat(Key, c); } else { for (int i = 0; i < int(sizeof(KeyList)/sizeof(KeyList[0])); i++) if (KeyList[i].Key == keyCode(ks.Key)) { strcat(Key, KeyList[i].Name); break; } } return 0; } EKey::EKey(char *aKey) { fNext = 0; ParseKey(aKey, fKey); fKeyMap = 0; Cmd = -1; } EKey::EKey(char *aKey, EKeyMap *aKeyMap) { fNext = 0; Cmd = -1; ParseKey(aKey, fKey); fKeyMap = aKeyMap; } EKey::~EKey() { // if there is child keymaps delete them delete fKeyMap; } #ifdef CONFIG_ABBREV EAbbrev::EAbbrev(const char *aMatch, const char *aReplace) { next = 0; Match = strdup(aMatch); Replace = strdup(aReplace); Cmd = -1; } EAbbrev::EAbbrev(const char *aMatch, int aCmd) { next = 0; Replace = 0; Match = strdup(aMatch); Cmd = aCmd; } EAbbrev::~EAbbrev() { if (Match) free(Match); if (Replace) free(Replace); } #endif int AddCommand(int no, int Command, int count, int ign) { if (count == 0) return 0; if (Command == 0) return 0; Macros[no].cmds = (CommandType *)realloc(Macros[no].cmds, sizeof(CommandType) * (Macros[no].Count + 1)); Macros[no].cmds[Macros[no].Count].type = CT_COMMAND; Macros[no].cmds[Macros[no].Count].u.num = Command; Macros[no].cmds[Macros[no].Count].repeat = short(count); Macros[no].cmds[Macros[no].Count].ign = short(ign); Macros[no].Count++; return 1; } int AddString(int no, const char *String) { Macros[no].cmds = (CommandType *)realloc(Macros[no].cmds, sizeof(CommandType) * (Macros[no].Count + 1)); Macros[no].cmds[Macros[no].Count].type = CT_STRING; Macros[no].cmds[Macros[no].Count].u.string = strdup(String); Macros[no].cmds[Macros[no].Count].repeat = 0; Macros[no].cmds[Macros[no].Count].ign = 0; Macros[no].Count++; return 1; } int AddNumber(int no, long number) { Macros[no].cmds = (CommandType *)realloc(Macros[no].cmds, sizeof(CommandType) * (Macros[no].Count + 1)); Macros[no].cmds[Macros[no].Count].type = CT_NUMBER; Macros[no].cmds[Macros[no].Count].u.num = number; Macros[no].cmds[Macros[no].Count].repeat = 0; Macros[no].cmds[Macros[no].Count].ign = 0; Macros[no].Count++; return 1; } int AddConcat(int no) { Macros[no].cmds = (CommandType *)realloc(Macros[no].cmds, sizeof(CommandType) * (Macros[no].Count + 1)); Macros[no].cmds[Macros[no].Count].type = CT_CONCAT; Macros[no].cmds[Macros[no].Count].u.num = 0; Macros[no].cmds[Macros[no].Count].repeat = 0; Macros[no].cmds[Macros[no].Count].ign = 0; Macros[no].Count++; return 1; } int AddVariable(int no, int number) { Macros[no].cmds = (CommandType *)realloc(Macros[no].cmds, sizeof(CommandType) * (Macros[no].Count + 1)); Macros[no].cmds[Macros[no].Count].type = CT_VARIABLE; Macros[no].cmds[Macros[no].Count].u.num = number; Macros[no].cmds[Macros[no].Count].repeat = 0; Macros[no].cmds[Macros[no].Count].ign = 0; Macros[no].Count++; return 1; } int NewCommand(const char *Name) { Macros = (ExMacro *) realloc(Macros, sizeof(ExMacro) * (1 + CMacros)); Macros[CMacros].Count = 0; Macros[CMacros].cmds = 0; Macros[CMacros].Name = (Name != NULL) ? strdup(Name) : 0; CMacros++; return CMacros - 1; } int ExState::GetStrParam(EView *view, char *str, int maxlen) { assert(maxlen >= 0); if (Macro == -1 || Pos == -1 || Pos >= Macros[Macro].Count) return 0; if (Macros[Macro].cmds[Pos].type == CT_STRING) { if (maxlen > 0) { strncpy(str, Macros[Macro].cmds[Pos].u.string, maxlen); str[maxlen - 1] = 0; } Pos++; } else if (view && Macros[Macro].cmds[Pos].type == CT_VARIABLE) { //puts("variable\x7"); if (view->GetStrVar(Macros[Macro].cmds[Pos].u.num, str, maxlen) == 0) return 0; Pos++; } else return 0; if (Pos < Macros[Macro].Count) { if (Macros[Macro].cmds[Pos].type == CT_CONCAT) { Pos++; int len = strlen(str); int left = maxlen - len; assert(left >= 0); //puts("concat\x7"); if (GetStrParam(view, str + len, left) == 0) return 0; } } return 1; } int ExState::GetIntParam(EView *view, int *value) { if (Macro == -1 || Pos == -1 || Pos >= Macros[Macro].Count) return 0; if (Macros[Macro].cmds[Pos].type == CT_NUMBER) { *value = Macros[Macro].cmds[Pos].u.num; Pos++; } else if (view && Macros[Macro].cmds[Pos].type == CT_VARIABLE) { if (view->GetIntVar(Macros[Macro].cmds[Pos].u.num, value) == 0) return 0; Pos++; } else return 0; return 1; } int HashStr(const char *p, int maxim) { unsigned int i = 1; while (p && *p) { i += i ^ (i << 3) ^ (unsigned int)(*p) ^ (i >> 3); p++; } return i % maxim; }