1: /*************************************************************************** 2: * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * 3: * is provided to you without charge, and with no warranty. You may give * 4: * away copies of JOVE, including sources, provided that this notice is * 5: * included in all the files. * 6: ***************************************************************************/ 7: 8: #include "jove.h" 9: 10: #ifdef ABBREV 11: 12: #include "io.h" 13: #include "ctype.h" 14: 15: #ifdef MSDOS 16: #include <io.h> 17: #endif 18: #define HASHSIZE 20 19: 20: struct abbrev { 21: unsigned int a_hash; 22: char *a_abbrev, 23: *a_phrase; 24: struct abbrev *a_next; 25: data_obj *a_cmdhook; 26: }; 27: 28: #ifdef MAC 29: # undef private 30: # define private 31: #endif 32: 33: #ifdef LINT_ARGS 34: private void 35: define(struct abbrev **, char *, char *), 36: def_abbrev(struct abbrev **), 37: rest_abbrevs(char *), 38: save_abbrevs(char *); 39: 40: private unsigned int hash(char *); 41: private struct abbrev * lookup(struct abbrev **, char *); 42: #else 43: private void 44: define(), 45: def_abbrev(), 46: rest_abbrevs(), 47: save_abbrevs(); 48: 49: private unsigned int hash(); 50: private struct abbrev * lookup(); 51: #endif /* LINT_ARGS */ 52: 53: #ifdef MAC 54: # undef private 55: # define private static 56: #endif 57: 58: #define GLOBAL NMAJORS 59: private struct abbrev *A_tables[NMAJORS + 1][HASHSIZE] = {0}; 60: 61: int AutoCaseAbbrev = 1; 62: 63: private unsigned int 64: hash(a) 65: register char *a; 66: { 67: register unsigned int hashval = 0; 68: register int c; 69: 70: while (c = *a++) 71: hashval = (hashval << 2) + c; 72: 73: return hashval; 74: } 75: 76: private void 77: def_abbrev(table) 78: struct abbrev *table[HASHSIZE]; 79: { 80: char abbrev[100], 81: phrase[100]; 82: 83: strcpy(abbrev, ask((char *) 0, "abbrev: ")); 84: strcpy(phrase, ask((char *) 0, "abbrev: %s phrase: ", abbrev)); 85: define(table, abbrev, phrase); 86: } 87: 88: private struct abbrev * 89: lookup(table, abbrev) 90: register struct abbrev *table[HASHSIZE]; 91: register char *abbrev; 92: { 93: register struct abbrev *ap; 94: unsigned int h; 95: 96: h = hash(abbrev); 97: for (ap = table[h % HASHSIZE]; ap; ap = ap->a_next) 98: if (ap->a_hash == h && strcmp(ap->a_abbrev, abbrev) == 0) 99: break; 100: return ap; 101: } 102: 103: private void 104: define(table, abbrev, phrase) 105: register struct abbrev *table[HASHSIZE]; 106: char *abbrev, 107: *phrase; 108: { 109: register struct abbrev *ap; 110: 111: ap = lookup(table, abbrev); 112: if (ap == 0) { 113: register unsigned int h = hash(abbrev); 114: 115: ap = (struct abbrev *) emalloc(sizeof *ap); 116: ap->a_hash = h; 117: ap->a_abbrev = copystr(abbrev); 118: h %= HASHSIZE; 119: ap->a_next = table[h]; 120: ap->a_cmdhook = 0; 121: table[h] = ap; 122: } else 123: free(ap->a_phrase); 124: ap->a_phrase = copystr(phrase); 125: } 126: 127: void 128: AbbrevExpand() 129: { 130: Bufpos point; 131: char wordbuf[100]; 132: register char *wp = wordbuf, 133: *cp; 134: #if !(defined(IBMPC) || defined(MAC)) 135: register int c; 136: #else 137: int c; 138: #endif 139: int UC_count = 0; 140: struct abbrev *ap; 141: 142: DOTsave(&point); 143: WITH_TABLE(curbuf->b_major) 144: b_word(1); 145: while (curchar < point.p_char && ismword(c = linebuf[curchar])) { 146: if (AutoCaseAbbrev) { 147: if (isupper(c)) { 148: UC_count += 1; 149: #if (defined(IBMPC) || defined(MAC)) 150: lower(&c); 151: #else 152: c = tolower(c); 153: #endif 154: } 155: } 156: *wp++ = c; 157: curchar += 1; 158: } 159: *wp = '\0'; 160: END_TABLE(); 161: 162: if ((ap = lookup(A_tables[curbuf->b_major], wordbuf)) == 0 && 163: (ap = lookup(A_tables[GLOBAL], wordbuf)) == 0) { 164: SetDot(&point); 165: return; 166: } 167: del_char(BACKWARD, (wp - wordbuf)); 168: 169: for (cp = ap->a_phrase; c = *cp; ) { 170: if (AutoCaseAbbrev) { 171: insert_c(islower(c) && UC_count && 172: (cp == ap->a_phrase || (UC_count > 1 && (cp[-1] == ' '))) ? 173: toupper(c) : c, 1); 174: } else 175: insert_c(c, 1); 176: cp += 1; 177: } 178: if (ap->a_cmdhook != 0) 179: ExecCmd(ap->a_cmdhook); 180: } 181: 182: private char *mode_names[NMAJORS + 1] = { 183: "Fundamental Mode", 184: "Text Mode", 185: "C Mode", 186: #ifdef LISP 187: "Lisp Mode", 188: #endif 189: "Global" 190: }; 191: 192: private void 193: save_abbrevs(file) 194: char *file; 195: { 196: File *fp; 197: struct abbrev *ap, 198: **tp; 199: char buf[LBSIZE]; 200: int i, 201: count = 0; 202: 203: fp = open_file(file, buf, F_WRITE, COMPLAIN, QUIET); 204: for (i = 0; i <= GLOBAL; i++) { 205: fprintf(fp, "------%s abbrevs------\n", mode_names[i]); 206: for (tp = A_tables[i]; tp < &A_tables[i][HASHSIZE]; tp++) 207: for (ap = *tp; ap; ap = ap->a_next) { 208: fprintf(fp, "%s:%s\n", 209: ap->a_abbrev, 210: ap->a_phrase); 211: count += 1; 212: } 213: } 214: f_close(fp); 215: add_mess(" %d written.", count); 216: } 217: 218: private void 219: rest_abbrevs(file) 220: char *file; 221: { 222: int eof = 0, 223: mode = -1, /* Will be ++'d immediately */ 224: lnum = 0; 225: char *phrase_p; 226: File *fp; 227: char buf[LBSIZE]; 228: 229: fp = open_file(file, buf, F_READ, COMPLAIN, QUIET); 230: while (mode <= GLOBAL) { 231: eof = f_gets(fp, genbuf, LBSIZE); 232: if (eof || genbuf[0] == '\0') 233: break; 234: lnum += 1; 235: if (strncmp(genbuf, "------", 6) == 0) { 236: mode += 1; 237: continue; 238: } 239: if (mode == -1) 240: fmterr: complain("Abbrev. format error, line %d.", file, lnum); 241: phrase_p = index(genbuf, ':'); 242: if (phrase_p == 0) 243: goto fmterr; 244: *phrase_p++ = '\0'; /* Null terminate the abbrev. */ 245: define(A_tables[mode], genbuf, phrase_p); 246: } 247: f_close(fp); 248: message(NullStr); 249: } 250: 251: void 252: DefGAbbrev() 253: { 254: def_abbrev(A_tables[GLOBAL]); 255: } 256: 257: void 258: DefMAbbrev() 259: { 260: def_abbrev(A_tables[curbuf->b_major]); 261: } 262: 263: void 264: SaveAbbrevs() 265: { 266: char filebuf[FILESIZE]; 267: 268: save_abbrevs(ask_file((char *) 0, (char *) 0, filebuf)); 269: } 270: 271: void 272: RestAbbrevs() 273: { 274: char filebuf[FILESIZE]; 275: 276: rest_abbrevs(ask_file((char *) 0, (char *) 0, filebuf)); 277: } 278: 279: void 280: EditAbbrevs() 281: { 282: char *tname = "jove_wam.$$$", 283: *EditName = "Abbreviation Edit"; 284: Buffer *obuf = curbuf, 285: *ebuf; 286: 287: if (ebuf = buf_exists(EditName)) { 288: if (ebuf->b_type != B_SCRATCH) 289: confirm("Over-write buffer %b?", ebuf); 290: } 291: SetBuf(ebuf = do_select(curwind, EditName)); 292: ebuf->b_type = B_SCRATCH; 293: initlist(ebuf); 294: /* Empty buffer. Save the definitions to a tmp file 295: and read them into this buffer so we can edit them. */ 296: save_abbrevs(tname); 297: read_file(tname, NO); 298: message("[Edit definitions and then type C-X C-C]"); 299: Recur(); /* We edit them ... now */ 300: /* RESetBuf in case we deleted the buffer while we were editing. */ 301: SetBuf(ebuf = do_select(curwind, EditName)); 302: if (IsModified(ebuf)) { 303: SetBuf(ebuf); 304: file_write(tname, 0); 305: rest_abbrevs(tname); 306: unmodify(); 307: } 308: (void) unlink(tname); 309: SetBuf(do_select(curwind, obuf->b_name)); 310: } 311: 312: void 313: BindMtoW() 314: { 315: struct abbrev *ap; 316: char *word; 317: data_obj *hook; 318: 319: word = ask((char *) 0, "Word: "); 320: 321: if ((ap = lookup(A_tables[curbuf->b_major], word)) == 0 && 322: (ap = lookup(A_tables[GLOBAL], word)) == 0) 323: complain("%s: unknown abbrev.", word); 324: 325: hook = findmac("Macro: "); 326: if (hook == 0) 327: complain("[Undefined macro]"); 328: ap->a_cmdhook = hook; 329: } 330: 331: #endif /* ABBREV */