1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: usr.c
6 * User interface tool: main module
7 * Written by: Steven M. Rubin, Static Free Software
8 *
9 * Copyright (c) 2000 Static Free Software.
10 *
11 * Electric(tm) is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * Electric(tm) is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Electric(tm); see the file COPYING. If not, write to
23 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24 * Boston, Mass 02111-1307, USA.
25 *
26 * Static Free Software
27 * 4119 Alpine Road
28 * Portola Valley, California 94028
29 * info@staticfreesoft.com
30 */
31
32 #include "global.h"
33 #include "egraphics.h"
34 #include "edialogs.h"
35 #include "tech.h"
36 #include "usr.h"
37 #include "usrtrack.h"
38 #include "usrdiacom.h"
39 #include "sim.h"
40 #include "tecart.h"
41 #include "tecgen.h"
42 #include "tecschem.h"
43 #include <setjmp.h> /* for nonlocal goto's */
44
45 TOOL *us_tool; /* the USER tool object */
46 INTBIG us_longcount; /* number of long commands */
47 void (*us_displayroutine)(POLYGON*, WINDOWPART*); /* routine for graphics display */
48 INTBIG us_currenteditor; /* the current editor (index to "us_editortable") */
49 INTBIG us_cursorstate; /* current cursor being displayed */
50 INTBIG us_normalcursor; /* default cursor to use */
51 BOOLEAN us_optionschanged; /* true if options changed */
52 INTBIG us_layer_letters_key; /* variable key for "USER_layer_letters" */
53 INTBIG us_highlightedkey; /* variable key for "USER_highlighted" */
54 INTBIG us_highlightstackkey; /* variable key for "USER_highlightstack" */
55 INTBIG us_binding_keys_key; /* variable key for "USER_binding_keys" */
56 INTBIG us_binding_buttons_key; /* variable key for "USER_binding_buttons" */
57 INTBIG us_binding_menu_key; /* variable key for "USER_binding_menu" */
58 INTBIG us_current_node_key; /* variable key for "USER_current_node" */
59 INTBIG us_current_arc_key; /* variable key for "USER_current_arc" */
60 INTBIG us_placement_angle_key; /* variable key for "USER_placement_angle" */
61 INTBIG us_alignment_ratio_key; /* variable key for "USER_alignment_ratio" */
62 INTBIG us_alignment_edge_ratio_key;/* variable key for "USER_alignment_edge_ratio" */
63 INTBIG us_arcstylekey; /* variable key for "USER_arc_style" */
64 INTBIG us_current_technology_key; /* variable key for "USER_current_technology" */
65 INTBIG us_current_window_key; /* variable key for "USER_current_window" */
66 INTBIG us_current_constraint_key; /* variable key for "USER_current_constraint" */
67 INTBIG us_colormap_red_key; /* variable key for "USER_colormap_red" */
68 INTBIG us_colormap_green_key; /* variable key for "USER_colormap_green" */
69 INTBIG us_colormap_blue_key; /* variable key for "USER_colormap_blue" */
70 INTBIG us_copyright_file_key; /* variable key for "USER_copyright_file" */
71 INTBIG us_menu_position_key; /* variable key for "USER_menu_position" */
72 INTBIG us_menu_x_key; /* variable key for "USER_menu_x" */
73 INTBIG us_menu_y_key; /* variable key for "USER_menu_y" */
74 INTBIG us_macrorunningkey; /* variable key for "USER_macrorunning" */
75 INTBIG us_macrobuildingkey; /* variable key for "USER_macrobuilding" */
76 INTBIG us_text_editorkey; /* variable key for "USER_text_editor" */
77 INTBIG us_optionflagskey; /* variable key for "USER_optionflags" */
78 INTBIG us_gridfloatskey; /* variable key for "USER_grid_floats" */
79 INTBIG us_gridboldspacingkey; /* variable key for "USER_grid_bold_spacing" */
80 INTBIG us_quickkeyskey; /* variable key for "USER_quick_keys" */
81 INTBIG us_interactiveanglekey; /* variable key for "USER_interactive_angle" */
82 INTBIG us_tinylambdaperpixelkey; /* variable key for "USER_tiny_lambda_per_pixel" */
83 INTBIG us_ignoreoptionchangeskey; /* variable key for "USER_ignore_option_changes" */
84 INTBIG us_displayunitskey; /* variable key for "USER_display_units" */
85 INTBIG us_electricalunitskey; /* variable key for "USER_electrical_units" */
86 INTBIG us_motiondelaykey; /* variable key for "USER_motion_delay" */
87 INTBIG us_java_flags_key; /* variable key for "JAVA_flags" */
88 INTBIG us_edtec_option_key; /* variable key for "EDTEC_option" */
89 INTBIG us_electricalunits; /* mirror for "USER_electrical_units" */
90 INTBIG us_javaflags; /* mirror for "JAVA_flags" */
91 INTBIG us_useroptions; /* mirror for "USER_optionflags" */
92 INTBIG us_tinyratio; /* mirror for "USER_tiny_lambda_per_pixel" */
93 INTBIG us_separatechar; /* separating character in port names */
94 INTBIG us_filetypecolormap; /* Color map file descriptor */
95 INTBIG us_filetypehelp; /* Help file descriptor */
96 INTBIG us_filetypelog; /* Log file descriptor */
97 INTBIG us_filetypemacro; /* Macro file descriptor */
98 INTBIG us_filetypenews; /* News file descriptor */
99
100 /* local state */
101 static BOOLEAN us_ignore_cadrc; /* set when user wants to ignore the cadrc file */
102 static CHAR *us_firstlibrary; /* library to read upon startup */
103 static CHAR *us_firstmacrofile; /* macro file to read upon startup */
104 static INTBIG us_techlaststatekey; /* variable key for "TECH_last_state" */
105 static INTBIG us_filetypecadrc; /* Startup file descriptor*/
106 static CHAR us_desiredlibrary[300]; /* library to be read at startup */
107 static BOOLEAN us_logging = TRUE; /* nonzero to start session logging */
108
109 /* for tracking broadcast changes */
110 static TOOL *us_batchsource;
111 static WINDOWPART us_oldwindow, *us_firstnewwindow, *us_secondnewwindow, *us_killedwindow;
112 static INTBIG us_maplow, us_maphigh, us_newwindowcount;
113 static BOOLEAN us_menuchanged, us_gridfactorschanged, us_cellstructurechanged;
114 static INTBIG us_oldstate, us_oldoptions;
115 static NODEPROTO *us_firstchangedcell, *us_secondchangedcell;
116 static NODEPROTO *us_cellwithkilledname; /* cell whose name was just killed */
117 static CHAR *us_killednameoncell; /* name that was removed from cell */
118
119 static VARMIRROR us_variablemirror[] =
120 {
121 {&us_optionflagskey, &us_useroptions},
122 {&us_tinylambdaperpixelkey, &us_tinyratio},
123 {&us_menu_x_key, &us_menux},
124 {&us_menu_y_key, &us_menuy},
125 {&us_menu_position_key, &us_menupos},
126 {&us_java_flags_key, &us_javaflags},
127 {&us_electricalunitskey, &us_electricalunits},
128 {0, 0}
129 };
130
131 /* internal state */
132 INTBIG us_state; /* miscellaneous state of user interface */
133
134 /* when modifying this list of status fields, update "usrcomwz.c:us_statusfields[]" */
135 STATUSFIELD *us_statusalign = 0; /* current node alignment */
136 STATUSFIELD *us_statusangle = 0; /* current placement angle */
137 STATUSFIELD *us_statusarc = 0; /* current arc prototype */
138 STATUSFIELD *us_statuscell = 0; /* current cell */
139 STATUSFIELD *us_statuscellsize = 0; /* current cell size */
140 STATUSFIELD *us_statusselectcount = 0; /* current selection count */
141 STATUSFIELD *us_statusgridsize = 0; /* current grid size */
142 STATUSFIELD *us_statuslambda = 0; /* current lambda */
143 STATUSFIELD *us_statusnode = 0; /* current node prototype */
144 STATUSFIELD *us_statustechnology = 0; /* current technology */
145 STATUSFIELD *us_statusxpos = 0; /* current x position */
146 STATUSFIELD *us_statusypos = 0; /* current y position */
147 STATUSFIELD *us_statusproject = 0; /* current project */
148 STATUSFIELD *us_statusroot = 0; /* current root */
149 STATUSFIELD *us_statuspart = 0; /* current part */
150 STATUSFIELD *us_statuspackage = 0; /* current package */
151 STATUSFIELD *us_statusselection = 0; /* current selection */
152
153 /* user interface state */
154 NODEPROTO *us_curnodeproto; /* current nodeproto */
155 ARCPROTO *us_curarcproto; /* current arcproto */
156 INTBIG us_alignment_ratio; /* current alignment in fractional units */
157 INTBIG us_edgealignment_ratio; /* current edge alignment in fractional units */
158 BOOLEAN us_dupdistset; /* true if duplication distance is valid */
159 NODEINST *us_dupnode; /* a node that was duplicated */
160 LIBRARY *us_clipboardlib; /* library with cut/copy/paste cell */
161 NODEPROTO *us_clipboardcell; /* cell with cut/copy/paste objects */
162 INTBIG us_dupx, us_dupy; /* amount to move duplicated objects */
163 WINDOWFRAME *us_menuframe; /* window frame on which menu resides */
164 #ifndef USEQT
165 INTSML us_erasech, us_killch; /* the erase and kill characters */
166 #endif
167 INTBIG us_menux, us_menuy; /* number of menu elements on the screen */
168 INTBIG us_menupos; /* position: 0:top 1:bottom 2:left 3:right */
169 INTBIG us_menuxsz,us_menuysz; /* size of menu elements */
170 INTBIG us_menuhnx,us_menuhny; /* highlighted nodeinst menu entry */
171 INTBIG us_menuhax,us_menuhay; /* highlighted arcinst menu entry */
172 INTBIG us_menulx,us_menuhx; /* X: low and high of menu area */
173 INTBIG us_menuly,us_menuhy; /* Y: low and high of menu area */
174 INTBIG us_lastmeasurex, us_lastmeasurey; /* last measured distance */
175 BOOLEAN us_validmesaure; /* true if a measure was done */
176 INTBIG us_explorerratio = 25; /* percentage of window used by cell explorer */
177 FILE *us_logrecord; /* logging record file */
178 FILE *us_logplay; /* logging playback file */
179 FILE *us_termaudit; /* messages window auditing file */
180 FILE *us_tracefile = NULL;
181 INTBIG us_logflushfreq; /* session logging flush frequency */
182 INTBIG us_quickkeyfactcount = 0; /* number of quick keys in "factory" setup */
183 CHAR **us_quickkeyfactlist; /* quick keys in "factory" setup */
184
185 INTBIG us_lastcommandcount; /* the keyword count for the last command set by the "remember" command */
186 INTBIG us_lastcommandtotal = 0; /* size of keyword array for the last command set by the "remember" command */
187 CHAR **us_lastcommandpar; /* the keywords for the last command set by the "remember" command */
188
189 MACROPACK *us_macropacktop; /* top of list of defined macro packages */
190 MACROPACK *us_curmacropack; /* current macro package */
191
192 USERCOM *us_usercomfree; /* list of free user commands */
193 USERCOM *us_lastcom; /* last command and arguments */
194
195 POPUPMENU *us_firstpopupmenu; /* list of existing pop-up menus */
196 INTBIG us_pulldownmenucount; /* number of pulldown menus */
197 INTBIG *us_pulldownmenupos; /* position of pulldown menus */
198 POPUPMENU **us_pulldowns; /* the current pulldown menus */
199
200 /* prototypes for local routines */
201 static BOOLEAN us_do2init(INTBIG*, CHAR1*[]);
202 static BOOLEAN us_do3init(void);
203 static void us_causeofslice(USERCOM*);
204 static void us_setcommand(CHAR*, USERCOM*, INTBIG, NODEPROTO*, ARCPROTO*, CHAR*, POPUPMENU*, BOOLEAN);
205 static BOOLEAN us_options(INTBIG*, CHAR1*[]);
206 static BOOLEAN us_docadrc(CHAR*);
207 static void us_findcadrc(void);
208 static void us_checkfontassociations(LIBRARY *lib);
209 static void us_setfontassociationdescript(UINTBIG *descript, INTBIG *fontmatch);
210 static void us_setfontassociationvar(INTSML numvar, VARIABLE *firstvar, INTBIG *fontmatch);
211 static void us_checkinplaceedits(NODEPROTO *cell);
212
213 /******************** CONTROL ********************/
214
215 /* initialize the user interface tool */
us_init(INTBIG * argc,CHAR1 * argv[],TOOL * thistool)216 void us_init(INTBIG *argc, CHAR1 *argv[], TOOL *thistool)
217 {
218 if (thistool == 0)
219 {
220 /* pass 3 */
221 if (us_do3init())
222 error(_("No memory to run the user interface"));
223 } else if (thistool == NOTOOL)
224 {
225 /* pass 2 */
226 if (us_do2init(argc, argv))
227 error(_("No memory to run the user interface"));
228 } else
229 {
230 /* pass 1 */
231 us_tool = thistool;
232 el_topwindowpart = NOWINDOWPART; /* no windows defined */
233 }
234 }
235
236 /* pass 2 of initialization */
us_do2init(INTBIG * argc,CHAR1 * argv[])237 BOOLEAN us_do2init(INTBIG *argc, CHAR1 *argv[])
238 {
239 CHAR *newpar[3], msg[150];
240 REGISTER INTBIG i;
241 INTBIG swid, shei, twid, thei;
242 INTBIG keys[2];
243 UINTBIG descript[TEXTDESCRIPTSIZE];
244 REGISTER TECHNOLOGY *tech;
245 extern GRAPHICS us_gbox, us_box;
246 REGISTER WINDOWFRAME *wf;
247 REGISTER VARIABLE *varred, *vargreen, *varblue;
248
249 /* initialize lists */
250 us_usercomfree = NOUSERCOM; /* no free command modules */
251
252 /* define the default macro called "macro" */
253 newpar[0] = newpar[1] = newpar[2] = x_("");
254 nextchangequiet();
255 (void)setvalkey((INTBIG)us_tool, VTOOL, makekey(x_("USER_macro_macro")),
256 (INTBIG)newpar, VSTRING|VISARRAY|(3<<VLENGTHSH)|VDONTSAVE);
257
258 /* basic initialization */
259 us_logplay = NULL; /* no session playback */
260 us_logrecord = NULL; /* no session recording */
261 us_termaudit = NULL; /* no terminal auditing */
262 us_logflushfreq = 10; /* flush session recording every 10 */
263 us_lastcom = NOUSERCOM; /* no last command issued */
264 us_macropacktop = NOMACROPACK; /* no defined macro packages */
265 us_curmacropack = NOMACROPACK; /* no current macro package */
266 us_menuhnx = us_menuhax = -1; /* no menu highlighting */
267 us_menupos = 0; /* menus on the top */
268 us_firstpopupmenu = NOPOPUPMENU; /* no popup menus yet */
269 us_pulldownmenucount = 0; /* no pulldown menus in menubar */
270 us_state = 0; /* all is well */
271 us_dupdistset = FALSE; /* duplication distance not set */
272 us_dupnode = NONODEINST; /* duplication node not set */
273 us_currenteditor = 0; /* use the first editor */
274 us_tool->toolstate |= INTERACTIVE; /* use interactive cursor commands */
275 us_validmesaure = FALSE; /* nothing measured */
276 us_tinyratio = K4; /* default ratio for hashing tiny cells */
277 us_javaflags = 0; /* default Java flags */
278 us_separatechar = '_'; /* default separating character */
279 us_curarcproto = NOARCPROTO;
280 us_curnodeproto = NONODEPROTO;
281 us_layer_letters_key = makekey(x_("USER_layer_letters"));
282 us_highlightedkey = makekey(x_("USER_highlighted"));
283 us_highlightstackkey = makekey(x_("USER_highlightstack"));
284 us_binding_keys_key = makekey(x_("USER_binding_keys"));
285 us_binding_buttons_key = makekey(x_("USER_binding_buttons"));
286 us_binding_menu_key = makekey(x_("USER_binding_menu"));
287 us_current_node_key = makekey(x_("USER_current_node"));
288 us_current_arc_key = makekey(x_("USER_current_arc"));
289 us_placement_angle_key = makekey(x_("USER_placement_angle"));
290 us_alignment_ratio_key = makekey(x_("USER_alignment_ratio"));
291 us_alignment_edge_ratio_key = makekey(x_("USER_alignment_edge_ratio"));
292 us_arcstylekey = makekey(x_("USER_arc_style"));
293 us_current_technology_key = makekey(x_("USER_current_technology"));
294 us_current_window_key = makekey(x_("USER_current_window"));
295 us_current_constraint_key = makekey(x_("USER_current_constraint"));
296 us_colormap_red_key = makekey(x_("USER_colormap_red"));
297 us_colormap_green_key = makekey(x_("USER_colormap_green"));
298 us_colormap_blue_key = makekey(x_("USER_colormap_blue"));
299 us_copyright_file_key = makekey(x_("USER_copyright_file"));
300 us_menu_position_key = makekey(x_("USER_menu_position"));
301 us_menu_x_key = makekey(x_("USER_menu_x"));
302 us_menu_y_key = makekey(x_("USER_menu_y"));
303 us_macrorunningkey = makekey(x_("USER_macrorunning"));
304 us_macrobuildingkey = makekey(x_("USER_macrobuilding"));
305 us_text_editorkey = makekey(x_("USER_text_editor"));
306 us_gridfloatskey = makekey(x_("USER_grid_floats"));
307 us_gridboldspacingkey = makekey(x_("USER_grid_bold_spacing"));
308 us_quickkeyskey = makekey(x_("USER_quick_keys"));
309 us_interactiveanglekey = makekey(x_("USER_interactive_angle"));
310 us_tinylambdaperpixelkey = makekey(x_("USER_tiny_lambda_per_pixel"));
311 us_techlaststatekey = makekey(x_("TECH_last_state"));
312 us_optionflagskey = makekey(x_("USER_optionflags"));
313 us_ignoreoptionchangeskey = makekey(x_("USER_ignore_option_changes"));
314 us_displayunitskey = makekey(x_("USER_display_units"));
315 us_electricalunitskey = makekey(x_("USER_electrical_units"));
316 us_motiondelaykey = makekey(x_("USER_motion_delay"));
317 us_java_flags_key = makekey(x_("JAVA_flags"));
318 us_edtec_option_key = makekey(x_("EDTEC_option"));
319
320 /* setup disk file descriptors */
321 us_filetypecadrc = setupfiletype(x_(""), x_("*.*"), MACFSTAG('TEXT'), FALSE, x_("cadrc"), _("Startup"));
322 us_filetypecolormap = setupfiletype(x_("map"), x_("*.map"), MACFSTAG('TEXT'), FALSE, x_("color"), _("Color map"));
323 us_filetypehelp = setupfiletype(x_("help"), x_("*.help"), MACFSTAG('TEXT'), FALSE, x_("help"), _("Help"));
324 us_filetypelog = setupfiletype(x_("log"), x_("*.log"), MACFSTAG('LOG '), FALSE, x_("log"), _("Log"));
325 us_filetypemacro = setupfiletype(x_("mac"), x_("*.mac"), MACFSTAG('TEXT'), FALSE, x_("macro"), _("Macro package"));
326 us_filetypenews = setupfiletype(x_("news"), x_("*.news"), MACFSTAG('TEXT'), FALSE, x_("news"), _("News"));
327
328 /* initially ignore all graphics */
329 us_displayroutine = us_nulldisplayroutine;
330
331 /* set opaque graphics data */
332 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
333 us_figuretechopaque(tech);
334
335 /* set selectability/invisibility on primitives */
336 us_figuretechselectability();
337
338 /* register technology-caching routines */
339 keys[0] = us_layer_letters_key;
340 registertechnologycache(us_initlayerletters, 1, keys);
341
342 /* count the number of commands */
343 us_longcount = 0;
344 for(i=0; us_lcommand[i].name != 0; i++) us_longcount++;
345
346 /* get switches to the program */
347 us_firstlibrary = 0;
348 us_desiredlibrary[0] = 0;
349 us_firstmacrofile = 0;
350 graphicsoptions(x_("display"), argc, argv);
351 if (us_options(argc, argv)) return(TRUE);
352
353 /* establish the library location */
354 setupenvironment();
355
356 /* initialize status output and graphics */
357 if (initgraphics(TRUE)) exit(1);
358 us_getcolormap(el_curtech, COLORSDEFAULT, FALSE);
359 varred = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_red_key);
360 vargreen = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_green_key);
361 varblue = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_blue_key);
362 colormapload((INTBIG *)varred->addr, (INTBIG *)vargreen->addr,
363 (INTBIG *)varblue->addr, 0, 255);
364
365 /* establish the colors to use for peripheral graphics */
366 if (el_maplength == 2)
367 {
368 el_colcelltxt = 0;
369 el_colcell = 0;
370 el_colwinbor = 0;
371 el_colhwinbor = 1;
372 el_colmenbor = 0;
373 el_colhmenbor = 1;
374 el_colmentxt = 0;
375 el_colmengly = 0;
376 el_colcursor = 0;
377 } else
378 {
379 if (el_maplength < 256)
380 {
381 us_gbox.bits = LAYERA;
382 us_gbox.col = BLACK;
383 } else
384 {
385 us_gbox.bits = LAYERG;
386 us_gbox.col = GRID;
387 }
388 el_colcelltxt = CELLTXT;
389 el_colcell = CELLOUT;
390 el_colwinbor = WINBOR;
391 el_colhwinbor = HWINBOR;
392 el_colmenbor = MENBOR;
393 el_colhmenbor = HMENBOR;
394 el_colmentxt = MENTXT;
395 el_colmengly = MENGLY;
396 }
397
398 us_initstatus();
399
400 /* initialize state */
401 nextchangequiet();
402 (void)setval((INTBIG)us_tool, VTOOL, x_("USER_icon_style"),
403 ICONSTYLEDEFAULT, VINTEGER|VDONTSAVE);
404
405 /* create the window frame that has the palette */
406 us_menuframe = newwindowframe(TRUE, 0);
407
408 /* create the initial window structure */
409 wf = newwindowframe(FALSE, 0);
410 if (wf == NOWINDOWFRAME) wf = getwindowframe(FALSE);
411 el_curwindowpart = newwindowpart(x_("entire"), NOWINDOWPART);
412 if (el_curwindowpart == NOWINDOWPART) return(TRUE);
413 el_curwindowpart->frame = wf;
414 nextchangequiet();
415 (void)setvalkey((INTBIG)us_tool, VTOOL, us_current_window_key,
416 (INTBIG)el_curwindowpart, VWINDOWPART|VDONTSAVE);
417 el_curwindowpart->buttonhandler = DEFAULTBUTTONHANDLER;
418 el_curwindowpart->charhandler = DEFAULTCHARHANDLER;
419 el_curwindowpart->changehandler = DEFAULTCHANGEHANDLER;
420 el_curwindowpart->termhandler = DEFAULTTERMHANDLER;
421 el_curwindowpart->redisphandler = DEFAULTREDISPHANDLER;
422
423 /* set shadows */
424 changesquiet(TRUE);
425 us_useroptions = PORTSFULL|CENTEREDPRIMITIVES|AUTOSWITCHTECHNOLOGY|CELLCENTERALWAYS;
426 (void)setvalkey((INTBIG)us_tool, VTOOL, us_optionflagskey,
427 (INTBIG)us_useroptions, VINTEGER|VDONTSAVE);
428 (void)setvalkey((INTBIG)us_tool, VTOOL, us_current_constraint_key,
429 (INTBIG)el_curconstraint, VCONSTRAINT|VDONTSAVE);
430 us_alignment_ratio = WHOLE;
431 us_edgealignment_ratio = 0;
432 (void)setvalkey((INTBIG)us_tool, VTOOL, us_displayunitskey,
433 el_units&DISPLAYUNITS, VINTEGER|VDONTSAVE);
434 us_electricalunits = ELEUNITDEFAULT;
435 (void)setvalkey((INTBIG)us_tool, VTOOL, us_electricalunitskey,
436 us_electricalunits, VINTEGER|VDONTSAVE);
437 changesquiet(FALSE);
438
439 /* if the screen is seriously wide, put menus on the left */
440 getwindowframesize(el_curwindowpart->frame, &swid, &shei);
441 if (swid*2 > shei*3) us_menupos = 2;
442
443 /* display initial message */
444 TDCLEAR(descript);
445 TDSETSIZE(descript, TXTSETPOINTS(20));
446 screensettextinfo(el_curwindowpart, NOTECHNOLOGY, descript);
447 us_box.col = BLACK;
448 esnprintf(msg, 150, _("Electric Version %s"), el_version);
449 screengettextsize(el_curwindowpart, msg, &twid, &thei);
450 screendrawtext(el_curwindowpart, (swid-twid)/2, shei/2+thei, msg, &us_box);
451 estrcpy(msg, _("Loading..."));
452 screengettextsize(el_curwindowpart, msg, &twid, &thei);
453 screendrawtext(el_curwindowpart, (swid-twid)/2, shei/2-thei, msg, &us_box);
454 flushscreen();
455 return(FALSE);
456 }
457
458 /* pass 3 of initialization */
us_do3init(void)459 BOOLEAN us_do3init(void)
460 {
461 REGISTER CHAR *libname, *libfile;
462 REGISTER INTBIG oldverbose, len, lambda, haveoptionsfile, *msgloc, filestatus;
463 REGISTER VARIABLE *var, *varred, *vargreen, *varblue;
464 CHAR *newpar[3], clipboardname[20];
465 REGISTER LIBRARY *lib;
466
467 /* default command binding */
468 if (us_initialbinding()) return(TRUE);
469
470 /* initial display in status area */
471 us_redostatus(NOWINDOWFRAME);
472
473 /* set application environment */
474 #if LANGLISP
475 nextchangequiet();
476 (void)setvalkey((INTBIG)us_tool, VTOOL, makekey(x_("USER_have_lisp")), 1,
477 VINTEGER|VDONTSAVE);
478 #endif
479 #if LANGTCL
480 nextchangequiet();
481 (void)setvalkey((INTBIG)us_tool, VTOOL, makekey(x_("USER_have_tcl")), 1,
482 VINTEGER|VDONTSAVE);
483 #endif
484 #if LANGJAVA
485 nextchangequiet();
486 (void)setvalkey((INTBIG)us_tool, VTOOL, makekey(x_("USER_have_java")), 1,
487 VINTEGER|VDONTSAVE);
488 #endif
489
490 #ifdef FORCECADENCE
491 nextchangequiet();
492 (void)setvalkey((INTBIG)us_tool, VTOOL, makekey(x_("USER_have_cadence")), 1,
493 VINTEGER|VDONTSAVE);
494 #endif
495
496 #ifdef FORCESUNTOOLS
497 nextchangequiet();
498 (void)setvalkey((INTBIG)us_tool, VTOOL, makekey(x_("USER_have_suntools")), 1,
499 VINTEGER|VDONTSAVE);
500 #endif
501
502 /* set variable to tell whether there needs to be a quit command */
503 if (!graphicshas(CANHAVEQUITCOMMAND))
504 {
505 nextchangequiet();
506 (void)setvalkey((INTBIG)us_tool, VTOOL, makekey(x_("USER_no_quit_command")), 1,
507 VINTEGER|VDONTSAVE);
508 }
509
510 /* read "cadrc" files */
511 if (!us_ignore_cadrc) us_findcadrc();
512 if (us_firstmacrofile != 0)
513 {
514 if (us_docadrc(us_firstmacrofile))
515 ttyputerr(_("Cannot find startup file '%s'"), us_firstmacrofile);
516 efree((CHAR *)us_firstmacrofile);
517 us_firstmacrofile = 0;
518 }
519
520 /* gather initial quick keys and remember them as "factory settings" */
521 us_buildquickkeylist();
522 us_getquickkeylist(&us_quickkeyfactcount, &us_quickkeyfactlist);
523 if (us_quickkeyfactcount > 0)
524 {
525 (void)setvalkey((INTBIG)us_tool, VTOOL, us_quickkeyskey, (INTBIG)us_quickkeyfactlist,
526 VSTRING|VISARRAY|(us_quickkeyfactcount<<VLENGTHSH)|VDONTSAVE);
527 }
528
529 /* initial setup of the color map */
530 us_getcolormap(el_curtech, COLORSDEFAULT, FALSE);
531
532 /* mark the current state of the color map as "unchanged" */
533 varred = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_red_key);
534 vargreen = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_green_key);
535 varblue = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_blue_key);
536 if (varred != NOVARIABLE) varred->type |= VDONTSAVE;
537 if (vargreen != NOVARIABLE) vargreen->type |= VDONTSAVE;
538 if (varblue != NOVARIABLE) varblue->type |= VDONTSAVE;
539
540 /* read the options library */
541 libname = us_tempoptionslibraryname();
542 libfile = optionsfilepath();
543 haveoptionsfile = 0;
544 filestatus = fileexistence(truepath(libfile));
545 if (filestatus == 1 || filestatus == 3)
546 {
547 haveoptionsfile = 1;
548 lib = newlibrary(libname, libfile);
549 if (lib == NOLIBRARY) ttyputerr(_("Cannot create options library %s"), libfile); else
550 {
551 lib->userbits |= HIDDENLIBRARY;
552 oldverbose = asktool(io_tool, x_("verbose"), 0);
553 (void)asktool(io_tool, x_("read"), (INTBIG)lib, (INTBIG)x_("binary"));
554 (void)asktool(io_tool, x_("verbose"), oldverbose);
555 killlibrary(lib);
556
557 /* adjust messages window position if information is there */
558 var = getval((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, x_("USER_messages_position"));
559 if (var != NOVARIABLE)
560 {
561 msgloc = (INTBIG *)var->addr;
562 setmessagesframeinfo(msgloc[0], msgloc[1], msgloc[2], msgloc[3]);
563 }
564 }
565 }
566 cacheoptionbitvalues();
567
568 /* read an initial library if it was specified in program parameters */
569 if (us_firstlibrary != 0)
570 {
571 if (reallocstring(&el_curlib->libfile, us_firstlibrary, el_curlib->cluster) != 0)
572 return(TRUE);
573 libname = skippath(us_firstlibrary);
574 if (reallocstring(&el_curlib->libname, libname, el_curlib->cluster) != 0)
575 return(TRUE);
576 len = estrlen(el_curlib->libname);
577 if (namesame(&el_curlib->libname[len-5], x_(".elib")) == 0)
578 el_curlib->libname[len-5] = 0;
579 if (asktool(io_tool, x_("read"), (INTBIG)el_curlib, (INTBIG)x_("binary")) != 0)
580 {
581 ttyputerr(_("Could not read %s"), el_curlib->libfile);
582 el_curlib->curnodeproto = NONODEPROTO;
583 } else
584 {
585 if (el_curlib->curnodeproto != NONODEPROTO)
586 {
587 if (el_curlib->curnodeproto->tech != gen_tech)
588 el_curtech = el_curlib->curnodeproto->tech;
589 if (el_curtech != sch_tech && el_curtech != art_tech && el_curtech != gen_tech)
590 el_curlayouttech = el_curtech;
591 }
592 }
593 efree((CHAR *)us_firstlibrary);
594 us_firstlibrary = 0;
595 } else el_curlib->curnodeproto = NONODEPROTO;
596
597 /* set the user's shadow of the current technology */
598 (void)setvalkey((INTBIG)us_tool, VTOOL, us_current_technology_key,
599 (INTBIG)el_curtech, VTECHNOLOGY|VDONTSAVE);
600
601 /* setup menu properly */
602 if (el_curtech != sch_tech)
603 {
604 newpar[0] = x_("size");
605 newpar[1] = x_("auto");
606 us_menu(2, newpar);
607 us_setmenunodearcs();
608 }
609
610 /* load the color map onto the display */
611 varred = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_red_key);
612 vargreen = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_green_key);
613 varblue = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_blue_key);
614 colormapload((INTBIG *)varred->addr, (INTBIG *)vargreen->addr,
615 (INTBIG *)varblue->addr, 0, 255);
616
617 /* setup current window */
618 lambda = el_curlib->lambda[el_curtech->techindex];
619 if (el_curwindowpart != NOWINDOWPART)
620 {
621 var = getval((INTBIG)us_tool, VTOOL, VFRACT|VISARRAY, x_("USER_default_grid"));
622 if (var == NOVARIABLE)
623 {
624 el_curwindowpart->gridx = el_curwindowpart->gridy = WHOLE;
625 } else
626 {
627 el_curwindowpart->gridx = ((INTBIG *)var->addr)[0];
628 el_curwindowpart->gridy = ((INTBIG *)var->addr)[1];
629 }
630 }
631 us_curarcproto = el_curtech->firstarcproto;
632 us_curnodeproto = NONODEPROTO;
633
634 /* create the clipboard cell */
635 estrcpy(clipboardname, x_("Clipboard!!"));
636 us_clipboardlib = newlibrary(clipboardname, clipboardname);
637 us_clipboardlib->userbits |= HIDDENLIBRARY;
638 us_clipboardcell = newnodeproto(clipboardname, us_clipboardlib);
639
640 /* now allow graphics to reach the screen */
641 us_displayroutine = us_showpoly;
642
643 /* now draw everything */
644 us_drawmenu(1, NOWINDOWFRAME); /* draw basic screen layout */
645
646 #ifndef MACOS
647 if (haveoptionsfile == 0)
648 {
649 if ((us_tool->toolstate&USEDIALOGS) != 0)
650 {
651 (void)us_aboutdlog();
652 } else
653 ttyputmsg(_("Electric, from Static Free Software"));
654 }
655 #endif
656
657 /* if there is a current cell in the library, edit it */
658 if (el_curlib->curnodeproto != NONODEPROTO)
659 {
660 newpar[0] = x_("editcell");
661 newpar[1] = describenodeproto(el_curlib->curnodeproto);
662 telltool(us_tool, 2, newpar);
663
664 /* must reset the library-changed bit now */
665 el_curlib->curnodeproto->lib->userbits &= ~(LIBCHANGEDMAJOR | LIBCHANGEDMINOR);
666 }
667
668 /* now end the batch to force these changes to be processed properly */
669 us_endbatch();
670 us_optionschanged = FALSE; /* options are unchanged */
671 return(FALSE);
672 }
673
674 /* terminate the user interface tool */
us_done(void)675 void us_done(void)
676 {
677 REGISTER WINDOWPART *w;
678 #ifdef DEBUGMEMORY
679 REGISTER INTBIG i;
680 #endif
681
682 /* close messages audit window */
683 if (us_termaudit != 0) xclose(us_termaudit);
684
685 /* delete all windows */
686 if (us_menuframe != NOWINDOWFRAME)
687 killwindowframe(us_menuframe);
688 while (el_topwindowpart != NOWINDOWPART)
689 {
690 w = el_topwindowpart;
691 el_topwindowpart = el_topwindowpart->nextwindowpart;
692 killwindowpart(w);
693 }
694
695 logfinishrecord();
696 termgraphics();
697
698 /* close trace */
699 if (us_tracefile != NULL)
700 {
701 xclose(us_tracefile);
702 us_tracefile = NULL;
703 }
704
705 #ifdef DEBUGMEMORY
706 /* free popups */
707 while (us_firstpopupmenu != NOPOPUPMENU)
708 {
709 REGISTER POPUPMENU *pm;
710 REGISTER POPUPMENUITEM *mi;
711
712 pm = us_firstpopupmenu;
713 us_firstpopupmenu = us_firstpopupmenu->nextpopupmenu;
714 efree((CHAR *)pm->name);
715 efree((CHAR *)pm->header);
716 efree((CHAR *)pm->list);
717 for(i=0; i<pm->total; i++)
718 {
719 mi = &pm->list[i];
720 efree((CHAR *)mi->attribute);
721 if (mi->value != 0) efree((CHAR *)mi->value);
722 us_freeusercom(mi->response);
723 }
724 efree((CHAR *)pm);
725 }
726 noundoallowed();
727 us_freeparsememory();
728 us_freehighmemory();
729 us_freemiscmemory();
730 us_freecomekmemory();
731 us_freecomtvmemory();
732 us_freediacommemory();
733 us_freenetmemory();
734 us_freeedtecpmemory();
735 us_freeedpacmemory();
736 us_freeedemacsmemory();
737 us_freetranslatememory();
738
739 /* free user commands */
740 while (us_usercomfree != NOUSERCOM)
741 {
742 REGISTER USERCOM *uc;
743
744 uc = us_usercomfree;
745 us_usercomfree = us_usercomfree->nextcom;
746 efree((CHAR *)uc);
747 }
748
749 /* free remembered command */
750 for(i=0; i<us_lastcommandtotal; i++)
751 {
752 if (us_lastcommandpar[i] != 0)
753 efree((CHAR *)us_lastcommandpar[i]);
754 }
755 efree((CHAR *)us_lastcommandpar);
756
757 /* free miscellaneous memory */
758 us_freestatusmemory();
759 us_freewindowmemory();
760
761 /* free quick-key settings */
762 {
763 REGISTER INTBIG i;
764
765 for(i=0; i<us_quickkeyfactcount; i++)
766 efree((CHAR *)us_quickkeyfactlist[i]);
767 }
768 if (us_quickkeyfactcount > 0) efree((CHAR *)us_quickkeyfactlist);
769
770 /* free pulldown bar */
771 if (us_pulldownmenucount != 0)
772 {
773 efree((CHAR *)us_pulldowns);
774 efree((CHAR *)us_pulldownmenupos);
775 }
776 us_pulldownmenucount = 0;
777 #endif
778 }
779
780 /* set the nature of the user interface tool */
us_set(INTBIG count,CHAR * par[])781 void us_set(INTBIG count, CHAR *par[])
782 {
783 REGISTER USERCOM *com;
784 REGISTER INTBIG i;
785 REGISTER void *infstr;
786
787 if (count == 0) return;
788
789 infstr = initinfstr();
790 for(i=0; i<count; i++)
791 {
792 addstringtoinfstr(infstr, par[i]);
793 addtoinfstr(infstr, ' ');
794 }
795 com = us_makecommand(returninfstr(infstr));
796 us_execute(com, FALSE, TRUE, FALSE);
797 us_freeusercom(com);
798 }
799
800 /*
801 * make requests of the user interface tool:
802 *
803 ***************** CONTROL OF HIGHLIGHTING ****************
804 * "show-object" TAKES: the GEOM module to highlight
805 * "show-port" TAKES: the GEOM module and PORTPROTO to highlight
806 * "show-area" TAKES: the lowx, highx, lowy, highy, cell of an area
807 * "show-line" TAKES: the x1, y1, x2, y2, cell of a line
808 * "show-multiple" TAKES: string of GEOM addresses separated by tabs
809 * "clear" clears all highlighting
810 * "down-stack" saves the currently highlighted objects on a stack
811 * "up-stack" restores the stacked highlighted objects
812 *
813 ***************** INFORMATION ABOUT HIGHLIGHTED OBJECTS ****************
814 * "get-node" RETURNS: the currently highlighted NODEINST
815 * "get-port" RETURNS: the currently highlighted PORTPROTO
816 * "get-arc" RETURNS: the currently highlighted ARCINST
817 * "get-object" RETURNS: the currently highlighted GEOM
818 * "get-all-nodes" RETURNS: a list of GEOMs
819 * "get-all-arcs" RETURNS: a list of GEOMs
820 * "get-all-objects" RETURNS: a list of GEOMs
821 * "get-highlighted-area" TAKES: reference lx, hx, ly, hy bounds RETGURNS: cell
822 *
823 ***************** WINDOW CONTROL ****************
824 * "window-new" RETURNS: newly created window
825 * "window-horiz-new" RETURNS: newly created window (prefers horizontal split)
826 * "window-vert-new" RETURNS: newly created window (prefers vertical split)
827 * "display-to-routine" TAKES: routine to call with polygons
828 * "display-highlighted-to-routine" TAKES: routine to call with polygons
829 * "flush-changes" forces display changes to be visible
830 *
831 ***************** EDITOR CONTROL ****************
832 * "edit-starteditor" TAKES: window, header, &chars, &lines RETURNS: zero: ok
833 * "edit-totallines" TAKES: window RETURNS: number of lines of text
834 * "edit-getline" TAKES: window and line index RETURNS: string
835 * "edit-addline" TAKES: window and line index and string to insert
836 * "edit-replaceline" TAKES: window and line index and new string
837 * "edit-deleteline" TAKES: window and line index to delete
838 * "edit-highlightline" TAKES: window and line index to highlight
839 * "edit-suspendgraphics" TAKES: window in which to suspends display changes
840 * "edit-resumegraphics" TAKES: window in which to resumes display of changes
841 * "edit-describe" RETURNS: name of editor
842 * "edit-readfile" TAKES: window and file name
843 * "edit-writefile" TAKES: window and file name
844 *
845 ***************** MISCELLANEOUS ****************
846 * "make-icon" TAKES: portlist, icon name, cell name, library RETURNS: cell
847 */
us_request(CHAR * command,va_list ap)848 INTBIG us_request(CHAR *command, va_list ap)
849 {
850 HIGHLIGHT newhigh;
851 REGISTER GEOM *from;
852 REGISTER PORTPROTO *pp;
853 REGISTER VARIABLE *var;
854 REGISTER NODEPROTO *np;
855 REGISTER void (*curdisplay)(POLYGON*, WINDOWPART*);
856 REGISTER INTBIG len, i, arg1, arg2, arg3, arg4, arg5;
857 REGISTER GEOM **list;
858
859 if (namesamen(command, x_("get-"), 4) == 0)
860 {
861 if (namesame(&command[4], x_("node")) == 0)
862 return((INTBIG)us_getobject(VNODEINST, FALSE));
863 if (namesame(&command[4], x_("arc")) == 0)
864 return((INTBIG)us_getobject(VARCINST, FALSE));
865 if (namesame(&command[4], x_("object")) == 0)
866 {
867 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
868 if (var == NOVARIABLE) return(-1);
869 len = getlength(var);
870 if (len > 1) return(-1);
871 (void)us_makehighlight(((CHAR **)var->addr)[0], &newhigh);
872 if ((newhigh.status&HIGHTYPE) != HIGHFROM) return(-1);
873 return((INTBIG)newhigh.fromgeom);
874 }
875 if (namesame(&command[4], x_("port")) == 0)
876 {
877 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
878 if (var == NOVARIABLE) return(-1);
879 len = getlength(var);
880 if (len > 1) return(-1);
881 (void)us_makehighlight(((CHAR **)var->addr)[0], &newhigh);
882 if ((newhigh.status&HIGHTYPE) != HIGHFROM || !newhigh.fromgeom->entryisnode)
883 return(-1);
884 return((INTBIG)newhigh.fromport);
885 }
886 if (namesame(&command[4], x_("all-nodes")) == 0)
887 return((INTBIG)us_gethighlighted(WANTNODEINST, 0, 0));
888 if (namesame(&command[4], x_("all-arcs")) == 0)
889 return((INTBIG)us_gethighlighted(WANTARCINST, 0, 0));
890 if (namesame(&command[4], x_("all-objects")) == 0)
891 return((INTBIG)us_gethighlighted(WANTNODEINST|WANTARCINST, 0, 0));
892 if (namesame(&command[4], x_("highlighted-area")) == 0)
893 {
894 /* get the arguments */
895 arg1 = va_arg(ap, INTBIG);
896 arg2 = va_arg(ap, INTBIG);
897 arg3 = va_arg(ap, INTBIG);
898 arg4 = va_arg(ap, INTBIG);
899 return((INTBIG)us_getareabounds((INTBIG *)arg1, (INTBIG *)arg2, (INTBIG *)arg3, (INTBIG *)arg4));
900 }
901 }
902
903 if (namesamen(command, x_("edit-"), 5) == 0)
904 {
905 if (namesame(&command[5], x_("getline")) == 0)
906 {
907 /* get the arguments */
908 arg1 = va_arg(ap, INTBIG);
909 arg2 = va_arg(ap, INTBIG);
910 return((INTBIG)us_getline((WINDOWPART *)arg1, arg2));
911 }
912 if (namesame(&command[5], x_("totallines")) == 0)
913 {
914 /* get the arguments */
915 arg1 = va_arg(ap, INTBIG);
916 return(us_totallines((WINDOWPART *)arg1));
917 }
918 if (namesame(&command[5], x_("addline")) == 0)
919 {
920 /* get the arguments */
921 arg1 = va_arg(ap, INTBIG);
922 arg2 = va_arg(ap, INTBIG);
923 arg3 = va_arg(ap, INTBIG);
924 us_addline((WINDOWPART *)arg1, arg2, (CHAR *)arg3);
925 return(0);
926 }
927 if (namesame(&command[5], x_("replaceline")) == 0)
928 {
929 /* get the arguments */
930 arg1 = va_arg(ap, INTBIG);
931 arg2 = va_arg(ap, INTBIG);
932 arg3 = va_arg(ap, INTBIG);
933 us_replaceline((WINDOWPART *)arg1, arg2, (CHAR *)arg3);
934 return(0);
935 }
936 if (namesame(&command[5], x_("deleteline")) == 0)
937 {
938 /* get the arguments */
939 arg1 = va_arg(ap, INTBIG);
940 arg2 = va_arg(ap, INTBIG);
941 us_deleteline((WINDOWPART *)arg1, arg2);
942 return(0);
943 }
944 if (namesame(&command[5], x_("highlightline")) == 0)
945 {
946 /* get the arguments */
947 arg1 = va_arg(ap, INTBIG);
948 arg2 = va_arg(ap, INTBIG);
949 us_highlightline((WINDOWPART *)arg1, arg2, arg2);
950 return(0);
951 }
952 if (namesame(&command[5], x_("starteditor")) == 0)
953 {
954 /* get the arguments */
955 arg1 = va_arg(ap, INTBIG);
956 arg2 = va_arg(ap, INTBIG);
957 arg3 = va_arg(ap, INTBIG);
958 arg4 = va_arg(ap, INTBIG);
959 if (us_makeeditor((WINDOWPART *)arg1, (CHAR *)arg2, (INTBIG *)arg3,
960 (INTBIG *)arg4) == NOWINDOWPART) return(-1);
961 return(0);
962 }
963 if (namesame(&command[5], x_("suspendgraphics")) == 0)
964 {
965 /* get the arguments */
966 arg1 = va_arg(ap, INTBIG);
967 us_suspendgraphics((WINDOWPART *)arg1);
968 return(0);
969 }
970 if (namesame(&command[5], x_("resumegraphics")) == 0)
971 {
972 /* get the arguments */
973 arg1 = va_arg(ap, INTBIG);
974 us_resumegraphics((WINDOWPART *)arg1);
975 return(0);
976 }
977 if (namesame(&command[5], x_("describe")) == 0)
978 {
979 /* get the arguments */
980 arg1 = va_arg(ap, INTBIG);
981 us_describeeditor((CHAR **)arg1);
982 return(0);
983 }
984 if (namesame(&command[5], x_("readfile")) == 0)
985 {
986 /* get the arguments */
987 arg1 = va_arg(ap, INTBIG);
988 arg2 = va_arg(ap, INTBIG);
989 us_readtextfile((WINDOWPART *)arg1, (CHAR *)arg2);
990 return(0);
991 }
992 if (namesame(&command[5], x_("writefile")) == 0)
993 {
994 /* get the arguments */
995 arg1 = va_arg(ap, INTBIG);
996 arg2 = va_arg(ap, INTBIG);
997 us_writetextfile((WINDOWPART *)arg1, (CHAR *)arg2);
998 return(0);
999 }
1000 }
1001
1002 if (namesamen(command, x_("show-"), 5) == 0)
1003 {
1004 if (namesame(&command[5], x_("object")) == 0)
1005 {
1006 /* get the arguments */
1007 arg1 = va_arg(ap, INTBIG);
1008
1009 /* fill in the highlight information */
1010 from = (GEOM *)arg1;
1011 us_ensurewindow(geomparent(from));
1012 newhigh.status = HIGHFROM;
1013 newhigh.cell = geomparent(from);
1014 newhigh.fromgeom = from;
1015 newhigh.fromport = NOPORTPROTO;
1016 newhigh.frompoint = 0;
1017 us_addhighlight(&newhigh);
1018 us_showallhighlight();
1019 return(0);
1020 }
1021 if (namesame(&command[5], x_("port")) == 0)
1022 {
1023 /* get the arguments */
1024 arg1 = va_arg(ap, INTBIG);
1025 arg2 = va_arg(ap, INTBIG);
1026
1027 /* fill in the highlight information */
1028 from = (GEOM *)arg1;
1029 pp = (PORTPROTO *)arg2;
1030 us_ensurewindow(geomparent(from));
1031 newhigh.status = HIGHFROM;
1032 newhigh.cell = geomparent(from);
1033 newhigh.fromgeom = from;
1034 newhigh.fromport = pp;
1035 newhigh.frompoint = 0;
1036 us_addhighlight(&newhigh);
1037 us_showallhighlight();
1038 return(0);
1039 }
1040 if (namesame(&command[5], x_("line")) == 0)
1041 {
1042 /* get the arguments */
1043 arg1 = va_arg(ap, INTBIG);
1044 arg2 = va_arg(ap, INTBIG);
1045 arg3 = va_arg(ap, INTBIG);
1046 arg4 = va_arg(ap, INTBIG);
1047 arg5 = va_arg(ap, INTBIG);
1048
1049 np = (NODEPROTO *)arg5;
1050 if (np == NONODEPROTO) return(0);
1051
1052 /* fill in the highlight information */
1053 us_ensurewindow(np);
1054 newhigh.status = HIGHLINE;
1055 newhigh.cell = np;
1056 newhigh.stalx = arg1;
1057 newhigh.staly = arg2;
1058 newhigh.stahx = arg3;
1059 newhigh.stahy = arg4;
1060 us_addhighlight(&newhigh);
1061 us_showallhighlight();
1062 return(0);
1063 }
1064 if (namesame(&command[5], x_("area")) == 0)
1065 {
1066 /* get the arguments */
1067 arg1 = va_arg(ap, INTBIG);
1068 arg2 = va_arg(ap, INTBIG);
1069 arg3 = va_arg(ap, INTBIG);
1070 arg4 = va_arg(ap, INTBIG);
1071 arg5 = va_arg(ap, INTBIG);
1072
1073 np = (NODEPROTO *)arg5;
1074 if (np == NONODEPROTO) return(0);
1075
1076 /* fill in the highlight information */
1077 us_ensurewindow(np);
1078 newhigh.status = HIGHBBOX;
1079 newhigh.cell = np;
1080 newhigh.stalx = arg1;
1081 newhigh.stahx = arg2;
1082 newhigh.staly = arg3;
1083 newhigh.stahy = arg4;
1084 us_addhighlight(&newhigh);
1085 us_showallhighlight();
1086 return(0);
1087 }
1088 if (namesame(&command[5], x_("multiple")) == 0)
1089 {
1090 /* get the arguments */
1091 arg1 = va_arg(ap, INTBIG);
1092
1093 /* fill in the highlight information */
1094 us_setmultiplehighlight((CHAR *)arg1, FALSE);
1095 us_showallhighlight();
1096 return(0);
1097 }
1098 }
1099
1100 if (namesame(command, x_("flush-changes")) == 0)
1101 {
1102 us_endchanges(NOWINDOWPART);
1103 us_showallhighlight();
1104 us_beginchanges();
1105 return(0);
1106 }
1107
1108 if (namesame(command, x_("display-to-routine")) == 0)
1109 {
1110 if (el_curwindowpart == NOWINDOWPART) return(0);
1111
1112 /* get the arguments */
1113 arg1 = va_arg(ap, INTBIG);
1114
1115 /* code cannot be called by multiple procesors: uses globals */
1116 NOT_REENTRANT;
1117
1118 curdisplay = us_displayroutine;
1119 us_displayroutine = (void (*)(POLYGON*, WINDOWPART*))arg1;
1120 us_redisplaynow(el_curwindowpart, FALSE);
1121 us_endchanges(el_curwindowpart);
1122 us_displayroutine = curdisplay;
1123 return(0);
1124 }
1125
1126 if (namesame(command, x_("display-highlighted-to-routine")) == 0)
1127 {
1128 if (el_curwindowpart == NOWINDOWPART) return(0);
1129
1130 /* get the arguments */
1131 arg1 = va_arg(ap, INTBIG);
1132
1133 /* code cannot be called by multiple procesors: uses globals */
1134 NOT_REENTRANT;
1135
1136 curdisplay = us_displayroutine;
1137 us_displayroutine = (void (*)(POLYGON*, WINDOWPART*))arg1;
1138
1139 /* get the objects to be displayed */
1140 list = us_gethighlighted(WANTNODEINST | WANTARCINST, 0, 0);
1141 begintraversehierarchy();
1142 for(i=0; list[i] != NOGEOM; i++)
1143 {
1144 if (list[i]->entryisnode)
1145 {
1146 if (us_drawcell(list[i]->entryaddr.ni, LAYERA,
1147 el_matid, 3, el_curwindowpart) < 0) break;
1148 } else
1149 {
1150 if (us_drawarcinst(list[i]->entryaddr.ai, LAYERA,
1151 el_matid, 3, el_curwindowpart) < 0) break;
1152 }
1153 }
1154 us_displayroutine = curdisplay;
1155 endtraversehierarchy();
1156 return(0);
1157 }
1158
1159 if (namesame(command, x_("make-icon")) == 0)
1160 {
1161 /* get the arguments */
1162 arg1 = va_arg(ap, INTBIG);
1163 arg2 = va_arg(ap, INTBIG);
1164 arg3 = va_arg(ap, INTBIG);
1165 arg4 = va_arg(ap, INTBIG);
1166
1167 return((INTBIG)us_makeiconcell((PORTPROTO *)arg1, (CHAR *)arg2,
1168 (CHAR *)arg3, (LIBRARY *)arg4));
1169 }
1170
1171 if (namesamen(command, x_("window-"), 7) == 0)
1172 {
1173 /* get a new window */
1174 if (namesame(&command[7], x_("new")) == 0)
1175 {
1176 return((INTBIG)us_wantnewwindow(0));
1177 }
1178 if (namesame(&command[7], x_("horiz-new")) == 0)
1179 {
1180 if (us_needwindow()) return(0);
1181 return((INTBIG)us_wantnewwindow(1));
1182 }
1183 if (namesame(&command[7], x_("vert-new")) == 0)
1184 {
1185 if (us_needwindow()) return(0);
1186 return((INTBIG)us_wantnewwindow(2));
1187 }
1188 return(0);
1189 }
1190
1191 if (namesame(command, x_("down-stack")) == 0)
1192 {
1193 us_pushhighlight();
1194 return(0);
1195 }
1196
1197 if (namesame(command, x_("up-stack")) == 0)
1198 {
1199 us_pophighlight(FALSE);
1200 return(0);
1201 }
1202
1203 if (namesame(command, x_("clear")) == 0)
1204 {
1205 us_clearhighlightcount();
1206 return(0);
1207 }
1208 return(-1);
1209 }
1210
1211 /* examine an entire cell */
us_examinenodeproto(NODEPROTO * np)1212 void us_examinenodeproto(NODEPROTO *np) { Q_UNUSED( np ); }
1213
1214 /* one time slice for the user tool: process a command */
us_slice(void)1215 void us_slice(void)
1216 {
1217 #ifndef USEQT
1218 INTBIG special, but, x, y;
1219 INTSML cmd;
1220 #endif
1221 CHAR *args[4];
1222
1223 if (us_desiredlibrary[0] != 0)
1224 {
1225 args[0] = x_("read");
1226 args[1] = us_desiredlibrary;
1227 args[2] = x_("make-current");
1228 us_library(3, args);
1229 us_desiredlibrary[0] = 0;
1230 }
1231
1232 /* reset the cursor if it was waiting */
1233 if (us_cursorstate == WAITCURSOR)
1234 setdefaultcursortype(us_normalcursor);
1235
1236 /* switch to the right technology */
1237 if ((us_state&CURCELLCHANGED) != 0)
1238 {
1239 us_state &= ~CURCELLCHANGED;
1240 if (el_curwindowpart != NOWINDOWPART)
1241 {
1242 switch (el_curwindowpart->state&WINDOWTYPE)
1243 {
1244 case DISPWINDOW:
1245 case DISP3DWINDOW:
1246 us_ensurepropertechnology(el_curwindowpart->curnodeproto, 0, FALSE);
1247 break;
1248 }
1249 us_setcellsize(el_curwindowpart);
1250 return;
1251 }
1252 }
1253
1254 /* set all cell message changes detected during the last broadcast */
1255 us_doubchanges();
1256
1257 /* handle language loops */
1258 if ((us_state&LANGLOOP) != 0)
1259 {
1260 if (languageconverse(0))
1261 {
1262 us_state &= ~LANGLOOP;
1263 ttyputmsg(_("Back to Electric"));
1264 }
1265
1266 setactivity(_("Language Interpreter"));
1267
1268 /* set all cell message changes detected during the last broadcast */
1269 us_doubchanges();
1270 return;
1271 }
1272
1273 /* start logging now if requested */
1274 if (us_logging)
1275 {
1276 logstartrecord();
1277 us_logging = FALSE;
1278 }
1279
1280 #ifndef USEQT
1281 /* first see if there is any pending input */
1282 el_pleasestop = 0;
1283 if (ttydataready())
1284 {
1285 el_pleasestop = 0;
1286 stoptablet();
1287 cmd = ttygetchar(&special);
1288 us_oncommand(cmd, special);
1289 return;
1290 }
1291 if (el_pleasestop != 0) return;
1292
1293 /* get a button */
1294 waitforbutton(&x, &y, &but);
1295 if (el_pleasestop != 0) return;
1296 if (but < 0) return;
1297
1298 /* execute the button */
1299 us_ontablet(x, y, but);
1300 #endif
1301 }
1302
1303 /*
1304 * handle button pushes
1305 */
us_ontablet(INTBIG x,INTBIG y,INTBIG but)1306 void us_ontablet(INTBIG x, INTBIG y, INTBIG but)
1307 {
1308 REGISTER USERCOM *item;
1309 REGISTER CHAR *str;
1310 CHAR *par[2];
1311 INTBIG lx, hx, ly, hy;
1312 BOOLEAN verbose, drawexplorericon;
1313 REGISTER VARIABLE *var;
1314 REGISTER LIBRARY *lib;
1315 REGISTER NODEPROTO *np;
1316 REGISTER WINDOWPART *w;
1317 REGISTER WINDOWFRAME *curframe, *wf;
1318 COMMANDBINDING commandbinding;
1319
1320 /* reset single-key suspension flag */
1321 if ((us_state&SKIPKEYS) != 0)
1322 {
1323 ttyputmsg(_("Single-key command suspension now lifted"));
1324 us_state &= ~SKIPKEYS;
1325 }
1326
1327 /* wheel rolls get handled immediately */
1328 if (wheelbutton(but))
1329 {
1330 if (el_curwindowpart->buttonhandler != 0)
1331 {
1332 (*el_curwindowpart->buttonhandler)(el_curwindowpart, but, x, y);
1333 }
1334 return;
1335 }
1336
1337 /* first see if this is a slide to a window partition divider */
1338 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1339 {
1340 /* see if the cursor is over a window partition separator */
1341 us_gettruewindowbounds(w, &lx, &hx, &ly, &hy);
1342 if (x >= lx-1 && x <= lx+1 && y > ly+1 && y < hy-1 &&
1343 us_hasotherwindowpart(lx-10, y, w))
1344 {
1345 us_vpartdividerbegin(x, ly, hy, w->frame);
1346 trackcursor(FALSE, us_nullup, us_nullvoid, us_vpartdividerdown, us_nullchar,
1347 us_vpartdividerdone, TRACKNORMAL);
1348 return;
1349 } else if (x >= hx-1 && x <= hx+1 && y > ly+1 && y < hy-1 &&
1350 us_hasotherwindowpart(hx+10, y, w))
1351 {
1352 us_vpartdividerbegin(x, ly, hy, w->frame);
1353 trackcursor(FALSE, us_nullup, us_nullvoid, us_vpartdividerdown, us_nullchar,
1354 us_vpartdividerdone, TRACKNORMAL);
1355 return;
1356 } else if (y >= ly-1 && y <= ly+1 && x > lx+1 && x < hx-1 &&
1357 us_hasotherwindowpart(x, ly-10, w))
1358 {
1359 us_hpartdividerbegin(y, lx, hx, w->frame);
1360 trackcursor(FALSE, us_nullup, us_nullvoid, us_hpartdividerdown, us_nullchar,
1361 us_hpartdividerdone, TRACKNORMAL);
1362 return;
1363 } else if (y >= hy-1 && y <= hy+1 && x > lx+1 && x < hx-1 &&
1364 us_hasotherwindowpart(x, hy+10, w))
1365 {
1366 us_hpartdividerbegin(y, lx, hx, w->frame);
1367 trackcursor(FALSE, us_nullup, us_nullvoid, us_hpartdividerdown, us_nullchar,
1368 us_hpartdividerdone, TRACKNORMAL);
1369 return;
1370 }
1371 }
1372
1373 /* switch windows to the current frame */
1374 curframe = getwindowframe(TRUE);
1375 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1376 {
1377 if (w->frame != curframe) continue;
1378 if (x >= w->uselx && x <= w->usehx && y >= w->usely && y <= w->usehy)
1379 {
1380 /* make this window the current one */
1381 if (w != el_curwindowpart)
1382 {
1383 (void)setvalkey((INTBIG)us_tool, VTOOL, us_current_window_key, (INTBIG)w,
1384 VWINDOWPART|VDONTSAVE);
1385 if (w->curnodeproto == NONODEPROTO) lib = el_curlib; else
1386 lib = w->curnodeproto->lib;
1387 (void)setval((INTBIG)lib, VLIBRARY, x_("curnodeproto"),
1388 (INTBIG)w->curnodeproto, VNODEPROTO);
1389 }
1390 break;
1391 }
1392 }
1393
1394 /* see if it is a fixed menu hit */
1395 if ((us_tool->toolstate&MENUON) != 0 &&
1396 (us_menuframe == NOWINDOWFRAME || curframe == us_menuframe) &&
1397 y >= us_menuly && y <= us_menuhy && x >= us_menulx && x <= us_menuhx)
1398 {
1399 x = (x-us_menulx) / us_menuxsz;
1400 y = (y-us_menuly) / us_menuysz;
1401 if (x < 0 || y < 0 || x >= us_menux || y >= us_menuy) return;
1402 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_binding_menu_key);
1403 if (var == NOVARIABLE) return;
1404 if (us_menupos <= 1) str = ((CHAR **)var->addr)[y * us_menux + x]; else
1405 str = ((CHAR **)var->addr)[x * us_menuy + y];
1406 us_parsebinding(str, &commandbinding);
1407 item = us_makecommand(commandbinding.command);
1408 us_freebindingparse(&commandbinding);
1409 if (item == NOUSERCOM || item->active < 0)
1410 {
1411 ttyputerr(_("No command is attached to this menu entry"));
1412 if (item != NOUSERCOM) us_freeusercom(item);
1413 return;
1414 }
1415 if ((us_tool->toolstate&ONESHOTMENU) != 0)
1416 {
1417 us_menuhnx = x; us_menuhny = y;
1418 us_highlightmenu(x, y, el_colhmenbor);
1419 }
1420 us_state &= ~GOTXY;
1421 us_forceeditchanges();
1422 if ((us_tool->toolstate&ECHOBIND) != 0) verbose = TRUE; else
1423 verbose = FALSE;
1424 us_execute(item, verbose, TRUE, TRUE);
1425 us_causeofslice(item);
1426 if ((us_tool->toolstate&ONESHOTMENU) != 0)
1427 {
1428 us_highlightmenu(us_menuhnx, us_menuhny, el_colmenbor);
1429 us_menuhnx = -1;
1430 }
1431 us_freeusercom(item);
1432 flushscreen();
1433 } else
1434 {
1435 /* get cursor position and check windows */
1436 if (us_setxy(x, y))
1437 {
1438 /* see if it is a slider hit in a display window */
1439 wf = getwindowframe(TRUE);
1440 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1441 {
1442 if (w->frame != wf) continue;
1443 if ((w->state&WINDOWTYPE) == WAVEFORMWINDOW)
1444 {
1445 if (x >= w->uselx-DISPLAYSLIDERSIZE && x < w->usehx &&
1446 y >= w->usely-DISPLAYSLIDERSIZE && y < w->usehy)
1447 {
1448 if (w->buttonhandler != 0)
1449 (*w->buttonhandler)(w, but, x, y);
1450 return;
1451 }
1452 }
1453 if ((w->state&WINDOWTYPE) == DISPWINDOW)
1454 {
1455 if (x > w->usehx && x <= w->usehx+DISPLAYSLIDERSIZE &&
1456 y > w->usely && y < w->usehy)
1457 {
1458 /* check for vertical slider hit */
1459 np = w->curnodeproto;
1460 if (w != el_curwindowpart)
1461 {
1462 (void)setvalkey((INTBIG)us_tool, VTOOL, us_current_window_key, (INTBIG)w,
1463 VWINDOWPART|VDONTSAVE);
1464 (void)setval((INTBIG)el_curlib, VLIBRARY, x_("curnodeproto"),
1465 (INTBIG)np, VNODEPROTO);
1466 }
1467 if (np == NONODEPROTO) return;
1468 if (np->highy == np->lowy) return;
1469 if (y <= w->usely+DISPLAYSLIDERSIZE)
1470 {
1471 /* small shift up (may repeat) */
1472 us_arrowclickbegin(w, w->usehx, w->usehx+DISPLAYSLIDERSIZE,
1473 w->usely, w->usely+DISPLAYSLIDERSIZE,
1474 (w->screenhy - w->screenly) / DISPLAYSMALLSHIFT);
1475 trackcursor(FALSE, us_nullup, us_nullvoid, us_varrowdown, us_nullchar,
1476 us_nullvoid, TRACKNORMAL);
1477 return;
1478 }
1479 if (y <= w->thumbly)
1480 {
1481 /* large shift up (may repeat) */
1482 us_arrowclickbegin(w, w->usehx, w->usehx+DISPLAYSLIDERSIZE,
1483 w->usely+DISPLAYSLIDERSIZE, w->thumbhy,
1484 (w->screenhy - w->screenly) / DISPLAYLARGESHIFT);
1485 trackcursor(FALSE, us_nullup, us_nullvoid, us_varrowdown, us_nullchar,
1486 us_nullvoid, TRACKNORMAL);
1487 return;
1488 }
1489 if (y <= w->thumbhy)
1490 {
1491 /* on thumb (track thumb motion) */
1492 us_vthumbbegin(y, w, w->usehx, w->usely, w->usehy, FALSE,
1493 us_vthumbtrackingcallback);
1494 trackcursor(FALSE, us_nullup, us_nullvoid, us_vthumbdown, us_nullchar,
1495 us_vthumbdone, TRACKNORMAL);
1496 return;
1497 }
1498 if (y <= w->usehy-DISPLAYSLIDERSIZE)
1499 {
1500 /* large shift down (may repeat) */
1501 us_arrowclickbegin(w, w->usehx, w->usehx+DISPLAYSLIDERSIZE,
1502 w->thumbhy, w->usehy-DISPLAYSLIDERSIZE,
1503 -(w->screenhy - w->screenly) / DISPLAYLARGESHIFT);
1504 trackcursor(FALSE, us_nullup, us_nullvoid, us_varrowdown, us_nullchar,
1505 us_nullvoid, TRACKNORMAL);
1506 return;
1507 }
1508 if (y <= w->usehy)
1509 {
1510 /* small shift down (may repeat) */
1511 us_arrowclickbegin(w, w->usehx, w->usehx+DISPLAYSLIDERSIZE,
1512 w->usehy-DISPLAYSLIDERSIZE, w->usehy,
1513 -(w->screenhy - w->screenly) / DISPLAYSMALLSHIFT);
1514 trackcursor(FALSE, us_nullup, us_nullvoid, us_varrowdown, us_nullchar,
1515 us_nullvoid, TRACKNORMAL);
1516 return;
1517 }
1518 }
1519 if (y < w->usely && y >= w->usely-DISPLAYSLIDERSIZE &&
1520 x > w->uselx && x < w->usehx)
1521 {
1522 /* see if the explorer button was hit */
1523 drawexplorericon = us_windowgetsexploericon(w);
1524 lx = w->uselx;
1525 if (drawexplorericon)
1526 {
1527 lx += DISPLAYSLIDERSIZE;
1528 if (x <= lx)
1529 {
1530 par[0] = "explore";
1531 us_window(1, par);
1532 return;
1533 }
1534 }
1535
1536 /* check for horizontal slider hit */
1537 np = w->curnodeproto;
1538 if (w != el_curwindowpart)
1539 {
1540 (void)setvalkey((INTBIG)us_tool, VTOOL, us_current_window_key, (INTBIG)w,
1541 VWINDOWPART|VDONTSAVE);
1542 (void)setval((INTBIG)el_curlib, VLIBRARY, x_("curnodeproto"),
1543 (INTBIG)np, VNODEPROTO);
1544 }
1545 if (np == NONODEPROTO) return;
1546 if (np->highx == np->lowx) return;
1547 if (x <= lx+DISPLAYSLIDERSIZE)
1548 {
1549 /* small shift left (may repeat) */
1550 us_arrowclickbegin(w, lx, lx+DISPLAYSLIDERSIZE,
1551 w->usely-DISPLAYSLIDERSIZE, w->usely,
1552 -(w->screenhx - w->screenlx) / DISPLAYSMALLSHIFT);
1553 trackcursor(FALSE, us_nullup, us_nullvoid, us_harrowdown, us_nullchar,
1554 us_nullvoid, TRACKNORMAL);
1555 return;
1556 }
1557 if (x <= w->thumblx)
1558 {
1559 /* large shift left (may repeat) */
1560 us_arrowclickbegin(w, lx+DISPLAYSLIDERSIZE, w->thumblx,
1561 w->usely-DISPLAYSLIDERSIZE, w->usely,
1562 -(w->screenhx - w->screenlx) / DISPLAYLARGESHIFT);
1563 trackcursor(FALSE, us_nullup, us_nullvoid, us_harrowdown, us_nullchar,
1564 us_nullvoid, TRACKNORMAL);
1565 return;
1566 }
1567 if (x <= w->thumbhx)
1568 {
1569 /* on thumb (track thumb motion) */
1570 us_hthumbbegin(x, w, w->usely, lx, w->usehx, us_hthumbtrackingcallback);
1571 trackcursor(FALSE, us_nullup, us_nullvoid, us_hthumbdown, us_nullchar,
1572 us_hthumbdone, TRACKNORMAL);
1573 return;
1574 }
1575 if (x <= w->usehx-DISPLAYSLIDERSIZE)
1576 {
1577 /* large shift right (may repeat) */
1578 us_arrowclickbegin(w, w->thumbhx, w->usehx-DISPLAYSLIDERSIZE,
1579 w->usely-DISPLAYSLIDERSIZE, w->usely,
1580 (w->screenhx - w->screenlx) / DISPLAYLARGESHIFT);
1581 trackcursor(FALSE, us_nullup, us_nullvoid, us_harrowdown, us_nullchar,
1582 us_nullvoid, TRACKNORMAL);
1583 return;
1584 }
1585 if (x <= w->usehx)
1586 {
1587 /* small shift right (may repeat) */
1588 us_arrowclickbegin(w, w->usehx-DISPLAYSLIDERSIZE, w->usehx,
1589 w->usely-DISPLAYSLIDERSIZE, w->usely,
1590 (w->screenhx - w->screenlx) / DISPLAYSMALLSHIFT);
1591 trackcursor(FALSE, us_nullup, us_nullvoid, us_harrowdown, us_nullchar,
1592 us_nullvoid, TRACKNORMAL);
1593 return;
1594 }
1595 }
1596 }
1597 }
1598 ttyputerr(_("Cursor off the screen"));
1599 return;
1600 }
1601 if (el_curwindowpart != NOWINDOWPART)
1602 {
1603 /* if in distance-measurement mode, track measurement */
1604 if ((us_state&MEASURINGDISTANCE) != 0)
1605 {
1606 if ((el_curwindowpart->state&WINDOWTYPE) == DISPWINDOW &&
1607 el_curwindowpart->curnodeproto != NONODEPROTO)
1608 {
1609 if ((us_state&MEASURINGDISTANCEINI) != 0)
1610 {
1611 us_state &= ~MEASURINGDISTANCEINI;
1612 us_distanceinit();
1613 }
1614 trackcursor(FALSE, us_ignoreup, us_nullvoid, us_distancedown,
1615 us_stoponchar, us_distanceup, TRACKDRAGGING);
1616 return;
1617 }
1618 }
1619
1620 /* handle normal button click in this window */
1621 if (el_curwindowpart->buttonhandler != 0)
1622 {
1623 (*el_curwindowpart->buttonhandler)(el_curwindowpart, but, x, y);
1624 }
1625 }
1626 }
1627 }
1628
1629 /*
1630 * Routine to return true if there is another window partion on the same frame as
1631 * "ow" that covers the coordinates (x,y).
1632 */
us_hasotherwindowpart(INTBIG x,INTBIG y,WINDOWPART * ow)1633 BOOLEAN us_hasotherwindowpart(INTBIG x, INTBIG y, WINDOWPART *ow)
1634 {
1635 REGISTER WINDOWPART *w;
1636 INTBIG lx, hx, ly, hy;
1637
1638 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1639 {
1640 if (w == ow) continue;
1641 if (w->frame != ow->frame) continue;
1642 us_gettruewindowbounds(w, &lx, &hx, &ly, &hy);
1643 if (x > lx && x < hx && y > ly && y < hy) return(TRUE);
1644 }
1645 return(FALSE);
1646 }
1647
1648 /*
1649 * default button handler for buttons pushed in normal windows
1650 */
us_buttonhandler(WINDOWPART * w,INTBIG but,INTBIG x,INTBIG y)1651 void us_buttonhandler(WINDOWPART *w, INTBIG but, INTBIG x, INTBIG y)
1652 {
1653 REGISTER USERCOM *item;
1654 REGISTER VARIABLE *var;
1655 BOOLEAN verbose;
1656 COMMANDBINDING commandbinding;
1657 INTBIG unimportant;
1658 Q_UNUSED( w );
1659 Q_UNUSED( x );
1660 Q_UNUSED( y );
1661
1662 /* get the command attached to the button */
1663 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_binding_buttons_key);
1664 if (var == NOVARIABLE) return;
1665 us_parsebinding(((CHAR **)var->addr)[but], &commandbinding);
1666 item = us_makecommand(commandbinding.command);
1667 us_freebindingparse(&commandbinding);
1668 if (item == NOUSERCOM || item->active < 0)
1669 {
1670 ttyputerr(_("No command is attached to the %s button"),
1671 buttonname(but, &unimportant));
1672 if (item != NOUSERCOM) us_freeusercom(item);
1673 return;
1674 }
1675 us_forceeditchanges();
1676 if ((us_tool->toolstate&ECHOBIND) != 0) verbose = TRUE; else
1677 verbose = FALSE;
1678 us_execute(item, verbose, TRUE, TRUE);
1679 us_causeofslice(item);
1680 us_freeusercom(item);
1681 flushscreen();
1682 }
1683
1684 /* routine that is called when keyboard input is ready */
us_oncommand(INTSML cmd,INTBIG special)1685 void us_oncommand(INTSML cmd, INTBIG special)
1686 {
1687 INTBIG x, y;
1688
1689 /* Read and execute the command */
1690 us_state &= ~GOTXY;
1691 (void)getxy(&x, &y);
1692
1693 if (el_curwindowpart != NOWINDOWPART && el_curwindowpart->charhandler != 0)
1694 {
1695 if ((*el_curwindowpart->charhandler)(el_curwindowpart, cmd, special))
1696 us_killcurrentwindow(TRUE);
1697 } else
1698 {
1699 (void)(*DEFAULTCHARHANDLER)(el_curwindowpart, cmd, special);
1700 }
1701 }
1702
1703 /* EMACS warning */
1704 static DIALOGITEM us_emawarndialogitems[] =
1705 {
1706 /* 1 */ {0, {160,116,184,196}, BUTTON, N_("OK")},
1707 /* 2 */ {0, {4,4,20,340}, MESSAGE, N_("You have just typed Control-X")},
1708 /* 3 */ {0, {24,4,40,340}, MESSAGE, N_("Followed quickly by another control character.")},
1709 /* 4 */ {0, {52,4,68,340}, MESSAGE, N_("Could it be that you think this is EMACS?")},
1710 /* 5 */ {0, {84,4,100,340}, MESSAGE, N_("The second control character has been ignored.")},
1711 /* 6 */ {0, {104,4,120,340}, MESSAGE, N_("If you wish to disable this check, click below.")},
1712 /* 7 */ {0, {128,32,144,284}, BUTTON, N_("Disable EMACS character check")}
1713 };
1714 static DIALOG us_emawarndialog = {{75,75,268,425}, N_("This is Not EMACS"), 0, 7, us_emawarndialogitems, 0, 0};
1715
1716 /* special items for the "EMACS warning" dialog: */
1717 #define DEMW_DISABLECHECK 7 /* Disable EMACS check (button) */
1718
1719 /*
1720 * default character handler for keys typed in normal windows
1721 */
us_charhandler(WINDOWPART * w,INTSML cmd,INTBIG special)1722 BOOLEAN us_charhandler(WINDOWPART *w, INTSML cmd, INTBIG special)
1723 {
1724 REGISTER INTBIG i, longintro, bits, itemHit;
1725 INTBIG count;
1726 BOOLEAN verbose;
1727 REGISTER void *dia;
1728 static CHAR prompt[] = {x_("-")};
1729 REGISTER USERCOM *uc;
1730 CHAR *paramstart[MAXPARS], *pt;
1731 static UINTBIG timeoflastctlx = 0;
1732 static BOOLEAN doemacscheck = TRUE;
1733 REGISTER UINTBIG thiseventtime;
1734 extern COMCOMP us_userp;
1735 COMMANDBINDING commandbinding;
1736 Q_UNUSED( w );
1737
1738 /* special case: warn about EMACS-like commands */
1739 thiseventtime = eventtime();
1740 bits = getbuckybits();
1741 if (thiseventtime - timeoflastctlx < 60)
1742 {
1743 /* another character typed less than a second after a ^X */
1744 if ((bits&CONTROLDOWN) != 0)
1745 {
1746 /* a control character! warn that this is not EMACS */
1747 if (doemacscheck)
1748 {
1749 dia = DiaInitDialog(&us_emawarndialog);
1750 if (dia == 0) return(FALSE);
1751 for(;;)
1752 {
1753 itemHit = DiaNextHit(dia);
1754 if (itemHit == OK) break;
1755 if (itemHit == DEMW_DISABLECHECK) doemacscheck = FALSE;
1756 }
1757 DiaDoneDialog(dia);
1758 return(FALSE);
1759 }
1760 }
1761 }
1762 if (cmd == 'x' && (bits&CONTROLDOWN) != 0)
1763 {
1764 timeoflastctlx = thiseventtime;
1765 }
1766
1767 /* get the command attached to the key */
1768 i = us_findboundkey(cmd, special, &pt);
1769 if (i < 0) pt = x_("");
1770 us_parsebinding(pt, &commandbinding);
1771
1772 /* see if the key introduces a long command */
1773 longintro = 0;
1774 if (namesame(commandbinding.command, x_("telltool user")) == 0) longintro = 1;
1775
1776 /* if single-key commands were suspended, wait for carriage-return */
1777 if ((us_state&SKIPKEYS) != 0)
1778 {
1779 if ((cmd&127) == '\r' || (cmd&127) == '\n' || longintro != 0)
1780 {
1781 ttyputmsg(_("Single-key command suspension now lifted"));
1782 us_state &= ~SKIPKEYS;
1783 }
1784 if (longintro == 0)
1785 {
1786 us_freebindingparse(&commandbinding);
1787 return(FALSE);
1788 }
1789 }
1790
1791 /* if this is a "telltool user" character, fill out the command */
1792 if (longintro != 0)
1793 {
1794 us_freebindingparse(&commandbinding);
1795
1796 /* get the full command */
1797 prompt[0] = (CHAR)cmd;
1798 count = ttygetfullparam(prompt, &us_userp, MAXPARS, paramstart);
1799 if (count <= 0) return(FALSE);
1800
1801 /* parse into fields and execute */
1802 uc = us_buildcommand(count, paramstart);
1803 if (uc == NOUSERCOM)
1804 {
1805 /* this is very bad! code should deal with it better!!! */
1806 ttyputnomemory();
1807 return(FALSE);
1808 }
1809 us_forceeditchanges();
1810 us_execute(uc, FALSE, TRUE, TRUE);
1811 us_causeofslice(uc);
1812 us_freeusercom(uc);
1813 } else
1814 {
1815 /* check for new windows and get set tablet position for command */
1816 if (*commandbinding.command == 0)
1817 {
1818 us_abortcommand(_("The '%s' key has no meaning in this window"),
1819 us_describeboundkey(cmd, special, 1));
1820 us_freebindingparse(&commandbinding);
1821 return(FALSE);
1822 }
1823 uc = us_makecommand(commandbinding.command);
1824 us_freebindingparse(&commandbinding);
1825 if (uc == NOUSERCOM) return(FALSE);
1826 if (uc->active >= 0)
1827 {
1828 us_forceeditchanges();
1829 if ((us_tool->toolstate&ECHOBIND) != 0) verbose = TRUE; else
1830 verbose = FALSE;
1831 us_execute(uc, verbose, TRUE, TRUE);
1832 us_causeofslice(uc);
1833 }
1834 us_freeusercom(uc);
1835 }
1836 flushscreen();
1837 return(FALSE);
1838 }
1839
1840 /*
1841 * routine to save the command in "uc" as the one that produced this slice
1842 */
us_causeofslice(USERCOM * uc)1843 void us_causeofslice(USERCOM *uc)
1844 {
1845 REGISTER void *infstr;
1846
1847 if (uc->active < 0) return;
1848 infstr = initinfstr();
1849 addstringtoinfstr(infstr, uc->comname);
1850 us_appendargs(infstr, uc);
1851 setactivity(returninfstr(infstr));
1852 }
1853
us_forceeditchanges(void)1854 void us_forceeditchanges(void)
1855 {
1856 REGISTER WINDOWPART *w;
1857
1858 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1859 if ((w->state&WINDOWTYPE) == TEXTWINDOW) us_shipchanges(w);
1860 }
1861
1862 /******************** CHANGES TO THE DISPLAY ********************/
1863
us_startbatch(TOOL * source,BOOLEAN undoredo)1864 void us_startbatch(TOOL *source, BOOLEAN undoredo)
1865 {
1866 /* code cannot be called by multiple procesors: uses globals */
1867 NOT_REENTRANT;
1868 Q_UNUSED( undoredo );
1869
1870 us_batchsource = source;
1871 us_firstchangedcell = us_secondchangedcell = NONODEPROTO;
1872 us_state &= ~HIGHLIGHTSET;
1873 us_beginchanges();
1874 us_menuchanged = FALSE;
1875 us_cellstructurechanged = FALSE;
1876 us_cellwithkilledname = NONODEPROTO;
1877 }
1878
us_endbatch(void)1879 void us_endbatch(void)
1880 {
1881 REGISTER WINDOWPART *w;
1882
1883 /* redraw windows whose in-place context has changed */
1884 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
1885 {
1886 if ((w->state&INPLACEQUEUEREDRAW) == 0) continue;
1887 w->state &= ~INPLACEQUEUEREDRAW;
1888 if (w->redisphandler != 0) (*w->redisphandler)(w);
1889 }
1890 us_endchanges(NOWINDOWPART);
1891 us_showallhighlight();
1892 if (us_cellstructurechanged)
1893 us_redoexplorerwindow();
1894 if (us_batchsource == us_tool && us_firstchangedcell != NONODEPROTO &&
1895 us_secondchangedcell != NONODEPROTO)
1896 {
1897 ttyputmsg(_("This change affected more than one cell"));
1898 }
1899 }
1900
1901 /*
1902 * routine to display any delayed highlighting
1903 */
us_showallhighlight(void)1904 void us_showallhighlight(void)
1905 {
1906 REGISTER INTBIG i, len;
1907 REGISTER VARIABLE *var;
1908 HIGHLIGHT high;
1909
1910 /* stop now if highlighting has not been delayed */
1911 if ((us_state&HIGHLIGHTSET) == 0) return;
1912
1913 /* show all highlighting */
1914 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
1915 if (var != NOVARIABLE)
1916 {
1917 len = getlength(var);
1918 for(i=0; i<len; i++)
1919 {
1920 if (us_makehighlight(((CHAR **)var->addr)[i], &high)) continue;
1921 us_sethighlight(&high, HIGHLIT);
1922 }
1923 }
1924
1925 /* mark that highlighting is not delayed */
1926 us_state &= ~HIGHLIGHTSET;
1927 }
1928
us_startobjectchange(INTBIG addr,INTBIG type)1929 void us_startobjectchange(INTBIG addr, INTBIG type)
1930 {
1931 switch (type&VTYPE)
1932 {
1933 case VNODEINST:
1934 us_undisplayobject(((NODEINST *)addr)->geom); break;
1935 case VARCINST:
1936 us_undisplayobject(((ARCINST *)addr)->geom); break;
1937 case VWINDOWPART:
1938 copywindowpart(&us_oldwindow, (WINDOWPART *)addr); break;
1939 case VTOOL:
1940 if ((TOOL *)addr == us_tool) us_maplow = -1;
1941 us_oldstate = us_tool->toolstate;
1942 us_oldoptions = us_useroptions;
1943 us_menuchanged = FALSE;
1944 us_newwindowcount = 0;
1945 us_firstnewwindow = us_secondnewwindow = NOWINDOWPART;
1946 us_killedwindow = NOWINDOWPART;
1947 us_gridfactorschanged = FALSE;
1948 break;
1949 }
1950 }
1951
us_endobjectchange(INTBIG addr,INTBIG type)1952 void us_endobjectchange(INTBIG addr, INTBIG type)
1953 {
1954 REGISTER WINDOWPART *w, *ow, *w1, *w2, *w3;
1955 REGISTER INTBIG ulx, uhx, uly, uhy, bits, lambda;
1956 static POLYGON *poly = NOPOLYGON;
1957 REGISTER NODEPROTO *np;
1958 REGISTER NODEINST *ni;
1959 REGISTER ARCINST *ai;
1960 REGISTER TECHNOLOGY *tech;
1961 INTBIG dummy, cenx, ceny;
1962 REGISTER INTBIG alignment;
1963 extern GRAPHICS us_egbox, us_gbox;
1964 REGISTER VARIABLE *varred, *vargreen, *varblue, *var;
1965
1966 switch (type&VTYPE)
1967 {
1968 case VNODEINST:
1969 ni = (NODEINST *)addr;
1970 us_queueredraw(ni->geom, FALSE);
1971 us_geomhaschanged(ni->geom);
1972 break;
1973 case VARCINST:
1974 ai = (ARCINST *)addr;
1975 us_queueredraw(ai->geom, FALSE);
1976 us_geomhaschanged(ai->geom);
1977 break;
1978 case VTOOL:
1979 if ((TOOL *)addr != us_tool) break;
1980
1981 /* handle changes to the menu */
1982 if ((us_oldstate&MENUON) != (us_tool->toolstate&MENUON) || us_menuchanged)
1983 {
1984 /* destroy or create the menu if requested */
1985 us_menuchanged = FALSE;
1986 if (us_menuframe != NOWINDOWFRAME && (us_tool->toolstate&MENUON) == 0)
1987 {
1988 killwindowframe(us_menuframe);
1989 us_menuframe = NOWINDOWFRAME;
1990 return;
1991 }
1992 if (us_menuframe == NOWINDOWFRAME && (us_tool->toolstate&MENUON) != 0)
1993 us_menuframe = newwindowframe(TRUE, 0);
1994 us_drawmenu(1, us_menuframe);
1995 return;
1996 }
1997
1998 /* handle changes to the color map */
1999 if (us_maplow != -1)
2000 {
2001 varred = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_red_key);
2002 vargreen = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_green_key);
2003 varblue = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_blue_key);
2004 if (varred != NOVARIABLE && vargreen != NOVARIABLE && varblue != NOVARIABLE)
2005 colormapload(&((INTBIG *)varred->addr)[us_maplow],
2006 &((INTBIG *)vargreen->addr)[us_maplow], &((INTBIG *)varblue->addr)[us_maplow],
2007 us_maplow, us_maphigh);
2008 }
2009
2010 /* rewrite status information in header if configuration changed */
2011 if (us_newwindowcount != 0 || us_killedwindow != NOWINDOWPART)
2012 {
2013 us_redostatus(NOWINDOWFRAME);
2014 }
2015
2016 /* see if windows were created */
2017 if (us_newwindowcount != 0)
2018 {
2019 /* special case for split edit windows */
2020 if (us_killedwindow != NOWINDOWPART && us_newwindowcount == 2 &&
2021 (us_firstnewwindow->state&WINDOWTYPE) == DISPWINDOW &&
2022 (us_secondnewwindow->state&WINDOWTYPE) == DISPWINDOW &&
2023 us_firstnewwindow->curnodeproto == us_secondnewwindow->curnodeproto &&
2024 us_firstnewwindow->curnodeproto == us_killedwindow->curnodeproto)
2025 {
2026 /* use block transfer */
2027 w1 = &us_oldwindow;
2028 w2 = us_firstnewwindow;
2029 w3 = us_secondnewwindow;
2030
2031 /* make sure the windows have the same scale */
2032 if (us_windowcansplit(w1, w2, w3))
2033 {
2034 /* make sure that "w3" is the larger window */
2035 if (w2->usehx - w2->uselx > w3->usehx - w3->uselx ||
2036 w2->usehy - w2->usely > w3->usehy - w3->usely)
2037 {
2038 w = w2; w2 = w3; w3 = w;
2039 }
2040 screenmovebox(w2, (w1->usehx+w1->uselx - w3->usehx+w3->uselx) / 2,
2041 (w1->usehy+w1->usely - w3->usehy+w3->usely) / 2,
2042 w3->usehx-w3->uselx+1, w3->usehy-w3->usely+1,
2043 w3->uselx, w3->usely);
2044 if (w2->curnodeproto != NONODEPROTO && w2->curnodeproto == w3->curnodeproto)
2045 screenmovebox(w2, w3->uselx, w3->usely, w2->usehx-w2->uselx+1,
2046 w2->usehy-w2->usely+1, w2->uselx, w2->usely);
2047 us_drawwindow(w2, el_colwinbor);
2048 us_drawwindow(w3, el_colwinbor);
2049 break;
2050 }
2051 }
2052
2053 /* simple window creation: draw and outline */
2054 if (us_newwindowcount > 2)
2055 {
2056 /* many windows created: redraw all of them */
2057 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2058 {
2059 us_drawwindow(w, el_colwinbor);
2060 if (w->redisphandler != 0) (*w->redisphandler)(w);
2061 }
2062 } else
2063 {
2064 /* one or two windows created: draw them */
2065 us_drawwindow(us_firstnewwindow, el_colwinbor);
2066 if (us_firstnewwindow->redisphandler != 0)
2067 (*us_firstnewwindow->redisphandler)(us_firstnewwindow);
2068 if (us_secondnewwindow != NOWINDOWPART)
2069 {
2070 us_drawwindow(us_secondnewwindow, el_colwinbor);
2071 if (us_secondnewwindow->redisphandler != 0)
2072 (*us_secondnewwindow->redisphandler)(us_secondnewwindow);
2073 }
2074 }
2075 break;
2076 }
2077
2078 /* redraw all windows if appropriate options changed */
2079 bits = DRAWTINYCELLS|PORTLABELS|EXPORTLABELS|HIDETXTNODE|HIDETXTARC|
2080 HIDETXTPORT|HIDETXTEXPORT|HIDETXTNONLAY|HIDETXTINSTNAME|HIDETXTCELL;
2081 if ((us_oldoptions&bits) != (us_useroptions&bits))
2082 {
2083 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2084 if (w->redisphandler != 0) (*w->redisphandler)(w);
2085 }
2086 break;
2087
2088 case VWINDOWPART:
2089 w = (WINDOWPART *)addr;
2090 ow = &us_oldwindow;
2091
2092 /* adjust window if changing in or out of being a display window */
2093 if ((w->state&WINDOWTYPE) == DISPWINDOW && (ow->state&WINDOWTYPE) != DISPWINDOW)
2094 {
2095 /* became a display window: shrink the bottom and right edge */
2096 w->usehx -= DISPLAYSLIDERSIZE;
2097 w->usely += DISPLAYSLIDERSIZE;
2098 computewindowscale(w);
2099 }
2100 if ((w->state&WINDOWTYPE) != DISPWINDOW && (ow->state&WINDOWTYPE) == DISPWINDOW)
2101 {
2102 /* no longer a display window: shrink the bottom and right edge */
2103 w->usehx += DISPLAYSLIDERSIZE;
2104 w->usely -= DISPLAYSLIDERSIZE;
2105 computewindowscale(w);
2106 }
2107
2108 /* adjust window if changing in or out of being a waveform/tec edit/outline edit window */
2109 if ((w->state&WINDOWTYPE) == WAVEFORMWINDOW && (ow->state&WINDOWTYPE) != WAVEFORMWINDOW)
2110 {
2111 /* became a waveform window: shrink the left edge */
2112 w->uselx += DISPLAYSLIDERSIZE;
2113 w->usely += DISPLAYSLIDERSIZE;
2114 computewindowscale(w);
2115 }
2116 if ((w->state&WINDOWTYPE) != WAVEFORMWINDOW && (ow->state&WINDOWTYPE) == WAVEFORMWINDOW)
2117 {
2118 /* no longer a waveform window: shrink the bottom and right edge */
2119 w->uselx -= DISPLAYSLIDERSIZE;
2120 w->usely -= DISPLAYSLIDERSIZE;
2121 computewindowscale(w);
2122 }
2123
2124 /* set the cursor according to the current window */
2125 if (el_curwindowpart == NOWINDOWPART) setnormalcursor(NORMALCURSOR); else
2126 {
2127 if ((el_curwindowpart->state&WINDOWOUTLINEEDMODE) != 0)
2128 {
2129 setnormalcursor(PENCURSOR);
2130 } else
2131 {
2132 if ((el_curwindowpart->state&WINDOWTECEDMODE) != 0)
2133 {
2134 setnormalcursor(TECHCURSOR);
2135 } else
2136 {
2137 setnormalcursor(NORMALCURSOR);
2138 }
2139 }
2140 }
2141
2142 /* switch between 2-D and 3-D drawing */
2143 if ((ow->state&WINDOWTYPE) == DISPWINDOW && (w->state&WINDOWTYPE) == DISP3DWINDOW)
2144 {
2145 if (w->redisphandler != 0) (*w->redisphandler)(w);
2146 break;
2147 }
2148 if ((ow->state&WINDOWTYPE) == DISP3DWINDOW && (w->state&WINDOWTYPE) == DISPWINDOW)
2149 {
2150 if (w->redisphandler != 0) (*w->redisphandler)(w);
2151 break;
2152 }
2153
2154 /* adjust window if mode changed */
2155 if ((w->state&WINDOWMODE) != (ow->state&WINDOWMODE))
2156 {
2157 us_setwindowmode(w, ow->state, w->state);
2158 computewindowscale(w);
2159 if (w->redisphandler != 0) (*w->redisphandler)(w);
2160 break;
2161 }
2162
2163 /* see if the cell changed */
2164 if (w->curnodeproto != ow->curnodeproto || w->buttonhandler != ow->buttonhandler ||
2165 w->charhandler != ow->charhandler || w->termhandler != ow->termhandler ||
2166 w->redisphandler != ow->redisphandler || w->changehandler != ow->changehandler)
2167 {
2168 us_setcellname(w);
2169 us_setcellsize(w);
2170 us_setgridsize(w);
2171 if (w->redisphandler != 0) (*w->redisphandler)(w);
2172 break;
2173 }
2174
2175 /* see if the window slid vertically */
2176 if (w->screenlx == ow->screenlx && w->screenhx == ow->screenhx &&
2177 w->screenly - ow->screenly == w->screenhy - ow->screenhy &&
2178 w->screenly != ow->screenly)
2179 {
2180 /* window slid vertically */
2181 ulx = w->uselx; uhx = w->usehx;
2182 uly = w->usely; uhy = w->usehy;
2183 ow->uselx = ulx; ow->usehx = uhx;
2184 ow->usely = uly; ow->usehy = uhy;
2185 computewindowscale(ow);
2186
2187 /* bit sliding didn't work, redisplay entire window */
2188 if (w->redisphandler != 0) (*w->redisphandler)(w);
2189 break;
2190 }
2191
2192 /* see if the window slid horizontally */
2193 if (w->screenly == ow->screenly && w->screenhy == ow->screenhy &&
2194 w->screenlx - ow->screenlx == w->screenhx - ow->screenhx &&
2195 w->screenlx != ow->screenlx)
2196 {
2197 /* window slid horizontally */
2198 ulx = w->uselx; uhx = w->usehx;
2199 uly = w->usely; uhy = w->usehy;
2200 ow->uselx = ulx; ow->usehx = uhx;
2201 ow->usely = uly; ow->usehy = uhy;
2202 computewindowscale(ow);
2203
2204 /* bit sliding didn't work, redisplay entire window */
2205 if (w->redisphandler != 0) (*w->redisphandler)(w);
2206 break;
2207 }
2208
2209 /* redraw waveform window */
2210 if ((w->state&WINDOWTYPE) == WAVEFORMWINDOW)
2211 {
2212 if (w->redisphandler != 0) (*w->redisphandler)(w);
2213 break;
2214 }
2215
2216 /* handle grid going off or changing size while on */
2217 if (((ow->state&GRIDON) != 0 && (w->state&GRIDON) == 0) ||
2218 ((w->state&GRIDON) != 0 &&
2219 (ow->gridx != w->gridx || ow->gridy != w->gridy || us_gridfactorschanged)))
2220 {
2221 /* must redraw everything on B&W displays or those with less than 8-bits */
2222 us_setgridsize(w);
2223 if (el_maplength < 256)
2224 {
2225 if (w->redisphandler != 0) (*w->redisphandler)(w);
2226 break;
2227 }
2228
2229 /* erase the grid layer */
2230 screendrawbox(w, w->uselx, w->usehx, w->usely, w->usehy, &us_egbox);
2231
2232 /* if grid went off and nothing else changed, all is done */
2233 if ((w->state&GRIDON) == 0 && w->screenlx == ow->screenlx &&
2234 w->screenhx == ow->screenhx && w->screenly == ow->screenly &&
2235 w->screenhy == ow->screenhy) break;
2236 }
2237
2238 /* handle grid going on or staying on and changing size */
2239 if (w->screenlx == ow->screenlx && w->screenhx == ow->screenhx &&
2240 w->screenly == ow->screenly && w->screenhy == ow->screenhy)
2241 if (((ow->state & (GRIDTOOSMALL|GRIDON)) != GRIDON &&
2242 (w->state & (GRIDTOOSMALL|GRIDON)) == GRIDON) ||
2243 ((ow->state&GRIDON) != 0 && (w->state&GRIDON) != 0 &&
2244 (ow->gridx != w->gridx || ow->gridy != w->gridy || us_gridfactorschanged)))
2245 {
2246 np = w->curnodeproto;
2247 if (np == NONODEPROTO) break;
2248
2249 /* get polygon */
2250 (void)needstaticpolygon(&poly, 6, us_tool->cluster);
2251
2252 /* grid spacing */
2253 lambda = np->lib->lambda[np->tech->techindex];
2254 poly->xv[0] = muldiv(w->gridx, lambda, WHOLE);
2255 poly->yv[0] = muldiv(w->gridy, lambda, WHOLE);
2256
2257 /* initial grid location */
2258 var = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER, us_gridfloatskey);
2259 if (var == NOVARIABLE || var->addr == 0)
2260 {
2261 poly->xv[1] = w->screenlx / poly->xv[0] * poly->xv[0];
2262 poly->yv[1] = w->screenly / poly->yv[0] * poly->yv[0];
2263 } else
2264 {
2265 grabpoint(np, &cenx, &ceny);
2266 tech = np->tech;
2267 if (tech == NOTECHNOLOGY) tech = el_curtech;
2268 alignment = muldiv(us_alignment_ratio, el_curlib->lambda[tech->techindex], WHOLE);
2269 poly->xv[1] = us_alignvalue(cenx, alignment, &dummy);
2270 poly->yv[1] = us_alignvalue(ceny, alignment, &dummy);
2271 poly->xv[1] += (w->screenlx-poly->xv[1]) / poly->xv[0] * poly->xv[0];
2272 poly->yv[1] += (w->screenly-poly->yv[1]) / poly->yv[0] * poly->yv[0];
2273 }
2274
2275 /* display screen extent */
2276 poly->xv[2] = w->uselx; poly->yv[2] = w->usely;
2277 poly->xv[3] = w->usehx; poly->yv[3] = w->usehy;
2278
2279 /* object space extent */
2280 poly->xv[4] = w->screenlx; poly->yv[4] = w->screenly;
2281 poly->xv[5] = w->screenhx; poly->yv[5] = w->screenhy;
2282
2283 poly->count = 6;
2284 poly->style = GRIDDOTS;
2285 poly->desc = &us_gbox;
2286 (*us_displayroutine)(poly, w);
2287 flushscreen();
2288 break;
2289 }
2290
2291 /* no sliding or grid change: simply redisplay the window */
2292 if (w->redisphandler != 0) (*w->redisphandler)(w);
2293 break;
2294 }
2295 }
2296
us_modifynodeinst(NODEINST * ni,INTBIG oldlx,INTBIG oldly,INTBIG oldhx,INTBIG oldhy,INTBIG oldrot,INTBIG oldtran)2297 void us_modifynodeinst(NODEINST *ni, INTBIG oldlx, INTBIG oldly, INTBIG oldhx, INTBIG oldhy,
2298 INTBIG oldrot, INTBIG oldtran)
2299 {
2300 REGISTER INTBIG dlx, dhx, dly, dhy;
2301 Q_UNUSED( oldrot );
2302 Q_UNUSED( oldtran );
2303
2304 /* look for the special "cell-center" and "essential-bounds" nodes in the "generic" technology */
2305 if (ni->proto == gen_cellcenterprim)
2306 us_setnodeprotocenter(ni->lowx, ni->lowy, ni->parent); else
2307 if (ni->proto == gen_essentialprim)
2308 us_setessentialbounds(ni->parent);
2309
2310 /* track changes to node that was duplicated */
2311 if (ni == us_dupnode)
2312 {
2313 us_dupx += (ni->lowx + ni->highx) / 2 - (oldlx + oldhx) / 2;
2314 us_dupy += (ni->lowy + ni->highy) / 2 - (oldly + oldhy) / 2;
2315 }
2316
2317 /* if node moved, remember the cell */
2318 dlx = ni->lowx - oldlx; dhx = ni->highx - oldhx;
2319 dly = ni->lowy - oldly; dhy = ni->highy - oldhy;
2320 if ((dlx == dhx && dlx != 0) || (dly == dhy && dly != 0))
2321 {
2322 if (us_firstchangedcell == NONODEPROTO || us_firstchangedcell == ni->parent)
2323 {
2324 us_firstchangedcell = ni->parent;
2325 } else if (us_secondchangedcell == NONODEPROTO || us_secondchangedcell != ni->parent)
2326 {
2327 us_secondchangedcell = ni->parent;
2328 }
2329 }
2330
2331 /* see if this affects in-place editing */
2332 us_checkinplaceedits(ni->parent);
2333 }
2334
us_modifynodeproto(NODEPROTO * np)2335 void us_modifynodeproto(NODEPROTO *np)
2336 {
2337 REGISTER WINDOWPART *w;
2338
2339 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2340 {
2341 if (np != w->curnodeproto) continue;
2342 us_setcellsize(w);
2343 us_drawdispwindowsliders(w);
2344 }
2345
2346 /* see if this affects in-place editing */
2347 us_checkinplaceedits(np);
2348 }
2349
us_modifydescript(INTBIG addr,INTBIG type,INTBIG key,UINTBIG * old)2350 void us_modifydescript(INTBIG addr, INTBIG type, INTBIG key, UINTBIG *old)
2351 {
2352 Q_UNUSED( key );
2353 Q_UNUSED( old );
2354
2355 switch (type&VTYPE)
2356 {
2357 case VNODEINST:
2358 us_computenodefartextbit((NODEINST *)addr);
2359 break;
2360 case VARCINST:
2361 us_computearcfartextbit((ARCINST *)addr);
2362 break;
2363 }
2364 }
2365
us_newobject(INTBIG addr,INTBIG type)2366 void us_newobject(INTBIG addr, INTBIG type)
2367 {
2368 REGISTER NODEINST *ni;
2369 REGISTER NODEPROTO *np;
2370 REGISTER ARCINST *ai;
2371 REGISTER PORTPROTO *pp;
2372 REGISTER UINTBIG wiped;
2373 REGISTER INTBIG i;
2374 REGISTER WINDOWPART *w;
2375 REGISTER NODEPROTO *onp;
2376 REGISTER EDITOR *ed;
2377
2378 switch (type&VTYPE)
2379 {
2380 case VNODEINST:
2381 ni = (NODEINST *)addr;
2382
2383 /* look for the "cell-center" or "essential-bounds" nodes in the "generic" technology */
2384 if (ni->proto == gen_cellcenterprim) us_addcellcenter(ni); else
2385 if (ni->proto == gen_essentialprim)
2386 us_setessentialbounds(ni->parent);
2387
2388 /* if a new instance was created, then the cell structure has changed */
2389 if (ni->proto->primindex == 0) us_cellstructurechanged = TRUE;
2390
2391 /* recompute the parent's technology */
2392 ni->parent->tech = whattech(ni->parent);
2393
2394 /* see if this affects in-place editing */
2395 us_checkinplaceedits(ni->parent);
2396 break;
2397
2398 case VARCINST:
2399 ai = (ARCINST *)addr;
2400
2401 /* see if this arcinst wipes out the visibility of some pins */
2402 if ((ai->proto->userbits&CANWIPE) != 0) for(i=0; i<2; i++)
2403 {
2404 ni = ai->end[i].nodeinst;
2405
2406 wiped = us_computewipestate(ni);
2407 if (wiped != (ni->userbits&WIPED))
2408 {
2409 /* if node was visible, erase it before setting WIPED bit */
2410 if ((ni->userbits&WIPED) == 0) us_undisplayobject(ni->geom);
2411 ni->userbits = (ni->userbits & ~WIPED) | wiped;
2412 }
2413 }
2414
2415 /* recompute the parent's technology */
2416 ai->parent->tech = whattech(ai->parent);
2417
2418 /* see if this affects in-place editing */
2419 us_checkinplaceedits(ai->parent);
2420 break;
2421
2422 case VNODEPROTO:
2423 np = (NODEPROTO *)addr;
2424
2425 /* update status display if this is new version of what's displayed */
2426 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2427 {
2428 if (w->curnodeproto == NONODEPROTO) continue;
2429 if (w->curnodeproto != np) continue;
2430 if ((w->state&WINDOWTYPE) == TEXTWINDOW)
2431 {
2432 ed = w->editor;
2433 if (ed != NOEDITOR) (void)reallocstring(&ed->header,
2434 describenodeproto(w->curnodeproto), us_tool->cluster);
2435 w->redisphandler(w);
2436 }
2437 us_setcellname(w);
2438 }
2439
2440 /* the cell structure has changed */
2441 us_cellstructurechanged = TRUE;
2442
2443 onp = us_curnodeproto;
2444 if (onp == NONODEPROTO) return;
2445 if (onp->primindex != 0) return;
2446 if (onp != np) return;
2447 us_curnodeproto = NONODEPROTO;
2448 us_shadownodeproto(NOWINDOWFRAME, onp);
2449
2450 /* recompute the technology */
2451 np->tech = whattech(np);
2452 break;
2453
2454 case VPORTPROTO:
2455 pp = (PORTPROTO *)addr;
2456
2457 /* look at all instances of this nodeproto for use on display */
2458 for(ni = pp->parent->firstinst; ni != NONODEINST; ni = ni->nextinst)
2459 if ((ni->userbits & NEXPAND) == 0 || (pp->userbits&PORTDRAWN) != 0)
2460 us_queueredraw(ni->geom, FALSE);
2461
2462 /* see if this affects in-place editing */
2463 us_checkinplaceedits(pp->parent);
2464 break;
2465
2466 case VLIBRARY:
2467 /* the cell structure has changed */
2468 us_cellstructurechanged = TRUE;
2469 break;
2470
2471 case VWINDOWPART:
2472 w = (WINDOWPART *)addr;
2473 us_newwindowcount++;
2474 if (us_firstnewwindow == NOWINDOWPART) us_firstnewwindow = w; else
2475 us_secondnewwindow = w;
2476 break;
2477 }
2478 }
2479
us_killobject(INTBIG addr,INTBIG type)2480 void us_killobject(INTBIG addr, INTBIG type)
2481 {
2482 REGISTER INTBIG i;
2483 REGISTER UINTBIG wiped;
2484 REGISTER NODEINST *ni;
2485 REGISTER NODEPROTO *np;
2486 REGISTER PORTPROTO *pp;
2487 REGISTER ARCINST *ai;
2488 REGISTER WINDOWPART *w;
2489
2490 switch (type&VTYPE)
2491 {
2492 case VNODEINST:
2493 ni = (NODEINST *)addr;
2494 ni->userbits |= (RETDONN|REODONN);
2495
2496 /* stop tracking duplicated node if it is deleted */
2497 if (ni == us_dupnode) us_dupnode = NONODEINST;
2498
2499 /* if an instance was deleted, then the cell structure has changed */
2500 if (ni->proto->primindex == 0) us_cellstructurechanged = TRUE;
2501
2502 /* look for the "cell-center" node in the "generic" technology */
2503 if (ni->proto == gen_cellcenterprim)
2504 us_delnodeprotocenter(ni->parent); else
2505 if (ni->proto == gen_essentialprim)
2506 us_setessentialbounds(ni->parent);
2507
2508 /* recompute the parent's technology */
2509 ni->parent->tech = whattech(ni->parent);
2510
2511 /* see if this affects in-place editing */
2512 us_checkinplaceedits(ni->parent);
2513 break;
2514
2515 case VARCINST:
2516 ai = (ARCINST *)addr;
2517
2518 /* see if this arcinst wiped out the visibility of some pins */
2519 if ((ai->proto->userbits&CANWIPE) != 0) for(i=0; i<2; i++)
2520 {
2521 ni = ai->end[i].nodeinst;
2522
2523 /* if nodeinst still live and has other arcs, leave it */
2524 if ((ni->userbits&DEADN) != 0) continue;
2525
2526 wiped = us_computewipestate(ni);
2527 if (wiped != (ni->userbits&WIPED))
2528 {
2529 /* if node was invisible, display before resetting WIPED bit */
2530 if ((ni->userbits&WIPED) != 0) us_queueredraw(ni->geom, FALSE);
2531 ni->userbits = (ni->userbits & ~WIPED) | wiped;
2532 }
2533 }
2534
2535 /* recompute the parent's technology */
2536 ai->parent->tech = whattech(ai->parent);
2537
2538 /* see if this affects in-place editing */
2539 us_checkinplaceedits(ai->parent);
2540 break;
2541
2542 case VNODEPROTO:
2543 np = (NODEPROTO *)addr;
2544
2545 /* if this may be a technology-edit cell, let it know */
2546 if (namesamen(np->protoname, x_("layer-"), 6) == 0)
2547 us_deltecedlayercell(np);
2548 if (namesamen(np->protoname, x_("node-"), 5) == 0)
2549 us_deltecednodecell(np);
2550
2551 us_removeubchange(np);
2552
2553 /* the cell structure has changed */
2554 us_cellstructurechanged = TRUE;
2555 break;
2556
2557 case VPORTPROTO:
2558 pp = (PORTPROTO *)addr;
2559
2560 /* look at all instances of this nodeproto for use on display */
2561 for(ni = pp->parent->firstinst; ni != NONODEINST; ni = ni->nextinst)
2562 if ((ni->userbits & NEXPAND) == 0 || (pp->userbits&PORTDRAWN) != 0)
2563 {
2564 us_undisplayobject(ni->geom);
2565 us_queueredraw(ni->geom, FALSE);
2566 }
2567
2568 /* see if this affects in-place editing */
2569 us_checkinplaceedits(pp->parent);
2570 break;
2571
2572 case VLIBRARY:
2573 /* the cell structure has changed */
2574 us_cellstructurechanged = TRUE;
2575 break;
2576
2577 case VWINDOWPART:
2578 w = (WINDOWPART *)addr;
2579 copywindowpart(&us_oldwindow, w);
2580 us_killedwindow = w;
2581 break;
2582 }
2583 }
2584
us_newvariable(INTBIG addr,INTBIG type,INTBIG key,INTBIG newtype)2585 void us_newvariable(INTBIG addr, INTBIG type, INTBIG key, INTBIG newtype)
2586 {
2587 REGISTER INTBIG len, i, x, y;
2588 REGISTER VARIABLE *var;
2589 REGISTER WINDOWPART *w;
2590 REGISTER POPUPMENU *pm;
2591 REGISTER POPUPMENUITEM *mi;
2592 REGISTER NODEPROTO *np;
2593 REGISTER ARCPROTO *ap;
2594 REGISTER LIBRARY *lib;
2595 REGISTER TOOL *tool;
2596 REGISTER TECHNOLOGY *tech;
2597 REGISTER CHAR *name, *pt;
2598 REGISTER USERCOM *rb;
2599 COMMANDBINDING commandbinding;
2600
2601 if ((newtype&VCREF) != 0)
2602 {
2603 name = changedvariablename(type, key, newtype);
2604
2605 /* see if cell name changed */
2606 if ((type&VTYPE) == VNODEPROTO && namesame(name, x_("protoname")) == 0)
2607 {
2608 np = (NODEPROTO *)addr;
2609 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2610 if (w->curnodeproto != NONODEPROTO && w->curnodeproto == np)
2611 us_setcellname(w);
2612 us_cellstructurechanged = TRUE;
2613 if (np == us_cellwithkilledname)
2614 {
2615 /* tell the technology editor that a cell name changed */
2616 us_renametecedcell(us_cellwithkilledname, us_killednameoncell);
2617 }
2618 return;
2619 }
2620
2621 /* see if screen extent changed */
2622 if ((type&VTYPE) == VWINDOWPART && namesamen(name, x_("screen"), 6) == 0)
2623 {
2624 w = (WINDOWPART *)addr;
2625 computewindowscale(w);
2626 return;
2627 }
2628
2629 /* see if technology name changed */
2630 if ((type&VTYPE) == VTECHNOLOGY && namesame(name, x_("techname")) == 0)
2631 {
2632 tech = (TECHNOLOGY *)addr;
2633 if (tech == el_curtech) us_settechname(NOWINDOWFRAME);
2634 return;
2635 }
2636
2637 /* see if layer visibility changed */
2638 if ((type&VTYPE) == VGRAPHICS && namesame(name, x_("colstyle")) == 0)
2639 {
2640 us_figuretechselectability();
2641 return;
2642 }
2643
2644 /* see if current cell or library name changed */
2645 if ((type&VTYPE) == VLIBRARY &&
2646 (namesame(name, x_("curnodeproto")) == 0 || namesame(name, x_("libname")) == 0))
2647 {
2648 lib = (LIBRARY *)addr;
2649 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2650 {
2651 if (w->curnodeproto == NONODEPROTO) continue;
2652 if (w->curnodeproto->lib == lib) us_setcellname(w);
2653 }
2654 if (namesame(name, x_("libname")) == 0) us_cellstructurechanged = TRUE;
2655 if (namesame(name, x_("curnodeproto")) == 0) us_state |= CURCELLCHANGED;
2656 return;
2657 }
2658
2659 /* see if a tool was turned on */
2660 if ((type&VTYPE) == VTOOL && namesame(name, x_("toolstate")) == 0)
2661 {
2662 tool = (TOOL *)addr;
2663 if ((tool->toolstate & TOOLON) != 0 &&
2664 (tool->toolstate & TOOLINCREMENTAL) != 0)
2665 us_toolturnedon(tool);
2666 }
2667 return;
2668 }
2669
2670 /* see if an option variable changed */
2671 if ((newtype&VDONTSAVE) == 0)
2672 {
2673 if (isoptionvariable(addr, type, makename(key)))
2674 us_optionschanged = TRUE;
2675 }
2676
2677 /* handle changes to objects on the user interface */
2678 if (addr == (INTBIG)us_tool)
2679 {
2680 /* pick up mirrors */
2681 for(i=0; us_variablemirror[i].key != 0; i++)
2682 {
2683 if (key == *us_variablemirror[i].key)
2684 {
2685 var = getvalkey(addr, type, -1, key);
2686 if (var != NOVARIABLE) *us_variablemirror[i].value = var->addr;
2687 if (key == us_menu_x_key || key == us_menu_y_key || key == us_menu_position_key)
2688 us_menuchanged = TRUE;
2689 return;
2690 }
2691 }
2692
2693 if (key == us_alignment_ratio_key)
2694 {
2695 var = getvalkey(addr, type, VINTEGER, key);
2696 if (var != NOVARIABLE) us_alignment_ratio = var->addr;
2697 us_setalignment(NOWINDOWFRAME);
2698 return;
2699 }
2700
2701 if (key == us_alignment_edge_ratio_key)
2702 {
2703 var = getvalkey(addr, type, VINTEGER, key);
2704 if (var != NOVARIABLE) us_edgealignment_ratio = var->addr;
2705 us_setalignment(NOWINDOWFRAME);
2706 return;
2707 }
2708
2709 if (key == us_displayunitskey)
2710 {
2711 var = getvalkey(addr, type, VINTEGER, key);
2712 if (var != NOVARIABLE)
2713 {
2714 /* code cannot be called by multiple procesors: uses globals */
2715 NOT_REENTRANT;
2716
2717 el_units = (el_units & ~DISPLAYUNITS) | (var->addr & DISPLAYUNITS);
2718 }
2719 return;
2720 }
2721
2722 /* see if default text editor changed */
2723 if (key == us_text_editorkey)
2724 {
2725 var = getvalkey(addr, type, VSTRING, key);
2726 if (var == NOVARIABLE) return;
2727 for(i=0; us_editortable[i].editorname != 0; i++)
2728 if (namesame((CHAR *)var->addr, us_editortable[i].editorname) == 0) break;
2729 if (us_editortable[i].editorname == 0) return;
2730
2731 /* code cannot be called by multiple procesors: uses globals */
2732 NOT_REENTRANT;
2733
2734 us_currenteditor = i;
2735 return;
2736 }
2737
2738 /* set current window if it changed */
2739 if (key == us_current_window_key)
2740 {
2741 var = getvalkey(addr, type, VWINDOWPART, key);
2742 if (var == NOVARIABLE) return;
2743 w = (WINDOWPART *)var->addr;
2744 us_highlightwindow(w, FALSE);
2745 if (w != NOWINDOWPART) us_setcellsize(w);
2746 return;
2747 }
2748
2749 /* set colormap updating if it changed */
2750 if (key == us_colormap_red_key || key == us_colormap_green_key ||
2751 key == us_colormap_blue_key)
2752 {
2753 us_maplow = 0;
2754 var = getvalkey(addr, type, VINTEGER|VISARRAY, key);
2755 if (var == NOVARIABLE) return;
2756 len = getlength(var);
2757 if (us_maplow == -1) us_maphigh = len-1; else
2758 if (len-1 > us_maphigh) us_maphigh = len-1;
2759 return;
2760 }
2761
2762 /* show highlight if it changed */
2763 if (key == us_highlightedkey)
2764 {
2765 us_state |= HIGHLIGHTSET;
2766 us_setselectioncount();
2767 us_highlighthaschanged();
2768 return;
2769 }
2770
2771 /* shadow current nodeproto or arcproto if it changed */
2772 if (key == us_current_node_key)
2773 {
2774 var = getvalkey(addr, type, VNODEPROTO, key);
2775 if (var != NOVARIABLE) us_shadownodeproto(NOWINDOWFRAME, (NODEPROTO *)var->addr);
2776 return;
2777 }
2778 if (key == us_current_arc_key)
2779 {
2780 var = getvalkey(addr, type, VARCPROTO, key);
2781 if (var != NOVARIABLE) us_shadowarcproto(NOWINDOWFRAME, (ARCPROTO *)var->addr);
2782 return;
2783 }
2784
2785 /* shadow placement angle if it changed */
2786 if (key == us_placement_angle_key)
2787 {
2788 us_setnodeangle(NOWINDOWFRAME);
2789 return;
2790 }
2791
2792 /* switch technology if it changed */
2793 if (key == us_current_technology_key)
2794 {
2795 var = getvalkey(addr, type, VTECHNOLOGY, key);
2796 if (var == NOVARIABLE) return;
2797 el_curtech = (TECHNOLOGY *)var->addr;
2798 if (el_curtech != sch_tech && el_curtech != art_tech && el_curtech != gen_tech)
2799 el_curlayouttech = el_curtech;
2800 us_settechname(NOWINDOWFRAME);
2801 us_setlambda(NOWINDOWFRAME);
2802 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart) us_setcellsize(w);
2803 return;
2804 }
2805
2806 /* switch constraint solver if it changed */
2807 if (key == us_current_constraint_key)
2808 {
2809 var = getvalkey(addr, type, VCONSTRAINT, key);
2810 if (var == NOVARIABLE) return;
2811 el_curconstraint = (CONSTRAINT *)var->addr;
2812 return;
2813 }
2814
2815 if (key == us_gridfloatskey || key == us_gridboldspacingkey)
2816 {
2817 us_gridfactorschanged = TRUE;
2818 return;
2819 }
2820
2821 if (key == us_quickkeyskey)
2822 {
2823 var = getvalkey(addr, type, VSTRING|VISARRAY, key);
2824 if (var != NOVARIABLE) us_adjustquickkeys(var, FALSE);
2825 return;
2826 }
2827
2828 /* see if popup menu was created */
2829 if (namesamen(makename(key), x_("USER_binding_popup_"), 19) == 0)
2830 {
2831 var = getvalkey(addr, type, VSTRING|VISARRAY, key);
2832 if (var == NOVARIABLE) return;
2833 len = getlength(var);
2834
2835 /* create the popup menu */
2836 pm = (POPUPMENU *)emalloc(sizeof(POPUPMENU), us_tool->cluster);
2837 if (pm == 0)
2838 {
2839 ttyputnomemory();
2840 return;
2841 }
2842 mi = (POPUPMENUITEM *)emalloc((len-1) * sizeof(POPUPMENUITEM), us_tool->cluster);
2843 if (mi == 0)
2844 {
2845 ttyputnomemory();
2846 return;
2847 }
2848
2849 /* code cannot be called by multiple procesors: uses globals */
2850 NOT_REENTRANT;
2851
2852 pm->nextpopupmenu = us_firstpopupmenu;
2853 us_firstpopupmenu = pm;
2854 (void)allocstring(&pm->name, &makename(key)[19], us_tool->cluster);
2855 (void)allocstring(&pm->header, ((CHAR **)var->addr)[0], us_tool->cluster);
2856 pm->list = mi;
2857 pm->total = len-1;
2858
2859 /* fill the menu */
2860 for(i=1; i<len; i++)
2861 {
2862 mi[i-1].response = rb = us_allocusercom();
2863 rb->active = -1;
2864 (void)allocstring(&mi[i-1].attribute, x_(""), us_tool->cluster);
2865 mi[i-1].value = 0;
2866 us_parsebinding(((CHAR **)var->addr)[i], &commandbinding);
2867 us_setcommand(commandbinding.command, rb, i-1, commandbinding.nodeglyph,
2868 commandbinding.arcglyph, commandbinding.menumessage,
2869 commandbinding.popup, commandbinding.inputpopup);
2870 us_freebindingparse(&commandbinding);
2871 }
2872 return;
2873 }
2874 return;
2875 }
2876
2877 /* detect change to SPICE primitive set */
2878 if (type == VTOOL && key == sim_spice_partskey)
2879 {
2880 us_checkspiceparts();
2881 return;
2882 }
2883
2884 /* handle changes to objects on technologies */
2885 if (type == VTECHNOLOGY)
2886 {
2887 /* changes to technology variables may invalidate caches */
2888 changedtechnologyvariable(key);
2889
2890 /* if layer letters changed, recache the data */
2891 if (key == us_layer_letters_key)
2892 {
2893 us_initlayerletters();
2894 return;
2895 }
2896
2897 if (key == el_techstate_key)
2898 {
2899 var = getvalkey(addr, VTECHNOLOGY, VINTEGER, el_techstate_key);
2900 if (var != NOVARIABLE)
2901 (void)asktech((TECHNOLOGY *)addr, x_("set-state"), var->addr);
2902 }
2903 return;
2904 }
2905
2906 /* handle changes to objects on NODEPROTOs */
2907 if (type == VNODEPROTO)
2908 {
2909 if (key == el_node_size_default_key)
2910 {
2911 /* remember the size of the wire-pin in Schematics */
2912 np = (NODEPROTO *)addr;
2913 if (np == sch_wirepinprim)
2914 {
2915 defaultnodesize(sch_wirepinprim, &sch_wirepinsizex, &sch_wirepinsizey);
2916 }
2917
2918 /* redraw the node in the component menu */
2919 if ((us_tool->toolstate&MENUON) == 0) return;
2920 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_binding_menu_key);
2921 if (var == NOVARIABLE) return;
2922 len = getlength(var);
2923 for(i=0; i<len; i++)
2924 {
2925 pt = ((CHAR **)var->addr)[i];
2926 us_parsebinding(pt, &commandbinding);
2927 if (commandbinding.nodeglyph != NONODEPROTO)
2928 {
2929 if (us_menupos <= 1)
2930 {
2931 y = i / us_menux;
2932 x = i % us_menux;
2933 } else
2934 {
2935 x = i / us_menuy;
2936 y = i % us_menuy;
2937 }
2938 us_drawmenuentry(x, y, pt);
2939 }
2940 us_freebindingparse(&commandbinding);
2941 }
2942 return;
2943 }
2944 return;
2945 }
2946
2947 /* update far text if displayable variable is added to NODEINST or ARCINST */
2948 if ((newtype&VDISPLAY) != 0)
2949 {
2950 if (type == VNODEINST) us_computenodefartextbit((NODEINST *)addr); else
2951 if (type == VARCINST) us_computearcfartextbit((ARCINST *)addr);
2952 }
2953
2954 /* handle changes to objects on ARCPROTOs */
2955 if (type == VARCPROTO)
2956 {
2957 if (key == el_arc_width_default_key)
2958 {
2959 /* redraw the arc in the component menu */
2960 if ((us_tool->toolstate&MENUON) == 0) return;
2961 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_binding_menu_key);
2962 if (var == NOVARIABLE) return;
2963 ap = (ARCPROTO *)addr;
2964 len = getlength(var);
2965 for(i=0; i<len; i++)
2966 {
2967 pt = ((CHAR **)var->addr)[i];
2968 us_parsebinding(pt, &commandbinding);
2969 if (commandbinding.arcglyph != NOARCPROTO)
2970 {
2971 if (us_menupos <= 1)
2972 {
2973 y = i / us_menux;
2974 x = i % us_menux;
2975 } else
2976 {
2977 x = i / us_menuy;
2978 y = i % us_menuy;
2979 }
2980 us_drawmenuentry(x, y, pt);
2981 }
2982 us_freebindingparse(&commandbinding);
2983 }
2984 return;
2985 }
2986 return;
2987 }
2988 }
2989
us_killvariable(INTBIG addr,INTBIG type,INTBIG key,INTBIG oldaddr,INTBIG oldtype,UINTBIG * olddescript)2990 void us_killvariable(INTBIG addr, INTBIG type, INTBIG key, INTBIG oldaddr,
2991 INTBIG oldtype, UINTBIG *olddescript)
2992 {
2993 REGISTER INTBIG len, i;
2994 REGISTER CHAR *name;
2995 REGISTER POPUPMENU *pm, *lastpm;
2996 HIGHLIGHT high;
2997 REGISTER WINDOWPART *w;
2998 REGISTER EDITOR *e;
2999 Q_UNUSED( olddescript );
3000
3001 if ((oldtype&VCREF) != 0)
3002 {
3003 name = changedvariablename(type, key, oldtype);
3004
3005 /* see if cell name changed */
3006 if ((type&VTYPE) == VNODEPROTO && namesame(name, x_("protoname")) == 0)
3007 {
3008 us_cellwithkilledname = (NODEPROTO *)addr;
3009 us_killednameoncell = (CHAR *)oldaddr;
3010 return;
3011 }
3012 return;
3013 }
3014
3015 /* see if an option variable changed */
3016 if (isoptionvariable(addr, type, makename(key)))
3017 us_optionschanged = TRUE;
3018
3019 /* close any text editor windows that are examining the variable */
3020 if ((oldtype&VTYPE) == VSTRING && (oldtype&VISARRAY) != 0)
3021 {
3022 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
3023 if ((w->state&WINDOWTYPE) == TEXTWINDOW)
3024 {
3025 e = w->editor;
3026 if (e == NOEDITOR) continue;
3027 if (e->editobjvar == NOVARIABLE) continue;
3028 if (e->editobjvar->addr != oldaddr || e->editobjvar->type != (UINTBIG)oldtype) continue;
3029 if ((INTBIG)e->editobjaddr != addr || e->editobjtype != type) continue;
3030 us_delcellmessage(w->curnodeproto);
3031 }
3032 }
3033
3034 /* handle changes to objects on the user interface */
3035 if (addr == (INTBIG)us_tool)
3036 {
3037 /* show highlight if it changed */
3038 if (key == us_highlightedkey && (us_state&HIGHLIGHTSET) == 0)
3039 {
3040 len = (oldtype&VLENGTH) >> VLENGTHSH;
3041 for(i=0; i<len; i++)
3042 {
3043 if (us_makehighlight(((CHAR **)oldaddr)[i], &high)) continue;
3044 us_sethighlight(&high, ALLOFF);
3045 }
3046 us_setselectioncount();
3047 us_highlighthaschanged();
3048 return;
3049 }
3050
3051 /* shadow placement angle if it changed */
3052 if (key == us_placement_angle_key)
3053 {
3054 us_setnodeangle(NOWINDOWFRAME);
3055 return;
3056 }
3057
3058 /* see if popup menu was deleted */
3059 if (namesamen(makename(key), x_("USER_binding_popup_"), 19) == 0)
3060 {
3061 /* code cannot be called by multiple procesors: uses globals */
3062 NOT_REENTRANT;
3063
3064 name = &makename(key)[19];
3065 lastpm = NOPOPUPMENU;
3066 for(pm = us_firstpopupmenu; pm != NOPOPUPMENU; pm = pm->nextpopupmenu)
3067 {
3068 if (namesame(name, pm->name) == 0) break;
3069 lastpm = pm;
3070 }
3071 if (pm == NOPOPUPMENU) return;
3072 if (lastpm == NOPOPUPMENU) us_firstpopupmenu = pm->nextpopupmenu; else
3073 lastpm->nextpopupmenu = pm->nextpopupmenu;
3074 for(i=0; i<pm->total; i++)
3075 {
3076 efree(pm->list[i].attribute);
3077 us_freeusercom(pm->list[i].response);
3078 }
3079 efree(pm->name);
3080 efree(pm->header);
3081 efree((CHAR *)pm->list);
3082 efree((CHAR *)pm);
3083 return;
3084 }
3085 }
3086 }
3087
us_modifyvariable(INTBIG addr,INTBIG type,INTBIG key,INTBIG vartype,INTBIG aindex,INTBIG oldvalue)3088 void us_modifyvariable(INTBIG addr, INTBIG type, INTBIG key, INTBIG vartype,
3089 INTBIG aindex, INTBIG oldvalue)
3090 {
3091 REGISTER VARIABLE *var;
3092 REGISTER INTBIG x, y;
3093 REGISTER CHAR *str;
3094 REGISTER USERCOM *rb;
3095 POPUPMENU *pm;
3096 COMMANDBINDING commandbinding;
3097 Q_UNUSED( oldvalue );
3098
3099 if ((vartype&VCREF) != 0)
3100 {
3101 /* see if PORTPROTO's "textdescript[1]" field changed */
3102 if ((type&VTYPE) == VPORTPROTO && aindex == 1)
3103 {
3104 str = changedvariablename(type, key, vartype);
3105 if (namesame(str, x_("textdescript")) == 0)
3106 us_computenodefartextbit(((PORTPROTO *)addr)->subnodeinst);
3107 }
3108 return;
3109 }
3110
3111 /* see if an option variable changed */
3112 if ((vartype&VDONTSAVE) == 0)
3113 {
3114 if (isoptionvariable(addr, type, makename(key)))
3115 us_optionschanged = TRUE;
3116 }
3117
3118 /* handle changes to objects on the user interface */
3119 if (addr == (INTBIG)us_tool)
3120 {
3121 /* set colormap updating if it changed */
3122 if (key == us_colormap_red_key || key == us_colormap_green_key || key == us_colormap_blue_key)
3123 {
3124 if (us_maplow == -1) us_maplow = us_maphigh = aindex; else
3125 {
3126 if (aindex < us_maplow) us_maplow = aindex;
3127 if (aindex > us_maphigh) us_maphigh = aindex;
3128 }
3129 }
3130
3131 /* set menu binding if it changed */
3132 if (key == us_binding_menu_key)
3133 {
3134 if (us_menuchanged) return;
3135 if ((us_tool->toolstate&MENUON) == 0) return;
3136 var = getvalkey(addr, type, VSTRING|VISARRAY, key);
3137 if (var == NOVARIABLE) return;
3138 us_parsebinding(((CHAR **)var->addr)[aindex], &commandbinding);
3139 if (us_menupos <= 1)
3140 {
3141 y = aindex / us_menux;
3142 x = aindex % us_menux;
3143 } else
3144 {
3145 x = aindex / us_menuy;
3146 y = aindex % us_menuy;
3147 }
3148 if (*commandbinding.command == 0) us_drawmenuentry(x, y, x_("")); else
3149 us_drawmenuentry(x, y, ((CHAR **)var->addr)[aindex]);
3150 us_freebindingparse(&commandbinding);
3151 return;
3152 }
3153
3154 /* set popup menu binding if it changed */
3155 if (namesamen(makename(key), x_("USER_binding_popup_"), 19) == 0)
3156 {
3157 var = getvalkey(addr, type, VSTRING|VISARRAY, key);
3158 if (var == NOVARIABLE) return;
3159 if (aindex == 0)
3160 {
3161 /* special case: set menu header */
3162 str = &makename(key)[19];
3163 for(pm = us_firstpopupmenu; pm != NOPOPUPMENU; pm = pm->nextpopupmenu)
3164 if (namesame(str, pm->name) == 0) break;
3165 if (pm != NOPOPUPMENU)
3166 (void)reallocstring(&pm->header, ((CHAR **)var->addr)[0], us_tool->cluster);
3167 return;
3168 }
3169 us_parsebinding(((CHAR **)var->addr)[aindex], &commandbinding);
3170 if (commandbinding.popup != NOPOPUPMENU)
3171 {
3172 rb = commandbinding.popup->list[aindex-1].response;
3173 us_setcommand(commandbinding.command, rb, aindex-1, commandbinding.nodeglyph,
3174 commandbinding.arcglyph, commandbinding.menumessage,
3175 commandbinding.popup, commandbinding.inputpopup);
3176 nativemenurename(commandbinding.popup, aindex-1);
3177 }
3178 us_freebindingparse(&commandbinding);
3179 return;
3180 }
3181 }
3182 }
3183
us_checkinplaceedits(NODEPROTO * cell)3184 void us_checkinplaceedits(NODEPROTO *cell)
3185 {
3186 REGISTER WINDOWPART *w;
3187 REGISTER INTBIG i;
3188
3189 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
3190 {
3191 if ((w->state&INPLACEEDIT) == 0) continue;
3192 for(i=0; i<w->inplacedepth; i++)
3193 if (cell == w->inplacestack[i]->parent) break;
3194 if (i < w->inplacedepth) continue;
3195
3196 /* must redraw window "w" */
3197 w->state |= INPLACEQUEUEREDRAW;
3198 }
3199 }
3200
3201 /*
3202 * routine to place the command "str" in the command object "rb". Also sets
3203 * the node glyph if "nodeglyph" is not NONODEPROTO, the arc glyph if
3204 * "arcglyph" is not NOARCPROTO and the menu message if "menumessage" is nonzero.
3205 * If "popup" is not NOPOPUPMENU, this is a popup (and is input-popup if
3206 * "inputpopup" is true). For popup menus, "mindex" is the menu entry.
3207 */
us_setcommand(CHAR * str,USERCOM * rb,INTBIG mindex,NODEPROTO * nodeglyph,ARCPROTO * arcglyph,CHAR * menumessage,POPUPMENU * popup,BOOLEAN inputpopup)3208 void us_setcommand(CHAR *str, USERCOM *rb, INTBIG mindex,
3209 NODEPROTO *nodeglyph, ARCPROTO *arcglyph, CHAR *menumessage,
3210 POPUPMENU *popup, BOOLEAN inputpopup)
3211 {
3212 CHAR *a[MAXPARS+1];
3213 REGISTER INTBIG newcount, j, i;
3214 COMCOMP *carray[MAXPARS];
3215 extern COMCOMP us_userp;
3216 REGISTER void *infstr;
3217
3218 /* handle un-binding */
3219 if (*str == 0)
3220 {
3221 if (popup != NOPOPUPMENU)
3222 {
3223 if (rb->message != 0) efree(rb->message);
3224 rb->message = 0;
3225 if (menumessage != 0)
3226 {
3227 (void)allocstring(&rb->message, menumessage, us_tool->cluster);
3228 }
3229 if (rb->message == 0)
3230 (void)reallocstring(&popup->list[mindex].attribute, x_(""), us_tool->cluster); else
3231 (void)reallocstring(&popup->list[mindex].attribute, rb->message, us_tool->cluster);
3232 popup->list[mindex].maxlen = -1;
3233 /* should "popup->list[mindex].value" be freed here? !!! */
3234 }
3235 if (rb->active >= 0)
3236 {
3237 for(j=0; j<rb->count; j++) efree(rb->word[j]);
3238 rb->count = 0;
3239 if (rb->message != 0) efree(rb->message);
3240 rb->message = 0;
3241 }
3242 rb->active = -1;
3243 return;
3244 }
3245
3246 /* parse this command */
3247 newcount = us_parsecommand(str, a);
3248 if (newcount <= 0) return;
3249 i = parse(a[0], &us_userp, TRUE);
3250 if (i < 0) return;
3251
3252 /* remove former command if it exists */
3253 if (rb->active >= 0)
3254 {
3255 for(j=0; j<rb->count; j++) efree(rb->word[j]);
3256 if (rb->message != 0) efree(rb->message);
3257 rb->message = 0;
3258 }
3259
3260 /* set the new command */
3261 for(j=0; j<newcount-1; j++)
3262 {
3263 if (allocstring(&rb->word[j], a[j+1], us_tool->cluster))
3264 {
3265 ttyputnomemory();
3266 rb->active = -1;
3267 return;
3268 }
3269 }
3270
3271 /* set all other information */
3272 if (menumessage == 0) rb->message = 0; else
3273 {
3274 if (rb->message != 0) efree(rb->message);
3275 (void)allocstring(&rb->message, menumessage, us_tool->cluster);
3276 }
3277 rb->count = newcount-1;
3278 rb->active = i;
3279 rb->menu = us_getpopupmenu(a[0]);
3280 if (rb->comname != 0) efree(rb->comname);
3281 (void)allocstring(&rb->comname, a[0], us_tool->cluster);
3282 rb->nodeglyph = nodeglyph;
3283 rb->arcglyph = arcglyph;
3284 if (popup != NOPOPUPMENU)
3285 {
3286 /* load popup menu with full command string */
3287 if (rb->message != 0)
3288 (void)reallocstring(&popup->list[mindex].attribute, rb->message, us_tool->cluster); else
3289 {
3290 infstr = initinfstr();
3291 addstringtoinfstr(infstr, rb->comname);
3292 us_appendargs(infstr, rb);
3293 (void)reallocstring(&popup->list[mindex].attribute, returninfstr(infstr), us_tool->cluster);
3294 }
3295 popup->list[mindex].valueparse = NOCOMCOMP;
3296 if (inputpopup)
3297 {
3298 /* determine command completion for input portion */
3299 i = us_fillcomcomp(rb, carray);
3300 if (i > rb->count && carray[rb->count] != NOCOMCOMP)
3301 popup->list[mindex].valueparse = carray[rb->count];
3302 }
3303 if (popup->list[mindex].valueparse == NOCOMCOMP)
3304 popup->list[mindex].maxlen = -1; else popup->list[mindex].maxlen = 20;
3305 }
3306 }
3307
3308 /* Technology: Different Options */
3309 static DIALOGITEM us_techdifoptdialogitems[] =
3310 {
3311 /* 1 */ {0, {140,264,164,440}, BUTTON, N_("Use Requested Options")},
3312 /* 2 */ {0, {140,32,164,208}, BUTTON, N_("Leave Current Options")},
3313 /* 3 */ {0, {8,8,24,344}, MESSAGE, N_("This library requests different options for technology:")},
3314 /* 4 */ {0, {8,348,24,472}, MESSAGE, x_("")},
3315 /* 5 */ {0, {32,8,48,132}, MESSAGE, N_("Current options:")},
3316 /* 6 */ {0, {32,136,80,472}, MESSAGE, x_("")},
3317 /* 7 */ {0, {84,8,100,132}, MESSAGE, N_("Requested options:")},
3318 /* 8 */ {0, {84,136,132,472}, MESSAGE, x_("")}
3319 };
3320 static DIALOG us_techdifoptdialog = {{75,75,248,556}, N_("Technology Options Conflict"), 0, 8, us_techdifoptdialogitems, 0, 0};
3321
3322 /* special items for the "technology options" dialog: */
3323 #define DDFT_USEREQUESTED 1 /* Use requested options (button) */
3324 #define DDFT_LEAVECURRENT 2 /* Leave current options (button) */
3325 #define DDFT_TECHNAME 4 /* Technology name (stat text) */
3326 #define DDFT_CUROPTION 6 /* Current options (stat text) */
3327 #define DDFT_REQOPTION 8 /* Requested options (stat text) */
3328
us_readlibrary(LIBRARY * lib)3329 void us_readlibrary(LIBRARY *lib)
3330 {
3331 REGISTER VARIABLE *var;
3332 REGISTER CHAR *pt, *name, *curstatename, *newstatename;
3333 CHAR *par[MAXPARS];
3334 REGISTER INTBIG majversion, minversion, found, i, j, nvers, len,
3335 curstate, itemHit, col;
3336 REGISTER BOOLEAN warnofchanges;
3337 REGISTER TECHNOLOGY *mocmostech, *tech;
3338 REGISTER POPUPMENU *pm;
3339 REGISTER POPUPMENUITEM *mi;
3340 REGISTER NODEPROTO *np;
3341 REGISTER NODEINST *ni;
3342 REGISTER ARCINST *ai;
3343 REGISTER USERCOM *rb;
3344 COMMANDBINDING commandbinding;
3345 extern COMCOMP us_yesnop;
3346 REGISTER void *infstr, *dia;
3347
3348 /* create any popup menus found in the library */
3349 for(i=0; i<us_tool->numvar; i++)
3350 {
3351 /* only want permanent user-interface variables (ones just read in) */
3352 var = &us_tool->firstvar[i];
3353 if ((var->type&VDONTSAVE) != 0) continue;
3354
3355 /* handle popup menus */
3356 if (namesamen(makename(var->key), x_("USER_binding_popup_"), 19) == 0)
3357 {
3358 name = &makename(var->key)[19];
3359 if (us_getpopupmenu(name) != NOPOPUPMENU) continue;
3360
3361 /* create the popup menu */
3362 len = getlength(var);
3363 pm = (POPUPMENU *)emalloc(sizeof(POPUPMENU), us_tool->cluster);
3364 if (pm == 0)
3365 {
3366 ttyputnomemory();
3367 break;
3368 }
3369 mi = (POPUPMENUITEM *)emalloc((len-1) * sizeof(POPUPMENUITEM), us_tool->cluster);
3370 if (mi == 0)
3371 {
3372 ttyputnomemory();
3373 return;
3374 }
3375 pm->nextpopupmenu = us_firstpopupmenu;
3376 us_firstpopupmenu = pm;
3377 (void)allocstring(&pm->name, name, us_tool->cluster);
3378 (void)allocstring(&pm->header, ((CHAR **)var->addr)[0], us_tool->cluster);
3379 pm->list = mi;
3380 pm->total = len-1;
3381
3382 /* initialize the menu */
3383 for(j=1; j<len; j++)
3384 {
3385 mi[j-1].response = rb = us_allocusercom();
3386 rb->active = -1;
3387 (void)allocstring(&mi[j-1].attribute, x_(""), us_tool->cluster);
3388 mi[j-1].value = 0;
3389 }
3390 us_scanforkeyequiv(pm);
3391 }
3392 }
3393
3394 /* fill any popup menus found in the library */
3395 for(i=0; i<us_tool->numvar; i++)
3396 {
3397 /* only want permanent user-interface variables (ones just read in) */
3398 var = &us_tool->firstvar[i];
3399 if ((var->type&VDONTSAVE) != 0) continue;
3400
3401 /* handle popup menus */
3402 if (namesamen(makename(var->key), x_("USER_binding_popup_"), 19) == 0)
3403 {
3404 var->type |= VDONTSAVE;
3405 name = &makename(var->key)[19];
3406 pm = us_getpopupmenu(name);
3407 mi = pm->list;
3408 len = getlength(var);
3409
3410 /* fill the menu */
3411 for(j=1; j<len; j++)
3412 {
3413 rb = mi[j-1].response;
3414 us_parsebinding(((CHAR **)var->addr)[j], &commandbinding);
3415 us_setcommand(commandbinding.command, rb, j-1, commandbinding.nodeglyph,
3416 commandbinding.arcglyph, commandbinding.menumessage,
3417 pm, commandbinding.inputpopup);
3418 us_freebindingparse(&commandbinding);
3419 }
3420 }
3421 }
3422
3423 /* recache mirrored variables now that the library may have overridden them */
3424 for(i=0; us_variablemirror[i].key != 0; i++)
3425 {
3426 var = getvalkey((INTBIG)us_tool, VTOOL, -1, *us_variablemirror[i].key);
3427 if (var != NOVARIABLE)
3428 {
3429 *us_variablemirror[i].value = var->addr;
3430 }
3431 }
3432
3433 var = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER, us_alignment_ratio_key);
3434 if (var != NOVARIABLE) us_alignment_ratio = var->addr;
3435 var = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER, us_alignment_edge_ratio_key);
3436 if (var != NOVARIABLE) us_edgealignment_ratio = var->addr;
3437
3438 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_quickkeyskey);
3439 if (var != NOVARIABLE)
3440 {
3441 if ((lib->userbits&HIDDENLIBRARY) == 0) warnofchanges = TRUE; else
3442 warnofchanges = FALSE;
3443 us_adjustquickkeys(var, warnofchanges);
3444 }
3445
3446 var = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER, us_displayunitskey);
3447 if (var != NOVARIABLE)
3448 el_units = (el_units & ~DISPLAYUNITS) | (var->addr & DISPLAYUNITS);
3449
3450 /* make sure the electrical units are the same */
3451 var = getvalkey((INTBIG)lib, VLIBRARY, VINTEGER, us_electricalunitskey);
3452 if (var != NOVARIABLE && var->addr != us_electricalunits)
3453 {
3454 us_adjustelectricalunits(lib, var->addr);
3455 }
3456
3457 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING, us_text_editorkey);
3458 if (var != NOVARIABLE)
3459 {
3460 for(i=0; us_editortable[i].editorname != 0; i++)
3461 if (namesame((CHAR *)var->addr, us_editortable[i].editorname) == 0) break;
3462 if (us_editortable[i].editorname != 0)
3463 us_currenteditor = i;
3464 }
3465 defaultnodesize(sch_wirepinprim, &sch_wirepinsizex, &sch_wirepinsizey);
3466
3467 /* grab new SPICE parts */
3468 var = getvalkey((INTBIG)sim_tool, VTOOL, VSTRING, sim_spice_partskey);
3469 if (var != NOVARIABLE) us_checkspiceparts();
3470
3471 /* recache technology variables */
3472 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3473 {
3474 /* reset technology state ("TECH_state") */
3475 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VINTEGER, el_techstate_key);
3476 if (var != NOVARIABLE)
3477 (void)asktech(tech, x_("set-state"), var->addr);
3478
3479 /* check out desired state ("TECH_last_state") */
3480 var = getvalkey((INTBIG)tech, VTECHNOLOGY, VINTEGER, us_techlaststatekey);
3481 if (var != NOVARIABLE)
3482 {
3483 curstate = asktech(tech, x_("get-state"));
3484 if (curstate != var->addr)
3485 {
3486 /* see if there is anything from this technology in the library */
3487 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
3488 {
3489 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
3490 {
3491 if (ni->proto->primindex == 0) continue;
3492 if (ni->proto->tech == tech) break;
3493 }
3494 if (ni != NONODEINST) break;
3495 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
3496 if (ai->proto->tech == tech) break;
3497 if (ai != NOARCINST) break;
3498 }
3499 if (np != NONODEPROTO)
3500 {
3501 curstatename = (CHAR *)asktech(tech, x_("describe-state"), curstate);
3502 newstatename = (CHAR *)asktech(tech, x_("describe-state"), var->addr);
3503 if (curstatename != 0 && newstatename != 0)
3504 {
3505 if ((lib->userbits&HIDDENLIBRARY) != 0) itemHit = DDFT_USEREQUESTED; else
3506 {
3507 /* display the technology option conflict dialog box */
3508 dia = DiaInitDialog(&us_techdifoptdialog);
3509 if (dia == 0) return;
3510
3511 /* load the message */
3512 DiaSetText(dia, DDFT_TECHNAME, tech->techname);
3513 DiaSetText(dia, DDFT_CUROPTION, curstatename);
3514 DiaSetText(dia, DDFT_REQOPTION, newstatename);
3515
3516 /* loop until done */
3517 for(;;)
3518 {
3519 itemHit = DiaNextHit(dia);
3520 if (itemHit == DDFT_USEREQUESTED || itemHit == DDFT_LEAVECURRENT) break;
3521 }
3522 DiaDoneDialog(dia);
3523 }
3524
3525 if (itemHit == DDFT_USEREQUESTED)
3526 {
3527 (void)asktech(tech, x_("set-state"), var->addr);
3528 setvalkey((INTBIG)tech, VTECHNOLOGY, el_techstate_key, var->addr, VINTEGER);
3529 if (el_curtech == tech)
3530 {
3531 par[0] = x_("size");
3532 par[1] = x_("auto");
3533 us_menu(2, par);
3534 us_setmenunodearcs();
3535 }
3536 }
3537 }
3538 }
3539 }
3540 }
3541
3542 /* see if layer patterns changed */
3543 for(i=0; i<tech->layercount; i++)
3544 {
3545 infstr = initinfstr();
3546 addstringtoinfstr(infstr, x_("TECH_layer_pattern_"));
3547 addstringtoinfstr(infstr, layername(tech, i));
3548 pt = returninfstr(infstr);
3549 var = getval((INTBIG)el_curtech, VTECHNOLOGY, VINTEGER|VISARRAY, pt);
3550 if (var == NOVARIABLE) continue;
3551
3552 /* adjust for old patterns with smaller amounts of data */
3553 len = getlength(var);
3554 if (len < 16)
3555 {
3556 INTBIG newpattern[18];
3557
3558 for(j=0; j<8; j++)
3559 newpattern[j] = newpattern[j+8] = ((INTBIG *)var->addr)[j];
3560 for(j=8; j<len; j++)
3561 newpattern[j+8] = ((INTBIG *)var->addr)[j];
3562 nextchangequiet();
3563 (void)setval((INTBIG)el_curtech, VTECHNOLOGY, pt,
3564 (INTBIG)newpattern, VINTEGER|VISARRAY|(18<<VLENGTHSH));
3565 var = getval((INTBIG)el_curtech, VTECHNOLOGY, VINTEGER|VISARRAY, pt);
3566 }
3567
3568 (el_curtech->layers[i])->colstyle = (INTSML)(((INTBIG *)var->addr)[16]);
3569 for(j=0; j<16; j++)
3570 (el_curtech->layers[i])->raster[j] = (INTSML)(((INTBIG *)var->addr)[j]);
3571 if (getlength(var) > 17)
3572 {
3573 col = ((INTBIG *)var->addr)[17];
3574 (el_curtech->layers[i])->col = col;
3575 if (col == COLORT1 || col == COLORT2 || col == COLORT3 ||
3576 col == COLORT4 || col == COLORT5)
3577 (el_curtech->layers[i])->bits = col; else
3578 (el_curtech->layers[i])->bits = LAYERO;
3579 }
3580 }
3581 }
3582
3583 /* redisplay the explorer window */
3584 us_cellstructurechanged = TRUE;
3585
3586 /* set cell's technology and center attributes */
3587 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
3588 {
3589 np->tech = whattech(np);
3590 us_setessentialbounds(np);
3591 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
3592 if (ni->proto == gen_cellcenterprim)
3593 us_setnodeprotocenter(ni->lowx, ni->lowy, np);
3594 }
3595
3596 /* do font conversion if any is specified */
3597 us_checkfontassociations(lib);
3598
3599 /*
3600 * see if the library is old enough to require MOCMOS conversion
3601 * or serpentine port conversion
3602 */
3603 var = getval((INTBIG)lib, VLIBRARY, VSTRING, x_("LIB_former_version"));
3604 if (var == NOVARIABLE) return;
3605
3606 /* parse the former Electric version number */
3607 pt = (CHAR *)var->addr;
3608 majversion = eatoi(pt);
3609 while (*pt != 0 && *pt != '.') pt++;
3610 if (*pt == 0) minversion = 0; else minversion = eatoi(pt+1);
3611 nvers = majversion*100 + minversion;
3612 if (nvers > 335) return;
3613
3614 /* versions 3.35 or earlier may require MOCMOS conversion */
3615 mocmostech = gettechnology(x_("mocmos"));
3616 if (mocmostech == NOTECHNOLOGY) return;
3617
3618 /* see if there is any MOCMOS data in the library */
3619 found = 0;
3620 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
3621 {
3622 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
3623 if (ni->proto->primindex != 0 && ni->proto->tech == mocmostech)
3624 {
3625 found++;
3626 break;
3627 }
3628 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
3629 if (ai->proto->tech == mocmostech)
3630 {
3631 found++;
3632 break;
3633 }
3634 if (found != 0) break;
3635 }
3636 if (found == 0) return;
3637
3638 /* there are MOCMOS elements in an old library: offer conversion */
3639 ttyputmsg(_("This library contains old format MOSIS CMOS (mocmos) cells"));
3640 i = ttygetparam(_("Would you like to convert them? [y] "), &us_yesnop, MAXPARS, par);
3641 if (i > 0 && namesamen(par[0], x_("no"), estrlen(par[0])) == 0)
3642 {
3643 ttyputmsg(_("No conversion done. To do this later, use:"));
3644 ttyputmsg(x_(" -technology tell mocmos convert-old-format-library"));
3645 return;
3646 }
3647
3648 /* do the conversion */
3649 tech_convertmocmoslib(lib);
3650 }
3651
3652 /*
3653 * Routine to examine the font associations stored in the library and correct if
3654 * necessary.
3655 */
us_checkfontassociations(LIBRARY * lib)3656 void us_checkfontassociations(LIBRARY *lib)
3657 {
3658 REGISTER NODEPROTO *np;
3659 REGISTER NODEINST *ni;
3660 REGISTER ARCINST *ai;
3661 REGISTER PORTARCINST *pi;
3662 REGISTER PORTEXPINST *pe;
3663 REGISTER PORTPROTO *pp;
3664 REGISTER INTBIG *fontmatch, i, len, index, j, maxindex;
3665 CHAR *facename, *pt;
3666 REGISTER VARIABLE *var;
3667
3668 var = getval((INTBIG)lib, VLIBRARY, VSTRING|VISARRAY, x_("LIB_font_associations"));
3669 if (var == NOVARIABLE) return;
3670 len = getlength(var);
3671 maxindex = 0;
3672 for(i=0; i<len; i++)
3673 {
3674 pt = ((CHAR **)var->addr)[i];
3675 index = eatoi(pt);
3676 if (index > maxindex) maxindex = index;
3677 }
3678 if (maxindex <= 0) return;
3679 maxindex++;
3680 fontmatch = (INTBIG *)emalloc(maxindex * SIZEOFINTBIG, us_tool->cluster);
3681 if (fontmatch == 0) return;
3682 for(i=0; i<maxindex; i++) fontmatch[i] = 0;
3683 for(i=0; i<len; i++)
3684 {
3685 pt = ((CHAR **)var->addr)[i];
3686 index = eatoi(pt);
3687 while (*pt != 0 && *pt != '/') pt++;
3688 if (*pt == 0) continue;
3689 facename = &pt[1];
3690
3691 /* see if there is face "facename" and associate it with font "index" */
3692 j = screenfindface(facename);
3693 if (j >= 0) fontmatch[index] = j; else
3694 {
3695 ttyputerr(x_("Font %s not found, using default"), facename);
3696 }
3697 }
3698
3699 /* now apply the transformation to all face indices */
3700 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
3701 {
3702 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
3703 {
3704 us_setfontassociationvar(ni->numvar, ni->firstvar, fontmatch);
3705 for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
3706 us_setfontassociationvar(pi->numvar, pi->firstvar, fontmatch);
3707 for(pe = ni->firstportexpinst; pe != NOPORTEXPINST; pe = pe->nextportexpinst)
3708 us_setfontassociationvar(pe->numvar, pe->firstvar, fontmatch);
3709 if (ni->proto->primindex == 0)
3710 us_setfontassociationdescript(ni->textdescript, fontmatch);
3711 }
3712 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
3713 us_setfontassociationvar(ai->numvar, ai->firstvar, fontmatch);
3714 for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
3715 {
3716 us_setfontassociationvar(pp->numvar, pp->firstvar, fontmatch);
3717 us_setfontassociationdescript(pp->textdescript, fontmatch);
3718 }
3719 us_setfontassociationvar(np->numvar, np->firstvar, fontmatch);
3720 }
3721 us_setfontassociationvar(lib->numvar, lib->firstvar, fontmatch);
3722
3723 (void)delval((INTBIG)lib, VLIBRARY, x_("LIB_font_associations"));
3724 efree((CHAR *)fontmatch);
3725 }
3726
3727 /*
3728 * Helper routine for "us_checkfontassociations".
3729 */
us_setfontassociationvar(INTSML numvar,VARIABLE * firstvar,INTBIG * fontmatch)3730 void us_setfontassociationvar(INTSML numvar, VARIABLE *firstvar, INTBIG *fontmatch)
3731 {
3732 REGISTER INTBIG i;
3733 REGISTER VARIABLE *var;
3734
3735 for(i=0; i<numvar; i++)
3736 {
3737 var = &firstvar[i];
3738 us_setfontassociationdescript(var->textdescript, fontmatch);
3739 }
3740 }
3741
3742 /*
3743 * Helper routine for "us_checkfontassociations".
3744 */
us_setfontassociationdescript(UINTBIG * descript,INTBIG * fontmatch)3745 void us_setfontassociationdescript(UINTBIG *descript, INTBIG *fontmatch)
3746 {
3747 REGISTER INTBIG face;
3748
3749 face = TDGETFACE(descript);
3750 if (face != 0) TDSETFACE(descript, fontmatch[face]);
3751 }
3752
us_eraselibrary(LIBRARY * lib)3753 void us_eraselibrary(LIBRARY *lib)
3754 {
3755 REGISTER NODEPROTO *np;
3756
3757 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
3758 us_removeubchange(np);
3759 us_unqueueredraw(lib);
3760 }
3761
us_writelibrary(LIBRARY * lib,BOOLEAN pass2)3762 void us_writelibrary(LIBRARY *lib, BOOLEAN pass2)
3763 {
3764 REGISTER INTBIG state;
3765 REGISTER TECHNOLOGY *tech;
3766 Q_UNUSED( pass2 );
3767
3768 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3769 {
3770 if (asktech(tech, x_("has-state")) == 0) continue;
3771 state = asktech(tech, x_("get-state"));
3772 nextchangequiet();
3773 setvalkey((INTBIG)tech, VTECHNOLOGY, us_techlaststatekey, state, VINTEGER);
3774 }
3775
3776 /* save electrical units on the library */
3777 nextchangequiet();
3778 setvalkey((INTBIG)lib, VLIBRARY, us_electricalunitskey, us_electricalunits, VINTEGER);
3779 }
3780
3781 /*
3782 * handle options. Returns true upon error
3783 */
us_options(INTBIG * argc,CHAR1 * argv[])3784 BOOLEAN us_options(INTBIG *argc, CHAR1 *argv[])
3785 {
3786 REGISTER CHAR *retur, *thisargv;
3787
3788 us_ignore_cadrc = FALSE;
3789 us_logging = TRUE;
3790
3791 while (*argc > 1 && argv[1][0] == '-')
3792 {
3793 thisargv = string2byte(argv[1]);
3794 switch (thisargv[1])
3795 {
3796 case '-': /* long options */
3797 if (estrcmp(&thisargv[2], x_("help")) == 0)
3798 {
3799 error(_("Usage: electric [-c] [-geom WxH+X+Y] [-i MACROFILE] [-m] [-n] [-t TECHNOLOGY] [LIBRARY]"));
3800 }
3801 if (estrcmp(&thisargv[2], x_("version")) == 0)
3802 {
3803 error(_("Electric version %s"), el_version);
3804 }
3805 break;
3806
3807 case 'c': /* ignore cadrc file */
3808 us_ignore_cadrc = TRUE;
3809 break;
3810
3811 case 'g': /* X11 Geometry spec SRP 2-19-91 */
3812 (*argc)--; argv++; /* bump past the geometry string */
3813 break;
3814
3815 case 'i': /* initial macro file to load after cadrc */
3816 allocstring(&us_firstmacrofile, string2byte(argv[2]), us_tool->cluster);
3817 (*argc)--; argv++;
3818 break;
3819
3820 case 'm': /* search for multiple monitors, used in graphXXX.c */
3821 case 'M':
3822 break;
3823
3824 case 'n': /* no session recording */
3825 us_logging = FALSE;
3826 break;
3827
3828 case 'q': /* qt drawing, used in graphqt.cpp */
3829 break;
3830
3831 case 't':
3832 if (thisargv[2] != 0) retur = &thisargv[2]; else
3833 {
3834 retur = string2byte(argv[2]);
3835 (*argc)--; argv++;
3836 }
3837 el_curtech = gettechnology(retur);
3838 if (el_curtech == NOTECHNOLOGY) error(_("Unknown technology: '%s'"), retur);
3839 if (el_curtech != sch_tech && el_curtech != art_tech && el_curtech != gen_tech)
3840 el_curlayouttech = el_curtech;
3841 break;
3842
3843 #ifdef sun
3844 case 'W': /* SUN window switches must be ignored */
3845 switch (thisargv[2])
3846 {
3847 case 'g': /* default color */
3848 case 'H': /* help */
3849 case 'i': /* iconic */
3850 case 'n': /* no label */
3851 break;
3852 case 'I': /* icon image */
3853 case 'l': /* label */
3854 case 'L': /* icon label */
3855 case 't': /* font */
3856 case 'T': /* icon font */
3857 case 'w': /* width */
3858 (*argc)--; argv++; break;
3859 case 'p': /* position */
3860 case 'P': /* closed position */
3861 case 's': /* size */
3862 (*argc) -= 2; argv += 2; break;
3863 case 'b': /* background color */
3864 case 'f': /* foreground color */
3865 (*argc) -= 3; argv += 3; break;
3866 }
3867 break;
3868 #endif
3869
3870 default:
3871 error(_("Unrecognized switch: %s"), thisargv);
3872 }
3873 (*argc)--;
3874 argv++;
3875 }
3876
3877 /* remember the initial library if specified */
3878 if (*argc == 2)
3879 {
3880 (*argc)--;
3881 allocstring(&us_firstlibrary, string2byte(argv[1]), us_tool->cluster);
3882 }
3883
3884 /* check the arguments */
3885 if (*argc > 1)
3886 error(_("Usage: electric [-o] [-n] [-c] [-f] [-geom WxH+X+Y] [-t TECHNOLOGY] [LIBRARY]"));
3887 return(FALSE);
3888 }
3889
us_findcadrc(void)3890 void us_findcadrc(void)
3891 {
3892 CHAR *suf, *hd;
3893 REGISTER void *infstr;
3894
3895 /* try "cadrc" in current directory */
3896 if (!us_docadrc(CADRCFILENAME)) return;
3897
3898 /* if there is a "home" directory, try it there */
3899 hd = hashomedir();
3900 if (hd != 0)
3901 {
3902 infstr = initinfstr();
3903 addstringtoinfstr(infstr, hd);
3904 addstringtoinfstr(infstr, CADRCFILENAME);
3905 suf = returninfstr(infstr);
3906 if (!us_docadrc(suf)) return;
3907 }
3908
3909 /* not found there: try library directory */
3910 infstr = initinfstr();
3911 addstringtoinfstr(infstr, el_libdir);
3912 addstringtoinfstr(infstr, CADRCFILENAME);
3913 suf = returninfstr(infstr);
3914 if (!us_docadrc(suf)) return;
3915
3916 ttyputerr(_("Cannot find '%s' startup file: installation may be incorrect"),
3917 CADRCFILENAME);
3918 }
3919
3920 /*
3921 * get the commands in the system's or user's "cadrc" file: "name".
3922 * Returns true if the file cannot be found.
3923 */
us_docadrc(CHAR * name)3924 BOOLEAN us_docadrc(CHAR *name)
3925 {
3926 FILE *in;
3927 CHAR *filename;
3928
3929 /* look for startup file */
3930 in = xopen(name, us_filetypecadrc, x_(""), &filename);
3931 if (in == NULL) return(TRUE);
3932
3933 /* create a new macro package */
3934 us_curmacropack = us_newmacropack(x_("CADRC"));
3935
3936 /* execute commands beginning with "electric" in this file */
3937 us_docommands(in, FALSE, x_("electric"));
3938 xclose(in);
3939
3940 /* now there is no macro package */
3941 us_curmacropack = NOMACROPACK;
3942 return(FALSE);
3943 }
3944
us_wanttoread(CHAR * name)3945 void us_wanttoread(CHAR *name)
3946 {
3947 estrcpy(us_desiredlibrary, name);
3948 }
3949