1 /* @(#)short.c 1.3 12/30/83 2 * 3 * Copyright -C- 1982 Barry S. Roitblat 4 * 5 * 6 * This file contains routines to implement the short commands 7 * of the gremlin picture editor. 8 * 9 */ 10 11 #include "gremlin.h" 12 #include "grem2.h" 13 #include <signal.h> 14 #include <sgtty.h> 15 16 /* imports from graphics files */ 17 18 extern GRVector(), GRPutText(); 19 extern GRCurve(); 20 extern GRClear(); 21 extern int GRArc(); 22 extern charxsize, charysize; 23 24 /* imports from display.c */ 25 26 extern DISScreenAdd(), DISScreenErase(); 27 extern DISDisplaySet(), DISEraseSet(), DISClearSetDisplay(); 28 29 /* imports from database files */ 30 31 extern ELT *DBInit(), *DBCreateElt(); 32 extern DBDelete(), DBGravitate(), DBClearElt(); 33 extern ELT *DBCopy(); 34 extern DBXform(), DBBounded(); 35 extern DBAddSet(), DBClearSet(); 36 extern POINT *PTInit(), *PTMakePoint(); 37 extern PTDeletePoint(); 38 39 /* imports from long.c */ 40 41 extern LGIncludeSet(); 42 43 /* imports from menu.c */ 44 45 extern MNHighLt(), MNUnHighLt(); 46 extern HiMen[], HiFont[], HiBrush[], HiMode[]; 47 48 int adj[4] = { 0, 0, 1, 2 }; 49 50 /* imports from textio.c */ 51 52 extern TxMsgOK(), TxPutString(), TxGetLine(), TxRedisplay(), TxPutMsg(); 53 extern char TxGetChar(); 54 extern TXFIELD TAlign, TAdjust, TBrush, TFont, TGravity, TCSize; 55 extern TXFIELD TEdit, TJustmode; 56 57 /* imports from c */ 58 59 extern char *malloc(); 60 extern char *sprintf(); 61 62 /* imports from main.c */ 63 64 extern globinit(); /* global initialization routine */ 65 extern ELT *PICTURE; /* current PICTURE database */ 66 extern ELT *cset; /* current set database */ 67 extern CBRUSH, CSIZE, CFONT; /* current brush, size, font */ 68 extern CJUST; /* text justification mode */ 69 extern Gridon; /* grid mode flag */ 70 extern Orientation; /* orientation of workspace */ 71 extern Alignment; /* point alignment indicator */ 72 extern float PX, PY; /* cursor coordinates */ 73 extern float Lastx, Lasty; /* previous cursor coordinates */ 74 extern SEQ; /* point sequence number */ 75 extern char *Editfile; /* current edit file */ 76 extern POINT *POINTLIST; /* accumulated point list */ 77 extern Adjustment; /* point adjustment mode */ 78 extern GravityOn; /* gravity mode flag */ 79 extern Consume; /* point clear flag */ 80 extern CHANGED; /* PICTURE changed flag */ 81 extern ELT *MEN[]; /* pointers for user symbols */ 82 extern POINT MENPOINT[]; /* pointers used fo user symbols */ 83 extern cmdbuf[]; /* line buffer for commands */ 84 extern ELT arhead; /* arrow head template */ 85 extern char *textpos[], *dispmode[];/* text positioning modes */ 86 extern int textmode[]; /* text positioning */ 87 88 89 extern SHUpdate(), SHDrawArc(), SHDrawCurve(), SHCopy(), SHRedis(), 90 SHDefineSet(), SHErase(), SHSetArea(), SHGravity(), 91 SHGrid(), SHRotate(), SHScale(), SHTranslate(), SHShellEsc(), 92 SHDrawVector(), SHMAdjust(), SHBox(), SHArrow(), 93 SHSave1(), SHSave2(), SHSave3(), SHSave4(); 94 95 /* The following two arrays define the short commands and the routines 96 * that process them. 97 */ 98 static char shcmds[] = { '\14', '!', '1', '2', '3', '4', 'a', 'b', 99 'c', 'd', 'e', 'f', 'g', 'l', 'q', 'r', 100 's', 't', 'v', 'w', 'x', 'z', '\0'}; 101 static (*(shrtns[]))() = { 102 SHUpdate, /* redraw screen */ 103 SHShellEsc, /* shell escape */ 104 SHSave1, /* save user symbol */ 105 SHSave2, /* save user symbol */ 106 SHSave3, /* save user symbol */ 107 SHSave4, /* save user symbol */ 108 SHDrawArc, /* draw arc */ 109 SHDrawCurve, /* draw curve */ 110 SHCopy, /* copy current set */ 111 SHDefineSet, /* define current set */ 112 SHErase, /* erase elements */ 113 SHSetArea, /* select area for current set */ 114 SHGravity, /* gravity */ 115 SHRedis, /* text screen redisplay */ 116 SHGrid, /* toggle grid display */ 117 SHRotate, /* rotate current set */ 118 SHScale, /* scale current set */ 119 SHTranslate, /* translate current set */ 120 SHDrawVector, /* draw vectors */ 121 SHArrow, /* arrowhead */ 122 SHBox, /* rectangle from two points */ 123 SHMAdjust}; /* manhattan adjust */ 124 125 126 int 127 SHLookup(c, table) 128 char c; /* Pointer to a char to be looked up */ 129 char table[]; /* Pointer to an array of characters 130 * which are the valid commands. The array 131 * must be sorted by ascii value. 132 */ 133 134 /*--------------------------------------------------------- 135 * SHLookup searches a table of characters to find one that matches a 136 * the given character. 137 * 138 * Results: If c is a valid command character, its index is 139 * returned, otherwise, if c is the null command, -2 is returned 140 * else -1 is returned. 141 * 142 * Side Effects: None. 143 * 144 * (Modified from software written by John Ousterhout for the caesar 145 * program) 146 *--------------------------------------------------------- 147 */ 148 149 { 150 int index; 151 152 if ((c == ' ') || (c == '\0')) return(-2); 153 for (index=0; table[index] != '\0'; index++) 154 { 155 if (table[index] == c) return(index); 156 if (table[index] > c) return(-1); 157 } 158 return(-1); 159 } /* end SHLookup */ 160 161 162 SHCommand(command) 163 char *command; 164 165 /*--------------------------------------------------------- 166 * This routine reads in, looks up, and executes a long command. 167 * 168 * Results: None. 169 * 170 * Side Effects: 171 * Depends on the command that is invoked. 172 *--------------------------------------------------------- 173 */ 174 175 { 176 int index; 177 index = SHLookup(*command, shcmds); 178 if (index == -2) return; 179 if (index >= 0) 180 { 181 182 (*(shrtns[index]))(); 183 } 184 else 185 { 186 error("no such command"); 187 } 188 } /* end SHCommand */ 189 190 static char nopnt[18] = "not enough points"; 191 static char noset[15] = "no current set"; 192 193 SHDrawVector() 194 /* 195 * This routine creates and displays a VECTOR element from the 196 * points previously specified. 197 */ 198 199 { 200 ELT *e1; 201 POINT *plist, *p1, *p2; 202 char *txt; 203 204 if (SEQ < 2) /* not enough points */ 205 { 206 error(nopnt); 207 return; 208 } 209 DBClearSet(); /* Clear current set in preparation */ 210 DISClearSetDisplay(); /* for making this the new one */ 211 GRsetwmask(linemask | setmask); 212 plist = PTInit(); 213 p1 = POINTLIST; 214 (void) PTMakePoint(p1->x, p1->y, &plist); 215 p2 = PTNextPoint(p1); 216 while ( !Nullpoint(p2) ) 217 { 218 (void) PTMakePoint(p2->x, p2->y, &plist); 219 GRVector(p1, p2, CBRUSH); 220 p1 = p2; 221 p2 = PTNextPoint(p1); 222 } /* end while */; 223 txt = malloc(1); 224 *txt = '\0'; 225 e1 = DBCreateElt(VECTOR, plist, CBRUSH, 0, txt, &PICTURE); 226 DBAddSet(e1); 227 CHANGED = TRUE; 228 } /* end SHDrawVector */ 229 230 #define twoPi 6.2832 231 232 SHDrawArc() 233 /* 234 * This routine creates and displays an ARC element based on the 235 * points previously defined. If 3 or more points are defined, the 236 * extent of the arc is calculated as the angle formed by the 237 * respective lines through the second and third points and the first 238 * point. If only 2 points are specified, a full circle is drawn. 239 */ 240 241 { 242 ELT *e1; 243 POINT *plist, *p1, *p2; 244 char *txt; 245 double a1, a2, angle, radius; 246 int stat; 247 248 if (SEQ < 2) /* not enough points */ 249 { 250 error(nopnt); 251 return; 252 } 253 plist = PTInit(); 254 p1 = POINTLIST; 255 p2 = PTNextPoint(p1); 256 radius = sqrt( pow((p2->x - p1->x), 2.0) 257 + pow((p2->y - p1->y), 2.0)); 258 if (SEQ == 2) /* draw full circle */ 259 { 260 angle = 0; 261 /* Add extra positioning points */ 262 (void) PTMakePoint(p1->x, p1->y, &plist); 263 (void) PTMakePoint(p2->x, p2->y, &plist); 264 (void) PTMakePoint(p1->x, p1->y + radius, &plist); 265 (void) PTMakePoint(p1->x, p1->y - radius, &plist); 266 (void) PTMakePoint(p1->x + radius, p1->y, &plist); 267 (void) PTMakePoint(p1->x - radius, p1->y, &plist); 268 } /* end if */ 269 else 270 { 271 (void) PTMakePoint(POINTLIST->x, POINTLIST->y, &plist); 272 p1 = PTNextPoint(POINTLIST); 273 (void) PTMakePoint(p1->x, p1->y, &plist); 274 p2 = PTNextPoint(p1); 275 a1 = atan2((p1->x - POINTLIST->x), (p1->y - POINTLIST->y)); 276 a2 = atan2((p2->x - POINTLIST->x), (p2->y - POINTLIST->y)); 277 angle = a1 - a2; 278 if (angle < 0.0) angle += twoPi; 279 280 /* Set second point to lie on arc */ 281 (void) PTMakePoint((radius * sin(a2) + POINTLIST->x), 282 (radius * cos(a2) + POINTLIST->y), 283 &plist); 284 285 angle *= 360.0/twoPi; /* convert to degrees */ 286 }; 287 p1 = PTNextPoint(POINTLIST); 288 DBClearSet(); /* Clear current set, this element becomes */ 289 DISClearSetDisplay(); /* the new current set */ 290 GRsetwmask(linemask | setmask); 291 stat = GRArc(POINTLIST, p1, angle, CBRUSH); 292 if (stat > -1) 293 { 294 txt = malloc(1); 295 *txt = '\0'; 296 e1 = DBCreateElt(ARC, plist, CBRUSH, (int) (angle + 0.5), 297 txt, &PICTURE); 298 DBAddSet(e1); 299 CHANGED = TRUE; 300 } 301 } /* end SHDrawARc */ 302 303 304 SHDrawCurve() 305 /* 306 * This routine creates and displays a curve using points previously 307 * defined. This is dependent on DISCurve which is not yet implemented. 308 */ 309 310 { 311 ELT *e1; 312 char *txt; 313 POINT *p1, *p2, *plist; 314 int stat; 315 316 stat = 0; 317 if (SEQ < 2) /* not enough points */ 318 { 319 error("need at least 2 points"); 320 return; 321 } 322 plist = PTInit(); 323 p1 = POINTLIST; 324 (void) PTMakePoint(p1->x, p1->y, &plist); 325 p2 = PTNextPoint(p1); 326 while ( !Nullpoint(p2) ) 327 { 328 (void) PTMakePoint(p2->x, p2->y, &plist); 329 p1 = p2; 330 p2 = PTNextPoint(p1); 331 } /* end while */; 332 DBClearSet(); /* Clear current set, this element */ 333 DISClearSetDisplay(); /* the new current set */ 334 GRsetwmask(linemask | setmask); 335 stat = GRCurve(plist, CBRUSH); 336 if (stat != 0) /* bad knots */ 337 { 338 error("too many consecutive knots at same place"); 339 return; 340 } 341 txt = malloc(1); 342 *txt = '\0'; 343 e1 = DBCreateElt(CURVE, plist, CBRUSH, 0, txt, &PICTURE); 344 DBAddSet(e1); 345 CHANGED = TRUE; 346 } /* end SHDrawCurve */ 347 348 SHErase() 349 /* 350 * This routine erases selected elements from the screen and deletes 351 * them from the picture database. 352 */ 353 354 { 355 ELT *e1; 356 357 while ( !DBNullelt(cset) ) /* delete elements in current set */ 358 { 359 DISScreenErase(cset, (linemask | setmask)); 360 e1 = DBNextofSet(cset); 361 DBDelete(cset, &PICTURE); 362 cset = e1; 363 }; 364 CHANGED = TRUE; 365 } /* end SHErase */ 366 367 368 SHGravity() 369 /* 370 * This routine toggles the gravity mode. 371 */ 372 373 { 374 if (GravityOn) 375 { 376 MNUnHighLt(HiMode[3]); 377 GravityOn = FALSE; 378 TxPutString(&TGravity, "OFF"); 379 } 380 else 381 { 382 MNHighLt(HiMode[3], hicolor); 383 GravityOn = TRUE; 384 TxPutString(&TGravity, " ON"); 385 } 386 Consume = FALSE; 387 } /* End GravityOn */ 388 389 SHGrid() 390 /* 391 * This routine toggles the display of the grid 392 */ 393 394 { 395 if (Gridon) 396 { 397 Gridon = FALSE; 398 GRBlankGrid(); 399 } 400 else 401 { 402 Gridon = TRUE; 403 GRDisplayGrid(); 404 } 405 Consume = FALSE; 406 } /* end SHGrid */ 407 408 409 SHMAdjust() 410 /* 411 * Manhattan Adjust - 412 * This routine toggles the adjustment mode. 413 */ 414 415 { 416 if (Adjustment == MAN) 417 { 418 MNUnHighLt(HiMode[adj[MAN]]); 419 Adjustment = NOADJ; 420 TxPutString(&TAdjust, "NO ADJUSTMENT"); 421 } 422 else 423 { 424 MNUnHighLt(HiMode[adj[Adjustment]]); 425 MNHighLt(HiMode[adj[MAN]], hicolor); 426 Adjustment = MAN; 427 TxPutString(&TAdjust, " MANHATTAN "); 428 } 429 Consume = FALSE; 430 } 431 432 433 SHDefineSet() 434 /* 435 * This routine defines the current set based upon previously 436 * defined points to select elements. The action is performed by 437 * clearing the current set and calling LGIncludeSet. 438 */ 439 440 { 441 DBClearSet(); 442 DISClearSetDisplay(); 443 LGIncludeSet(""); 444 } /* end SHDefineSet */ 445 446 SHSetArea() 447 /* 448 * This routine defines the current set by selecting all elements 449 * bounded by a rectangle whose diagonal is defined by specifed points. 450 */ 451 452 { 453 ELT *e1; 454 POINT *p1; 455 float x1, y1, x2, y2; 456 457 if (SEQ < 2) 458 { 459 error(nopnt); 460 return; 461 } 462 DBClearSet(); 463 DISClearSetDisplay(); 464 x1 = POINTLIST->x; 465 y1 = POINTLIST->y; 466 p1 = PTNextPoint(POINTLIST); 467 x2 = p1->x; 468 y2 = p1->y; 469 e1 = PICTURE; 470 while ( !DBNullelt(e1) ) 471 { 472 if ( DBBounded(e1, x1, y1, x2, y2) ) 473 { 474 DBAddSet(e1); 475 DISDisplaySet(e1); 476 } /* end if */ 477 e1 = DBNextElt(e1); 478 } /* end while */ 479 } /* end SHSetArea */ 480 481 482 SHTranslate() 483 /* 484 * This routine translates the elements in the current set as defined 485 * by points. The translation is accomplished by defining a transformation 486 * matrix and calling DBXform. 487 */ 488 489 { 490 ELT *e1; 491 POINT *p1; 492 float xmat[3][2]; 493 494 if (SEQ < 2) /* not enough points */ 495 { 496 error(nopnt); 497 return; 498 } 499 if (DBNullelt(cset)) 500 { 501 error(noset); 502 return; 503 } 504 p1 = PTNextPoint(POINTLIST); 505 xmat[0][0] = xmat[1][1] = 1; /* set up translation matrix */ 506 xmat[1][0] = xmat[0][1] = 0; 507 xmat[2][0] = p1->x - POINTLIST->x; 508 xmat[2][1] = p1->y - POINTLIST->y; 509 e1 = cset; 510 while ( !DBNullelt(e1) ) 511 { 512 DISScreenErase(e1, (linemask | setmask)); 513 TxMsgOK(); 514 DBXform(e1, xmat, &PICTURE); 515 DISScreenAdd(e1, (linemask | setmask)); 516 e1 = DBNextofSet(e1); 517 } /* end while */ 518 CHANGED = TRUE; 519 } /* end SHTranslate */ 520 521 522 SHCopy() 523 /* 524 * This routine copies the elements in the current set as defined 525 * by points. To copy, the current set pointer is cleared so that new 526 * elements as added by DBCopy can be used to comprise the new current 527 * set. A pointer is maintained to the old current set which is traversed 528 * to determine the elements to be copied. This process continues for all 529 * points specified. 530 * 531 * NOTE: This assumes that the DBClearSet routine does not alter the 532 * pointers between elements in the set (which is currently true), 533 * and must be changed it this does not hold. 534 */ 535 536 { 537 ELT *e1, *e2; 538 POINT *p1, *p2; 539 float xmat[3][2]; 540 541 if (SEQ < 2) /* not enough points */ 542 { 543 error(nopnt); 544 return; 545 } 546 if (DBNullelt(cset)) 547 { 548 error(noset); 549 return; 550 } 551 p1 = POINTLIST; 552 p2 = PTNextPoint(POINTLIST); 553 while ( !Nullpoint(p2) ) 554 { 555 xmat[0][0] = xmat[1][1] = 1; /* set up translation matrix */ 556 xmat[1][0] = xmat[0][1] = 0; 557 xmat[2][0] = p2->x - p1->x; 558 xmat[2][1] = p2->y - p1->y; 559 DISClearSetDisplay(); 560 e1 = cset; 561 DBClearSet(); /* Dependent on Clearset preserving pointers */ 562 while ( !DBNullelt(e1) ) 563 { 564 e2 = DBCopy(e1, xmat, &PICTURE); 565 DBAddSet(e2); 566 DISScreenAdd(e2, (linemask | setmask)); 567 e1 = DBNextofSet(e1); 568 } /* end while ! null elt */ 569 p1 = p2; 570 p2 = PTNextPoint(p2); 571 } /* end while ! null point */ 572 CHANGED = TRUE; 573 } /* end SHCopy */ 574 575 576 SHRotate() 577 /* 578 * This routine rotates the elements in the current set as defined 579 * by points. The rotation is accomplished by defining a transformation 580 * matrix and calling DBXform. 581 */ 582 583 { 584 ELT *e1; 585 POINT pos, *p1, *p2; 586 float xmat[3][2], angle, s, c; 587 int i, j; 588 589 if (SEQ < 3) /* not enough points */ 590 { 591 error(nopnt); 592 return; 593 } 594 if (DBNullelt(cset)) 595 { 596 error(noset); 597 return; 598 } 599 p1 = PTNextPoint(POINTLIST); /* calculate rotation angle */ 600 p2 = PTNextPoint(p1); 601 angle = (float) atan2((p2->x - POINTLIST->x),(p2->y - POINTLIST->y)) 602 -(float) atan2((p1->x - POINTLIST->x),(p1->y - POINTLIST->y)); 603 s = (float) sin(angle); 604 c = (float) cos(angle); 605 606 /* Define transformation matrix to translate set to origin, rotate, 607 and translate back. */ 608 609 xmat[0][0] = c; 610 xmat[0][1] = -s; 611 xmat[1][0] = s; 612 xmat[1][1] = c; 613 xmat[2][0] = (-c) * POINTLIST->x - s * POINTLIST->y + POINTLIST->x; 614 xmat[2][1] = (-c) * POINTLIST->y + s * POINTLIST->x + POINTLIST->y; 615 e1 = cset; 616 while ( !DBNullelt(e1) ) 617 { 618 DISScreenErase(e1, (linemask | setmask)); 619 TxMsgOK(); 620 DBXform(e1, xmat, &PICTURE); 621 if (TEXT(e1->type)) 622 { 623 GRsetwmask(textmask | setmask); 624 p1 = e1->ptlist; 625 GRPutText(e1->type, p1, e1->brushf, 626 e1->size,e1->textpt, &pos); 627 i= strlen(e1->textpt); 628 p2 = PTInit(); 629 (void) PTMakePoint(p1->x, p1->y, &p2); 630 /* add extra positioning points */ 631 (void) PTMakePoint(pos.x, pos.y, &p2); 632 (void) PTMakePoint(pos.x + i * charxsize / 2, 633 pos.y, &p2); 634 (void) PTMakePoint(pos.x + i * charxsize, 635 pos.y, &p2); 636 e1->ptlist = p2; 637 } /* end if TEXT */ 638 else 639 DISScreenAdd(e1, (linemask | setmask)); 640 e1 = DBNextofSet(e1); 641 } /* end while */ 642 CHANGED = TRUE; 643 } /* end SHRotate */ 644 645 646 SHScale() 647 /* 648 * This routine scales the elements in the current set as defined 649 * by points. The scaling is accomplished by defining a transformation 650 * matrix and calling DBXform. 651 */ 652 653 { 654 ELT *e1; 655 POINT pos, *p1, *p2; 656 float xmat[3][2], d1, d2, scalex, scaley; 657 int i, j; 658 659 if (SEQ < 3) /* not enough points */ 660 { 661 error(nopnt); 662 return; 663 } 664 if (DBNullelt(cset)) 665 { 666 error(noset); 667 return; 668 } 669 p1 = PTNextPoint(POINTLIST); 670 p2 = PTNextPoint(p1); 671 d1 = sqrt( pow((p1->x - POINTLIST->x), 2.0) 672 + pow((p1->y - POINTLIST->y), 2.0)); 673 d2 = sqrt( pow((p2->x - POINTLIST->x), 2.0) 674 + pow((p2->y - POINTLIST->y), 2.0)); 675 if (d1 == 0) 676 { 677 error("infinite scale"); 678 return; 679 } 680 scalex = scaley = d2 / d1; 681 682 /* create transformation matrix to translate set to origin, 683 performaing the scaling and translating back */ 684 685 xmat[0][0] = scalex; 686 xmat[1][1] = scaley; 687 xmat[1][0] = xmat[0][1] = 0; 688 xmat[2][0] = - POINTLIST->x * (scalex - 1.0); 689 xmat[2][1] = - POINTLIST->y * (scaley - 1.0); 690 e1 = cset; 691 while ( !DBNullelt(e1) ) 692 { 693 DISScreenErase(e1, (linemask | setmask)); 694 TxMsgOK(); 695 DBXform(e1, xmat, &PICTURE); 696 if (TEXT(e1->type)) 697 { 698 GRsetwmask(textmask | setmask); 699 p1 = e1->ptlist; 700 GRPutText(e1->type, p1, e1->brushf, 701 e1->size,e1->textpt, &pos); 702 i= strlen(e1->textpt); 703 p2 = PTInit(); 704 (void) PTMakePoint(p1->x, p1->y, &p2); 705 /* add extra positioning points */ 706 (void) PTMakePoint(pos.x, pos.y, &p2); 707 (void) PTMakePoint(pos.x + i * charxsize / 2, 708 pos.y, &p2); 709 (void) PTMakePoint(pos.x + i * charxsize, 710 pos.y, &p2); 711 e1->ptlist = p2; 712 } /* end if TEXT */ 713 else 714 DISScreenAdd(e1, (linemask | setmask)); 715 e1 = DBNextofSet(e1); 716 } /* end while */ 717 CHANGED = TRUE; 718 } /* end SHScale */ 719 720 721 SHUpdate() 722 /* 723 * This routine redraws the graphics screen by clearing the screen , 724 * redisplaying the menu and adding each element back to the display. 725 */ 726 727 { 728 ELT *e1; 729 int i; 730 731 GRClear(linemask | setmask | textmask); 732 MNDisplayMenu(); 733 e1 = PICTURE; 734 while ( !DBNullelt(e1) ) 735 { 736 DISScreenAdd(e1, linemask); 737 e1 = DBNextElt(e1); 738 }; 739 e1 = cset; 740 while ( !DBNullelt(e1) ) 741 { 742 DISScreenAdd(e1, setmask); 743 e1 = DBNextofSet(e1); 744 }; 745 if ( Adjustment != NOADJ) MNHighLt(HiMode[adj[Adjustment]], hicolor); 746 if (GravityOn) MNHighLt(HiMode[3], hicolor); /* re highlight */ 747 MNHighLt(HiFont[CFONT-1], hicolor); /* selected menu */ 748 MNHighLt(HiBrush[CBRUSH-1], hicolor); /* menu attributes */ 749 for (i = 0; i < NUSER; ++i) 750 if ( !DBNullelt(MEN[i]) ) MNHighLt(HiMen[i], hicolor); 751 Consume = FALSE; 752 } /* end SHUpdate */ 753 754 755 SHRedis() 756 /* 757 * This routine is used to redisplay the text screen. 758 * It clears the screen, then redisplays the text and each of the 759 * defined fields. 760 */ 761 762 { 763 char string[4]; 764 765 TxRedisplay(); 766 TxPutString(&TEdit, Editfile); 767 (void) sprintf(string,"%1d",CBRUSH); 768 TxPutString(&TBrush,string); 769 (void) sprintf(string, "%1d",CFONT); 770 TxPutString(&TFont,string); 771 (void) sprintf(string, "%1d",CSIZE); 772 TxPutString(&TCSize,string); 773 TxPutString(&TJustmode,dispmode[CJUST]); 774 (void) sprintf(string, "%3d",Alignment); 775 TxPutString(&TAlign,string); 776 (void) sprintf(string,"%1d",CBRUSH); 777 TxPutString(&TBrush,string); 778 if (GravityOn) TxPutString(&TGravity, " ON"); 779 else TxPutString(&TGravity, "OFF"); 780 switch(Adjustment) 781 { 782 case NOADJ: TxPutString(&TAdjust, "NO ADJUSTMENT"); 783 break; 784 case HORZ: TxPutString(&TAdjust, " HORIZONTAL "); 785 break; 786 case VERT: TxPutString(&TAdjust, " VERTICAL "); 787 break; 788 case MAN: TxPutString(&TAdjust, " MANHATTAN "); 789 break; 790 } /* end switch */; 791 Consume = FALSE; 792 } /* end SHRedis */ 793 794 795 SHShellEsc() 796 /* 797 * This routine performs a shell escape through the c 'system' 798 * function. It first retrieves the command line through TxGetLine. 799 */ 800 801 { 802 char line[80]; 803 804 TxGetLine("!",line,80); 805 TxClose(); /* Restore text terminal to 'normal' state */ 806 (void) system(line); /* do command */ 807 /* allow time for user to digest command */ 808 printf("Type <cr> to continue"); 809 (void) fflush(stdout); 810 line[1] = TxGetChar(); 811 SHRedis(); /* reclaim terminal */ 812 } /* end ShellEsc */ 813 814 815 static savemen(sym) 816 int sym; 817 /* 818 * This local routine stores the current set in the specified 819 * user symbol. 820 */ 821 822 { 823 ELT *elist; 824 float xmat[3][2]; 825 826 xmat[0][0] = xmat[1][1] = 1; /* set up copy transformation */ 827 xmat[0][1] = xmat[1][0] = 0; /* matrix for no */ 828 xmat[2][0] = xmat[2][1] = 0; /* transformation */ 829 while ( !DBNullelt(MEN[sym]) ) 830 { /* clear out existing symbol */ 831 elist = DBNextElt(MEN[sym]); 832 DBClearElt(MEN[sym]); 833 MEN[sym] = elist; 834 }; 835 elist = cset; /* copy current set to symbol */ 836 while ( !DBNullelt(elist) ) 837 { 838 (void) DBCopy(elist, xmat, &(MEN[sym])); 839 elist = DBNextofSet(elist); 840 } /* end while */; 841 if (SEQ == 0) /* no positioning points */ 842 { 843 MENPOINT[sym].x = 0; 844 MENPOINT[sym].y = 0; 845 } 846 else 847 { 848 MENPOINT[sym].x = POINTLIST->x; 849 MENPOINT[sym].y = POINTLIST->y; 850 } 851 if ( !DBNullelt(MEN[sym]) ) MNHighLt(HiMen[sym], hicolor); 852 else MNUnHighLt(HiMen[sym]); 853 CHANGED = TRUE; 854 } /* end savemen */ 855 856 SHSave1() 857 /* 858 * This routine saves the current set in user symbol 1 by 859 * calling savemen. 860 */ 861 862 { 863 savemen(0); 864 } 865 866 SHSave2() 867 /* 868 * This routine saves the current set in user symbol 2 by 869 * calling savemen. 870 */ 871 872 { 873 savemen(1); 874 } 875 876 SHSave3() 877 /* 878 * This routine saves the current set in user symbol 3 by 879 * calling savemen. 880 */ 881 882 { 883 savemen(2); 884 } 885 886 SHSave4() 887 /* 888 * This routine saves the current set in user symbol 4 by 889 * calling savemen. 890 */ 891 892 { 893 savemen(3); 894 } 895 896 897 898 SHBox() 899 /* 900 * This routine creates and displays a rectangle whose diagonal is 901 * defined by two points. The routine uses the coordinates of these 902 * points to define a VECTOR element with the appropriate vertices. 903 */ 904 905 { 906 POINT *plist, *p1, *p2; 907 char *txt; 908 ELT *e1; 909 910 if (SEQ < 2) 911 { 912 error("not enough points"); 913 return; 914 } 915 p1 = POINTLIST; 916 p2 = PTNextPoint(p1); 917 plist = PTInit(); /* create points for vector element which defines 918 the rectangle */ 919 (void) PTMakePoint(p1->x, p1->y, &plist); 920 (void) PTMakePoint(p1->x, p2->y, &plist); 921 (void) PTMakePoint(p2->x, p2->y, &plist); 922 (void) PTMakePoint(p2->x, p1->y, &plist); 923 (void) PTMakePoint(p1->x, p1->y, &plist); /* close rectangle */ 924 txt = malloc(1); 925 *txt = '\0'; 926 DBClearSet(); /* clear old set in preparation to make */ 927 DISClearSetDisplay(); /* the new current set */ 928 e1 = DBCreateElt(VECTOR, plist, CBRUSH, 0, txt, &PICTURE); 929 DBAddSet(e1); 930 DISScreenAdd(e1, (linemask | setmask)); 931 CHANGED = TRUE; 932 } /* end LGBox */ 933 934 SHArrow() 935 /* 936 * This routine draws arrow heads by 'copying' the arrow head template 937 * into the picture appropriately transformed. 938 */ 939 940 { 941 ELT *e1; 942 POINT p1, *p2; 943 float xmat[3][2], angle, s, c; 944 945 if (SEQ < 2) /* not enough points */ 946 { 947 error(nopnt); 948 return; 949 } 950 p1.x = POINTLIST->x - 1; 951 p1.y = POINTLIST->y; 952 p2 = PTNextPoint(POINTLIST); 953 angle = (float) atan2((p2->x - POINTLIST->x),(p2->y - POINTLIST->y)) 954 -(float) atan2((p1.x - POINTLIST->x),(p1.y - POINTLIST->y)); 955 s = (float) sin(angle); 956 c = (float) cos(angle); 957 958 /* Define transformation matrix to translate element from origin 959 and rotate. */ 960 961 xmat[0][0] = c; 962 xmat[0][1] = -s; 963 xmat[1][0] = s; 964 xmat[1][1] = c; 965 xmat[2][0] = POINTLIST->x; 966 xmat[2][1] = POINTLIST->y; 967 968 DBClearSet(); /* clear old set in preparation to make */ 969 DISClearSetDisplay(); /* the new current set */ 970 arhead.brushf = CBRUSH; 971 e1 = DBCopy(&arhead, xmat, &PICTURE); 972 DBAddSet(e1); 973 DISScreenAdd(e1, (linemask | setmask)); 974 CHANGED = TRUE; 975 } /* end SHArrow */ 976