1: #include <X/mit-copyright.h> 2: 3: /* Copyright Massachusetts Institute of Technology 1984, 1985 */ 4: 5: #include "gedit.h" 6: 7: #ifndef lint 8: static char *rcsid_gedit_c = "$Header: gedit.c,v 10.6 86/02/01 16:18:53 tony Rel $"; 9: #endif lint 10: 11: char *malloc(), *gentry(), *strcpy(), *strcat(); 12: 13: struct state cur_state = { /* everything about what we are doing */ 14: NULL, 1, 4, 0, 0, 0, 0, 0, 0, 16, 0, NULL, 0, 0, 0 15: }; 16: 17: /*extern char Aborted;*/ 18: 19: struct prototype *directory; 20: 21: short incol; /* current text prompt column */ 22: char *prompt; /* what the current user prompt is */ 23: char typein[100]; /* user input buffer */ 24: 25: char ocomp[8][8] = /* orientation composition matrix */ 26: { NORTH, EAST, SOUTH, WEST, RNORTH, REAST, RSOUTH, RWEST, 27: EAST, SOUTH, WEST, NORTH, RWEST, RNORTH, REAST, RSOUTH, 28: SOUTH, WEST, NORTH, EAST, RSOUTH, RWEST, RNORTH, REAST, 29: WEST, NORTH, EAST, SOUTH, REAST, RSOUTH, RWEST, RNORTH, 30: RNORTH, REAST, RSOUTH, RWEST, NORTH, EAST, SOUTH, WEST, 31: REAST, RSOUTH, RWEST, RNORTH, WEST, NORTH, EAST, SOUTH, 32: RSOUTH, RWEST, RNORTH, REAST, SOUTH, WEST, NORTH, EAST, 33: RWEST, RNORTH, REAST, RSOUTH, EAST, SOUTH, WEST, NORTH 34: }; 35: 36: char lcomp[8][9] = /* orient & label composition matrix */ 37: { CC, TC, BC, CL, TL, BL, CR, TR, BR, /* north */ 38: CC, CR, CL, TC, TR, TL, BC, BR, BL, /* east */ 39: CC, BC, TC, CR, BR, TR, CL, BL, TL, /* south */ 40: CC, CL, CR, BC, BL, BR, TC, TL, TR, /* west */ 41: CC, TC, BC, CR, TR, BR, CL, TL, BL, /* rnorth */ 42: CC, CL, CR, TC, TL, TR, BC, BL, BR, /* reast */ 43: CC, BC, TC, CL, BL, TL, CR, BR, TR, /* rsouth */ 44: CC, CR, CL, BC, BR, BL, TC, TR, TL /* rwest */ 45: }; 46: 47: char *lorient[] = { "cc", "tc", "bc", "cl", "tl", "bl", "cr", "tr", "br" }; 48: char *oorient[] = { "n", "e", "s", "w", "rn", "re", "rs", "rw" }; 49: 50: /* read a coordinate from the input file */ 51: short read_coord(f) 52: FILE *f; 53: { register int ch; 54: register short coord = 0; 55: char sign = 0; 56: 57: /* skip over leading blanks */ 58: while ((ch = getc(f))<=' ' && ch!=EOF); 59: 60: /* look for negative coord */ 61: if (ch == '~') { sign = 1; ch = getc(f); } 62: 63: /* read in the number itself */ 64: while (ch>='0' && ch<='9') { 65: coord *= 10; 66: coord += ch - '0'; 67: ch = getc(f); 68: } 69: 70: return(sign ? -coord : coord); 71: } 72: 73: /* read a token from the input file */ 74: read_token(f,t) 75: FILE *f; 76: register char *t; 77: { register int ch; 78: 79: /* skip over leading blanks */ 80: while ((ch = getc(f))<=' ' && ch!=EOF); 81: 82: /* read in the number itself */ 83: while (ch > ' ' && ch!=EOF) { 84: if (ch == '~') *t++ = ' '; /* embedded blank */ 85: else *t++ = ch; 86: ch = getc(f); 87: } 88: *t = 0; 89: } 90: 91: /* read a .def file and return pointer to linked list of objects. For now, 92: * not much error checking is done... 93: */ 94: struct prototype *read_def(name) 95: char *name; 96: { register int ch; 97: register gptr p; 98: struct prototype *d; 99: FILE *in; 100: char token[200],iname[100],buf[100]; 101: short x1,y1,x2,y2; 102: 103: /* see if we've already got a copy in core */ 104: for (d = directory; d != NULL; d = d->next) 105: if (strcmp(name,d->name) == 0) return(d); 106: 107: /* new widget, set up directory entry */ 108: d = (struct prototype *)malloc(sizeof(struct prototype)); 109: 110: d->recent = cur_state; /* Copy current parameters. */ 111: d->recent.curobj = d; 112: d->recent.editee = NULL; 113: d->recent.curx = d->recent.cury = 0; 114: d->recent.oldx = d->recent.oldy = 0; 115: d->recent.lxoff = d->recent.lyoff = 0; 116: new_window(&d->recent,0,0); 117: 118: d->next = directory; 119: directory = d; 120: d->name = malloc((unsigned) (strlen(name) + 1)); 121: strcpy(d->name,name); 122: d->body = NULL; 123: d->modified = 0; 124: 125: strcpy(iname,name); 126: strcat(iname,".def"); 127: if ((in = fopen(iname,"r")) == NULL) return(d); 128: sprintf(buf,"reading in %s",iname); 129: msg(buf); 130: 131: /* read through file processing commands */ 132: while ((ch = getc(in)) != EOF) switch (ch) { 133: case ' ': 134: case '\n': 135: case '\r': 136: case '\t': continue; 137: 138: case '|': while ((ch = getc(in))!='\n' && ch!=EOF); 139: continue; 140: 141: case 'd': read_token(in,token); 142: continue; 143: 144: case 'e': goto done; 145: 146: case 'm': x1 = read_coord(in); 147: y1 = read_coord(in); 148: continue; 149: 150: case 'A': 151: case 'l': x2 = read_coord(in); 152: y2 = read_coord(in); 153: if (ch == 'A') read_token(in,token); /* angle */ 154: if ((p = (gptr)malloc(sizeof(struct segment))) == NULL) { 155: msg("out of room!"); 156: continue; 157: } 158: p->s.type = SEGMENT; 159: p->s.selink = NULL; 160: p->s.next = d->body; 161: d->body = p; 162: p->s.parent = d; 163: p->s.x1 = x1; 164: p->s.y1 = y1; 165: p->s.x2 = x2; 166: p->s.y2 = y2; 167: if (ch == 'A') p->s.angle = atoi(token); 168: else p->s.angle = 0; 169: p->s.cache = NULL; 170: newalist(&p->s,p->s.x1,p->s.y1,p->s.x2,p->s.y2); 171: x1 = x2; 172: y1 = y2; 173: continue; 174: 175: case 'c': read_token(in,token); /* label orientation */ 176: x2 = token[0]; 177: y2 = token[1]; 178: read_token(in,token); /* the label itself */ 179: if ((p = (gptr)malloc(sizeof(struct label))) == NULL) { 180: msg("out of room!"); 181: continue; 182: } 183: p->l.type = LABEL; 184: p->l.selink = NULL; 185: p->l.next = d->body; 186: d->body = p; 187: p->l.parent = d; 188: p->l.x = x1; 189: p->l.y = y1; 190: switch (x2) { 191: default: 192: case 'c': x2 = CC; break; 193: case 't': x2 = TC; break; 194: case 'b': x2 = BC; break; 195: } 196: switch (y2) { 197: default: 198: case 'c': p->l.orient = CC + x2; break; 199: case 'l': p->l.orient = CL + x2; break; 200: case 'r': p->l.orient = CR + x2; break; 201: } 202: if ((p->l.string = malloc((unsigned) (strlen(token)+1))) == NULL) { 203: msg("out of room!"); 204: continue; 205: } 206: strcpy(p->l.string,token); 207: continue; 208: 209: case 'i': read_token(in,iname); /* name of file */ 210: 211: /* next is "___" or scale factor */ 212: read_token(in,token); 213: if (token[0]>='0' && token[0]<='9') 214: sscanf(token,"%hd:%hd",&x2,&y2); 215: else x2 = y2 = 1; 216: 217: read_token(in,token); /* orientation */ 218: if ((p = (gptr)malloc(sizeof(struct object))) == NULL) { 219: msg("out of room!"); 220: continue; 221: } 222: p->o.type = OBJECT; 223: p->o.selink = NULL; 224: p->o.next = d->body; 225: d->body = p; 226: p->o.parent = d; 227: p->o.x = x1; 228: p->o.y = y1; 229: if (token[0] == 'r') { 230: p->o.orient = RNORTH; 231: token[0] = token[1]; 232: } else p->o.orient = NORTH; 233: switch (token[0]) { 234: default: 235: case 'n': ch = NORTH; break; 236: case 'e': ch = EAST; break; 237: case 's': ch = SOUTH; break; 238: case 'w': ch = WEST; break; 239: } 240: p->o.orient = ocomp[p->o.orient][ch]; 241: p->o.proto = read_def(iname); 242: p->o.mscale = x2; 243: p->o.dscale = y2; 244: continue; 245: 246: default: sprintf(buf,"%s: unrecognized .def command: 0%o, ESC continues...",d->name,ch); 247: userinput("",buf); 248: continue; 249: } 250: 251: done: fclose(in); 252: clearprompt(); 253: return(d); 254: } 255: 256: /* print .def file coordinate */ 257: pcoord(f,n) 258: FILE *f; 259: { if (n < 0) fprintf(f," ~%d",-n); 260: else fprintf(f," %d",n); 261: } 262: 263: /* write out a object list */ 264: write_defn(p) 265: register struct prototype *p; 266: { register gptr o; 267: char *s,temp[100],buf[100]; 268: FILE *out; 269: 270: strcpy(temp,p->name); 271: strcat(temp,".def"); 272: if ((out = fopen(temp,"w")) == NULL) { 273: sprintf(buf,"cannot open %s for output, ESC continues...",temp); 274: userinput("",buf); 275: return(1); 276: } 277: 278: sprintf(buf,"writing out %s",temp); 279: msg(buf); 280: fprintf(out,"d main\n"); 281: 282: for (o = p->body; o != NULL; o = o->s.next) { 283: putc('m',out); 284: pcoord(out,o->s.x1); 285: pcoord(out,o->s.y1); 286: putc(' ',out); 287: switch (o->s.type) { 288: case SEGMENT: 289: if (o->s.angle == 0) { 290: putc('l',out); 291: pcoord(out,o->s.x2); 292: pcoord(out,o->s.y2); 293: } else { 294: putc('A',out); 295: pcoord(out,o->s.x2); 296: pcoord(out,o->s.y2); 297: fprintf(out," %d",o->s.angle); 298: } 299: break; 300: 301: case LABEL: 302: fprintf(out,"c %s ",lorient[o->l.orient]); 303: for (s = o->l.string; *s; s += 1) 304: putc(*s==' ' ? '~' : *s,out); 305: break; 306: 307: case OBJECT: 308: fprintf(out,"i %s %d:%d %s", 309: o->o.proto->name, 310: o->o.mscale,o->o.dscale, 311: oorient[o->o.orient]); 312: break; 313: } 314: putc('\n',out); 315: } 316: 317: fprintf(out,"e\n"); 318: fclose(out); 319: clearprompt(); 320: p->modified = 0; /* we've saved away changes */ 321: return(0); 322: } 323: 324: /* remove an object from its prototype and reclaim its storage */ 325: rmalist(q) 326: register gptr q; 327: { register gptr r; 328: 329: for (; q != NULL; q = r) { 330: r = q->s.next; 331: free((char *)q); 332: } 333: } 334: 335: remove(p) 336: register gptr p; 337: { register gptr q; 338: 339: p->s.parent->modified = 1; 340: 341: if ((q = p->s.parent->body) == p) p->s.parent->body = p->s.next; 342: else { 343: while (q->s.next!=p && q!=NULL) q = q->s.next; 344: if (q != NULL) q->s.next = p->s.next; 345: } 346: 347: if (p->s.type == LABEL) free(p->l.string); 348: else if (p->s.type == SEGMENT) rmalist(p->s.cache); 349: free((char *)p); 350: } 351: 352: main(argc,argv) 353: char **argv; 354: { register struct prototype *d; 355: char *fname; 356: char buf[100]; 357: 358: fname = gentry(argc,argv); /* initialize display and keyboard */ 359: 360: prompt = NULL; /* not reading anything from user */ 361: typein[0] = 0; 362: directory = NULL; 363: 364: cur_state.mscale = 1; /* initial state settings */ 365: cur_state.dscale = 4; 366: cur_state.csize = 16; 367: cur_state.grid = 0; 368: 369: redisplay(); /* start with a fresh slate */ 370: 371: if (fname == NULL) { 372: again: do if(userinput("","name of definition to edit: ")) goto done; 373: while (typein[0] == 0); 374: d = read_def(typein); 375: } else d = read_def(fname); 376: 377: cur_state = d->recent; /* Restore state at last edit */ 378: redisplay(); 379: 380: while (1) { 381: extern char mousechanged; 382: if (mousechanged || UserReady()) { 383: if (command()) break; 384: } else { 385: DpyUp(0); } 386: } 387: d->recent = cur_state; 388: 389: /* check to see if we should write anything out */ 390: for (d = directory; d != NULL; d = d->next) 391: if (d->modified) { 392: sprintf(buf,"%s has not been written out, should it be? (y,n) ",d->name); 393: if (userinput("",buf)) 394: goto again; 395: if (typein[0] == 'y') 396: if (write_defn(d)) goto again; 397: } 398: 399: /* return to system */ 400: done: gexit(); 401: }