1 /***************************************************************************
2 SCED - Schematic Capture Editor
3 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
4 Copyright 1990 Regents of the University of California.  All rights reserved.
5 Authors: 1981 Giles C. Billingsley  (parts of KIC layout editor)
6          1992 Stephen R. Whiteley
7 ****************************************************************************/
8 
9 /*
10  * SCED viewport management code.
11  *
12  */
13 
14 #include "spice.h"
15 #include "sced.h"
16 #include "scedmacs.h"
17 
18 /* for point marks */
19 struct mark {
20     long X;
21     long Y;
22     int Delta;
23     int Type;
24     int Orient;
25     struct mark *next;
26 };
27 
28 #ifdef __STDC__
29 static int  get_menu_index(MENU*,char*);
30 static void fix_menu_entry_prefix(MENU*,int);
31 static void display_menu_entry(MENU*,int);
32 static void display_selected_entry(MENU*,int);
33 static void mark_object(struct o*);
34 static void show_mark(struct mark*,int);
35 static void gp_mark(int,int,int,int,int,int);
36 static int  my_strnicmp(char*,char*,int);
37 #else
38 static int  get_menu_index();
39 static void fix_menu_entry_prefix();
40 static void display_menu_entry();
41 static void display_selected_entry();
42 static void mark_object();
43 static void show_mark();
44 static void gp_mark();
45 static int  my_strnicmp();
46 #endif
47 
48 /***********************************************************************
49  *
50  * Routines used to process cursor data.
51  *
52  *
53  ***********************************************************************/
54 
55 /* also see macros in coords.h */
56 
57 
58 void
PToL(Window,X,Y)59 PToL(Window,X,Y)
60 
61 /* convert viewport to window coordinates */
62 struct ka *Window;
63 long *X, *Y;
64 {
65     if (Window == View->kvCoarseWindow) {
66         *X = .5+(*X - View->kvCoarseViewport->kaLeft)/
67             View->kvCoarseRatio;
68         *X += Window->kaLeft;
69         *Y = .5+(*Y - View->kvCoarseViewport->kaBottom)/
70             View->kvCoarseRatio;
71         *Y += Window->kaBottom;
72     }
73     elif (Window == View->kvFineWindow) {
74         *X = .5+(*X - View->kvFineViewport->kaLeft)/
75             View->kvFineRatio;
76         *X += Window->kaLeft;
77         *Y = .5+(*Y - View->kvFineViewport->kaBottom)/
78             View->kvFineRatio;
79         *Y += Window->kaBottom;
80     }
81     else {
82         *X = *Y = 0;
83         return;
84     }
85 }
86 
87 
88 void
ClipToGridPoint(x,y)89 ClipToGridPoint(x,y)
90 
91 /* Clip to nearest window grid coordinate */
92 long *x,*y;
93 {
94 
95     long k;
96 
97     /* snap to grid/2 points */
98     k = Parameters.kpGrid/2;
99 
100     if (*x > 0)
101         *x = ((*x+k/2)/k)*k;
102     else
103         *x = ((*x-k/2)/k)*k;
104 
105     if (*y > 0)
106         *y = ((*y+k/2)/k)*k;
107     else
108         *y = ((*y-k/2)/k)*k;
109 }
110 
111 
112 /***********************************************************************
113  *
114  * Routines to dislay and manipulate menus.
115  *
116  *
117  ***********************************************************************/
118 
119 
120 void
ShowCommandMenu()121 ShowCommandMenu()
122 
123 {
124     if (Parameters.kpMenu == BASICMENU) {
125         ShowMenu(BasicMenu);
126         return;
127     }
128     if (Parameters.kpMenu == AMBIGUITYMENU) {
129         ShowMenu(AmbiguityMenu);
130         return;
131     }
132 }
133 
134 
135 void
ShowMenu(Menu)136 ShowMenu(Menu)
137 
138 MENU *Menu;
139 {
140     int Int1,Int2;
141 
142     /*
143      * Erase the entire menu viewport.
144      */
145     OutlineText((int)MenuViewport.kaLeft,(int)MenuViewport.kaBottom,
146     (int)MenuViewport.kaRight,(int)MenuViewport.kaTop,FILL,ERASE,0);
147     /*
148      * Display Menu Table
149      */
150     for (Int1 = 0; ; Int1++) {
151         if (Menu[Int1].mEntry == NULL) break;
152         if (Menu[Int1].mActive)
153             display_selected_entry(Menu,Int1);
154         else
155             display_menu_entry(Menu,Int1);
156     }
157     if (Menu == BasicMenu) {
158         Int2 = Int1;
159         if (Int2 < MenuViewport.kaY)
160             Int2 = MenuViewport.kaY;
161         for (Int1 = 0; ; Int1++) {
162             if (DeviceMenu[Int1].mEntry == NULL) break;
163             if (DeviceMenu[Int1].mActive)
164                 display_selected_entry(DeviceMenu-Int2,Int1+Int2);
165             else
166                 display_menu_entry(DeviceMenu-Int2,Int1+Int2);
167         }
168     }
169     DevUpdate();
170 }
171 
172 
173 MENU *
GetCurrentMenu()174 GetCurrentMenu()
175 
176 {
177     if (Parameters.kpMenu == BASICMENU)
178         return (BasicMenu);
179     if (Parameters.kpMenu == AMBIGUITYMENU)
180         return (AmbiguityMenu);
181     return (NULL);
182 }
183 
184 
185 void
AlterMenuEntries(Word1,Word2)186 AlterMenuEntries(Word1,Word2)
187 
188 /* Change all the entries of Word1 in the menus to Word2. */
189 char *Word1,*Word2;
190 {
191     int i;
192 
193     i = get_menu_index(BasicMenu,Word1);
194     if (i >= 0) {
195         BasicMenu[i].mEntry = Word2;
196         fix_menu_entry_prefix(BasicMenu,i);
197     }
198     i = get_menu_index(AmbiguityMenu,Word1);
199     if (i >= 0) {
200         AmbiguityMenu[i].mEntry = Word2;
201         fix_menu_entry_prefix(AmbiguityMenu,i);
202     }
203 }
204 
205 
206 void
MenuSelect(Selection)207 MenuSelect(Selection)
208 
209 char *Selection;
210 {
211     int Int1;
212 
213     Int1 = get_menu_index(BasicMenu,Selection);
214     if (Int1 >= 0) {
215         BasicMenu[Int1].mActive = True;
216         if (Parameters.kpMenu == BASICMENU)
217             display_selected_entry(BasicMenu,Int1);
218     }
219     Int1 = get_menu_index(AmbiguityMenu,Selection);
220     if (Int1 >= 0) {
221         AmbiguityMenu[Int1].mActive = True;
222         if (Parameters.kpMenu == AMBIGUITYMENU)
223             display_selected_entry(AmbiguityMenu,Int1);
224     }
225 }
226 
227 
228 void
MenuDeselect(Selection)229 MenuDeselect(Selection)
230 
231 char *Selection;
232 {
233     int Int1;
234 
235     Int1 = get_menu_index(BasicMenu,Selection);
236     if (Int1 >= 0) {
237         BasicMenu[Int1].mActive = False;
238         if (Parameters.kpMenu == BASICMENU)
239             display_menu_entry(BasicMenu,Int1);
240     }
241     Int1 = get_menu_index(AmbiguityMenu,Selection);
242     if (Int1 >= 0) {
243         AmbiguityMenu[Int1].mActive = False;
244         if (Parameters.kpMenu == AMBIGUITYMENU)
245             display_menu_entry(AmbiguityMenu,Int1);
246     }
247 }
248 
249 
250 void
MenuSelectDev(Selection)251 MenuSelectDev(Selection)
252 
253 char *Selection;
254 {
255     int Int1,Int2;
256 
257     Int1 = get_menu_index(DeviceMenu,Selection);
258     if (Int1 >= 0) {
259         for (Int2 = 0; ; Int2++)
260             if (BasicMenu[Int2].mEntry == NULL) break;
261         if (Int2 < MenuViewport.kaY)
262             Int2 = MenuViewport.kaY;
263         DeviceMenu[Int1].mActive = True;
264         display_selected_entry(DeviceMenu-Int2,Int1+Int2);
265     }
266 }
267 
268 
269 void
MenuDeselectDev(Selection)270 MenuDeselectDev(Selection)
271 
272 char *Selection;
273 {
274     int Int1,Int2;
275 
276     Int1 = get_menu_index(DeviceMenu,Selection);
277     if (Int1 >= 0) {
278         for (Int2 = 0; ; Int2++)
279             if (BasicMenu[Int2].mEntry == NULL) break;
280         if (Int2 < MenuViewport.kaY)
281             Int2 = MenuViewport.kaY;
282         DeviceMenu[Int1].mActive = False;
283         display_menu_entry(DeviceMenu-Int2,Int1+Int2);
284     }
285 }
286 
287 
288 void
FixMenuPrefix(Menu)289 FixMenuPrefix(Menu)
290 
291 MENU *Menu;
292 {
293     int i;
294 
295     for (i = 0; Menu[i].mEntry; i++)
296         fix_menu_entry_prefix(Menu,i);
297 }
298 
299 
300 static void
fix_menu_entry_prefix(Menu,Index)301 fix_menu_entry_prefix(Menu,Index)
302 
303 /* Find a unique prefix for the menu entry and save it
304  * in the mPrefix field.
305  */
306 MENU *Menu;
307 int Index;
308 {
309     int Count;
310     char m1[32], m2[32];
311     int j,k;
312 
313     memset(Menu[Index].mPrefix,0,6);
314 
315     Count = 1;
316     strcpy(m1,Menu[Index].mEntry);
317     for (j = 0; Menu[j].mEntry; j++) {
318         if (Index == j) continue;
319         strcpy(m2,Menu[j].mEntry);
320         if (cieq(m1,m2)) {
321             if (*Menu[Index].mEntry != ' ')
322                 for (k = j; Menu[k].mEntry; k++) {
323                     strcpy(Menu[k].mPrefix,Menu[k+1].mPrefix);
324                     Menu[k].mEntry = Menu[k+1].mEntry;
325                     Menu[k].mActive = Menu[k+1].mActive;
326                 }
327             continue;
328         }
329         while (!my_strnicmp(m1,m2,Count))
330             Count++;
331     }
332     if (Count > 5) Count = 5;
333     while (Count--)
334         Menu[Index].mPrefix[Count] = Menu[Index].mEntry[Count];
335 }
336 
337 
338 static int
get_menu_index(Menu,String)339 get_menu_index(Menu,String)
340 
341 MENU *Menu;
342 char *String;
343 {
344     int i = 0;
345 
346     while (Menu[i].mEntry != NULL) {
347         if (!strcmp(Menu[i].mEntry,String)) return (i);
348         i++;
349     }
350     return (-1);
351 }
352 
353 
354 static void
display_menu_entry(Menu,Index)355 display_menu_entry(Menu,Index)
356 
357 MENU *Menu;
358 int Index;
359 {
360     char MenuSelection[8],*prefix;
361     int Left;
362 
363     strncpy(MenuSelection,Menu[Index].mEntry,MenuViewport.kaX);
364     MenuSelection[MenuViewport.kaX] = '\0';
365     prefix = Menu[Index].mPrefix;
366 
367     Index += MenuViewport.kaTop;
368     Left = MenuViewport.kaLeft;
369     if (Index > MenuViewport.kaY) {
370         Left += 6;
371         Index -= MenuViewport.kaY;
372     }
373     /*
374      * Erase highlight box.
375      */
376     OutlineText(Left,Index,Left+4,Index,FILL,ERASE,0);
377     /*
378      * Redisplay menu selection.
379      */
380     DevSetColor(MenuTextColor);
381     FBText(ROW_COLUMN,Index,Left,MenuSelection);
382 
383     DevSetColor(MenuTextPrefixColor);
384     FBText(ROW_COLUMN,Index,Left,prefix);
385 }
386 
387 
388 static void
display_selected_entry(Menu,Index)389 display_selected_entry(Menu,Index)
390 
391 MENU *Menu;
392 int Index;
393 {
394     char MenuSelection[8], *prefix;
395     int Left;
396 
397     strncpy(MenuSelection,Menu[Index].mEntry,MenuViewport.kaX);
398     MenuSelection[MenuViewport.kaX] = '\0';
399     prefix = Menu[Index].mPrefix;
400 
401     Index += MenuViewport.kaTop;
402     Left = MenuViewport.kaLeft;
403     if (Index > MenuViewport.kaY) {
404         Left += 6;
405         Index -= MenuViewport.kaY;
406     }
407     /*
408      * Erase Menu command
409      */
410     OutlineText(Left,Index,Left+4,Index,FILL,ERASE,0);
411 
412     /*
413      * Display highlight box.
414      */
415     OutlineText(Left,Index,Left+4,Index,FILL,DISPLAY,
416         MenuHighlightingColor);
417 
418     /*
419      * Redisplay menu selection.
420      */
421     DevSetColor(MenuSelectedColor);
422     FBText(ROW_COLUMN,Index,Left,MenuSelection);
423 
424     DevSetColor(MenuSelectedPrefixColor);
425     FBText(ROW_COLUMN,Index,Left,prefix);
426 }
427 
428 
429 /***********************************************************************
430  *
431  * Routines to display message text.
432  *
433  *
434  ***********************************************************************/
435 
436 static char BackPrompt[200];
437 static char BackColor;
438 
439 
440 void
ShowPrompt(Prompt)441 ShowPrompt(Prompt)
442 
443 char *Prompt;
444 {
445     ShowPromptWithColor(Prompt,PromptTextColor);
446 }
447 
448 
449 void
ShowPromptAndWait(cp)450 ShowPromptAndWait(cp)
451 
452 char *cp;
453 {
454     putchar('\007');
455     fflush(stdout);
456     ShowPrompt(cp);
457     sleep(2);
458 }
459 
460 
461 void
ShowPromptWithColor(Prompt,Color)462 ShowPromptWithColor(Prompt,Color)
463 
464 char *Prompt;
465 int Color;
466 {
467     /*
468      * Implements a basic scroller in a prompt window.
469      * Displays MORE when window is full and continues when
470      * user hits and key.
471      */
472     char *cp;
473     char *TypeIn;
474     char buffer[200];
475     int Int1;
476     int Row;
477 
478     Row = gi_numtextrows;
479     ErasePrompt();
480     DevSetColor(Color);
481     BackColor = Color;
482     cp = Prompt;
483     Int1 = 0;
484     while (*cp != EOS) {
485         buffer[Int1] = *cp++;
486         if (buffer[Int1] == '\n')
487             buffer[Int1] = EOS;
488         Int1++;
489         if (*cp == EOS) {
490             buffer[Int1++] = EOS;
491             strcpy(BackPrompt,buffer);
492             FBText(ROW_COLUMN,Row,1,buffer);
493             DevUpdate();
494             Parameters.kpLastCursorColumn = strlen(buffer) + 1;
495         }
496         elif ((Int1 > gi_numtextcols - 8) Or (Int1 > 190)) {
497             sprintf(&buffer[Int1]," MORE");
498             strcpy(BackPrompt,buffer);
499             FBText(ROW_COLUMN,Row,1,buffer);
500             DevUpdate();
501             Parameters.kpLastCursorColumn = strlen(buffer);
502             (void)FBGetchar(ERASE);
503             ErasePrompt();
504             DevSetColor(Color);
505             Int1 = 0;
506         }
507     }
508 }
509 
510 
511 void
RedrawPrompt()512 RedrawPrompt()
513 
514 {
515     if (BackPrompt[0] == '\0') return;
516     DevSetColor(BackColor);
517     FBText(ROW_COLUMN,gi_numtextrows,1,BackPrompt);
518     Parameters.kpLastCursorColumn = 1 + strlen(BackPrompt);
519 }
520 
521 
522 void
AppendToOldPrompt(c)523 AppendToOldPrompt(c)
524 
525 char c;
526 {
527     char s[4];
528 
529     s[0] = ' ';
530     s[1] = s[0];
531     s[2] = c;
532     s[3] = '\0';
533     strcat(BackPrompt,s);
534 }
535 
536 
537 void
ErasePrompt()538 ErasePrompt()
539 
540 {
541     OutlineText(1,gi_numtextrows,gi_numtextcols,
542         gi_numtextrows,FILL,ERASE,0);
543     Parameters.kpLastCursorColumn = 1;
544     BackPrompt[0] = '\0';
545     DevUpdate();
546 }
547 
548 
549 void
OutlineText(Left,Bottom,Right,Top,Type,DisplayOrErase,Pixel)550 OutlineText(Left,Bottom,Right,Top,Type,DisplayOrErase,Pixel)
551 
552 int Left,Bottom,Right,Top,Pixel;
553 char Type,DisplayOrErase;
554 {
555     /*
556      * Outline the box defined by LeftColumn, BottomRow, RightColumn, and
557      * TopRow in the color associated with Pixel.
558      */
559 
560     Bottom = gi_maxy-Bottom*gi_fntheight;
561     if (Bottom < 0) Bottom = 0;
562     Top = gi_maxy-(Top-1)*gi_fntheight;
563     if (Top > gi_maxy) Top = gi_maxy;
564     Left = (Left-1) * gi_fntwidth;
565     Right = (Right * gi_fntwidth) + 1;
566     if (Type == OUTLINE) {
567         ++Bottom;
568         --Top;
569     }
570     FBBox(Pixel,DisplayOrErase,Type,Left,Bottom,Right,Top-1);
571 }
572 
573 
574 /***********************************************************************
575  *
576  * Routines to dislay and erase viewports.
577  *
578  *
579  ***********************************************************************/
580 
581 
582 void
EraseLargeCoarseViewport()583 EraseLargeCoarseViewport()
584 
585 {
586     FBEraseBox(View->kvLargeCoarseViewport->kaLeft-1,
587         View->kvLargeCoarseViewport->kaBottom-1,
588         View->kvLargeCoarseViewport->kaRight,
589         View->kvLargeCoarseViewport->kaTop);
590 }
591 
592 
593 void
EraseFineViewport()594 EraseFineViewport()
595 
596 {
597     /*
598      * Erase fine positioning window in coarse window and patch
599      * up the hole.  'c' will disable showing of fine positioning
600      * window in Redisplay.
601      */
602     Parameters.kpRedisplayControl = COARSEVIEWPORTONLY;
603     EraseBox(View->kvFineWindow);
604     Redisplay(View->kvFineWindow);
605     Parameters.kpRedisplayControl = SPLITSCREEN;
606 }
607 
608 
609 void
ShowFineViewport()610 ShowFineViewport()
611 
612 {
613     if (Parameters.kpRedisplayControl == COARSEVIEWPORTONLY) {
614         EraseLargeCoarseViewport();
615         Redisplay(View->kvCoarseWindow);
616     }
617     else {
618         FBEraseBox(View->kvFineViewport->kaLeft-1,
619             View->kvFineViewport->kaBottom-1,
620             View->kvFineViewport->kaRight,
621             View->kvFineViewport->kaTop);
622         /* Show fine positioning window in coarse window. */
623         ShowEmptyBox(HighlightingColor,View->kvFineWindow);
624         /* Redisplay in magnifying glass. */
625         Parameters.kpRedisplayControl = FINEVIEWPORTONLY;
626         Redisplay(View->kvFineWindow);
627         Parameters.kpRedisplayControl = SPLITSCREEN;
628     }
629     DevUpdate();
630 }
631 
632 
633 /***********************************************************************
634  *
635  * Routines to dislay and erase marked objects and points.
636  *
637  *
638  ***********************************************************************/
639 
640 
641 void
ShowCurrentObject(Pointer,DisplayOrErase)642 ShowCurrentObject(Pointer,DisplayOrErase)
643 
644 struct o *Pointer;
645 char DisplayOrErase;
646 {
647     struct ka AOI;
648     static struct ks *ObjQ;
649     struct ks *q,*qq;
650 
651     if (Pointer == NULL) {
652         for (q = ObjQ; q; q = qq) {
653             qq = q->ksSucc;
654             if (DisplayOrErase == DISPLAY)
655                 mark_object(q->ksPointer);
656             else {
657                 CDBB(Parameters.kpCellDesc,q->ksPointer,&AOI.kaLeft,
658                     &AOI.kaBottom,&AOI.kaRight,&AOI.kaTop);
659                 EraseBox(&AOI);
660                 ObjQ = NULL;
661                 Redisplay(&AOI);
662                 tfree(q);
663             }
664         }
665         SetCurrentAOI(View->kvCoarseWindow);
666         DevUpdate();
667         return;
668     }
669 
670     if (DisplayOrErase == DISPLAY) {
671         mark_object(Pointer);
672         q = alloc(ks);
673         if (q == NULL) MallocFailed();
674         q->ksPointer = Pointer;
675         q->ksSucc = ObjQ;
676         ObjQ = q;
677     }
678     else {
679         for (qq = NULL,q = ObjQ; q; qq = q,q = q->ksSucc)
680             if (q->ksPointer == Pointer) {
681                 if (qq)
682                     qq->ksSucc = q->ksSucc;
683                 else
684                     ObjQ = q->ksSucc;
685                 tfree(q);
686                 break;
687             }
688         CDBB(Parameters.kpCellDesc,Pointer,&AOI.kaLeft,&AOI.kaBottom,
689             &AOI.kaRight,&AOI.kaTop);
690         EraseBox(&AOI);
691         Redisplay(&AOI);
692     }
693     SetCurrentAOI(View->kvCoarseWindow);
694     DevUpdate();
695 }
696 
697 
698 static void
mark_object(Pointer)699 mark_object(Pointer)
700 
701 struct o *Pointer;
702 {
703     struct ka AOI;
704     struct p *Path;
705     int Layer;
706     long Width;
707 
708 
709     if (Pointer->oType == CDWIRE) {
710         CDWire(Pointer,&Layer,&Width,&Path);
711         ShowWire(HighlightingColor,Width,Path);
712     }
713     else {
714         /*
715          * Show the object with an X through the bounding box.
716          */
717         CDBB(Parameters.kpCellDesc,Pointer,&AOI.kaLeft,&AOI.kaBottom,
718         &AOI.kaRight,&AOI.kaTop);
719         ShowLine(HighlightingColor,AOI.kaLeft,AOI.kaBottom,
720             AOI.kaRight,AOI.kaTop);
721         ShowLine(HighlightingColor,AOI.kaLeft,AOI.kaTop,
722             AOI.kaRight,AOI.kaBottom);
723         ShowEmptyBox(HighlightingColor,&AOI);
724     }
725 }
726 
727 
728 void
ShowMarker(DisplayOrErase,Color,X,Y,Delta,Type,Orient)729 ShowMarker(DisplayOrErase,Color,X,Y,Delta,Type,Orient)
730 
731 char DisplayOrErase;
732 int Color;
733 long X,Y;
734 int Delta;
735 int Type;
736 int Orient;
737 {
738     struct t *TGen;
739     struct ka BB;
740     long X1,Y1,X2,Y2;
741     long DX, DY;
742 
743     /* SRW ** save markers for redraw after screen alteration */
744     static struct mark *mlist;
745     struct mark *mm, *mtmp;
746 
747     /* SRW ** display stored marks */
748     if (!Delta && DisplayOrErase == DISPLAY) {
749         for (mm = mlist; mm; mm = mm->next) {
750             show_mark(mm,Color);
751         }
752         ShowCurrentObject((struct o *)NULL,DISPLAY);
753         return;
754     }
755 
756     /* SRW ** constant size on screen */
757     if (Parameters.kpRedisplayControl == COARSEVIEWPORTONLY)
758         Delta *= View->kvCoarseWindow->kaHeight/100;
759     else
760         Delta *= View->kvFineWindow->kaHeight/50;
761     Delta /= RESOLUTION;
762 
763     if (DisplayOrErase == DISPLAY) {
764         DevSetColor(Color);
765 
766         /* add marker to list */
767         mm = alloc(mark);
768         if (!mm) MallocFailed();
769         mm->X = X;
770         mm->Y = Y;
771         mm->Delta = Delta;
772         mm->Type = Type;
773         mm->Orient = Orient;
774         mm->next = mlist;
775         mlist = mm;
776 
777         show_mark(mm,Color);
778     }
779     else {
780         /* remove from list */
781         for (mtmp = NULL,mm = mlist; mm; mtmp = mm,mm = mm->next) {
782             if (mm->X == X && mm->Y == Y) {
783                 Delta = mm->Delta;
784                 if (mm == mlist) mlist = mm->next;
785                 else mtmp->next = mm->next;
786                 tfree(mm);
787                 break;
788             }
789         }
790         BB.kaLeft = X - Delta;
791         BB.kaRight = X + Delta;
792         BB.kaBottom = Y - Delta;
793         BB.kaTop = Y + Delta;
794         EraseBox(&BB);
795         Redisplay(&BB);
796     }
797     SetCurrentAOI(View->kvCoarseWindow);
798 }
799 
800 
801 static void
show_mark(m,Color)802 show_mark(m,Color)
803 
804 struct mark *m;
805 int Color;
806 {
807     long X, Y;
808     int Delta;
809 
810     X = m->X;
811     Y = m->Y;
812     Delta = m->Delta;
813 
814     /* transform for PUSH */
815     TPoint(&X,&Y);
816 
817     switch (m->Type) {
818         case MARK_ARROW:
819             switch (m->Orient) {
820                 default:
821                 case MARK_UP:
822                     ShowLine(Color,X,Y-Delta,X,Y+Delta);
823                     ShowLine(Color,X-Delta,Y,X,Y+Delta);
824                     ShowLine(Color,X+Delta,Y,X,Y+Delta);
825                     break;
826                 case MARK_RT:
827                     ShowLine(Color,X-Delta,Y,X+Delta,Y);
828                     ShowLine(Color,X,Y+Delta,X+Delta,Y);
829                     ShowLine(Color,X,Y-Delta,X+Delta,Y);
830                     break;
831                 case MARK_DN:
832                     ShowLine(Color,X,Y-Delta,X,Y+Delta);
833                     ShowLine(Color,X-Delta,Y,X,Y-Delta);
834                     ShowLine(Color,X+Delta,Y,X,Y-Delta);
835                     break;
836                 case MARK_LT:
837                     ShowLine(Color,X-Delta,Y,X+Delta,Y);
838                     ShowLine(Color,X,Y+Delta,X-Delta,Y);
839                     ShowLine(Color,X,Y-Delta,X-Delta,Y);
840                     break;
841             }
842             break;
843         case MARK_CROSS:
844             /* cross (no orientation) */
845             ShowLine(Color,X-Delta,Y,X+Delta,Y);
846             ShowLine(Color,X,Y-Delta,X,Y+Delta);
847             break;
848         default:
849             /* graphical post-processor marks */
850             gp_mark(m->Type,Color,X,Y,Delta,m->Orient);
851             break;
852     }
853 }
854 
855 
856 static void
gp_mark(c,Color,x,y,delta,orient)857 gp_mark(c,Color,x,y,delta,orient)
858 
859 int c, Color, x, y, delta, orient;
860 {
861     int x0, x1, y0, y1, y2;
862     struct ka AOI;
863 
864     delta /= 2;
865     x0 = x - delta;
866     x1 = x + delta;
867     y0 = y - delta;
868     y1 = y;
869     y2 = y + delta;
870 
871     AOI.kaLeft = x0;
872     AOI.kaRight = x1;
873     AOI.kaTop = y2;
874     AOI.kaBottom = y0;
875 
876     switch (orient) {
877         case MARK_NONE:
878             EraseBox(&AOI);
879             ShowLine(Color,x0,y2,x1,y2);
880             ShowLine(Color,x1,y2,x1,y0);
881             ShowLine(Color,x1,y0,x0,y0);
882             ShowLine(Color,x0,y0,x0,y2);
883             break;
884         case MARK_UP: /* up */
885             AOI.kaTop += delta;
886             EraseBox(&AOI);
887             ShowLine(Color,x0,y2,(x0+x1)/2,y2+delta);
888             ShowLine(Color,(x0+x1)/2,y2+delta,x1,y2);
889             ShowLine(Color,x1,y2,x1,y0);
890             ShowLine(Color,x1,y0,x0,y0);
891             ShowLine(Color,x0,y0,x0,y2);
892             break;
893         case MARK_RT: /* right */
894             AOI.kaRight += delta;
895             EraseBox(&AOI);
896             ShowLine(Color,x0,y2,x1,y2);
897             ShowLine(Color,x1,y2,x1+delta,y1);
898             ShowLine(Color,x1+delta,y1,x1,y0);
899             ShowLine(Color,x1,y0,x0,y0);
900             ShowLine(Color,x0,y0,x0,y2);
901             break;
902         case MARK_DN: /* down */
903             AOI.kaBottom -= delta;
904             EraseBox(&AOI);
905             ShowLine(Color,x0,y2,x1,y2);
906             ShowLine(Color,x1,y2,x1,y0);
907             ShowLine(Color,x1,y0,(x0+x1)/2,y0-delta);
908             ShowLine(Color,(x0+x1)/2,y0-delta,x0,y0);
909             ShowLine(Color,x0,y0,x0,y2);
910             break;
911         case MARK_LT: /* left */
912             AOI.kaLeft -= delta;
913             EraseBox(&AOI);
914             ShowLine(Color,x0,y2,x1,y2);
915             ShowLine(Color,x1,y2,x1,y0);
916             ShowLine(Color,x1,y0,x0,y0);
917             ShowLine(Color,x0,y0,x0-delta,y1);
918             ShowLine(Color,x0-delta,y1,x0,y2);
919             break;
920     }
921 
922     delta /= 2;
923     x0 += delta;
924     x1 -= delta;
925     y0 += delta;
926     y2 -= delta;
927 
928     switch (c) {
929         case MARK_GP1:
930             ShowLine(Color,x1,y2,x1,y0);
931             break;
932         case MARK_GP2:
933             ShowLine(Color,x0,y2,x1,y2);
934             ShowLine(Color,x1,y2,x1,y1);
935             ShowLine(Color,x1,y1,x0,y1);
936             ShowLine(Color,x0,y1,x0,y0);
937             ShowLine(Color,x0,y0,x1,y0);
938             break;
939         case MARK_GP3:
940             ShowLine(Color,x1,y2,x1,y0);
941             ShowLine(Color,x0,y2,x1,y2);
942             ShowLine(Color,x0,y1,x1,y1);
943             ShowLine(Color,x0,y0,x1,y0);
944             break;
945         case MARK_GP4:
946             ShowLine(Color,x1,y2,x1,y0);
947             ShowLine(Color,x0,y2,x0,y1);
948             ShowLine(Color,x0,y1,x1,y1);
949             break;
950         case MARK_GP5:
951             ShowLine(Color,x1,y2,x0,y2);
952             ShowLine(Color,x0,y2,x0,y1);
953             ShowLine(Color,x0,y1,x1,y1);
954             ShowLine(Color,x1,y1,x1,y0);
955             ShowLine(Color,x1,y0,x0,y0);
956             break;
957         case MARK_GP6:
958             ShowLine(Color,x0,y2,x0,y0);
959             ShowLine(Color,x0,y1,x1,y1);
960             ShowLine(Color,x1,y1,x1,y0);
961             ShowLine(Color,x1,y0,x0,y0);
962             break;
963         case MARK_GP7:
964             ShowLine(Color,x0,y2,x1,y2);
965             ShowLine(Color,x1,y2,x1,y0);
966             break;
967         case MARK_GP8:
968             ShowLine(Color,x0,y2,x1,y2);
969             ShowLine(Color,x0,y1,x1,y1);
970             ShowLine(Color,x0,y0,x1,y0);
971             ShowLine(Color,x1,y2,x1,y0);
972             ShowLine(Color,x0,y2,x0,y0);
973             break;
974     }
975 }
976 
977 
978 /***********************************************************************
979  *
980  * Etc.
981  *
982  *
983  ***********************************************************************/
984 
985 static int
my_strnicmp(s1,s2,n)986 my_strnicmp(s1,s2,n)
987 
988 /* strnicmp function - many libraries lack this */
989 char *s1, *s2;
990 int n;
991 {
992     char c, d;
993 
994     while (n--) {
995         c = *s1;
996         d = *s2;
997         if (c == '\0') return (-1);
998         if (d == '\0') return (1);
999         if (isupper(c)) c = tolower(c);
1000         if (isupper(d)) d = tolower(d);
1001         if (c != d) return (c-d);
1002         s1++;
1003         s2++;
1004     }
1005     return (0);
1006 }
1007 
1008