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  * JSPICE3 interface to SCED.
11  */
12 
13 #include "spice.h"
14 #include "sced.h"
15 #include "scedmacs.h"
16 #include "scedio.h"
17 #include <setjmp.h>
18 #include <signal.h>
19 
20 
21 /* imports from spice */
22 extern int ft_nutmeg;
23 extern int ft_intrpt;
24 #ifdef __STDC__
25 extern int  cp_getvar(char*,int,char*);
26 extern wordlist *cp_lexer(char*);
27 extern void wl_free(wordlist*);
28 extern int  cp_evloop(char*);
29 extern void cp_pushcontrol(void);
30 extern void cp_popcontrol(void);
31 extern wordlist *GetAnalysisFromDeck(void);
32 #else
33 extern int  cp_getvar();
34 extern wordlist *cp_lexer();
35 extern void wl_free();
36 extern int  cp_evloop();
37 extern void cp_pushcontrol();
38 extern void cp_popcontrol();
39 extern wordlist *GetAnalysisFromDeck();
40 #endif
41 
42 
43 /***********************************************************************
44  *
45  * Menu definition package.
46  *
47  ***********************************************************************/
48 
49 MENU *BasicMenu;
50 MENU *DeviceMenu;
51 MENU AmbiguityMenu[DefMenuSize];
52 
53 char *Menu0;
54 char *Menu90;
55 char *Menu180;
56 char *Menu270;
57 char *MenuMINSB;
58 char *MenuMINSG;
59 char *MenuMINSR;
60 char *MenuPLUSB;
61 char *MenuPLUSG;
62 char *MenuPLUSR;
63 char *MenuABORT;
64 char *MenuAREA;
65 char *MenuARRAY;
66 char *MenuBGRND;
67 char *MenuBREAK;
68 char *MenuCOLOR;
69 char *MenuCOPY;
70 char *MenuCRSYM;
71 char *MenuDELET;
72 char *MenuDESEL;
73 char *MenuDIR;
74 char *MenuDOTS;
75 char *MenuEDIT;
76 char *MenuEXPND;
77 char *MenuFLATN;
78 char *MenuGRAF;
79 char *MenuGRID;
80 char *MenuHCOPY;
81 char *MenuHELP;
82 char *MenuHLITE;
83 char *MenuIPLOT;
84 char *MenuLABEL;
85 char *MenuLAST;
86 char *MenuMENU;
87 char *MenuMORE;
88 char *MenuMOVE;
89 char *MenuMUTUL;
90 char *MenuMX;
91 char *MenuMY;
92 char *MenuNEWSC;
93 char *MenuPAN;
94 char *MenuPLACE;
95 char *MenuPOP;
96 char *MenuPRMPT;
97 char *MenuPRPTY;
98 char *MenuPUSH;
99 char *MenuRDRAW;
100 char *MenuRGB;
101 char *MenuRUN;
102 char *MenuSAVE;
103 char *MenuSELEC;
104 char *MenuSHOW;
105 char *MenuSTRCH;
106 char *MenuSUBCT;
107 char *MenuTERMS;
108 char *MenuUNDO;
109 char *MenuUPDAT;
110 char *MenuVIEW;
111 char *MenuWINDO;
112 char *MenuWIRES;
113 char *MenuZOOM;
114 static char *MenuSpace;
115 
116 
117 void
InitMenus()118 InitMenus()
119 
120 {
121 
122     Menu0        = "0    ";
123     Menu90       = "90   ";
124     Menu180      = "180  ";
125     Menu270      = "270  ";
126     MenuMINSB    = "-b   ";
127     MenuMINSG    = "-g   ";
128     MenuMINSR    = "-r   ";
129     MenuPLUSB    = "+b   ";
130     MenuPLUSG    = "+g   ";
131     MenuPLUSR    = "+r   ";
132     MenuABORT    = "quit ";
133     MenuAREA     = "area ";
134     MenuARRAY    = "array";
135     MenuBGRND    = "bgrnd";
136     MenuBREAK    = "break";
137     MenuCOLOR    = "color";
138     MenuCOPY     = "copy ";
139     MenuCRSYM    = "crsym";
140     MenuDELET    = "delet";
141     MenuDESEL    = "desel";
142     MenuDIR      = "dir  ";
143     MenuDOTS     = "dots ";
144     MenuEDIT     = "edit ";
145     MenuEXPND    = "expnd";
146     MenuFLATN    = "flatn";
147     MenuGRAF     = "graf ";
148     MenuGRID     = "grid ";
149     MenuHCOPY    = "hcopy";
150     MenuHELP     = "help";
151     MenuHLITE    = "hlite";
152     MenuIPLOT    = "iplot";
153     MenuLABEL    = "label";
154     MenuLAST     = "last ";
155     MenuMENU     = "menu ";
156     MenuMORE     = "more ";
157     MenuMOVE     = "move ";
158     MenuMUTUL    = "mutul";
159     MenuMX       = "mx   ";
160     MenuMY       = "my   ";
161     MenuNEWSC    = "newsc";
162     MenuPAN      = "pan  ";
163     MenuPLACE    = "place";
164     MenuPOP      = "pop  ";
165     MenuPRMPT    = "prmpt";
166     MenuPRPTY    = "prpty";
167     MenuPUSH     = "push ";
168     MenuRDRAW    = "rdraw";
169     MenuRGB      = "rgb  ";
170     MenuRUN      = "run  ";
171     MenuSAVE     = "save ";
172     MenuSELEC    = "selec";
173     MenuSTRCH    = "strch";
174     MenuSUBCT    = "subct";
175     MenuTERMS    = "terms";
176     MenuUNDO     = "undo ";
177     MenuUPDAT    = "updat";
178     MenuVIEW     = "view ";
179     MenuWINDO    = "windo";
180     MenuWIRES    = "wires";
181     MenuZOOM     = "zoom ";
182     MenuSpace    = "     ";
183 
184     InitBasicMenu();
185     InitDeviceMenu();
186 }
187 
188 
189 void
InitBasicMenu()190 InitBasicMenu()
191 
192 {
193     int i = 0, NumBasicMenu = 53;
194     int nrows = MenuViewport.kaY;
195 
196     if (BasicMenu == NULL)
197         BasicMenu = (MENU *) malloc(NumBasicMenu*sizeof(MENU));
198     if (BasicMenu == NULL) MallocFailed();
199     memset(BasicMenu,0,NumBasicMenu*sizeof(MENU));
200 
201     BasicMenu[i++].mEntry = MenuHELP;
202     BasicMenu[i++].mEntry = MenuCOLOR;
203     BasicMenu[i++].mEntry = MenuEDIT;
204     BasicMenu[i++].mEntry = MenuDIR;
205     BasicMenu[i++].mEntry = MenuSAVE;
206 
207     BasicMenu[i++].mEntry = MenuABORT;
208     BasicMenu[i++].mEntry = MenuSpace;
209     BasicMenu[i++].mEntry = MenuPAN;
210     BasicMenu[i++].mEntry = MenuZOOM;
211     BasicMenu[i++].mEntry = MenuWINDO;
212 
213     BasicMenu[i++].mEntry = MenuVIEW;
214     BasicMenu[i++].mEntry = MenuLAST;
215     BasicMenu[i++].mEntry = MenuEXPND;
216     BasicMenu[i++].mEntry = MenuGRID;
217     BasicMenu[i++].mEntry = MenuSpace;
218 
219     BasicMenu[i++].mEntry = MenuAREA;
220     BasicMenu[i++].mEntry = MenuSELEC;
221     BasicMenu[i++].mEntry = MenuDESEL;
222     BasicMenu[i++].mEntry = MenuMOVE;
223     BasicMenu[i++].mEntry = MenuCOPY;
224 
225     BasicMenu[i++].mEntry = MenuPUSH;
226     BasicMenu[i++].mEntry = MenuPOP;
227     if (i < nrows) BasicMenu[i++].mEntry = MenuSpace;
228     BasicMenu[i++].mEntry = MenuSTRCH;
229     BasicMenu[i++].mEntry = MenuBREAK;
230 
231     BasicMenu[i++].mEntry = MenuCRSYM;
232     BasicMenu[i++].mEntry = MenuFLATN;
233     BasicMenu[i++].mEntry = MenuDELET;
234     if (i < nrows) BasicMenu[i++].mEntry = MenuSpace;
235     BasicMenu[i++].mEntry = MenuUNDO;
236 
237     BasicMenu[i++].mEntry = MenuMX;
238     BasicMenu[i++].mEntry = MenuMY;
239     BasicMenu[i++].mEntry = Menu0;
240     if (i < nrows) BasicMenu[i++].mEntry = MenuSpace;
241     BasicMenu[i++].mEntry = MenuWIRES;
242 
243     BasicMenu[i++].mEntry = MenuLABEL;
244     BasicMenu[i++].mEntry = MenuDOTS;
245     if (i < nrows) BasicMenu[i++].mEntry = MenuSpace;
246     BasicMenu[i++].mEntry = MenuTERMS;
247     BasicMenu[i++].mEntry = MenuSUBCT;
248 
249     BasicMenu[i++].mEntry = MenuMUTUL;
250     BasicMenu[i++].mEntry = MenuPRPTY;
251     if (i < nrows) BasicMenu[i++].mEntry = MenuSpace;
252     BasicMenu[i++].mEntry = MenuRUN;
253     if (i < nrows) BasicMenu[i++].mEntry = MenuSpace;
254 
255     BasicMenu[i++].mEntry = MenuGRAF;
256     BasicMenu[i++].mEntry = MenuIPLOT;
257     BasicMenu[i++].mEntry = MenuHCOPY;
258     if (i < nrows) BasicMenu[i++].mEntry = MenuSpace;
259     BasicMenu[i++].mEntry = MenuNEWSC;
260 
261     BasicMenu[i++].mEntry = MenuSpace;
262     BasicMenu[i++].mEntry = NULL;
263 }
264 
265 
266 
267 /***********************************************************************
268  *
269  * Top level entry point and dispatch code.
270  *
271  ***********************************************************************/
272 
273 /* set if circuit sourced, so we don't do it again in spice */
274 static int SourceDone;
275 static enum Active SCEDisActive;
276 
277 static jmp_buf errjbuf;
278 
279 /* from spice */
280 extern FILE *cp_err;
281 
282 #ifdef __STDC__
283 static int  sced_main(void);
284 static void do_update(void);
285 static RETSIGTYPE sced_interrupt();
286 static void fix_spice_deck(struct line*);
287 #else
288 static int  sced_main();
289 static void do_update();
290 static RETSIGTYPE sced_interrupt();
291 static void fix_spice_deck();
292 #endif
293 
294 
295 int
sced(nameptr)296 sced(nameptr)
297 
298 /* main routine, called from com_sced in input.c
299  * return values:
300  * -1  "fatal" error, such as malloc failure
301  * 0   ok, circuit sourced
302  * 1   ok, circuit not sourced
303  * 2   user quit without saving file
304  * 3   bad file or file name
305  */
306 char **nameptr;
307 {
308     FILE *fp;
309     char *c, *name;
310     int i;
311     GRAPH *graph;
312     RETSIGTYPE (*sc_intr)();
313     RETSIGTYPE (*sc_float)();
314 
315     if (SCEDisActive) {
316         ShowPromptAndWait("SCED is already running!");
317         return (-1);
318     }
319     name = *nameptr;
320     SourceDone = False;
321     SetPathFromSpice();
322     if (name && *name) {
323 
324         fp = POpen(name,"r",(char **)NULL);
325         if (fp) {
326             if (!IsSymFile(fp)) return (3);
327             fclose(fp);
328         }
329     }
330     else
331         return (3);
332 
333     graph = (GRAPH*)Init();     /* push graph context on success */
334     if (graph == NULL)
335         return (-1);
336 
337     sc_intr = signal(SIGINT,SIG_IGN);
338     sc_float = signal(SIGFPE,SIG_IGN);
339 
340     /* clear out iplots */
341     {wordlist wl; wl.wl_next = NULL; wl.wl_word = "iplot";
342     (*ft_sced->sc_clriplot)(&wl);}
343 
344     if (!strcmp(Parameters.kpCellName,name) && Parameters.kpCellDesc) {
345         if (Not CDClose(Parameters.kpCellDesc)) MallocFailed();
346         Parameters.kpCellDesc = NULL;
347     }
348     else
349         strcpy(Parameters.kpCellName,name);
350     LibraryOpen(DeviceLibrary);
351     ModelLibraryOpen(ModelLibrary);
352     if (BasicMenu == NULL)
353         InitMenus();
354     if (setjmp(errjbuf) !=  1) {
355         SCEDisActive = SCED_active;
356         i = sced_main();
357         DevHalt();
358         PopGraphContext();
359         DestroyGraph(graph->graphid);
360         signal(SIGINT,sc_intr);
361         signal(SIGFPE,sc_float);
362         *nameptr = Parameters.kpCellName;
363         SCEDisActive = SCED_inactive;
364         return (i);
365     }
366     else {
367         ClearContext();
368         PopGraphContext();
369         DestroyGraph(graph->graphid);
370         signal(SIGINT,sc_intr);
371         signal(SIGFPE,sc_float);
372         SCEDisActive = SCED_inactive;
373         return (-1);  /* malloc failed */
374     }
375 }
376 
377 
378 static int
sced_main()379 sced_main()
380 
381 {
382     int i, LookedAhead = False;
383     char *TypeIn;
384 
385     InitVLT();
386     Basic(&LookedAhead);
387     Edit(True,True,False);
388     loop {
389         InitSignals();
390         if (Not LookedAhead)
391             Point();
392         else
393             LookedAhead = False;
394         if (Parameters.kpCellName[0] == EOS) {
395             /*
396              * The CD package doesn't check the integrity of symbol
397              * descriptors and now Parameters.kpCellDesc == NULL.
398              * Except for a few commands, each command invokes the
399              * CD package.  If such a command is invoked now, the
400              * CD package will crash and thus SCED will.  So, force user
401              * to select a cell to edit before invoking any such command.
402              */
403             if (Not (Matching(MenuEDIT) Or
404                 Matching(MenuDIR) Or Matching(MenuABORT))) {
405                 ShowPrompt("You haven't selected a cell to edit.");
406                 continue;
407             }
408         }
409         if (SafeCmds(&LookedAhead)) continue;
410 
411         if (Matching(MenuABORT)) {
412             i = CheckSaved();
413             if (i == -1) continue;
414             ClearContext();
415             if (i == 0) {
416                 if (SourceDone) return (0);
417                 return (1);
418             }
419             return (2);
420         }
421 
422         if (Matching(MenuAREA))  { Area(&LookedAhead);           continue; }
423         if (Matching(MenuBREAK)) { Break(&LookedAhead);          continue; }
424         if (Matching(MenuCOPY))  { Copy(&LookedAhead);           continue; }
425         if (Matching(MenuCRSYM)) { NewSymbol();                  continue; }
426         if (Matching(MenuDELET)) { Del(&LookedAhead);            continue; }
427         if (Matching(MenuDESEL)) { Desel();                      continue; }
428         if (Matching(MenuDOTS))  { Dots(&LookedAhead);           continue; }
429         if (Matching(MenuEDIT))  { SourceDone = False;
430                                    Edit(False,True,False);       continue; }
431         if (Matching(MenuFLATN)) { Flatten(&LookedAhead);        continue; }
432         if (Matching(MenuGRAF))  { ShowOutput(&LookedAhead);     continue; }
433         if (Matching(MenuHELP))  { SCEDhelp();                   continue; }
434         if (Matching(MenuLABEL)) { Label(&LookedAhead);          continue; }
435         if (Matching(MenuMOVE))  { Move(&LookedAhead);           continue; }
436         if (Matching(MenuMUTUL)) { ShowMutual(&LookedAhead);     continue; }
437         if (Matching(MenuNEWSC)) { NewSubckt();                  continue; }
438         if (Matching(MenuPLACE)) { Place(&LookedAhead);          continue; }
439         if (Matching(MenuPOP))   { Pop();                        continue; }
440         if (Matching(MenuPRPTY)) { ShowProperties(&LookedAhead); continue; }
441         if (Matching(MenuPUSH))  { Push(&LookedAhead);           continue; }
442         if (Matching(MenuRUN))   { RunSpice();                   continue; }
443         if (Matching(MenuSAVE))  { SourceDone = False;
444                                    WriteCell();                  continue; }
445         if (Matching(MenuSELEC)) { Sel(&LookedAhead);            continue; }
446         if (Matching(MenuSTRCH)) { StretchPath(&LookedAhead);    continue; }
447         if (Matching(MenuSUBCT)) { Subcircuit(&LookedAhead);     continue; }
448         if (Matching(MenuUNDO))  { Undo();                       continue; }
449         if (Matching(MenuWIRES)) { Wires(&LookedAhead);          continue; }
450     }
451 }
452 
453 
454 int
SafeCmds(LookedAhead)455 SafeCmds(LookedAhead)
456 
457 int *LookedAhead;
458 {
459 
460     if (Matching(Menu0))     { Rotat0();                    return (True); }
461     if (Matching(Menu90))    { Rotat90();                   return (True); }
462     if (Matching(Menu180))   { Rotat180();                  return (True); }
463     if (Matching(Menu270))   { Rotat270();                  return (True); }
464     if (Matching(MenuBGRND)) { Bgrnd(LookedAhead);          return (True); }
465     if (Matching(MenuCOLOR)) { Color(LookedAhead);          return (True); }
466     if (Matching(MenuDIR))   { Dir();                       return (True); }
467     if (Matching(MenuEXPND)) { Expand();                    return (True); }
468     if (Matching(MenuGRID))  { SetGrid(LookedAhead);        return (True); }
469     if (Matching(MenuHCOPY)) { Hcopy();                     return (True); }
470     if (Matching(MenuHLITE)) { Hlite(LookedAhead);          return (True); }
471     if (Matching(MenuIPLOT)) { DoIplot();                   return (True); }
472     if (Matching(MenuLAST))  { LastView();                  return (True); }
473     if (Matching(MenuMENU))  { MenuParams(LookedAhead);     return (True); }
474     if (Matching(MenuMINSB)) { AlterColor('b','-');         return (True); }
475     if (Matching(MenuMINSG)) { AlterColor('g','-');         return (True); }
476     if (Matching(MenuMINSR)) { AlterColor('r','-');         return (True); }
477     if (Matching(MenuMORE))  { MenuMore(LookedAhead);       return (True); }
478     if (Matching(MenuMX))    { MX();                        return (True); }
479     if (Matching(MenuMY))    { MY();                        return (True); }
480     if (Matching(MenuPAN))   { Pan(LookedAhead);            return (True); }
481     if (Matching(MenuPLUSB)) { AlterColor('b','+');         return (True); }
482     if (Matching(MenuPLUSG)) { AlterColor('g','+');         return (True); }
483     if (Matching(MenuPLUSR)) { AlterColor('r','+');         return (True); }
484     if (Matching(MenuPRMPT)) { MenuPrompt(LookedAhead);     return (True); }
485     if (Matching(MenuRDRAW)) { Rdraw();                     return (True); }
486     if (Matching(MenuRGB))   { RGB();                       return (True); }
487     if (Matching(MenuTERMS)) { ShowTerminals();             return (True); }
488     if (Matching(MenuUPDAT)) { do_update();                 return (True); }
489     if (Matching(MenuVIEW))  { ShowFull();                  return (True); }
490     if (Matching(MenuWINDO)) { Windo(LookedAhead);          return (True); }
491     if (Matching(MenuZOOM))  { Zoom(LookedAhead);           return (True); }
492 
493     return (False);
494 }
495 
496 static char *PathFromFile;
497 
498 static void
do_update()499 do_update()
500 
501 /* update the init file */
502 {
503     /* set path to what was in file for stand-alone sced */
504     PSetPath(PathFromFile);
505     UpdateSCED();
506     SetPathFromSpice();
507 }
508 
509 
510 
511 /***********************************************************************
512  *
513  * Routines for running spice analysis.
514  *
515  ***********************************************************************/
516 
517 
518 void
RunSpice()519 RunSpice()
520 
521 {
522     char *TypeIn;
523     wordlist *wl;
524     struct line *deck;
525     static char Rcmd[64];
526     RETSIGTYPE (*intrpt)();
527 
528     if (Parameters.kpCellDesc != Parameters.kpTopDesc) {
529         ShowPrompt("Pop to top level first.");
530         return;
531     }
532     MenuSelect(MenuRUN);
533 
534 
535     if ((*ft_sced->sc_inprogress)()) {
536         ShowPrompt("Resume run in progress? [y] ");
537         if ((TypeIn = FBEdit(NULL)) == NULL) {
538             MenuDeselect(MenuRUN);
539             ErasePrompt();
540             return;
541         }
542         if (*TypeIn != 'n' && *TypeIn != 'N') {
543             if (IplotStatusChanged) {
544                 ClearIplot();
545                 SetIplot();
546             }
547             intrpt = signal(SIGINT,sced_interrupt);
548             (*ft_sced->sc_resume)(NULL);
549             (void)signal(SIGINT,intrpt);
550             if (!dispdev->windows && !dispdev->hardcopy)
551                 if ((*ft_sced->sc_isiplot)())
552                     RedisplaySCED(currentgraph);
553             (void)CheckError();
554             if (!(*ft_sced->sc_inprogress)()) {
555                 ShowPrompt("Analysis complete.");
556                 ClearIplot();
557             }
558             MenuDeselect(MenuRUN);
559             return;
560         }
561 
562     }
563 
564     ClearIplot();
565     deck = MakeSpiceDeck();
566     fix_spice_deck(deck);
567     if (SourceDone)
568         (*ft_sced->sc_cktclear)();
569     (*ft_sced->sc_source)(deck,False,Parameters.kpCellName);
570     (void)CheckError();
571     SourceDone = True;
572 
573     wl = GetAnalysisFromDeck();
574     if (wl == NULL) {
575         ShowPrompt("Enter analysis command : ");
576         if ((TypeIn = FBEdit(Rcmd)) != NULL) {
577             wl = cp_lexer(TypeIn);
578             strncpy(Rcmd,TypeIn,64);
579             Rcmd[63] = '\0';
580         }
581         else
582             ErasePrompt();
583     }
584     if (wl) {
585         if (wl->wl_word && *wl->wl_word) {
586             ShowPrompt("Performing analysis, please wait.");
587             SetIplot();
588             intrpt = signal(SIGINT,sced_interrupt);
589             (*ft_sced->sc_dosim)(wl->wl_word,wl->wl_next);
590             (void)signal(SIGINT,intrpt);
591             if (!dispdev->windows && !dispdev->hardcopy)
592                 if ((*ft_sced->sc_isiplot)())
593                     RedisplaySCED(currentgraph);
594             (void)CheckError();
595             if (!(*ft_sced->sc_inprogress)()) {
596                 ShowPrompt("Analysis complete.");
597                 ClearIplot();
598             }
599         }
600         wl_free(wl);
601     }
602     MenuDeselect(MenuRUN);
603 }
604 
605 
606 static RETSIGTYPE
sced_interrupt()607 sced_interrupt()
608 
609 {
610     (void)signal(SIGINT,sced_interrupt);
611     ft_intrpt = True;
612 }
613 
614 
615 static void
fix_spice_deck(deck)616 fix_spice_deck(deck)
617 
618 /* Concatenate continuation lines for spice. */
619 struct line *deck;
620 {
621     struct line *d,*d0,*d1,*dn;
622     char *s;
623 
624     for (d = deck; d; d = dn) {
625         dn = d->li_next;
626         if (*d->li_line == '+') {
627             /* continuation line */
628             d->li_next = NULL;
629             s = d0->li_line;
630             d0->li_line = AllocateNewString(s,d->li_line+1);
631             d0->li_next = dn;
632             if (d0->li_actual == NULL) {
633                 d0->li_actual = AllocateLine(s);
634                 d0->li_actual->li_linenum = d0->li_linenum;
635                 d0->li_actual->li_next = d;
636             }
637             else {
638                 for (d1 = d0->li_actual; d1->li_next; d1 = d1->li_next) ;
639                 d1->li_next = d;
640             }
641             continue;
642         }
643         d0 = d;
644     }
645 }
646 
647 
648 
649 /***********************************************************************
650  *
651  * Routines to check for error conditions.
652  *
653  ***********************************************************************/
654 
655 int
CheckSaved()656 CheckSaved()
657 
658 /* Determine if the circuit, and parent (if any) have been saved,
659  * and query user on intentions.
660  *  return values:
661  *  0   saved, quit
662  *  1   not saved, quit anyway
663  *  -1  not saved, don't quit
664  */
665 {
666     int i,j;
667     char *TypeIn;
668 
669     MenuSelect(MenuABORT);
670     i = CheckModified();
671     j = (Parameters.kpModified And Parameters.kpCellName[0]);
672     if (i And j)
673         TypeIn  =
674         "Both parent and current circuit have changed.  Quit anyway? (n): ";
675     elif (i And Not j)
676         TypeIn  = "Parent circuit has been modified.  Quit anyway? (n): ";
677     elif (Not i And j)
678         TypeIn  = "Current circuit has been modified.  Quit anyway? (n): ";
679     else {
680         MenuDeselect(MenuABORT);
681         return (0);
682     }
683     ShowPrompt(TypeIn);
684     TypeIn = FBEdit(NULL);
685     if (TypeIn != NULL And (TypeIn[0] == 'Y' Or TypeIn[0] == 'y')){
686         MenuDeselect(MenuABORT);
687         return (1);
688     }
689     ErasePrompt();
690     MenuDeselect(MenuABORT);
691     return (-1);
692 }
693 
694 
695 int
CheckError()696 CheckError()
697 
698 /* find out if spice has put anything in the error output file.  If
699  * so, display it and return True.
700  */
701 {
702     int c;
703     struct ka *AOI,BB;
704 
705     rewind(cp_err);
706     if ((c = getc(cp_err)) == EOF) return (False);
707     ungetc(c,cp_err);
708     if (!PopUpErrMessage(cp_err)) {
709         AOI = View->kvLargeCoarseViewport;
710         FBEraseBox(AOI->kaLeft,AOI->kaBottom,
711             AOI->kaRight,AOI->kaTop);
712         MoreText((int)AOI->kaLeft-1,(int)AOI->kaBottom-1,
713             (int)AOI->kaRight-1,(int)AOI->kaTop-1,cp_err,MoreTextColor);
714         RedisplaySCED(currentgraph);
715     }
716     rewind(cp_err);
717 #ifdef HAVE_NO_FTRUNCATE
718     /* have to add something here */
719 #else
720     ftruncate(fileno(cp_err),0);
721 #endif
722     return (True);
723 }
724 
725 
726 int
IsSymFile(fp)727 IsSymFile(fp)
728 
729 /* Check if the file just opened is a symbol file. */
730 FILE *fp;
731 {
732     char buf[12];
733 
734     (void)fgets(buf,8,fp);
735 
736     if (buf[0] != '(') return (False);
737     if (buf[1] != 'S') return (False);
738     if (buf[2] != 'y') return (False);
739     if (buf[3] != 'm') return (False);
740     if (buf[4] != 'b') return (False);
741     if (buf[5] != 'o') return (False);
742     if (buf[6] != 'l') return (False);
743     return (True);
744 }
745 
746 
747 
748 /***********************************************************************
749  *
750  * Routines to set the search path as obtained from spice, and get
751  * device name for haedcopy.
752  *
753  ***********************************************************************/
754 
755 
756 void
SetPathFromSpice()757 SetPathFromSpice()
758 
759 /* Set the CD path to the spice search path. */
760 {
761     char buf[80], *t;
762     struct variable *v;
763     extern char *kw_sourcepath;
764     int len;
765 
766     TypeOut[0] = '\0';
767 
768     if (!cp_getvar(kw_sourcepath,VT_LIST,(char *)&v)) {
769         CDPath(".");
770         return;
771     }
772     len = 256;
773     t = tmalloc(len);
774     switch (v->va_type) {
775         case VT_STRING:
776             sprintf(t,"%s",v->va_string);
777             break;
778         case VT_NUM:
779             sprintf(t,"%d",v->va_num);
780             break;
781         case VT_REAL:
782             sprintf(t,"%lg",v->va_real);
783             break;
784     }
785     for (v = v->va_next; v; v = v->va_next) {
786         switch (v->va_type) {
787             case VT_STRING:
788                 sprintf(buf," %s",v->va_string);
789                 break;
790             case VT_NUM:
791                 sprintf(buf," %d",v->va_num);
792                 break;
793             case VT_REAL:
794                 sprintf(buf," %lg",v->va_real);
795                 break;
796         }
797         if (strlen(t) + strlen(buf) >= len)
798             t = trealloc(t, len += 256);
799         strcat(t,buf);
800     }
801     /* append the path to the sced system files */
802     if (strlen(t) + strlen(Sced_Path) > len)
803         t = trealloc(t, len += 256);
804     strcat(t," ");
805     strcat(t,Sced_Path);
806     CDPath(t);
807     txfree(t);
808 }
809 
810 
811 void
SetCDPath(Path)812 SetCDPath(Path)
813 
814 char *Path;
815 {
816     if (PathFromFile != NULL)
817         free(PathFromFile);
818     PathFromFile = CopyString(Path);
819 }
820 
821 
822 char *
GetHardCopyDevice()823 GetHardCopyDevice()
824 
825 /* Return the name of the device used for output as set in spice. */
826 {
827     struct variable *v;
828     extern char *kw_hcopydev;
829 
830     if (!cp_getvar(kw_hcopydev, VT_STRING, (char *)&v))
831         return ("prn");
832     return (v->va_string);
833 }
834 
835 
836 
837 /***********************************************************************
838  *
839  * Routines needed to satisfy references in SCED library, for error and
840  * signal handling.
841  *
842  ***********************************************************************/
843 
844 void
InitSignals()845 InitSignals()
846 {
847     ft_intrpt = false;
848     vec_gc();
849 }
850 
851 char *
NextCellName()852 NextCellName()
853 {return (NULL);}
854 
855 
856 void
MallocFailed()857 MallocFailed()
858 
859 {
860     char *cp;
861     char *mktemp();
862     cp = mktemp("scXXXXXX");
863     DevHalt();
864     fprintf(stderr,"OUT OF MEMORY.  SCED is DEAD!\n");
865 
866     if (Parameters.kpCellName[0] != EOS) {
867         if (Not CDUpdate(Parameters.kpCellDesc,cp))
868             fprintf(stderr,"\007Sorry.  Couldn't save current circuit.\n");
869         else
870             fprintf(stderr,"\007Current circuit saved in %s.\n",cp);
871     }
872     longjmp(errjbuf,1);
873 }
874 
875 
876 
877 /***********************************************************************
878  *
879  * Routines which allocate memory from spice, etc.
880  *
881  ***********************************************************************/
882 
883 extern char *copy();
884 
885 
886 struct line *
AllocateLine(string)887 AllocateLine(string)
888 
889 /* create and initialize a line structure */
890 char *string;
891 {
892     struct line *l;
893 
894     /* allocate memory in spice */
895 
896     l = alloc(line);
897     l->li_line = copy(string);
898     return (l);
899 }
900 
901 
902 char *
AllocateNewString(string,buf)903 AllocateNewString(string,buf)
904 
905 /* Create a new concatenated string from a previous string and buffer.
906  */
907 char *string;
908 char *buf;
909 {
910     char *c;
911 
912     c = tmalloc(strlen(string) + strlen(buf) + 2);
913     sprintf(c,"%s %s",string,buf);
914     return (c);
915 }
916 
917 
918 
919 /***********************************************************************
920  *
921  * Routines to execute spice commands, or enter a shell;
922  *
923  *
924  ***********************************************************************/
925 
926 #ifdef __STDC__
927 static int  do_spice_cmd(char*);
928 #else
929 static int  do_spice_cmd();
930 #endif
931 
932 /* imports from spice */
933 extern int  cp_evloop();
934 extern void cp_pushcontrol();
935 extern void cp_popcontrol();
936 extern FILE *cp_out;
937 extern FILE *cp_in;
938 
939 
940 void
ShowProcess(cp)941 ShowProcess(cp)
942 
943 char *cp;
944 {
945     char buffer[80];
946     int i, gicalls;
947 
948     if (!cp || !strlen(cp)) {
949         if (!dispdev->windows) {
950 #ifdef MSDOS
951             cp = "command";
952 #else
953             cp = "csh";
954 #endif
955             DevHalt();
956             system(cp);
957             DevNewViewport(currentgraph);
958             RedisplaySCED(currentgraph);
959         }
960         else
961             system("xterm &");
962         return;
963     }
964     gicalls = numgraphcxsw;
965     i = do_spice_cmd(cp);
966 
967     if (!CheckError()) {
968         if (!dispdev->windows) {
969             /* CheckError() redraws screen if error */
970             if (i) {
971                 /* Cmd showed some text */
972                 ShowPrompt("Hit any key to continue.");
973                 (void)FBGetchar(ERASE);
974                 ErasePrompt();
975             }
976             if (gicalls != numgraphcxsw)
977                 InitVLT();
978             if (i || gicalls != numgraphcxsw)
979                 RedisplaySCED(currentgraph);
980         }
981     }
982 }
983 
984 
985 static int
do_spice_cmd(Cmd)986 do_spice_cmd(Cmd)
987 
988 char *Cmd;
989 {
990     *TypeOut = '\0';
991     (void)EnableMore(True);
992     cp_pushcontrol();
993     cp_evloop(Cmd);
994     cp_popcontrol();
995     return (EnableMore(False));
996 }
997 
998 
999 int
SCEDline(string)1000 SCEDline(string)
1001 
1002 /* Called from output.c in spice, redirects output to
1003  * graphics window.
1004  */
1005 char *string;
1006 {
1007     if (SCEDisActive) {
1008         if (strlen(TypeOut) + strlen(string) < 200)
1009             strcat(TypeOut,string);
1010         else
1011             strcat(TypeOut,"\n");
1012         if (strchr(TypeOut,'\n') == NULL) return (False);
1013         if (MoreLine(TypeOut))
1014             EnableMore(False);
1015         *TypeOut = '\0';
1016         return (True);
1017     }
1018     return (False);
1019 }
1020 
1021 
1022 void
SCEDfflush()1023 SCEDfflush()
1024 
1025 {
1026     if (!SCEDisActive) {
1027         fflush(cp_out);
1028         return;
1029     }
1030     strcat(TypeOut,"\n");
1031     if (MoreLine(TypeOut))
1032         EnableMore(False);
1033     *TypeOut = '\0';
1034 }
1035 
1036 
1037 char *
SCEDfgets(s,n,fp,prompt)1038 SCEDfgets(s,n,fp,prompt)
1039 
1040 /* replacement for fgets() for use in spice */
1041 char *s;
1042 int n;
1043 FILE *fp;
1044 char *prompt;
1045 {
1046     char *c;
1047 
1048     if (!SCEDisActive) {
1049         if (prompt != NULL) {
1050             (void)fprintf(cp_out,prompt);
1051             (void)fflush(cp_out);
1052         }
1053         c = fgets(s,n,fp);
1054         if (c == NULL) {
1055             clearerr(fp);
1056         }
1057         return (c);
1058     }
1059     if (!prompt) {
1060         ErasePrompt();
1061         return (NULL);
1062     }
1063     ShowPrompt(prompt);
1064     MorePageDisplay();
1065     c = FBEdit(NULL);
1066     ErasePrompt();
1067     if (c == NULL || *c == '\0' || *c == '\n') return (NULL);
1068     strncpy(s,c,n);
1069     return (s);
1070 }
1071 
1072 
1073 enum Active
SCEDactive()1074 SCEDactive()
1075 
1076 {
1077     return (SCEDisActive);
1078 }
1079 
1080 
1081 
1082 /***********************************************************************
1083  *
1084  * Help interface.
1085  *
1086  *
1087  ***********************************************************************/
1088 
1089 void
SCEDhelp()1090 SCEDhelp()
1091 
1092 {
1093     int dummy;
1094     char cmd[32];
1095 
1096     MenuSelect(MenuHELP);
1097     ShowPrompt("Point to menu item for help (ESC to exit help).");
1098     SCEDisActive = SCED_inhelp;
1099     loop {
1100         switch (PointLoopSafe(&dummy)) {
1101             case PL_ESC:
1102                 MenuDeselect(MenuHELP);
1103                 if (!dispdev->windows)
1104                     RedisplaySCED(currentgraph);
1105                 else
1106                     ErasePrompt();
1107                 SCEDisActive = SCED_active;
1108                 return;
1109             case PL_PCW:
1110                 continue;
1111             case PL_CMD:
1112                 if (Matching(MenuMINSR) ||
1113                     Matching(MenuPLUSR) ||
1114                     Matching(MenuMINSG) ||
1115                     Matching(MenuPLUSG) ||
1116                     Matching(MenuMINSB) ||
1117                     Matching(MenuPLUSB))
1118                     strcpy(Parameters.kpCommand,"chgcolor");
1119 
1120                 else
1121 
1122                 if (Matching(Menu0)   ||
1123                     Matching(Menu90)  ||
1124                     Matching(Menu180) ||
1125                     Matching(Menu270))
1126                     strcpy(Parameters.kpCommand,"rotate");
1127 
1128                 else
1129 
1130                 if (Matching(MenuMX) ||
1131                     Matching(MenuMY))
1132                     strcpy(Parameters.kpCommand,"mirror");
1133 
1134                 else
1135 
1136                 if (Matching(MenuSpace))
1137                     continue;
1138 
1139                 sprintf(cmd,"help sced:%s",Parameters.kpCommand);
1140                 (void)do_spice_cmd(cmd);
1141         }
1142     }
1143 }
1144