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