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: }

Defined functions

Help defined in line 970; used 2 times
adj_org defined in line 992; used 2 times
angle defined in line 74; used 7 times
cline defined in line 854; used 5 times
command defined in line 19; used 1 times
ctext defined in line 818; used 3 times
curdown defined in line 390; used 2 times
curup defined in line 384; used 2 times
dcurxor defined in line 902; used 2 times
delobj defined in line 179; used 2 times
deselect defined in line 651; used 6 times
disp_grid defined in line 876; used 1 times
display defined in line 766; used 5 times
editlast defined in line 62; used 2 times
editobj defined in line 130; used 2 times
fixwindow defined in line 91; used 2 times
home defined in line 451; used 2 times
instantiate defined in line 264; used 2 times
lastgo defined in line 201; used 2 times
letgo defined in line 195; used 2 times
magnify defined in line 422; used 2 times
mdown defined in line 378; used 2 times
mleft defined in line 366; used 2 times
mright defined in line 360; used 2 times
msg defined in line 810; used 17 times
multiplier defined in line 396; used 2 times
mup defined in line 372; used 2 times
nearby defined in line 622; used 1 times
new_window defined in line 599; used 6 times
newin defined in line 313; used 2 times
newlabel defined in line 292; used 2 times
newline defined in line 233; used 2 times
newobj defined in line 250; used 3 times
neworg defined in line 443; used 2 times
newout defined in line 324; used 2 times
quit defined in line 189; used 2 times
redisplay defined in line 722; used 8 times
rescale defined in line 157; used 2 times
rotateobj defined in line 105; used 2 times
scale defined in line 402; used 2 times
scaledn defined in line 438; used 2 times
scaleup defined in line 435; used 2 times
selectobj defined in line 705; used 2 times
selobj defined in line 207; used 2 times
setwindow defined in line 100; used 2 times
snap defined in line 345; used 2 times
snap_coord defined in line 350; used 2 times
stop defined in line 457; used 2 times
toggle defined in line 463; used 2 times
userinput defined in line 471; used 12 times
xorient defined in line 737; used 2 times
yorient defined in line 751; used 2 times

Defined variables

dx defined in line 14; used 7 times
dy defined in line 14; used 7 times
ends defined in line 14; used 4 times
mult defined in line 13; used 6 times
previous defined in line 16; used 6 times
rcsid_gcmd_c defined in line 6; never used
redo defined in line 15; used 4 times

Defined macros

abs defined in line 619; used 4 times
code defined in line 851; used 2 times
  • in line 871(2)
Last modified: 1986-02-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3531
Valid CSS Valid XHTML 1.0 Strict