1: #include <X/mit-copyright.h> 2: 3: /* Copyright Massachusetts Institute of Technology 1984, 1985 */ 4: 5: #ifndef lint 6: static char *rcsid_gcmd_c = "$Header: gcmd.c,v 10.6 86/02/01 16:18:44 tony Rel $"; 7: #endif lint 8: 9: char *malloc(), *strcpy(); 10: 11: #include "gedit.h" 12: 13: int mult = 1; /* command multiplier */ 14: int dx,dy,ends; /* used during select operation */ 15: int redo; /* set to one if arc cache should be recalculated */ 16: struct prototype *previous = NULL; /* last proto to be edited */ 17: 18: /* process command input from user -- return 1 if it's time to exit, 0 otherwise */ 19: command() 20: { register int ch; 21: fptr cmd; 22: extern char mousechanged; 23: char buf[100]; 24: 25: while (mousechanged) { 26: ch = track(); 27: if (ch & (RECENTER+REDISPLAY)) { 28: if (ch & RECENTER) { 29: new_window(&cur_state,cur_state.curx,cur_state.cury); 30: remouse(cur_state.curx, cur_state.cury, 1); 31: } 32: redisplay(); 33: } 34: if (!UserReady()) return(0); 35: } 36: 37: ch = UserChar() & 0xFF; 38: if (ch == 0377) return(0); 39: 40: cmd = dispatch[ch]; 41: if (cmd == NULL) { 42: Beep(); 43: sprintf(buf, "unrecognized command: 0%o", ch); 44: msg(buf); 45: } else { 46: ch = (*cmd)(); 47: if (!(ch & MULTIPLIER)) mult = 1; 48: if (ch & (RECENTER+REDISPLAY)) { 49: if (ch & RECENTER) { 50: new_window(&cur_state,cur_state.curx,cur_state.cury); 51: remouse(cur_state.curx, cur_state.cury, 1); 52: } 53: redisplay(); 54: } 55: if (ch & DONE) return(1); 56: } 57: 58: return(0); 59: } 60: 61: /* go back to editing last thing we were working on */ 62: editlast() 63: { struct prototype *temp; 64: 65: if (previous == NULL) return(0); 66: 67: if (temp = cur_state.curobj) temp->recent = cur_state; 68: cur_state = previous->recent; 69: previous = temp; 70: return(REDISPLAY); 71: } 72: 73: /* accept angle for SEGMENT */ 74: angle() 75: { register gptr p; 76: char buf[100]; 77: 78: if ((p = cur_state.editee) == NULL) goto done; 79: if (p->s.type != SEGMENT) goto done; 80: sprintf(buf,"angle = %d, new value (2048 units in a circle): ",p->s.angle); 81: if (userinput("",buf)) 82: goto done; 83: if (typein[0] == 0) goto done; 84: p->s.angle = atoi(typein) & 2047; 85: redo = 1; 86: 87: done: return(0); 88: } 89: 90: /* resize window and redisplay */ 91: fixwindow() 92: { new_window(&cur_state, 93: (cur_state.worgx+cur_state.wmaxx)>>1, 94: (cur_state.worgy+cur_state.wmaxy)>>1); 95: remouse(cur_state.curx, cur_state.cury, 1); 96: return(REDISPLAY); 97: } 98: 99: /* recenter window at cursor position */ 100: setwindow() 101: { return(RECENTER); 102: } 103: 104: /* frob orient parameter of selected object */ 105: rotateobj() 106: { register gptr p; 107: short temp; 108: 109: if ((p = cur_state.editee) != NULL) switch (p->s.type) { 110: case SEGMENT: if (p->s.angle == 0) break; 111: temp = p->s.x1; p->s.x1 = p->s.x2; p->s.x2 = temp; 112: temp = p->s.y1; p->s.y1 = p->s.y2; p->s.y2 = temp; 113: cur_state.whichend = 3 - cur_state.whichend; 114: redo = 1; 115: break; 116: 117: case LABEL: p->l.orient += 1; 118: if (p->l.orient > BR) p->l.orient = CC; 119: break; 120: 121: case OBJECT: p->o.orient += 1; 122: if (p->o.orient > RWEST) p->o.orient = NORTH; 123: break; 124: } 125: 126: return(0); 127: } 128: 129: /* edit selected object */ 130: editobj() 131: { register gptr p; 132: 133: if ((p = cur_state.editee) != NULL) switch (p->s.type) { 134: case LABEL: if (userinput(p->l.string,"edit label: ")) break; 135: if (strlen(typein) <= strlen(p->l.string)) 136: strcpy(p->l.string,typein); 137: else { 138: free(p->l.string); 139: if ((p->l.string = malloc((unsigned)(strlen(typein)+1))) == NULL) { 140: msg("out of room!"); 141: break; 142: } 143: strcpy(p->l.string,typein); 144: } 145: break; 146: 147: case OBJECT: cur_state.curobj->recent = cur_state; 148: previous = cur_state.curobj; 149: cur_state = p->o.proto->recent; 150: return(REDISPLAY); 151: } 152: 153: return(0); 154: } 155: 156: /* rescale subpicture */ 157: rescale() 158: { register gptr p; 159: register int ch; 160: char buf[100]; 161: int in1,in2; 162: 163: if ((p = cur_state.editee)==NULL || p->o.type!=OBJECT) return(0); 164: sprintf(buf,"subpicture scale = %d:%d, new scale: ",p->o.mscale,p->o.dscale); 165: if (userinput("",buf)) return(0); 166: ch = sscanf(typein,"%d:%d",&in1,&in2); 167: if (ch == 1) { 168: p->o.mscale = in1; 169: p->o.dscale = 1; 170: } else if (ch == 2) { 171: p->o.mscale = in1; 172: p->o.dscale = in2; 173: } else return(0); 174: remouse(cur_state.curx, cur_state.cury, 1); 175: return(REDISPLAY); 176: } 177: 178: /* delete object */ 179: delobj() 180: { register gptr p; 181: 182: if ((p = cur_state.editee) == NULL) return(0); 183: deselect(0); 184: remove(p); 185: return(0); 186: } 187: 188: /* abort current selection */ 189: quit() 190: { deselect(REDISPLAY); 191: return(0); 192: } 193: 194: /* drop current selection where cursor is */ 195: letgo() 196: { deselect(UPDATE+REDISPLAY); 197: return(0); 198: } 199: 200: /* drop current selection with same offset as last time */ 201: lastgo() 202: { deselect(UPDATE+USEOFFSET+REDISPLAY); 203: return(0); 204: } 205: 206: /* select nearby object */ 207: selobj() 208: { register gptr p; 209: register int in1 = 0; 210: 211: if ((p = cur_state.editee) == NULL) { 212: if ((p = cur_state.curobj->body) == NULL) return(0); 213: in1 = 1; 214: } else p = p->s.next; 215: 216: while (1) { 217: if (p == NULL) { 218: if (!in1) { 219: in1 = 1; 220: p = cur_state.curobj->body; 221: continue; 222: } else break; 223: } else if (p == cur_state.editee) break; 224: 225: if (nearby(p)) { selectobj(p,0); break; } 226: else p = p->s.next; 227: } 228: 229: return(0); 230: } 231: 232: /* create a new line segment */ 233: newline() 234: { register gptr p; 235: 236: if ((p = (gptr)malloc(sizeof(struct segment))) == NULL) 237: msg("out of room!"); 238: else { 239: p->s.type = SEGMENT; 240: p->s.x2 = cur_state.curx; 241: p->s.y2 = cur_state.cury; 242: p->s.angle = 0; 243: p->s.cache = NULL; 244: newobj(p); 245: } 246: return(0); 247: } 248: 249: /* finish creation of new object */ 250: newobj(p) 251: register gptr p; 252: { p->s.next = cur_state.curobj->body; 253: cur_state.curobj->body = p; 254: cur_state.curobj->modified = 1; 255: p->s.parent = cur_state.curobj; 256: p->s.x1 = cur_state.curx; 257: p->s.y1 = cur_state.cury; 258: dx = dy = 0; 259: ends = 2; 260: selectobj(p,1); 261: } 262: 263: /* instantiate an object */ 264: instantiate() 265: { register gptr p; 266: register struct prototype *new; 267: char buf[100]; 268: 269: if (userinput("","name of definition to instantiate: ")) return(0); 270: new = read_def(typein); 271: if (new->body == NULL) { 272: sprintf(buf,"definition for %s not found",new->name); 273: msg(buf); 274: retdef: free(new->name); 275: directory = new->next; /* remove dir entry */ 276: free((char *)new); 277: return(0); 278: }; 279: if ((p = (gptr)malloc(sizeof(struct object))) == NULL) { 280: msg("out of room!"); 281: goto retdef; 282: } 283: p->o.type = OBJECT; 284: p->o.orient = NORTH; 285: p->o.proto = new; 286: p->o.mscale = p->o.dscale = 1; 287: newobj(p); 288: return(0); 289: } 290: 291: /* new label */ 292: newlabel() 293: { register gptr p; 294: 295: if (userinput("","label: ")) return(0); 296: if ((p = (gptr)malloc(sizeof(struct label))) == NULL) { 297: msg("out of room!"); 298: return(0); 299: } 300: p->l.type = LABEL; 301: p->l.orient = CC; 302: if ((p->l.string = malloc((unsigned) (strlen(typein)+1))) == NULL) { 303: msg("out of room!"); 304: free((char *) p); 305: return(0); 306: } 307: strcpy(p->l.string,typein); 308: newobj(p); 309: return(0); 310: } 311: 312: /* start editing new .def file */ 313: newin() 314: { if (userinput("","name of definition to edit: ") || typein[0]==0) 315: return(0); 316: 317: previous = cur_state.curobj; 318: cur_state.curobj->recent = cur_state; 319: cur_state = read_def(typein)->recent; 320: return(REDISPLAY); 321: } 322: 323: /* write out current .def file */ 324: newout() 325: { if (userinput(cur_state.curobj->name,"name of output file: ")) return(0); 326: if (typein[0] == 0) return(0); 327: if (strcmp(typein,cur_state.curobj->name) != 0) { 328: if (strlen(typein) <= strlen(cur_state.curobj->name)) 329: strcpy(cur_state.curobj->name,typein); 330: else { 331: free(cur_state.curobj->name); 332: if ((cur_state.curobj->name = malloc((unsigned) (strlen(typein)+1))) == NULL) { 333: msg("out of room!"); 334: return(0); 335: } 336: strcpy(cur_state.curobj->name,typein); 337: } 338: } 339: write_defn(cur_state.curobj); 340: banner(); 341: return(0); 342: } 343: 344: /* snap cursor to grid */ 345: snap() 346: { return(remouse(snap_coord(cur_state.curx), 347: snap_coord(cur_state.cury), 0)); 348: } 349: 350: snap_coord(coord) 351: register int coord; 352: { register int mask = ~(cur_state.csize - 1); 353: 354: coord += cur_state.csize >> 1; 355: coord &= mask; 356: return(coord); 357: } 358: 359: /* move cursor to the right */ 360: mright() 361: { return(remouse(cur_state.curx + mult*cur_state.csize, 362: cur_state.cury, 0)); 363: } 364: 365: /* move cursor to the left */ 366: mleft() 367: { return(remouse(cur_state.curx - mult*cur_state.csize, 368: cur_state.cury, 0)); 369: } 370: 371: /* move cursor up */ 372: mup() 373: { return(remouse(cur_state.curx, 374: cur_state.cury + mult*cur_state.csize, 0)); 375: } 376: 377: /* move cursor down */ 378: mdown() 379: { return(remouse(cur_state.curx, 380: cur_state.cury - mult*cur_state.csize, 0)); 381: } 382: 383: /* make cursor larger */ 384: curup() 385: { if (cur_state.csize < 128) cur_state.csize <<= 1; 386: return(0); 387: } 388: 389: /* make cursor smaller */ 390: curdown() 391: { if (cur_state.csize > 1) cur_state.csize >>= 1; 392: return(0); 393: } 394: 395: /* multiply multiplier */ 396: multiplier() 397: { mult <<= 2; 398: return(MULTIPLIER); 399: } 400: 401: /* rescale picture */ 402: scale() 403: { register int ch; 404: int in1,in2; 405: 406: if (userinput("","new scale (screen:defn): ")) return(0); 407: ch = sscanf(typein,"%d:%d",&in1,&in2); 408: if (ch == 1) { 409: cur_state.mscale = in1; 410: cur_state.dscale = 1; 411: } else if (ch == 2) { 412: cur_state.mscale = in1; 413: cur_state.dscale = in2; 414: } else return(1); 415: 416: return(RECENTER); 417: } 418: 419: /* Scale picture up/down by factor of +n/-n: 420: */ 421: 422: magnify(n) 423: { if (n<0) /* Make it smaller? */ 424: { n = -n; 425: if ((cur_state.mscale % n) == 0) cur_state.mscale /= n; 426: else cur_state.dscale *= n; 427: } 428: else if (n > 0) 429: { if ((cur_state.dscale % n) == 0) cur_state.dscale /= n; 430: else cur_state.mscale *= n; 431: } 432: return RECENTER; 433: } 434: 435: scaleup() 436: { return magnify(4); 437: } 438: scaledn() 439: { return magnify(-4); 440: } 441: 442: /* move origin */ 443: neworg() 444: { adj_org(cur_state.curobj,cur_state.curx,cur_state.cury); 445: cur_state.curobj->modified = 1; 446: remouse(0, 0, 0); 447: return(RECENTER); 448: } 449: 450: /* move cursor to origin */ 451: home() 452: { remouse(0, 0, 0); 453: return(RECENTER); 454: } 455: 456: /* finished editing current picture */ 457: stop() 458: { deselect(UPDATE+REDISPLAY); 459: return(DONE); 460: } 461: 462: /* toggle grid flag */ 463: toggle() 464: { cur_state.grid ^= 1; 465: return(REDISPLAY); 466: } 467: 468: /* get some input from the user, leave in typein array. Return 1 469: * if user aborted, 0 if he thinks there's something worth reading. 470: */ 471: userinput(seed,cue) 472: char *seed,*cue; 473: { register int ch; 474: register char *p = typein; 475: char temp[100],save[100]; 476: int curcol,times,mch; 477: 478: strcpy(typein,seed); 479: sprintf(temp,cue); 480: prompt = temp; 481: curcol = strlen(prompt); 482: times = 1; 483: mch = mousechanged; 484: mousechanged = 0; 485: goto redraw; 486: 487: while (1) { 488: if (mousechanged || UserReady()) { 489: if (mousechanged) { 490: mch = 1; 491: mousechanged = 0; 492: continue; 493: } 494: switch (ch = UserChar() & 0xFF) { 495: default: times = 1; 496: if (ch < ' ' || ch > 0177) { 497: Beep(); 498: break; 499: } 500: if (*p == 0) { /* char at end */ 501: *p++ = ch; 502: *p = 0; 503: disp_char(ch,curcol * chrwid,0,0,NORMAL,1); 504: curcol += 1; 505: break; 506: } 507: strcpy(save,p); /* insert char */ 508: *p++ = ch; 509: curcol += 1; 510: strcpy(p,save); 511: goto redraw; 512: 513: case 'C'-0100: 514: case 'Q'-0100: 515: case 'G'-0100: 516: prompt = NULL; 517: clearprompt(); 518: mousechanged = mch; 519: return(1); 520: 521: case 'A'-0100: 522: p = typein; 523: curcol = strlen(prompt); 524: ctldone: times = 1; 525: break; 526: 527: case 'B'-0100: 528: case 'H'-0100: 529: while (p!=typein && times>0) { 530: times -= 1; 531: p -= 1; 532: curcol -= 1; 533: } 534: goto ctldone; 535: 536: case 'D'-0100: 537: while (*p && times>0) { 538: strcpy(p,p+1); 539: times -= 1; 540: } 541: goto redraw; 542: 543: case 'E'-0100: 544: for (p=prompt, curcol=0; *p; p+=1, curcol+=1); 545: for (p = typein; *p; p += 1) curcol += 1; 546: goto ctldone; 547: 548: case 'F'-0100: 549: while (*p && times>0) { 550: times -= 1; 551: p += 1; 552: curcol += 1; 553: } 554: goto ctldone; 555: 556: case 'K'-0100: 557: *p = 0; 558: goto redraw; 559: 560: case 'Y'-0100: 561: new_window(&cur_state,cur_state.curx,cur_state.cury); 562: case 'L'-0100: 563: redisplay(); 564: goto redraw; 565: 566: case 'U'-0100: 567: times <<= 2; 568: break; 569: 570: case '\r': 571: case '\n': 572: case 033: prompt = NULL; 573: clearprompt(); 574: mousechanged = mch; 575: return(0); 576: 577: case 0177: 578: while (p!=typein && times>0) { 579: strcpy(p-1,p); 580: p -= 1; 581: curcol -= 1; 582: times -= 1; 583: } 584: goto redraw; 585: 586: redraw: msg(prompt); 587: incol += disp_str(typein, incol * chrwid, 0, 0, NORMAL,1); 588: times = 1; 589: break; 590: } 591: } else { 592: incol = curcol; 593: DpyUp(1); 594: } 595: } 596: } 597: 598: /* given center, calculate various window coords */ 599: new_window(s,cx,cy) 600: register struct state *s; 601: { int wx,wy; 602: 603: /* half-width of window in defn coords */ 604: wx = (wmaxx - wminx) >> 1; 605: wx *= s->dscale; 606: wx /= s->mscale; 607: 608: /* half-height of window in defn coords */ 609: wy = (wmaxy - wminy) >> 1; 610: wy *= s->dscale; 611: wy /= s->mscale; 612: 613: s->worgx = cx - wx; 614: s->worgy = cy - wy; 615: s->wmaxx = cx + wx; 616: s->wmaxy = cy + wy; 617: } 618: 619: #define abs(x) ((x) < 0 ? -(x) : (x)) 620: 621: /* see if an object is "near enough" to the cursor, sets dx, dy, ends */ 622: nearby(p) 623: register gptr p; 624: { switch (p->s.type) { 625: case SEGMENT: dx = p->s.x2 - cur_state.curx; 626: dy = p->s.y2 - cur_state.cury; 627: if (abs(dx) <= cur_state.csize && 628: abs(dy) <= cur_state.csize) { 629: ends = 2; 630: return(1); 631: } 632: case OBJECT: 633: case LABEL: dx = p->s.x1 - cur_state.curx; 634: dy = p->s.y1 - cur_state.cury; 635: if (abs(dx) <= cur_state.csize && 636: abs(dy) <= cur_state.csize) { 637: ends = 1; 638: return(1); 639: } 640: break; 641: } 642: 643: return(0); 644: } 645: 646: /* unselect currently selected object: 647: * update & UPDATE update object's info 648: * + USEOFFSET -- use lxoff, lyoff 649: * update & REDISPLAY redisplay when done 650: */ 651: deselect(update) 652: { register gptr p = cur_state.editee; 653: register int temp; 654: gptr save; 655: 656: if (p == NULL) return; /* nothing to do */ 657: 658: if (update & UPDATE) { 659: switch (p->s.type) { 660: case SEGMENT: if (cur_state.whichend == 2) { 661: if (update & USEOFFSET) { 662: p->s.x2 += cur_state.lxoff; 663: p->s.y2 += cur_state.lyoff; 664: } else { 665: temp = cur_state.curx + cur_state.xoff; 666: cur_state.lxoff = temp - p->s.x2; 667: p->s.x2 = temp; 668: temp = cur_state.cury + cur_state.yoff; 669: cur_state.lyoff = temp - p->s.y2; 670: p->s.y2 = temp; 671: } 672: break; 673: }; 674: case LABEL: 675: case OBJECT: if (update & USEOFFSET) { 676: p->s.x1 += cur_state.lxoff; 677: p->s.y1 += cur_state.lyoff; 678: } else { 679: temp = cur_state.curx + cur_state.xoff; 680: cur_state.lxoff = temp - p->s.x1; 681: p->s.x1 = temp; 682: temp = cur_state.cury + cur_state.yoff; 683: cur_state.lyoff = temp - p->s.y1; 684: p->s.y1 = temp; 685: } 686: break; 687: } 688: cur_state.curobj->modified = 1; 689: } 690: 691: if (p->s.type == SEGMENT) newalist(&p->s,p->s.x1,p->s.y1,p->s.x2,p->s.y2); 692: 693: cur_state.editee = NULL; 694: 695: /* to update display we only have to redraw selected object */ 696: if (update & REDISPLAY) { 697: save = p->s.next; 698: p->s.next = NULL; 699: display(p,0,0,NORTH,1,1,NORMAL); 700: p->s.next = save; 701: } 702: } 703: 704: /* update database to reflect newly selected object */ 705: selectobj(p,new) 706: register gptr p; 707: { deselect(UPDATE+REDISPLAY); 708: cur_state.editee = p; 709: cur_state.xoff = 0; 710: cur_state.yoff = 0; 711: cur_state.whichend = ends; 712: if (!new) { 713: if (remouse(cur_state.curx+dx, cur_state.cury+dy,1)) { 714: new_window(&cur_state,cur_state.curx+dx,cur_state.cury+dy); 715: remouse(cur_state.curx, cur_state.cury, 1); 716: } 717: redisplay(); 718: } 719: } 720: 721: /* redisplay entire screen */ 722: redisplay() 723: { 724: clearscreen(); 725: if (cur_state.curobj != NULL) { 726: display(cur_state.curobj->body,0,0,NORTH,1,1,NORMAL); 727: ctext("*",0,0,CC,NORMAL); 728: } 729: 730: /* grid points fall every csize points */ 731: if (cur_state.grid) disp_grid(); 732: 733: return(0); /* return code when used as a command */ 734: } 735: 736: /* return appropriately oriented x and y coords */ 737: xorient(x,y,orient) 738: { switch (orient) { 739: case NORTH: return(x); 740: case EAST: return(y); 741: case SOUTH: return(-x); 742: case WEST: return(-y); 743: case RNORTH: return(-x); 744: case REAST: return(-y); 745: case RSOUTH: return(x); 746: case RWEST: return(y); 747: } 748: /*NOTREACHED*/ 749: } 750: 751: yorient(x,y,orient) 752: { switch (orient) { 753: case NORTH: return(y); 754: case EAST: return(-x); 755: case SOUTH: return(-y); 756: case WEST: return(x); 757: case RNORTH: return(y); 758: case REAST: return(-x); 759: case RSOUTH: return(-y); 760: case RWEST: return(x); 761: } 762: /*NOTREACHED*/ 763: } 764: 765: /* display objects with specified translation and rotation */ 766: display(o,x,y,orient,mscale,dscale,dflag) 767: register gptr o; 768: { short tx,ty; 769: short ex,ey; 770: 771: while (o != NULL) { 772: tx = xorient(o->l.x, o->l.y, orient); 773: tx *= mscale; tx /= dscale; 774: tx += x; 775: ty = yorient(o->l.x, o->l.y, orient); 776: ty *= mscale; ty /= dscale; 777: ty += y; 778: 779: if (cur_state.editee != o) switch (o->s.type) { 780: case LABEL: 781: ctext(o->l.string,tx,ty,lcomp[orient][o->l.orient],dflag); 782: break; 783: 784: case OBJECT: 785: display(o->o.proto->body,tx,ty, 786: ocomp[orient][o->o.orient], 787: mscale * o->o.mscale, dscale * o->o.dscale, 788: dflag); 789: break; 790: 791: case SEGMENT: 792: if (o->s.cache != NULL) { 793: display(o->s.cache,x,y,orient,mscale,dscale,dflag); 794: break; 795: } 796: ex = xorient(o->s.x2, o->s.y2, orient); 797: ex *= mscale; ex /= dscale; 798: ex += x; 799: ey = yorient(o->s.x2, o->s.y2, orient); 800: ey *= mscale; ey /= dscale; 801: ey += y; 802: cline(tx,ty,ex,ey,dflag); 803: break; 804: } 805: o = o->s.next; 806: } 807: } 808: 809: /* output a message on the bottom-most line */ 810: msg(string) 811: char *string; 812: { 813: clearprompt(); 814: incol += disp_str(string, incol * chrwid, 0, 0, NORMAL,1); 815: } 816: 817: /* display text string with proper orientation clipped by current window */ 818: ctext(string,x,y,orient,dflag) 819: register char *string; 820: { register int i = (strlen(string) * chrwid) >> 1; 821: 822: /* first translate and scale to the window coord system */ 823: y -= cur_state.worgy; 824: x -= cur_state.worgx; 825: 826: y *= cur_state.mscale; y /= cur_state.dscale; 827: x *= cur_state.mscale; x /= cur_state.dscale; 828: 829: /* adjust for character orientation */ 830: switch (orient) { 831: case CC: x -= i; y -= (chrhgt >> 1); break; 832: case TC: x -= i; y -= chrhgt; break; 833: case BC: x -= i; break; 834: case CL: y -= (chrhgt >> 1); break; 835: case TL: y -= chrhgt; break; 836: case BL: break; 837: case CR: x -= i+i; y -= (chrhgt >> 1); break; 838: case TR: x -= i+i; y -= chrhgt; break; 839: case BR: x -= i+i; 840: } 841: 842: /* only display chars that lie within current window */ 843: x += wminx; 844: y += wminy; 845: if (y <= wmaxy && y+chrhgt >= wminy && 846: x <= wmaxx && x+(strlen(string)*chrwid) >= wminx) 847: disp_str(string,x,y,0,dflag,0); 848: } 849: 850: /* draw a clipped vector */ 851: #define code(x,y) \ 852: ((x<wminx ? 1 : x>wmaxx ? 2 : 0) + (y<wminy ? 4 : y>wmaxy ? 8 : 0)) 853: 854: cline(fx,fy,tx,ty,dflag) 855: { 856: 857: /* first translate and scale to the window coord system */ 858: fx -= cur_state.worgx; 859: fy -= cur_state.worgy; 860: tx -= cur_state.worgx; 861: ty -= cur_state.worgy; 862: 863: fy *= cur_state.mscale; fy /= cur_state.dscale; 864: fx *= cur_state.mscale; fx /= cur_state.dscale; 865: ty *= cur_state.mscale; ty /= cur_state.dscale; 866: tx *= cur_state.mscale; tx /= cur_state.dscale; 867: 868: fx += wminx; fy += wminy; 869: tx += wminx; ty += wminy; 870: 871: if ((code(fx,fy) & code(tx,ty)) == 0) 872: line(fx,fy,tx,ty,dflag); 873: } 874: 875: /* display grid points at csize intervals */ 876: disp_grid() 877: { int x,y,incrx,incry; 878: 879: /* find window coord of lower left grid point */ 880: x = cur_state.worgx + cur_state.csize - 1; 881: x &= ~(cur_state.csize - 1); 882: x -= cur_state.worgx; 883: x *= cur_state.mscale; x /= cur_state.dscale; 884: 885: y = cur_state.worgy + cur_state.csize - 1; 886: y &= ~(cur_state.csize - 1); 887: y -= cur_state.worgy; 888: y *= cur_state.mscale; y /= cur_state.dscale; 889: 890: x += wminx; 891: y = wmaxy - y - wminy; 892: 893: incrx = (cur_state.csize * cur_state.mscale) / cur_state.dscale; 894: if (incrx <= 0) incrx = 8; 895: else while (incrx < 8) incrx <<= 1; 896: incry = incrx; 897: 898: drawgrid(x,y,incrx,incry); 899: } 900: 901: /* Xor drawing cursor and selected object */ 902: dcurxor() 903: { register gptr p; 904: int x,y; 905: 906: if (cur_state.curobj == NULL) return; /* no object on screen */ 907: 908: if ((p = cur_state.editee) != NULL) { 909: if (p->s.type == SEGMENT && (redo || (p->s.angle != 0 && 910: (cur_state.curx!=cur_state.oldx || 911: cur_state.cury!=cur_state.oldy)))) { 912: cur_state.oldx = cur_state.curx; 913: cur_state.oldy = cur_state.cury; 914: redo = 0; 915: if (cur_state.whichend == 2) 916: newalist(&p->s,p->s.x1,p->s.y1, 917: cur_state.curx + cur_state.xoff, 918: cur_state.cury + cur_state.yoff); 919: else 920: newalist(&p->s,cur_state.curx + cur_state.xoff, 921: cur_state.cury + cur_state.yoff, 922: p->s.x2,p->s.y2); 923: } 924: switch(p->s.type) { 925: case SEGMENT: 926: if (p->s.cache != NULL) { 927: for (p = p->s.cache; p != NULL; p = p->s.next) 928: cline(p->s.x1,p->s.y1,p->s.x2,p->s.y2,HIGHLIGHT); 929: break; 930: } 931: if (cur_state.whichend == 2) { x = p->s.x1; y = p->s.y1; } 932: else { x = p->s.x2; y = p->s.y2; } 933: cline(x,y, 934: cur_state.curx + cur_state.xoff, 935: cur_state.cury + cur_state.yoff,HIGHLIGHT); 936: break; 937: 938: case LABEL: 939: ctext(p->l.string, 940: cur_state.curx + cur_state.xoff, 941: cur_state.cury + cur_state.yoff, 942: p->l.orient, 943: HIGHLIGHT); 944: break; 945: 946: case OBJECT: 947: display(p->o.proto->body, 948: cur_state.curx + cur_state.xoff, 949: cur_state.cury + cur_state.yoff, 950: p->o.orient,p->o.mscale,p->o.dscale, 951: HIGHLIGHT); 952: return; /* no cursor needed here */ 953: } 954: } 955: 956: /* draw x-shaped graphic cursor */ 957: cline(cur_state.curx - cur_state.csize, 958: cur_state.cury - cur_state.csize, 959: cur_state.curx + cur_state.csize, 960: cur_state.cury + cur_state.csize, 961: HIGHLIGHT); 962: cline(cur_state.curx - cur_state.csize, 963: cur_state.cury + cur_state.csize, 964: cur_state.curx + cur_state.csize, 965: cur_state.cury - cur_state.csize, 966: HIGHLIGHT); 967: } 968: 969: /* Help stuff */ 970: Help() 971: { struct prototype *help_proto; 972: char buf[100]; 973: 974: help_proto = read_def(HELPFILE); /* Load the file, if any. */ 975: 976: if (help_proto->body == NULL) { 977: sprintf(buf, "Can't read '%s.DEF' -- NO HELP", HELPFILE); 978: msg(buf); 979: return 0; 980: } 981: previous = cur_state.curobj; 982: if (cur_state.curobj) cur_state.curobj->recent = cur_state; 983: cur_state = help_proto->recent; 984: return REDISPLAY; 985: } 986: 987: /* Adjust coordinates in body of an object by the origin of that object. 988: * This routine is called after an object is edited, so that an adjusted 989: * subpicture origin is reflected immediately in pictures which reference 990: * it. 991: */ 992: adj_org(p,adjx,adjy) 993: register struct prototype *p; 994: { register gptr o; 995: struct prototype temp; 996: 997: for (o = p->body; o != NULL; o = o->s.next) switch (o->s.type) { 998: case SEGMENT: o->s.x1 -= adjx; 999: o->s.y1 -= adjy; 1000: o->s.x2 -= adjx; 1001: o->s.y2 -= adjy; 1002: if (o->s.cache) { 1003: temp.body = o->s.cache; 1004: adj_org(&temp,adjx,adjy); 1005: } 1006: break; 1007: 1008: case LABEL: o->l.x -= adjx; 1009: o->l.y -= adjy; 1010: break; 1011: 1012: case OBJECT: o->o.x -= adjx; 1013: o->o.y -= adjy; 1014: break; 1015: } 1016: }