1 /*
2  * Author:      William Chia-Wei Cheng (bill.cheng@acm.org)
3  *
4  * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5  *
6  * This file may be distributed under the terms of the Q Public License
7  * as defined by Trolltech AS of Norway and appearing in the file
8  * LICENSE.QPL included in the packaging of this file.
9  *
10  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11  * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12  * PURPOSE.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  * @(#)$Header: /mm2/home/cvs/bc-src/tgif/exec.c,v 1.59 2011/05/18 22:41:20 william Exp $
19  */
20 
21 #define _INCLUDE_FROM_EXEC_C_
22 
23 #include "tgifdefs.h"
24 #include "patchlvl.h"
25 #include "expfdefs.h"
26 #include "cmdids.h"
27 
28 #include "align.e"
29 #include "arc.e"
30 #include "attr.e"
31 #include "auxtext.e"
32 #include "box.e"
33 #include "cmd.e"
34 #include "color.e"
35 #include "choice.e"
36 #include "cursor.e"
37 #include "cutpaste.e"
38 #include "dialog.e"
39 #include "drawing.e"
40 #include "dup.e"
41 #include "edit.e"
42 #include "eps.e"
43 #include "exec.e"
44 #include "expr.e"
45 #include "file.e"
46 #include "font.e"
47 #include "grid.e"
48 #include "import.e"
49 #include "ini.e"
50 #include "mainloop.e"
51 #include "mainmenu.e"
52 #include "mark.e"
53 #include "menu.e"
54 #include "miniline.e"
55 #include "move.e"
56 #include "msg.e"
57 #include "names.e"
58 #include "navigate.e"
59 #include "obj.e"
60 #include "oval.e"
61 #include "page.e"
62 #include "pattern.e"
63 #include "pngtrans.e"
64 #include "poly.e"
65 #include "polygon.e"
66 #include "raster.e"
67 #include "rcbox.e"
68 #include "rect.e"
69 #include "remote.e"
70 #include "ruler.e"
71 #include "select.e"
72 #include "setup.e"
73 #include "shortcut.e"
74 #include "special.e"
75 #include "stk.e"
76 #include "stretch.e"
77 #include "strtbl.e"
78 #include "tangram2.e"
79 #include "tcp.e"
80 #include "text.e"
81 #include "util.e"
82 #include "version.e"
83 #include "wb.e"
84 #include "xbitmap.e"
85 #include "xpixmap.e"
86 #include "xprtfltr.e"
87 #include "z_intrf.e"
88 
89 int execAnimating=FALSE;
90 int execAnimateRedraw=FALSE;
91 int execCurDepth=0;
92 int replaceAttrFirstValueRedraw=TRUE;
93 int execNavigateBack=FALSE;
94 int userAbortExec=FALSE;
95 
96 static char gsPath[MAXSTRING+1];
97 
98 static int execInterruptEnabled=TRUE;
99 static int execInterruptQueued=FALSE;
100 
101 struct AttrRec *warpToAttr=NULL;
102 
103 char *cmdToExecAfterHyperJump=NULL;
104 
105 struct StrRec *topTmpStr=NULL;
106 struct StrRec *botTmpStr=NULL;
107 
108 #define MAXEXECOPENFILES 16
109 
110 struct OpenFileRec {
111    FILE *fp;
112    char *fname;
113    int eof;
114 } gaOpenFileInfo[MAXEXECOPENFILES];
115 
116 #define TOK_INVALID	(INVALID)
117 #define TOK_EMPTY	0
118 #define TOK_STR		1
119 #define TOK_LEFT_P	2
120 #define TOK_RIGHT_P	3
121 #define TOK_LEFT_B	4
122 #define TOK_RIGHT_B	5
123 #define TOK_LEFT_CB	6
124 #define TOK_RIGHT_CB	7
125 #define TOK_COMMA	8
126 #define TOK_SEMI	9
127 
128 static char execDummyStr[2048];
129 static int gnAbortExec=FALSE;
130 static int gnStopCmdExecuted=TRUE;
131 
132 int ExecLaunch ARGS_DECL((char**, struct ObjRec *, char*));
133 int ExecExec ARGS_DECL((char**, struct ObjRec *, char*));
134 int ExecMktemp ARGS_DECL((char**, struct ObjRec *, char*));
135 int ExecUseTemplate ARGS_DECL((char**, struct ObjRec *, char*));
136 int ExecUpdEPSChild ARGS_DECL((char**, struct ObjRec *, char*));
137 int ExecUpdXBMChild ARGS_DECL((char**, struct ObjRec *, char*));
138 int ExecUpdXPMChild ARGS_DECL((char**, struct ObjRec *, char*));
139 int ExecDelEPSChild ARGS_DECL((char**, struct ObjRec *, char*));
140 int ExecDelXBMChild ARGS_DECL((char**, struct ObjRec *, char*));
141 int ExecDelXPMChild ARGS_DECL((char**, struct ObjRec *, char*));
142 int ExecFlipDeck ARGS_DECL((char**, struct ObjRec *, char*));
143 int ExecReadFileIntoAttr ARGS_DECL((char**, struct ObjRec *, char*));
144 int ExecWriteAttrIntoFile ARGS_DECL((char**, struct ObjRec *, char*));
145 int ExecAppendAttrIntoFile ARGS_DECL((char**, struct ObjRec *, char*));
146 int ExecSelectObjByName ARGS_DECL((char**, struct ObjRec *, char*));
147 void ExecSelectTopObj ARGS_DECL((struct ObjRec *, char*));
148 void ExecDelAllSelObj ARGS_DECL((struct ObjRec *, char*));
149 void ExecUnSelectAllObj ARGS_DECL((struct ObjRec *, char*));
150 int ExecMoveSelObjRel ARGS_DECL((char**, struct ObjRec *, char*));
151 int ExecRepeat ARGS_DECL((char**, struct ObjRec *, char*));
152 int ExecHyperJump ARGS_DECL((char**, struct ObjRec *, char*));
153 int ExecMakeCGIQuery ARGS_DECL((char**, struct ObjRec *, char*));
154 int ExecWaitClick ARGS_DECL((char**, struct ObjRec *, char*));
155 int ExecSleep ARGS_DECL((char**, struct ObjRec *, char*));
156 void ExecBeginAnimate ARGS_DECL((struct ObjRec *, char*));
157 void ExecEndAnimate ARGS_DECL((struct ObjRec *, char*));
158 int ExecSetRedraw ARGS_DECL((char**, struct ObjRec *, char*));
159 int ExecSetSelObjColor ARGS_DECL((char**, struct ObjRec *, char*));
160 int ExecSetSelObjFill ARGS_DECL((char**, struct ObjRec *, char*));
161 int ExecSetSelObjPen ARGS_DECL((char**, struct ObjRec *, char*));
162 int ExecSetSelObjLineWidth ARGS_DECL((char**, struct ObjRec *, char*));
163 int ExecSetSelObjSpline ARGS_DECL((char**, struct ObjRec *, char*));
164 int ExecSetSelObjArrow ARGS_DECL((char**, struct ObjRec *, char*));
165 int ExecSetSelObjDash ARGS_DECL((char**, struct ObjRec *, char*));
166 int ExecSetSelObjTransPat ARGS_DECL((char**, struct ObjRec *, char*));
167 int ExecSetSelObjRCBRadius ARGS_DECL((char**, struct ObjRec *, char*));
168 int ExecSetSelTextVSpace ARGS_DECL((char**, struct ObjRec *, char*));
169 int ExecSetSelTextJust ARGS_DECL((char**, struct ObjRec *, char*));
170 int ExecSetSelTextFont ARGS_DECL((char**, struct ObjRec *, char*));
171 int ExecSetSelTextStyle ARGS_DECL((char**, struct ObjRec *, char*));
172 int ExecSetSelTextSize ARGS_DECL((char**, struct ObjRec *, char*));
173 int ExecSetSelTextUnderline ARGS_DECL((char**, struct ObjRec *, char*));
174 int ExecSetSelTextOverline ARGS_DECL((char**, struct ObjRec *, char*));
175 int ExecInc ARGS_DECL((char**, struct ObjRec *, char*));
176 int ExecDec ARGS_DECL((char**, struct ObjRec *, char*));
177 int ExecShuffleObjToTop ARGS_DECL((char**, struct ObjRec *, char*));
178 int ExecShuffleObjToBot ARGS_DECL((char**, struct ObjRec *, char*));
179 void ExecDisableUndo ARGS_DECL((struct ObjRec *, char*));
180 void ExecEnableUndo ARGS_DECL((struct ObjRec *, char*));
181 int ExecGetDrawingArea ARGS_DECL((char**, struct ObjRec *, char*));
182 int ExecGetSelObjBBox ARGS_DECL((char**, struct ObjRec *, char*));
183 int ExecGetNamedObjBBox ARGS_DECL((char**, struct ObjRec *, char*));
184 int ExecMoveSelObjAbs ARGS_DECL((char**, struct ObjRec *, char*));
185 int ExecAssign ARGS_DECL((char**, struct ObjRec *, char*));
186 int ExecStrCpy ARGS_DECL((char**, struct ObjRec *, char*));
187 int ExecStrCat ARGS_DECL((char**, struct ObjRec *, char*));
188 int ExecCopyStrToCutBuffer ARGS_DECL((char**, struct ObjRec *, char*));
189 int ExecWhile ARGS_DECL((char**, char**, struct ObjRec *, char*));
190 int ExecIf ARGS_DECL((char**, struct ObjRec *, char*));
191 int ExecGetCurrentFile ARGS_DECL((char**, struct ObjRec *, char*));
192 int ExecGetCurrentExportFile ARGS_DECL((char**, struct ObjRec *, char*));
193 int ExecGetCurrentDir ARGS_DECL((char**, struct ObjRec *, char*));
194 int ExecGetEnv ARGS_DECL((char**, struct ObjRec *, char*));
195 int ExecStrLen ARGS_DECL((char**, struct ObjRec *, char*));
196 int ExecSubStr ARGS_DECL((char**, struct ObjRec *, char*));
197 int ExecStrStr ARGS_DECL((char**, struct ObjRec *, char*));
198 int ExecStrRStr ARGS_DECL((char**, struct ObjRec *, char*));
199 void ExecUnMakeSelObjIconic ARGS_DECL((struct ObjRec *, char*));
200 int ExecHyperJumpThenExec ARGS_DECL((char**, struct ObjRec *, char*));
201 int ExecShowAttr ARGS_DECL((char**, struct ObjRec *, char*));
202 int ExecHideAttr ARGS_DECL((char**, struct ObjRec *, char*));
203 int ExecShowAttrName ARGS_DECL((char**, struct ObjRec *, char*));
204 int ExecHideAttrName ARGS_DECL((char**, struct ObjRec *, char*));
205 int ExecShowValue ARGS_DECL((char**, struct ObjRec *, char*));
206 int ExecHideValue ARGS_DECL((char**, struct ObjRec *, char*));
207 int ExecGetAttrBBox ARGS_DECL((char**, struct ObjRec *, char*));
208 int ExecSizeSelObjAbs ARGS_DECL((char**, struct ObjRec *, char*));
209 int ExecSizeNamedObjAbs ARGS_DECL((char**, struct ObjRec *, char*));
210 int ExecMessageBox ARGS_DECL((char**, struct ObjRec *, char*));
211 int ExecGetUserInput ARGS_DECL((char**, struct ObjRec *, char*));
212 int ExecAddAttrToSelObj ARGS_DECL((char**, struct ObjRec *, char*));
213 int ExecDelAttrFromSelObj ARGS_DECL((char**, struct ObjRec *, char*));
214 int ExecUserEndAnEdge ARGS_DECL((char**, struct ObjRec *, char*));
215 int ExecUserDrawAnEdge ARGS_DECL((char**, struct ObjRec *, char*));
216 int ExecGetAPolyVertexAbs ARGS_DECL((char**, struct ObjRec *, char*));
217 int ExecMoveAPolyVertexAbs ARGS_DECL((char**, struct ObjRec *, char*));
218 int ExecPostAttrAndGetCGI ARGS_DECL((char**, struct ObjRec *, char*));
219 void ExecNavigateBack ARGS_DECL((struct ObjRec *, char*));
220 void ExecStop ARGS_DECL((struct ObjRec *, char*));
221 int ExecSqrt ARGS_DECL((char**, struct ObjRec *, char*));
222 int ExecRandom ARGS_DECL((char**, struct ObjRec *, char*));
223 int ExecSRand48 ARGS_DECL((char**, struct ObjRec *, char*));
224 int ExecDRand48 ARGS_DECL((char**, struct ObjRec *, char*));
225 int ExecRound ARGS_DECL((char**, struct ObjRec *, char*));
226 int ExecRedrawObj ARGS_DECL((char**, struct ObjRec *, char*));
227 void ExecRedrawDrawingArea ARGS_DECL((struct ObjRec *, char*));
228 int ExecIntToHex ARGS_DECL((char**, struct ObjRec *, char*));
229 int ExecForI ARGS_DECL((char**, struct ObjRec *, char*));
230 void ExecSetFileNotModified ARGS_DECL((struct ObjRec *, char*));
231 int ExecNewId ARGS_DECL((char**, struct ObjRec *, char*));
232 int ExecRotateSelObj ARGS_DECL((char**, struct ObjRec *, char*));
233 int ExecCallSimpleShortCut ARGS_DECL((char**, struct ObjRec *, char*));
234 int ExecCallOneArgShortCut ARGS_DECL((char**, struct ObjRec *, char*));
235 int ExecSubstituteAttr ARGS_DECL((char**, struct ObjRec *, char*));
236 int ExecGetFileSize ARGS_DECL((char**, struct ObjRec *, char*));
237 int ExecIsFile ARGS_DECL((char**, struct ObjRec *, char*));
238 int ExecIndex ARGS_DECL((char**, struct ObjRec *, char*));
239 int ExecRIndex ARGS_DECL((char**, struct ObjRec *, char*));
240 int ExecGetNumberOfLines ARGS_DECL((char**, struct ObjRec *, char*));
241 int ExecGetLineInAttr ARGS_DECL((char**, struct ObjRec *, char*));
242 int ExecTrim ARGS_DECL((char**, struct ObjRec *, char*));
243 int ExecIsAttr ARGS_DECL((char**, struct ObjRec *, char*));
244 int ExecFindObjNames ARGS_DECL((char**, struct ObjRec *, char*));
245 int ExecFindObjNamesOnAllPgs ARGS_DECL((char**, struct ObjRec *, char*));
246 int ExecTg2FindObjNsOnAllPgs ARGS_DECL((char**, struct ObjRec *, char*));
247 int ExecTokenize ARGS_DECL((char**, struct ObjRec *, char*));
248 int ExecMoveAttrRel ARGS_DECL((char**, struct ObjRec *, char*));
249 int ExecGetNumberOfVs ARGS_DECL((char**, struct ObjRec *, char*));
250 int ExecIsObjTransformed ARGS_DECL((char**, struct ObjRec *, char*));
251 int ExecMakeSelObjIconic ARGS_DECL((char**, struct ObjRec *, char*));
252 int ExecMoveNamedObjRel ARGS_DECL((char**, struct ObjRec *, char*));
253 int ExecMoveNamedObjAbs ARGS_DECL((char**, struct ObjRec *, char*));
254 int ExecGetTgifVersion ARGS_DECL((char**, struct ObjRec *, char*));
255 int ExecGetTgifDir ARGS_DECL((char**, struct ObjRec *, char*));
256 int ExecGetProfileString ARGS_DECL((char**, struct ObjRec *, char*));
257 int ExecWriteProfileString ARGS_DECL((char**, struct ObjRec *, char*));
258 int ExecSelectAdditionalObj ARGS_DECL((char**, struct ObjRec *, char*));
259 int ExecOpenFile ARGS_DECL((char**, struct ObjRec *, char*));
260 int ExecCloseFile ARGS_DECL((char**, struct ObjRec *, char*));
261 int ExecReadFile ARGS_DECL((char**, struct ObjRec *, char*));
262 int ExecWriteFile ARGS_DECL((char**, struct ObjRec *, char*));
263 int ExecFlushFile ARGS_DECL((char**, struct ObjRec *, char*));
264 int ExecAppendFile ARGS_DECL((char**, struct ObjRec *, char*));
265 int ExecSetOutputFormat ARGS_DECL((char**, struct ObjRec *, char*));
266 int ExecSetExportClipRect ARGS_DECL((char**, struct ObjRec *, char*));
267 int ExecImportFile ARGS_DECL((char**, struct ObjRec *, char*));
268 int ExecSetXpmOutputVersion ARGS_DECL((char**, struct ObjRec *, char*));
269 int ExecEditIniSection ARGS_DECL((char**, struct ObjRec *, char*));
270 int ExecSelectFromIniSection ARGS_DECL((char**, struct ObjRec *, char*));
271 int ExecAppendLineIntoAttr ARGS_DECL((char**, struct ObjRec *, char*));
272 int ExecInsertLineIntoAttr ARGS_DECL((char**, struct ObjRec *, char*));
273 int ExecClearAttr ARGS_DECL((char**, struct ObjRec *, char*));
274 int ExecCreateText ARGS_DECL((char**, struct ObjRec *, char*));
275 int ExecCreateBox ARGS_DECL((char**, struct ObjRec *, char*));
276 int ExecCreateCornerOval ARGS_DECL((char**, struct ObjRec *, char*));
277 int ExecCreateCenterOval ARGS_DECL((char**, struct ObjRec *, char*));
278 int ExecCreateEdgeOval ARGS_DECL((char**, struct ObjRec *, char*));
279 int ExecCreateRCBox ARGS_DECL((char**, struct ObjRec *, char*));
280 int ExecCreateArc ARGS_DECL((char**, struct ObjRec *, char*));
281 int ExecCreateFirstVertex ARGS_DECL((char**, struct ObjRec *, char*));
282 int ExecCreateNextVertex ARGS_DECL((char**, struct ObjRec *, char*));
283 void ExecCreatePoly ARGS_DECL((struct ObjRec *, char*));
284 void ExecCreatePolygon ARGS_DECL((struct ObjRec *, char*));
285 void ExecStartCreateGroup ARGS_DECL((struct ObjRec *, char*));
286 void ExecCreateGroup ARGS_DECL((struct ObjRec *, char*));
287 int ExecSetAllowInterrupt ARGS_DECL((char**, struct ObjRec *, char*));
288 int ExecSelectEachObjAndExec ARGS_DECL((char**, struct ObjRec *, char*));
289 int ExecEditAttrInTextMode ARGS_DECL((char**, struct ObjRec *, char*));
290 void ExecSetFileUnSavable ARGS_DECL((struct ObjRec *, char*));
291 int ExecPsToEpsi ARGS_DECL((char**, struct ObjRec *, char*));
292 int ExecObjsBBoxIntersect ARGS_DECL((char**, struct ObjRec *, char*));
293 void ExecDelAllAttrFromSelObj ARGS_DECL((struct ObjRec *, char*));
294 int ExecRndPermLinesInAttr ARGS_DECL((char**, struct ObjRec *, char*));
295 
296 static
297 ExecInfo gExecInfo[] = {
298    /* do not translate -- program constants */
299    { (NLFN*)ExecLaunch,              "launch",                            1, 0},
300    { (NLFN*)ExecExec,                "exec",                              1, 0},
301    { (NLFN*)ExecMktemp,              "mktemp",                            2, 0},
302    { (NLFN*)ExecUseTemplate,         "create_file_using_simple_template", 4, 0},
303    { (NLFN*)ExecUpdEPSChild,         "update_eps_child",                  1, 0},
304    { (NLFN*)ExecUpdXBMChild,         "update_xbm_child",                  1, 0},
305    { (NLFN*)ExecUpdXPMChild,         "update_xpm_child",                  1, 0},
306    { (NLFN*)ExecDelEPSChild,         "delete_eps_child",                  1, 0},
307    { (NLFN*)ExecDelXBMChild,         "delete_xbm_child",                  1, 0},
308    { (NLFN*)ExecDelXPMChild,         "delete_xpm_child",                  1, 0},
309    { (NLFN*)ExecFlipDeck,            "flip_deck",                         3, 0},
310    { (NLFN*)ExecReadFileIntoAttr,    "read_file_into_attr",               2, 0},
311    { (NLFN*)ExecWriteAttrIntoFile,   "write_attr_into_file",              2, 0},
312    { (NLFN*)ExecAppendAttrIntoFile,  "append_attr_into_file",             2, 0},
313    { (NLFN*)ExecSelectObjByName,     "select_obj_by_name",                1, 0},
314    { (NLFN*)ExecSelectTopObj,        "select_top_obj",                    0, 0},
315    { (NLFN*)ExecDelAllSelObj,        "delete_selected_obj",               0, 0},
316    { (NLFN*)ExecUnSelectAllObj,      "unselect_all_obj",                  0, 0},
317    { (NLFN*)ExecMoveSelObjRel,       "move_selected_obj_relative",        2, 0},
318    { (NLFN*)ExecRepeat,              "repeat",                            2, 0},
319    { (NLFN*)ExecHyperJump,           "hyperjump",                         1, 0},
320    { (NLFN*)ExecMakeCGIQuery,        "make_cgi_query",                    3, 0},
321    { (NLFN*)ExecWaitClick,           "wait_click",                        3, 0},
322    { (NLFN*)ExecSleep,               "sleep",                             2, 0},
323    { (NLFN*)ExecBeginAnimate,        "begin_animate",                     0, 0},
324    { (NLFN*)ExecEndAnimate,          "end_animate",                       0, 0},
325    { (NLFN*)ExecSetRedraw,           "set_redraw",                        1, 0},
326    { (NLFN*)ExecSetSelObjColor,      "set_selected_obj_color",            1, 0},
327    { (NLFN*)ExecSetSelObjFill,       "set_selected_obj_fill",             1, 0},
328    { (NLFN*)ExecSetSelObjPen,        "set_selected_obj_pen",              1, 0},
329    { (NLFN*)ExecSetSelObjLineWidth,  "set_selected_obj_line_width",       3, 0},
330    { (NLFN*)ExecSetSelObjSpline,     "set_selected_obj_spline",           1, 0},
331    { (NLFN*)ExecSetSelObjArrow,      "set_selected_obj_arrow",            1, 0},
332    { (NLFN*)ExecSetSelObjDash,       "set_selected_obj_dash",             1, 0},
333    { (NLFN*)ExecSetSelObjTransPat,   "set_selected_obj_trans_pat",        1, 0},
334    { (NLFN*)ExecSetSelObjRCBRadius,  "set_selected_obj_rcb_radius",       1, 0},
335    { (NLFN*)ExecSetSelTextVSpace,    "set_selected_text_vspace",          1, 0},
336    { (NLFN*)ExecSetSelTextJust,      "set_selected_text_just",            1, 0},
337    { (NLFN*)ExecSetSelTextFont,      "set_selected_text_font",            1, 0},
338    { (NLFN*)ExecSetSelTextStyle,     "set_selected_text_style",           1, 0},
339    { (NLFN*)ExecSetSelTextSize,      "set_selected_text_size",            1, 0},
340    { (NLFN*)ExecSetSelTextUnderline, "set_selected_text_underline",       1, 0},
341    { (NLFN*)ExecSetSelTextOverline,  "set_selected_text_overline",        1, 0},
342    { (NLFN*)ExecInc,                 "inc",                               2, 0},
343    { (NLFN*)ExecDec,                 "dec",                               2, 0},
344    { (NLFN*)ExecShuffleObjToTop,     "shuffle_obj_to_top",                1, 0},
345    { (NLFN*)ExecShuffleObjToBot,     "shuffle_obj_to_bottom",             1, 0},
346    { (NLFN*)ExecDisableUndo,         "disable_undo",                      0, 0},
347    { (NLFN*)ExecEnableUndo,          "enable_undo",                       0, 0},
348    { (NLFN*)ExecGetDrawingArea,      "get_drawing_area",                  4, 0},
349    { (NLFN*)ExecGetSelObjBBox,       "get_selected_obj_bbox",             4, 0},
350    { (NLFN*)ExecGetNamedObjBBox,     "get_named_obj_bbox",                5, 0},
351    { (NLFN*)ExecMoveSelObjAbs,       "move_selected_obj_absolute",        2, 0},
352    { (NLFN*)ExecAssign,              "assign",                            2, 0},
353    { (NLFN*)ExecStrCpy,              "strcpy",                            2, 0},
354    { (NLFN*)ExecStrCat,              "strcat",                            2, 0},
355    { (NLFN*)ExecCopyStrToCutBuffer,  "copy_string_to_cut_buffer",         1, 0},
356    { (NLFN*)ExecWhile,               "while",                            -2, 1},
357    { (NLFN*)ExecIf,                  "if",                                3, 1},
358    { (NLFN*)ExecGetCurrentFile,      "get_current_file",                  1, 0},
359    { (NLFN*)ExecGetCurrentExportFile,"get_current_export_file",           1, 0},
360    { (NLFN*)ExecGetCurrentDir,       "get_current_dir",                   1, 0},
361    { (NLFN*)ExecGetEnv,              "getenv",                            2, 0},
362    { (NLFN*)ExecStrLen,              "strlen",                            2, 1},
363    { (NLFN*)ExecSubStr,              "substr",                            4, 1},
364    { (NLFN*)ExecStrStr,              "strstr",                            3, 1},
365    { (NLFN*)ExecStrRStr,             "strrstr",                           3, 1},
366    { (NLFN*)ExecUnMakeSelObjIconic,  "unmake_selected_obj_iconic",        0, 0},
367    { (NLFN*)ExecHyperJumpThenExec,   "hyperjump_then_exec",               2, 0},
368    { (NLFN*)ExecShowAttr,            "show_attr",                         1, 0},
369    { (NLFN*)ExecHideAttr,            "hide_attr",                         1, 0},
370    { (NLFN*)ExecShowAttrName,        "show_attr_name",                    1, 0},
371    { (NLFN*)ExecHideAttrName,        "hide_attr_name",                    1, 0},
372    { (NLFN*)ExecShowValue,           "show_value",                        1, 0},
373    { (NLFN*)ExecHideValue,           "hide_value",                        1, 0},
374    { (NLFN*)ExecGetAttrBBox,         "get_attr_bbox",                     5, 0},
375    { (NLFN*)ExecSizeSelObjAbs,       "size_selected_obj_absolute",        2, 0},
376    { (NLFN*)ExecSizeNamedObjAbs,     "size_named_obj_absolute",           3, 0},
377    { (NLFN*)ExecMessageBox,          "message_box",                       4, 0},
378    { (NLFN*)ExecGetUserInput,        "get_user_input",                    3, 0},
379    { (NLFN*)ExecAddAttrToSelObj,     "add_attr_to_selected_obj",          4, 1},
380    { (NLFN*)ExecDelAttrFromSelObj,   "delete_attr_from_selected_obj",     1, 0},
381    { (NLFN*)ExecUserEndAnEdge,       "user_end_an_edge",                  3, 1},
382    { (NLFN*)ExecUserDrawAnEdge,      "user_draw_an_edge",                 2, 0},
383    { (NLFN*)ExecGetAPolyVertexAbs,   "get_a_poly_vertex_absolute",        4, 0},
384    { (NLFN*)ExecMoveAPolyVertexAbs,  "move_a_poly_vertex_absolute",       4, 0},
385    { (NLFN*)ExecPostAttrAndGetCGI,   "post_attr_and_get_cgi_result",      3, 0},
386    { (NLFN*)ExecNavigateBack,        "navigate_back",                     0, 0},
387    { (NLFN*)ExecStop,                "stop",                              0, 0},
388    { (NLFN*)ExecSqrt,                "sqrt",                              2, 0},
389    { (NLFN*)ExecRandom,              "random",                            1, 0},
390    { (NLFN*)ExecSRand48,             "srand48",                           1, 0},
391    { (NLFN*)ExecDRand48,             "drand48",                           1, 0},
392    { (NLFN*)ExecRound,               "round",                             2, 0},
393    { (NLFN*)ExecRedrawObj,           "redraw_obj",                        1, 0},
394    { (NLFN*)ExecRedrawDrawingArea,   "redraw_drawing_area",               0, 0},
395    { (NLFN*)ExecIntToHex,            "itox",                              3, 0},
396    { (NLFN*)ExecForI,                "for_i",                             5, 0},
397    { (NLFN*)ExecSetFileNotModified,  "set_file_not_modified",             0, 0},
398    { (NLFN*)ExecNewId,               "new_id",                            1, 0},
399    { (NLFN*)ExecRotateSelObj,        "rotate_selected_obj",               1, 0},
400    { (NLFN*)ExecCallSimpleShortCut,  "call_simple_shortcut",              1, 0},
401    { (NLFN*)ExecCallOneArgShortCut,  "call_one_arg_shortcut",             2, 0},
402    { (NLFN*)ExecSubstituteAttr,      "substitute_attr",                   4, 0},
403    { (NLFN*)ExecGetFileSize,         "get_file_size",                     2, 0},
404    { (NLFN*)ExecIsFile,              "is_file",                           2, 0},
405    { (NLFN*)ExecIndex,               "index",                             3, 1},
406    { (NLFN*)ExecRIndex,              "rindex",                            3, 1},
407    { (NLFN*)ExecGetNumberOfLines,    "get_number_of_lines_in_attr",       2, 0},
408    { (NLFN*)ExecGetLineInAttr,       "get_line_in_attr",                  3, 0},
409    { (NLFN*)ExecTrim,                "trim",                              1, 1},
410    { (NLFN*)ExecIsAttr,              "is_attr",                           2, 0},
411    { (NLFN*)ExecFindObjNames,        "find_obj_names",                    3, 0},
412    { (NLFN*)ExecFindObjNamesOnAllPgs,"find_obj_names_on_all_pages",       2, 0},
413    { (NLFN*)ExecTg2FindObjNsOnAllPgs,"tg2_find_obj_names_on_all_pages",   2, 0},
414    { (NLFN*)ExecTokenize,            "tokenize",                          3, 0},
415    { (NLFN*)ExecMoveAttrRel,         "move_attr_relative",                3, 0},
416    { (NLFN*)ExecGetNumberOfVs,       "get_number_of_vertices",            2, 0},
417    { (NLFN*)ExecIsObjTransformed,    "is_obj_transformed",                2, 0},
418    { (NLFN*)ExecMakeSelObjIconic,    "make_selected_obj_iconic",          1, 0},
419    { (NLFN*)ExecMoveNamedObjRel,     "move_named_obj_relative",           3, 0},
420    { (NLFN*)ExecMoveNamedObjAbs,     "move_named_obj_absolute",           3, 0},
421    { (NLFN*)ExecGetTgifVersion,      "get_tgif_version",                  4, 0},
422    { (NLFN*)ExecGetTgifDir,          "get_tgif_dir",                      1, 0},
423    { (NLFN*)ExecGetProfileString,    "get_profile_string",                5, 0},
424    { (NLFN*)ExecWriteProfileString,  "write_profile_string",              4, 0},
425    { (NLFN*)ExecSelectAdditionalObj, "select_additional_obj",             1, 0},
426    { (NLFN*)ExecOpenFile,            "open_file",                         3, 0},
427    { (NLFN*)ExecCloseFile,           "close_file",                        1, 0},
428    { (NLFN*)ExecReadFile,            "read_file",                         2, 0},
429    { (NLFN*)ExecWriteFile,           "write_file",                        2, 0},
430    { (NLFN*)ExecFlushFile,           "flush_file",                        1, 0},
431    { (NLFN*)ExecAppendFile,          "append_file",                       2, 0},
432    { (NLFN*)ExecSetOutputFormat,     "set_output_format",                 2, 0},
433    { (NLFN*)ExecSetExportClipRect,   "set_export_clip_rect",              4, 0},
434    { (NLFN*)ExecImportFile,          "import_file",                       4, 0},
435    { (NLFN*)ExecSetXpmOutputVersion, "set_xpm_output_version",            1, 0},
436    { (NLFN*)ExecEditIniSection,      "edit_ini_section",                  4, 0},
437    { (NLFN*)ExecSelectFromIniSection,"select_from_ini_section",           4, 0},
438    { (NLFN*)ExecAppendLineIntoAttr,  "append_line_into_attr",             2, 0},
439    { (NLFN*)ExecInsertLineIntoAttr,  "insert_line_into_attr",             3, 0},
440    { (NLFN*)ExecClearAttr,           "clear_attr",                        1, 0},
441    { (NLFN*)ExecCreateText,          "create_text_obj",                   3, 0},
442    { (NLFN*)ExecCreateBox,           "create_box_obj",                    4, 0},
443    { (NLFN*)ExecCreateCornerOval,    "create_corner_oval_obj",            4, 0},
444    { (NLFN*)ExecCreateCenterOval,    "create_center_oval_obj",            3, 0},
445    { (NLFN*)ExecCreateEdgeOval,      "create_edge_oval_obj",              4, 0},
446    { (NLFN*)ExecCreateRCBox,         "create_rcbox_obj",                  4, 0},
447    { (NLFN*)ExecCreateArc,           "create_arc_obj",                    6, 0},
448    { (NLFN*)ExecCreateFirstVertex,   "create_first_vertex",               2, 0},
449    { (NLFN*)ExecCreateNextVertex,    "create_next_vertex",                2, 0},
450    { (NLFN*)ExecCreatePoly,          "create_poly_obj",                   0, 0},
451    { (NLFN*)ExecCreatePolygon,       "create_polygon_obj",                0, 0},
452    { (NLFN*)ExecStartCreateGroup,    "start_create_group_obj",            0, 0},
453    { (NLFN*)ExecCreateGroup,         "create_group_obj",                  0, 0},
454    { (NLFN*)ExecSetAllowInterrupt,   "set_allow_interrupt",               1, 0},
455    { (NLFN*)ExecSelectEachObjAndExec,"select_each_obj_and_exec",          1, 0},
456    { (NLFN*)ExecEditAttrInTextMode,  "edit_attr_in_text_mode",            1, 0},
457    { (NLFN*)ExecSetFileUnSavable,    "set_file_unsavable",                0, 0},
458    { (NLFN*)ExecPsToEpsi,            "pstoepsi",                          3, 0},
459    { (NLFN*)ExecObjsBBoxIntersect,   "objs_bbox_intersect",               3, 0},
460    { (NLFN*)ExecDelAllAttrFromSelObj,"delete_all_attr_from_selected_objs",0, 0},
461    { (NLFN*)ExecRndPermLinesInAttr,  "random_permute_lines_in_attr",      1, 0},
462    { NULL, NULL, 0, 0 }
463 };
464 
CleanTmpStr()465 void CleanTmpStr()
466 {
467    struct StrRec *next_str=NULL;
468 
469    for ( ; topTmpStr != NULL; topTmpStr=next_str) {
470       next_str = topTmpStr->next;
471       FreeStr(topTmpStr);
472    }
473    topTmpStr = botTmpStr = NULL;
474 }
475 
PrependToTmpStr(psz)476 int PrependToTmpStr(psz)
477    char *psz;
478 {
479    struct StrRec *str_ptr=NewStr();
480 
481    if (str_ptr == NULL) return FALSE;
482 
483    DynStrSet(&str_ptr->dyn_str, psz);
484 
485    str_ptr->prev = NULL;
486    str_ptr->next = topTmpStr;
487 
488    if (topTmpStr == NULL) {
489       botTmpStr = str_ptr;
490    } else {
491       topTmpStr->prev = str_ptr;
492    }
493    topTmpStr = str_ptr;
494    return TRUE;
495 }
496 
AppendToTmpStr(psz)497 int AppendToTmpStr(psz)
498    char *psz;
499 {
500    struct StrRec *str_ptr=NewStr();
501 
502    if (str_ptr == NULL) return FALSE;
503 
504    DynStrSet(&str_ptr->dyn_str, psz);
505 
506    str_ptr->prev = botTmpStr;
507    str_ptr->next = NULL;
508 
509    if (botTmpStr == NULL) {
510       topTmpStr = str_ptr;
511    } else {
512       botTmpStr->next = str_ptr;
513    }
514    botTmpStr = str_ptr;
515    return TRUE;
516 }
517 
AppendToTmpStr2(psz1,psz2,tg2)518 int AppendToTmpStr2(psz1, psz2, tg2)
519    char *psz1, *psz2;
520 {
521    int len1=strlen(psz1), len2=strlen(psz2), rc=0;
522    char *psz=(char*)malloc((len1+len2+1)*sizeof(char));
523 
524    if (psz == NULL) FailAllocMessage();
525    if (tg2) {
526       sprintf(psz, "%s%s", psz2, psz1);
527    } else {
528       sprintf(psz, "%s%s", psz1, psz2);
529    }
530    rc = AppendToTmpStr(psz);
531    free(psz);
532 
533    return rc;
534 }
535 
ExecuteCmdGetResult(cmd,result_list,max_lines)536 int ExecuteCmdGetResult(cmd, result_list, max_lines)
537    char *cmd;
538    CVList *result_list;
539    int max_lines;
540 {
541    char *buf=NULL;
542    FILE *pfp=NULL;
543    int count=0;
544 
545    EndMeasureTooltip(FALSE);
546    if (!FindProgramInPath(cmd, NULL, FALSE)) {
547       return FALSE;
548    }
549    sprintf(gszMsgBox, TgLoadCachedString(CSTID_EXECUTING_GIVEN_PROGRAM), cmd);
550    SetStringStatus(gszMsgBox);
551    if (!PRTGIF) XSync(mainDisplay, False);
552    if ((pfp=(FILE*)popen(cmd, "r")) == NULL) {
553       return FALSE;
554    }
555    while ((buf=UtilGetALine(pfp)) != NULL) {
556       if (PRTGIF) {
557          fprintf(stderr, "%s", buf);
558       } else {
559          Msg(buf);
560       }
561       if (max_lines == (-1) || count++ < max_lines) {
562          ListAppend(result_list, buf);
563       }
564    }
565    pclose(pfp);
566    SetStringStatus(TgLoadCachedString(CSTID_DOTS_DONE));
567 
568    if (max_lines != (-1) && count < max_lines) {
569       return FALSE;
570    }
571    return TRUE;
572 }
573 
FindObjWithName(BotObj,OrigObj,obj_name,inside_root_obj,inside_this_obj,pp_owner_obj,pp_top_owner)574 struct ObjRec *FindObjWithName(BotObj, OrigObj, obj_name, inside_root_obj,
575       inside_this_obj, pp_owner_obj, pp_top_owner)
576    struct ObjRec *BotObj, *OrigObj, **pp_owner_obj, **pp_top_owner;
577    char *obj_name;
578    int inside_root_obj, inside_this_obj;
579 {
580    register struct AttrRec *attr_ptr=NULL;
581    register struct ObjRec *obj_ptr=NULL;
582    struct ObjRec *bot_obj=BotObj;
583    char *bang_ptr=NULL;
584 
585    if (obj_name == NULL || *obj_name == '\0') return NULL;
586    if (*obj_name == '!') {
587       if (inside_root_obj || inside_this_obj) return NULL;
588       obj_name++;
589       inside_root_obj = TRUE;
590       inside_this_obj = FALSE;
591       if (pp_owner_obj != NULL) *pp_owner_obj = NULL;
592       if (pp_top_owner != NULL) *pp_top_owner = NULL;
593       bot_obj = botObj;
594       if (*obj_name == '*') {
595          if (topSel == NULL) return NULL;
596          obj_name++;
597          if (pp_owner_obj != NULL) *pp_owner_obj = topSel->obj;
598          if (pp_top_owner != NULL) *pp_top_owner = topSel->obj;
599          if (*obj_name == '\0') {
600             return topSel->obj;
601          }
602          switch (topSel->obj->type) {
603          case OBJ_GROUP:
604          case OBJ_ICON:
605          case OBJ_SYM:
606          case OBJ_PIN: break;
607 
608          default: return NULL;
609          }
610          return FindObjWithName(topSel->obj->detail.r->last, OrigObj,
611                obj_name, TRUE, FALSE, pp_owner_obj, pp_top_owner);
612       }
613    }
614    if (*obj_name == '!') return NULL;
615 
616    if ((bang_ptr=strchr(obj_name, '!')) != NULL) {
617       *bang_ptr = '\0';
618       /* do not translate -- program constants */
619       if (OrigObj != NULL && strcmp(obj_name, "THIS") == 0) {
620          int this_ok=FALSE;
621 
622          *bang_ptr++ = '!';
623          if (inside_root_obj || inside_this_obj) return NULL;
624          switch (OrigObj->type) {
625          case OBJ_GROUP:
626          case OBJ_ICON:
627          case OBJ_SYM:
628          case OBJ_PIN: break;
629 
630          default: return NULL;
631          }
632          for (obj_ptr=botObj; obj_ptr!=NULL; obj_ptr=obj_ptr->prev) {
633             if (obj_ptr == OrigObj) {
634                this_ok = TRUE;
635                break;
636             }
637          }
638          if (!this_ok) return NULL;
639          if (pp_top_owner != NULL) *pp_top_owner = OrigObj;
640          if (pp_owner_obj != NULL) *pp_owner_obj = OrigObj;
641 
642          return FindObjWithName(OrigObj->detail.r->last, OrigObj,
643                bang_ptr, FALSE, TRUE, pp_owner_obj, pp_top_owner);
644       } else {
645          for (obj_ptr=bot_obj; obj_ptr!=NULL; obj_ptr=obj_ptr->prev) {
646             if (obj_ptr->fattr != NULL &&
647                   (attr_ptr=FindAttrWithName(obj_ptr,"name=",NULL)) != NULL &&
648                   strcmp(attr_ptr->attr_value.s, obj_name) == 0) {
649                *bang_ptr++ = '!';
650                switch (obj_ptr->type) {
651                case OBJ_GROUP:
652                case OBJ_ICON:
653                case OBJ_SYM:
654                case OBJ_PIN: break;
655 
656                default: return NULL;
657                }
658                if (pp_owner_obj != NULL) *pp_owner_obj = obj_ptr;
659                if (pp_top_owner != NULL && bot_obj == botObj) {
660                   *pp_top_owner = obj_ptr;
661                }
662                return FindObjWithName(obj_ptr->detail.r->last, obj_ptr,
663                      bang_ptr, inside_root_obj, inside_this_obj, pp_owner_obj,
664                      pp_top_owner);
665             }
666          }
667          *bang_ptr = '!';
668          return NULL;
669       }
670    } else if (strcmp(obj_name, "THIS") == 0) {
671       int this_ok=FALSE;
672 
673       if (inside_root_obj || inside_this_obj) return NULL;
674       for (obj_ptr=botObj; obj_ptr!=NULL; obj_ptr=obj_ptr->prev) {
675          if (obj_ptr == OrigObj) {
676             this_ok = TRUE;
677             break;
678          }
679       }
680       if (!this_ok) return NULL;
681       if (pp_top_owner != NULL) *pp_top_owner = NULL;
682       if (pp_owner_obj != NULL) *pp_owner_obj = NULL;
683 
684       return OrigObj;
685    }
686    for (obj_ptr=bot_obj; obj_ptr!=NULL; obj_ptr=obj_ptr->prev) {
687       if (obj_ptr->fattr != NULL &&
688             (attr_ptr=FindAttrWithName(obj_ptr,"name=",NULL)) != NULL &&
689             strcmp(attr_ptr->attr_value.s, obj_name) == 0) {
690          if (pp_top_owner != NULL && bot_obj == botObj) {
691             *pp_top_owner = obj_ptr;
692          }
693          return (obj_ptr);
694       }
695    }
696    return NULL;
697 }
698 
699 static int gnSeenLeftParan=FALSE;
700 
701 static
EndingRightParan(inbuf)702 int EndingRightParan(inbuf)
703    char *inbuf;
704 {
705    for ( ; *inbuf != '\0'; inbuf++) {
706       if (*inbuf != ' ' && *inbuf != '\t') {
707          return (*inbuf == ';');
708       }
709    }
710    return TRUE;
711 }
712 
713 static
OnlyBlanksLeft(inbuf)714 int OnlyBlanksLeft(inbuf)
715    char *inbuf;
716 {
717    for ( ; *inbuf != '\0'; inbuf++) {
718       if (*inbuf != ' ' && *inbuf != '\t') {
719          return FALSE;
720       }
721    }
722    return TRUE;
723 }
724 
725 static
GetToken(inbuf,outbuf,obuf_sz,tok_type)726 char *GetToken(inbuf, outbuf, obuf_sz, tok_type)
727    char *inbuf, *outbuf;
728    int obuf_sz, *tok_type;
729    /* returns NULL of the input string is invalid */
730    /* otherwise, the return value points to the character */
731    /*        immediately following the end of the token */
732    /* *tok_type contains the token type */
733 {
734    register char *c_ptr, *obuf_ptr=outbuf;
735    int obuf_index=0;
736 
737    *tok_type = TOK_INVALID;
738    while (*inbuf == ' ' || *inbuf == '\t') inbuf++;
739    switch (*inbuf) {
740    case '\0':
741       *tok_type = TOK_EMPTY;
742       return (inbuf);
743 /* case '\'':
744    case '"':
745       *tok_type = TOK_STR;
746       for (c_ptr=(&inbuf[1]); *c_ptr!=(*inbuf) && *c_ptr!='\0';
747             c_ptr++, obuf_ptr++) {
748          switch (*c_ptr) {
749          case '\\':
750             switch (*(++c_ptr)) {
751             case 'n': *obuf_ptr = '\n'; break;
752             case 'r': *obuf_ptr = '\r'; break;
753             case 't': *obuf_ptr = '\t'; break;
754             default: *obuf_ptr = *c_ptr; break;
755             }
756             break;
757          default: *obuf_ptr = *c_ptr; break;
758          }
759       }
760       if (*c_ptr == '\0') return (NULL);
761       *obuf_ptr++ = '\0';
762       return (++c_ptr);
763  */
764    case '(':
765       if (gnSeenLeftParan) {
766          break;
767       } else {
768          strcpy(obuf_ptr,"(");
769          *tok_type = TOK_LEFT_P;
770          gnSeenLeftParan = TRUE;
771          return(&inbuf[1]);
772       }
773    case ')':
774       if (gnSeenLeftParan && !EndingRightParan(&inbuf[1])) {
775          break;
776       } else {
777          strcpy(obuf_ptr,")");
778          *tok_type = TOK_RIGHT_P;
779          return(&inbuf[1]);
780       }
781 /* case '[': strcpy(obuf_ptr,"["); *tok_type=TOK_LEFT_B; return(&inbuf[1]); */
782 /* case ']': strcpy(obuf_ptr,"]"); *tok_type=TOK_RIGHT_B; return(&inbuf[1]); */
783 /* case '{': strcpy(obuf_ptr,"{"); *tok_type=TOK_LEFT_CB; return(&inbuf[1]); */
784 /* case '}': strcpy(obuf_ptr,"}"); *tok_type=TOK_RIGHT_CB; return(&inbuf[1]); */
785    case ',': strcpy(obuf_ptr,","); *tok_type=TOK_COMMA; return(&inbuf[1]);
786    case ';': strcpy(obuf_ptr,";"); *tok_type=TOK_SEMI; return(&inbuf[1]);
787    }
788    *tok_type = TOK_STR;
789    c_ptr = inbuf;
790 /* while (*c_ptr != '\0' && strchr (" \t()[]{},;", *c_ptr) == NULL) {
791       if (*c_ptr == '$' && c_ptr[1] == '(') {
792          *obuf_ptr++ = *c_ptr++;
793          *obuf_ptr++ = *c_ptr++;
794          while (*c_ptr != '\0' && *c_ptr != ')') *obuf_ptr++ = *c_ptr++;
795          if (*c_ptr == '\0') return NULL;
796       } else {
797          *obuf_ptr++ = *c_ptr++;
798       }
799    }
800  */
801    while (*c_ptr != '\0') {
802       int max_obuf_index=0;
803 
804       if (*c_ptr == '$' && c_ptr[1] == '(') {
805          max_obuf_index = (obuf_sz-3);
806          if (obuf_index >= max_obuf_index) return NULL;
807          *obuf_ptr++ = (*c_ptr++);
808          *obuf_ptr++ = (*c_ptr++);
809          obuf_index += 2;
810          max_obuf_index++;
811          while (*c_ptr != '\0' && *c_ptr != ')') {
812             if (obuf_index++ >= max_obuf_index) return NULL;
813             *obuf_ptr++ = *c_ptr++;
814          }
815          if (*c_ptr == '\0') return NULL;
816       } else if (*c_ptr == '"' || *c_ptr == '\'') {
817          char *tmp_c_ptr=NULL;
818 
819          max_obuf_index = (obuf_sz-2);
820          if (obuf_index++ >= max_obuf_index) return NULL;
821          *obuf_ptr++ = (*c_ptr);
822          for (tmp_c_ptr=(&c_ptr[1]); *tmp_c_ptr!=(*c_ptr) && *tmp_c_ptr!='\0';
823                tmp_c_ptr++) {
824             if (obuf_index++ >= max_obuf_index) return NULL;
825             switch (*tmp_c_ptr) {
826             case '\\':
827                switch (*(++tmp_c_ptr)) {
828                case 'n': *obuf_ptr++ = '\n'; break;
829                case 'r': *obuf_ptr++ = '\r'; break;
830                case 't': *obuf_ptr++ = '\t'; break;
831                default: *obuf_ptr++ = *tmp_c_ptr; break;
832                }
833                break;
834             default: *obuf_ptr++ = *tmp_c_ptr; break;
835             }
836          }
837          if (*tmp_c_ptr == '\0') return NULL;
838          c_ptr = tmp_c_ptr;
839          if (obuf_index++ >= max_obuf_index) return NULL;
840          *obuf_ptr++ = *c_ptr++;
841       } else {
842          if (obuf_index++ >= obuf_sz-2) return NULL;
843          *obuf_ptr++ = *c_ptr++;
844       }
845       if (*c_ptr == ')') {
846          if (!gnSeenLeftParan || EndingRightParan(&c_ptr[1])) {
847             break;
848          }
849       } else if (*c_ptr == '(') {
850          if (!gnSeenLeftParan) {
851             break;
852          }
853       } else if (*c_ptr == ',' || *c_ptr == ';') {
854          break;
855       }
856    }
857    *obuf_ptr = '\0';
858    return (c_ptr);
859 }
860 
861 static
convert_str(inbuf,obj_ptr,double_quotes_for_null)862 char *convert_str(inbuf, obj_ptr, double_quotes_for_null)
863    char *inbuf;
864    struct ObjRec *obj_ptr;
865    int double_quotes_for_null;
866 {
867    register char *buf_ptr;
868    char *return_str, *return_ptr, quote_char='\0';
869    int cur_size=(MAXSTRING<<1), count=0, return_len=0, inside_quote=FALSE;
870 
871    return_ptr = return_str = (char *)malloc((cur_size+2)*sizeof(char));
872    if (return_str == NULL) return (char*)(long)FailAllocMessage();
873    *return_str = '\0';
874    buf_ptr = inbuf;
875    while (*inbuf != '\0') {
876       struct AttrRec *attr_ptr;
877       int null_string=FALSE, n, need_to_free_tmp_buf=FALSE;
878       char *c_ptr=inbuf, *new_c_ptr=NULL, *cp, *cp1;
879       char *tmp_buf=NULL, *attr_value=NULL;
880       MiniLineInfo *pMiniLine=NULL;
881 
882       while (new_c_ptr == NULL) {
883          if (inside_quote) {
884             for ( ; *c_ptr != '\0'; c_ptr++) {
885                if (*c_ptr == quote_char) {
886                   inside_quote = FALSE;
887                   c_ptr++;
888                   break;
889                } else if (*c_ptr == '$' && c_ptr[1] == '(') {
890                   new_c_ptr = c_ptr;
891                   break;
892                }
893             }
894          } else {
895             for ( ; *c_ptr != '\0'; c_ptr++) {
896                if (*c_ptr == '"' || *c_ptr == '\'') {
897                   quote_char = *c_ptr;
898                   inside_quote = TRUE;
899                   c_ptr++;
900                   break;
901                } else if (*c_ptr == '$' && c_ptr[1] == '(') {
902                   new_c_ptr = c_ptr;
903                   break;
904                }
905             }
906          }
907          if (*c_ptr == '\0') break;
908       }
909       if (new_c_ptr == NULL) {
910          count = strlen(inbuf);
911          if (count != 0) {
912             if (count+return_len >= cur_size) {
913                n = return_ptr-return_str;
914                cur_size += count+MAXSTRING;
915                return_str = (char*)realloc(return_str,
916                      (cur_size+2)*sizeof(char));
917                return_ptr = &return_str[n];
918             }
919             strncpy(return_ptr, inbuf, count);
920             return_ptr += count;
921             *return_ptr = '\0';
922          }
923          return return_str;
924       }
925       buf_ptr = new_c_ptr;
926       count = buf_ptr-inbuf;
927       return_len += count;
928       if (count != 0) {
929          if (count+return_len >= cur_size) {
930             n = return_ptr-return_str;
931             cur_size += count+MAXSTRING;
932             return_str = (char*)realloc(return_str, (cur_size+2)*sizeof(char));
933             return_ptr = &return_str[n];
934          }
935          strncpy(return_ptr, inbuf, count);
936          return_ptr += count;
937          *return_ptr = '\0';
938       }
939       if ((attr_ptr=ValidAttrArg(buf_ptr, obj_ptr, &new_c_ptr)) == NULL) {
940          free(return_str);
941          return NULL;
942       }
943       pMiniLine = attr_ptr->obj->detail.t->minilines.first;
944       tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
945       attr_value = UtilStrDup(tmp_buf);
946       if (attr_value == NULL) FailAllocMessage();
947       ParseAttrStr(tmp_buf, NULL, 0, attr_value, strlen(attr_value)+1);
948       if (need_to_free_tmp_buf) UtilFree(tmp_buf);
949       need_to_free_tmp_buf = TRUE;
950 
951       count = strlen(attr_value);
952       if (count == 0 && double_quotes_for_null && !inside_quote) {
953          null_string = TRUE;
954          count += 2;
955       }
956       if (count+return_len >= cur_size) {
957          n = return_ptr-return_str;
958          cur_size += count+MAXSTRING;
959          return_str = (char*)realloc(return_str, (cur_size+2)*sizeof(char));
960          return_ptr = &return_str[n];
961       }
962       if (null_string) {
963          return_ptr[0] = return_ptr[1] = '"';
964          return_ptr[2] = '\0';
965       } else {
966          strcpy(return_ptr, attr_value);
967       }
968       UtilFree(attr_value);
969 
970       if ((cp=strstr(return_ptr, "//")) != NULL) {
971          *cp = '\0';
972          count = cp-return_ptr;
973       }
974       if (!double_quotes_for_null && *return_ptr == '"' &&
975             return_ptr[count-1] == '"') {
976          int n;
977 
978          for (n=1, cp1=return_ptr, cp=(&return_ptr[1]); n < count-1; n++) {
979             *cp1++ = *cp++;
980          }
981          *cp1 = '\0';
982          count -= 2;
983       }
984       return_ptr += count;
985       inbuf = buf_ptr = ++new_c_ptr;
986    }
987    return return_str;
988 }
989 
PipeReachedEOF(fp)990 int PipeReachedEOF(fp)
991    FILE *fp;
992 {
993    if (feof(fp)) return TRUE;
994 
995    /* this works because of non-blocking I/O */
996    while (getc(fp) != EOF) ;
997 #ifdef EAGAIN
998    if (errno == EINPROGRESS || errno == EAGAIN) {
999 #else /* ~EAGAIN */
1000    if (errno == EINPROGRESS) {
1001 #endif /* EAGAIN */
1002       /* do nothing */
1003       return FALSE;
1004    }
1005    /* a real EOF */
1006    return TRUE;
1007 }
1008 
WaitForEvent(fp,fp_is_pipe,fp_is_named_pipe,pn_quit,what_to_do_with_x_events,pf_abort_callback,p_void)1009 int WaitForEvent(fp, fp_is_pipe, fp_is_named_pipe, pn_quit,
1010       what_to_do_with_x_events, pf_abort_callback, p_void)
1011    FILE *fp;
1012    int fp_is_pipe, fp_is_named_pipe, *pn_quit, what_to_do_with_x_events;
1013    AbortCallbackFunc *pf_abort_callback;
1014    void *p_void;
1015    /*
1016     * returns TRUE if there's character waiting in fp
1017     *
1018     * This routine is not really general purpose because characters can
1019     *       swallowed in the PipeReachedEOF() routine.
1020     * So if for any reason the content of the pipe is required, don't
1021     *       use this function!
1022     * fp_is_pipe is TRUE if fp is opened with popen().  This is not the
1023     *       same as a named pipe.
1024     * fp_is_named_pipe is TRUE if fp is a named pipe (S_IFIFO).
1025     */
1026 {
1027    int rc=FALSE;
1028 
1029    *pn_quit = FALSE;
1030 
1031    if (fp != stdin && !fp_is_pipe && !fp_is_named_pipe) {
1032       return TRUE;
1033    }
1034    for (;;) {
1035       struct timeval timeout;
1036       fd_set fdset;
1037       int select_width=XConnectionNumber(mainDisplay)+1, status=0, nfds=0;
1038 
1039       nfds = max(select_width, (int)(fileno(fp)+1));
1040 
1041       timeout.tv_sec = 0;
1042       timeout.tv_usec = 100000;
1043 
1044       FD_ZERO(&fdset);
1045       FD_SET(select_width-1, &fdset);
1046       FD_SET(fileno(fp), &fdset);
1047 #ifdef __hpux
1048       status = select(nfds, (int*)&fdset, NULL, NULL, &timeout);
1049 #else /* !__hpux */
1050       status = select(nfds, &fdset, NULL, NULL, &timeout);
1051 #endif /* __hpux */
1052       if (status < 0) {
1053          if (errno == EINTR) {
1054             /* interrupted by a system call, not a problem */
1055             if (fp_is_pipe && !fp_is_named_pipe && PipeReachedEOF(fp)) {
1056                return FALSE;
1057             }
1058             CheckInterrupt(TRUE);
1059          } else {
1060             sprintf(gszMsgBox, TgLoadString(STID_FUNC_SELECT_SYS_CALL_FAILED),
1061                   "WaitForEvent()"),
1062             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1063             break;
1064          }
1065       } else if (status == 0) {
1066          if (fp_is_pipe && !fp_is_named_pipe && PipeReachedEOF(fp)) {
1067             return FALSE;
1068          }
1069          CheckInterrupt(TRUE);
1070       } else if (status == 1) {
1071          if (FD_ISSET(fileno(fp), &fdset)) {
1072             /* character waiting to be processed at fp */
1073             return TRUE;
1074          } else if (FD_ISSET(select_width-1, &fdset)) {
1075             switch (what_to_do_with_x_events) {
1076             case DO_ALL_X_EV:
1077                while (XPending(mainDisplay) > 0) {
1078                   if (TryProcessAnXEvent(NULL) != 0) {
1079                      *pn_quit = TRUE;
1080                      return FALSE;
1081                   }
1082                }
1083                break;
1084             case EXPOSE_AND_ESC_X_EV_ONLY:
1085                while (XPending(mainDisplay) > 0) {
1086                   CheckInterrupt(FALSE);
1087                   if (TryProcessAnAbortXEvent(FALSE, pf_abort_callback,
1088                         p_void)) {
1089                      if (fp_is_pipe && !fp_is_named_pipe &&
1090                            PipeReachedEOF(fp)) {
1091                         return FALSE;
1092                      }
1093                      *pn_quit = TRUE;
1094                      return TRUE;
1095                   }
1096                }
1097                break;
1098             }
1099             if (fp_is_pipe && !fp_is_named_pipe && PipeReachedEOF(fp)) {
1100                return FALSE;
1101             }
1102          }
1103       } else if (status == 2) {
1104          rc = TRUE;
1105          break;
1106       } else {
1107          sprintf(gszMsgBox, TgLoadString(STID_FUNC_INVALID_RC_FOR_SELECT),
1108                "WaitForEvent()", status);
1109          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1110          break;
1111       }
1112    }
1113    return rc;
1114 }
1115 
1116 static
AbortLaunch(pVoid)1117 int AbortLaunch(pVoid)
1118    void *pVoid;
1119 {
1120    if (MsgBox(TgLoadString(STID_CNTRL_C_ABORT_LAUNCH), TOOL_NAME, YNC_MB) ==
1121          MB_ID_YES) {
1122       return TRUE;
1123    }
1124    return FALSE;
1125 }
1126 
1127 static
LaunchIt(cmd)1128 void LaunchIt(cmd)
1129    char *cmd;
1130 {
1131    int len=strlen(cmd);
1132 
1133    while (len > 0 && (cmd[len-1] == ' ')) cmd[--len] = '\0';
1134    if (cmd[0] != '\0' && FindProgramInPath(cmd, NULL, FALSE)) {
1135       SetWatchCursor(drawWindow);
1136       SetWatchCursor(mainWindow);
1137       if (cmd[len-1] == '&') {
1138          cmd[--len] = '\0';
1139          while (len > 0 && (cmd[len-1] == ' ')) cmd[--len] = '\0';
1140          if (cmd[0] != '\0') {
1141 #ifdef _BACKGROUND_DONT_FORK
1142             fprintf(stderr, TgLoadCachedString(CSTID_BACKGROUNDING_CMD), cmd);
1143             fprintf(stderr, "\n");
1144             strcat(cmd, " &");
1145             (void)system(cmd);
1146 #else /* ~_BACKGROUND_DONT_FORK */
1147             int pid;
1148 
1149             fprintf(stderr, TgLoadCachedString(CSTID_BACKGROUNDING_CMD), cmd);
1150             fprintf(stderr, "\n");
1151             pid = fork();
1152             if (pid == 0) {
1153                (void)system(cmd);
1154                exit(0);
1155             }
1156 #endif /* _BACKGROUND_DONT_FORK */
1157          }
1158       } else {
1159          FILE *fp=NULL;
1160 
1161          sprintf(gszMsgBox, TgLoadCachedString(CSTID_EXECUTING_GIVEN_PROGRAM),
1162                cmd);
1163          SetStringStatus(gszMsgBox);
1164          Msg(TgLoadCachedString(CSTID_CNTRL_C_TO_INTR_AND_ABEND));
1165          EndMeasureTooltip(FALSE);
1166          XSync(mainDisplay, False);
1167          if ((fp=(FILE*)popen(cmd, "r")) == NULL) {
1168             sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_EXECUTE_CMD), cmd);
1169             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1170          } else {
1171             int quit=FALSE, got_eof=FALSE, fd=fileno(fp);
1172 
1173             SetSocketBlockingState(&fd, FALSE);
1174 
1175             /*
1176              * Note: Calling WaitForEvent() with the second argument being
1177              *       TRUE can lose data in the pipe.  Can do this here
1178              *       because the data in the pipe is ignored.
1179              */
1180             while (WaitForEvent(fp, TRUE, FALSE, &quit,
1181                   EXPOSE_AND_ESC_X_EV_ONLY, AbortLaunch, NULL)) {
1182                if (quit) {
1183                   break;
1184                } else if (PipeReachedEOF(fp)) {
1185                   got_eof = TRUE;
1186                   break;
1187                }
1188             }
1189             if (quit && !got_eof) {
1190                sprintf(gszMsgBox,
1191                      TgLoadString(STID_CMD_ABORT_LAUNCH_CLOSE_TOOL),
1192                      cmd, TOOL_NAME);
1193                MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1194             } else {
1195                pclose(fp);
1196             }
1197          }
1198          Msg("");
1199          SetStringStatus(TgLoadCachedString(CSTID_DOTS_DONE));
1200       }
1201       SetDefaultCursor(mainWindow);
1202       SetDefaultCursor(drawWindow);
1203    }
1204 }
1205 
DoLaunch(launch_attr,obj_ptr)1206 int DoLaunch(launch_attr, obj_ptr)
1207    struct AttrRec *launch_attr;
1208    struct ObjRec *obj_ptr;
1209 {
1210    char *c_ptr=NULL, *buf_ptr=NULL;
1211    char *new_c_ptr=NULL, buf[MAXSTRING+1], *cmd=NULL, *cmd_ptr=NULL;
1212    int cur_size=2*MAXSTRING, count=0, cmd_len=0, n, first_time=TRUE;
1213    MiniLineInfo *pMiniLine=NULL;
1214 
1215    cmd = (char *)malloc((cur_size+1)*sizeof(char));
1216    if (cmd == NULL) return FailAllocMessage();
1217    cmd_ptr = cmd;
1218    buf_ptr = buf;
1219    for (pMiniLine=launch_attr->obj->detail.t->minilines.first;
1220          pMiniLine != NULL; pMiniLine=pMiniLine->next) {
1221       struct AttrRec *attr_ptr=NULL;
1222       int need_to_free_tmp_buf=FALSE;
1223       char *tmp_buf=NULL;
1224 
1225       if (first_time) {
1226          char *attr_value=NULL;
1227 
1228          first_time = FALSE;
1229          tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
1230          attr_value = UtilStrDup(tmp_buf);
1231          if (attr_value == NULL) FailAllocMessage();
1232          ParseAttrStr(tmp_buf, NULL, 0, attr_value, strlen(attr_value)+1);
1233          if (need_to_free_tmp_buf) UtilFree(tmp_buf);
1234          need_to_free_tmp_buf = TRUE;
1235          c_ptr = tmp_buf = attr_value;
1236       } else {
1237          tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
1238          c_ptr = tmp_buf;
1239       }
1240       for ( ; *c_ptr != '\0'; c_ptr++, count++) {
1241          switch (*c_ptr) {
1242          case '\\': c_ptr++; *buf_ptr++ = *c_ptr; break;
1243          case '$':
1244             if (count != 0) {
1245                *buf_ptr = '\0';
1246                if (count+cmd_len >= cur_size) {
1247                   n = cmd_ptr-cmd;
1248                   cur_size += MAXSTRING;
1249                   cmd = (char*)realloc(cmd, (cur_size+2)*sizeof(char));
1250                   cmd_ptr = cmd+n;
1251                }
1252                strcpy(cmd_ptr, buf);
1253                cmd_ptr += count;
1254                count = 0;
1255                buf_ptr = buf;
1256             }
1257             if ((attr_ptr=ValidAttrArg(c_ptr,obj_ptr,&new_c_ptr)) == NULL) {
1258                free(cmd);
1259                sprintf(gszMsgBox, TgLoadString(STID_INVALID_GIVEN_ATTR_SPEC),
1260                      c_ptr);
1261                MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1262                return FALSE;
1263             }
1264             count = attr_ptr->attr_value.sz-1;
1265             if (count+cmd_len >= cur_size) {
1266                n = cmd_ptr-cmd;
1267                cur_size += MAXSTRING;
1268                cmd = (char*)realloc(cmd, (cur_size+2)*sizeof(char));
1269                cmd_ptr = cmd+n;
1270             }
1271             strcpy(cmd_ptr, attr_ptr->attr_value.s);
1272             cmd_ptr += count;
1273             count = -1;
1274             c_ptr = new_c_ptr;
1275             break;
1276          default: *buf_ptr++ = *c_ptr; break;
1277          }
1278       }
1279       if (need_to_free_tmp_buf) UtilFree(tmp_buf);
1280 
1281       if (count != 0) {
1282          *buf_ptr = '\0';
1283          if (count+cmd_len >= cur_size) {
1284             n = cmd_ptr-cmd;
1285             cur_size += MAXSTRING;
1286             cmd = (char*)realloc(cmd, (cur_size+2)*sizeof(char));
1287             cmd_ptr = cmd+n;
1288          }
1289          strcpy(cmd_ptr, buf);
1290          cmd_ptr += count;
1291          count = 0;
1292          buf_ptr = buf;
1293       }
1294       if (pMiniLine->next != NULL) { *cmd_ptr++ = ' '; *cmd_ptr = '\0'; }
1295    }
1296    if (inHyperSpace && !allowLaunchInHyperSpace) {
1297       XFlush(mainDisplay);
1298       XSync(mainDisplay, False);
1299       sprintf(gszMsgBox, TgLoadString(STID_LAUNCH_NOT_AUTO_IN_HYPER_EXEC), cmd);
1300       if (MsgBox(gszMsgBox, TOOL_NAME, YN_MB) != MB_ID_YES) {
1301          MsgBox(TgLoadString(STID_USER_ABORT_LAUNCH_IN_HYPER), TOOL_NAME,
1302                INFO_MB);
1303          return FALSE;
1304       }
1305    }
1306    SaveStatusStrings();
1307    LaunchIt(cmd);
1308    RestoreStatusStrings();
1309    free(cmd);
1310    return TRUE;
1311 }
1312 
1313 static
BadCmd(cmd_name)1314 int BadCmd(cmd_name)
1315    char *cmd_name;
1316 {
1317    sprintf(gszMsgBox, TgLoadString(STID_MALFORMED_CMD_EXEC_ABORT),
1318          cmd_name);
1319    MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1320    return FALSE;
1321 }
1322 
1323 static
BadSelectedObj(cmd_name)1324 int BadSelectedObj(cmd_name)
1325    char *cmd_name;
1326 {
1327    sprintf(gszMsgBox, TgLoadString(STID_NO_OBJ_SEL_WHILE_EXEC_CMD),
1328          cmd_name);
1329    MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1330    return FALSE;
1331 }
1332 
1333 static
BadAttr(attr_name,cmd_name)1334 int BadAttr(attr_name, cmd_name)
1335    char *attr_name, *cmd_name;
1336 {
1337    char msg[MAXSTRING+1];
1338 
1339    sprintf(msg, TgLoadString(STID_CANT_FIND_NAMED_ATTR_EXEC),
1340          attr_name, cmd_name);
1341    MsgBox(msg, TOOL_NAME, INFO_MB);
1342    return FALSE;
1343 }
1344 
1345 static
FileAttrNotAllowed(attr_name,cmd_name)1346 int FileAttrNotAllowed(attr_name, cmd_name)
1347    char *attr_name, *cmd_name;
1348 {
1349    char msg[MAXSTRING+1];
1350 
1351    sprintf(msg, TgLoadString(STID_FILE_ATTR_NOT_ALLOWED_FOR_CMD),
1352          attr_name, cmd_name);
1353    MsgBox(msg, TOOL_NAME, INFO_MB);
1354    return FALSE;
1355 }
1356 
1357 static
BadObjName(obj_name,cmd_name)1358 int BadObjName(obj_name, cmd_name)
1359    char *obj_name, *cmd_name;
1360 {
1361    sprintf(gszMsgBox, TgLoadString(STID_CANT_FIND_NAMED_OBJ_EXEC),
1362          obj_name, cmd_name);
1363    MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1364    return FALSE;
1365 }
1366 
1367 static
BadArg(arg_name,cmd_name)1368 int BadArg(arg_name, cmd_name)
1369    char *arg_name, *cmd_name;
1370 {
1371    sprintf(gszMsgBox, TgLoadString(STID_INVALID_ARG_WHILE_EXEC_CMD),
1372          arg_name, cmd_name);
1373    MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1374    return FALSE;
1375 }
1376 
1377 static ReplAttrValueCallback *gpfReplaceAttrValueCallback=NULL;
1378 static void *gpvReplAttrValueCallbackUserData=NULL;
1379 
SetReplaceAttrValueCallback(pf_replace_attr_value,pv_userdata)1380 void SetReplaceAttrValueCallback(pf_replace_attr_value, pv_userdata)
1381    ReplAttrValueCallback *pf_replace_attr_value;
1382    void *pv_userdata;
1383 {
1384    gpfReplaceAttrValueCallback = pf_replace_attr_value;
1385    gpvReplAttrValueCallbackUserData = pv_userdata;
1386 }
1387 
ReplaceAttrFirstValue(obj_ptr,attr_ptr,new_value)1388 int ReplaceAttrFirstValue(obj_ptr, attr_ptr, new_value)
1389    struct ObjRec *obj_ptr;
1390    struct AttrRec *attr_ptr;
1391    char *new_value;
1392    /* obj_ptr better be a top-level object */
1393 {
1394    int value_len=0, same=FALSE;
1395    MiniLineInfo *pFirstMiniLine=attr_ptr->obj->detail.t->minilines.first;
1396 
1397    if (obj_ptr == NULL && historyDepth != 0) {
1398       sprintf(gszMsgBox, TgLoadString(STID_NEED_DISABLE_UNDO_WILL_CRASH),
1399             TOOL_NAME);
1400       MsgBox(gszMsgBox, TOOL_NAME, STOP_MB);
1401    }
1402    value_len = strlen(new_value);
1403    if (value_len >= 2 && (*new_value == '\'' || *new_value == '"') &&
1404          new_value[value_len-1] == *new_value) {
1405       new_value[value_len-1] = '\0';
1406       if (strcmp(attr_ptr->attr_value.s, &new_value[1]) == 0 &&
1407             (obj_ptr == tgifObj || pFirstMiniLine->first_block->next == NULL)) {
1408          same = TRUE;
1409       }
1410       new_value[value_len-1] = *new_value;
1411    } else {
1412       if (strcmp(attr_ptr->attr_value.s, new_value) == 0 &&
1413             (obj_ptr == tgifObj || pFirstMiniLine->first_block->next == NULL)) {
1414          same = TRUE;
1415       }
1416    }
1417    if (!same) {
1418       int ltx=0, lty=0, rbx=0, rby=0, switch_selected=FALSE;
1419       struct SelRec *saved_top_sel=topSel, *saved_bot_sel=botSel;
1420 
1421       if (obj_ptr != NULL && obj_ptr == tgifObj && gstWBInfo.do_whiteboard) {
1422          /*
1423           * Now it's allowed.
1424           *
1425           * MsgBox(TgLoadString(STID_MODIFY_FILE_ATTR_IN_WB), TOOL_NAME,
1426           *       INFO_MB);
1427           * gnAbortExec = TRUE;
1428           * return FALSE;
1429           */
1430       }
1431       if (obj_ptr != NULL &&
1432             (topSel == NULL || topSel != botSel || topSel->obj != obj_ptr)) {
1433          switch_selected = TRUE;
1434          topSel = botSel = NULL;
1435          if (obj_ptr == tgifObj) AddObj(NULL, topObj, tgifObj);
1436          UpdSelBBox();
1437       }
1438       if (obj_ptr != NULL) {
1439          ltx = obj_ptr->bbox.ltx; lty = obj_ptr->bbox.lty;
1440          rbx = obj_ptr->bbox.rbx; rby = obj_ptr->bbox.rby;
1441       }
1442       PrepareToReplaceAnObj(obj_ptr);
1443       if (value_len >= 2 && (*new_value == '\'' || *new_value == '"') &&
1444             new_value[value_len-1] == *new_value) {
1445          new_value[value_len-1] = '\0';
1446          DynStrSet(&attr_ptr->attr_value, &new_value[1]);
1447          new_value[value_len-1] = *new_value;
1448       } else {
1449          DynStrSet(&attr_ptr->attr_value, new_value);
1450       }
1451       FreeStrBlockList(pFirstMiniLine->first_block->next);
1452       pFirstMiniLine->first_block->next = NULL;
1453       pFirstMiniLine->last_block = pFirstMiniLine->first_block;
1454       UpdAttr(attr_ptr);
1455 
1456       attr_ptr->obj->detail.t->cached_zoom = 0;
1457       if (attr_ptr->obj->detail.t->cached_bitmap != None) {
1458          XFreePixmap(mainDisplay, attr_ptr->obj->detail.t->cached_bitmap);
1459          attr_ptr->obj->detail.t->cached_bitmap = None;
1460       }
1461       if (obj_ptr != NULL && attr_ptr->shown) {
1462          AdjObjCache(obj_ptr);
1463          AdjObjBBox(obj_ptr);
1464       }
1465       if (gpfReplaceAttrValueCallback != NULL) {
1466          ReplAttrValueCallbackInfo ravci;
1467 
1468          memset(&ravci, 0, sizeof(ReplAttrValueCallbackInfo));
1469          ravci.obj_ptr = obj_ptr;
1470          ravci.attr_ptr = attr_ptr;
1471          ravci.new_attr_value = new_value;
1472          ravci.pv_userdata = gpvReplAttrValueCallbackUserData;
1473          if ((gpfReplaceAttrValueCallback)(&ravci)) {
1474          }
1475       }
1476       if (obj_ptr != NULL && obj_ptr == tgifObj) recordCmdIncludeTgifObj = TRUE;
1477       RecordReplaceAnObj(obj_ptr);
1478       if (obj_ptr != NULL && obj_ptr == tgifObj) recordCmdIncludeTgifObj = FALSE;
1479       if (obj_ptr != NULL && switch_selected) {
1480          RemoveAllSel();
1481          if (obj_ptr == tgifObj) UnlinkObj(topObj);
1482          topSel = saved_top_sel;
1483          botSel = saved_bot_sel;
1484          UpdSelBBox();
1485       }
1486       if (obj_ptr != NULL && replaceAttrFirstValueRedraw && obj_ptr != tgifObj &&
1487             attr_ptr->shown) {
1488          RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
1489                rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
1490                obj_ptr->bbox.ltx-GRID_ABS_SIZE(1),
1491                obj_ptr->bbox.lty-GRID_ABS_SIZE(1),
1492                obj_ptr->bbox.rbx+GRID_ABS_SIZE(1),
1493                obj_ptr->bbox.rby+GRID_ABS_SIZE(1));
1494       }
1495       SetFileModified(TRUE);
1496    }
1497    return (!same);
1498 }
1499 
ReplaceAttrAllValues(obj_ptr,attr_ptr,ppTopStr,ppBotStr)1500 int ReplaceAttrAllValues(obj_ptr, attr_ptr, ppTopStr, ppBotStr)
1501    struct ObjRec *obj_ptr;
1502    struct AttrRec *attr_ptr;
1503    struct StrRec **ppTopStr, **ppBotStr;
1504    /* obj_ptr better be a top-level object */
1505 {
1506    int count=0, need_to_change=TRUE;
1507    struct StrRec *str_ptr=NULL;
1508    MiniLineInfo *pMiniLine=NULL;
1509 
1510    for (str_ptr=(*ppTopStr); str_ptr != NULL; str_ptr=str_ptr->next) {
1511       count++;
1512    }
1513    /*
1514     * if (count != attr_ptr->obj->detail.t->lines) {
1515     *    need_to_change = TRUE;
1516     * } else {
1517     *    for (str_ptr=(*ppTopStr),
1518     *          pMiniLine=attr_ptr->obj->detail.t->minilines.first;
1519     *          str_ptr != NULL;
1520     *          str_ptr=str_ptr->next, pMiniLine=pMiniLine->next) {
1521     *       if (pMiniLine == NULL) {
1522     *          need_to_change = TRUE;
1523     *          break;
1524     *       } else {
1525     *          if (pMiniLine == attr_ptr->obj->detail.t->minilines.first) {
1526     *             if (strcmp(attr_ptr->attr_value.s, str_ptr->dyn_str.s) != 0) {
1527     *                need_to_change = TRUE;
1528     *                break;
1529     *             }
1530     *          } else {
1531     *             if (strcmp(str_ptr->dyn_str.s, str_ptr->dyn_str.s) != 0) {
1532     *                need_to_change = TRUE;
1533     *                break;
1534     *             }
1535     *          }
1536     *       }
1537     *    }
1538     * }
1539     */
1540    if (need_to_change) {
1541       int ltx, lty, rbx, rby, switch_selected=FALSE;
1542       MiniLineInfo *pFirstMiniLine=NULL, *pLastMiniLine=NULL;
1543       struct SelRec *saved_top_sel=topSel, *saved_bot_sel=botSel;
1544       struct StrRec *next_str=NULL;
1545 
1546       if (obj_ptr == tgifObj && gstWBInfo.do_whiteboard) {
1547          /*
1548           * Now it's allowed.
1549           *
1550           * MsgBox(TgLoadString(STID_MODIFY_FILE_ATTR_IN_WB), TOOL_NAME,
1551           *       INFO_MB);
1552           * gnAbortExec = TRUE;
1553           * return FALSE;
1554           */
1555       }
1556       if (topSel == NULL || topSel != botSel || topSel->obj != obj_ptr) {
1557          switch_selected = TRUE;
1558          topSel = botSel = NULL;
1559          if (obj_ptr == tgifObj) AddObj(NULL, topObj, tgifObj);
1560          UpdSelBBox();
1561       }
1562       ltx = obj_ptr->bbox.ltx; lty = obj_ptr->bbox.lty;
1563       rbx = obj_ptr->bbox.rbx; rby = obj_ptr->bbox.rby;
1564       PrepareToReplaceAnObj(obj_ptr);
1565 
1566       FreeMiniLines(&attr_ptr->obj->detail.t->minilines, FALSE);
1567 
1568       for (str_ptr=(*ppTopStr); str_ptr != NULL; str_ptr=next_str) {
1569          next_str = str_ptr->next;
1570          pMiniLine = CreateMiniLineFromString(str_ptr->dyn_str.s,
1571                &pFirstMiniLine, &pLastMiniLine);
1572          FreeStr(str_ptr);
1573       }
1574       attr_ptr->obj->detail.t->minilines.first = pFirstMiniLine;
1575       attr_ptr->obj->detail.t->minilines.last = pLastMiniLine;
1576       attr_ptr->obj->detail.t->lines = count;
1577       (*ppTopStr) = (*ppBotStr) = NULL;
1578 
1579       UpdateAttr(attr_ptr->obj->detail.t, attr_ptr);
1580       AdjObjCache(obj_ptr);
1581       AdjObjBBox(obj_ptr);
1582 
1583       if (obj_ptr == tgifObj) recordCmdIncludeTgifObj = TRUE;
1584       RecordReplaceAnObj(obj_ptr);
1585       if (obj_ptr == tgifObj) recordCmdIncludeTgifObj = FALSE;
1586       if (switch_selected) {
1587          RemoveAllSel();
1588          if (obj_ptr == tgifObj) UnlinkObj(topObj);
1589          topSel = saved_top_sel;
1590          botSel = saved_bot_sel;
1591          UpdSelBBox();
1592       }
1593       if (obj_ptr != tgifObj && attr_ptr->shown) {
1594          RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
1595                rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
1596                obj_ptr->bbox.ltx-GRID_ABS_SIZE(1),
1597                obj_ptr->bbox.lty-GRID_ABS_SIZE(1),
1598                obj_ptr->bbox.rbx+GRID_ABS_SIZE(1),
1599                obj_ptr->bbox.rby+GRID_ABS_SIZE(1));
1600       }
1601       SetFileModified(TRUE);
1602    }
1603    return need_to_change;
1604 }
1605 
JustReadFileIntoAttr(FP,attr_ptr,attr_owner_obj)1606 void JustReadFileIntoAttr(FP, attr_ptr, attr_owner_obj)
1607    FILE *FP;
1608    struct AttrRec *attr_ptr;
1609    struct ObjRec *attr_owner_obj;
1610 {
1611    int ltx=attr_owner_obj->bbox.ltx, lty=attr_owner_obj->bbox.ltx;
1612    int rbx=attr_owner_obj->bbox.rbx, rby=attr_owner_obj->bbox.rby;
1613    int saved_color_index=colorIndex;
1614    int x=attr_ptr->obj->x, baseline_y=attr_ptr->obj->detail.t->baseline_y;
1615    struct ObjRec *text_obj_ptr=NULL;
1616    struct TextRec *text_ptr=attr_ptr->obj->detail.t;
1617 
1618    colorIndex = text_ptr->minilines.first->first_block->seg->color;
1619    PushCurFont();
1620    ObjFontInfoToCurFontInfo(text_ptr);
1621    StrSegInfoToCurFontInfo(GetTextPtrFirstStrSeg(text_ptr));
1622 
1623    penPat = attr_ptr->obj->detail.t->pen;
1624    objFill = attr_ptr->obj->detail.t->fill;
1625    transPat = attr_ptr->obj->trans_pat;
1626 
1627    SetCanvasFont();
1628 
1629    FreeTextObj(attr_ptr->obj);
1630    attr_ptr->obj = NULL;
1631    text_obj_ptr = FormTextObjectFromFile(FP, x, baseline_y);
1632 
1633    PopCurFont();
1634 
1635    colorIndex = saved_color_index;
1636 
1637    if (text_obj_ptr == NULL) {
1638       DynStrSet(&attr_ptr->attr_value, "");
1639    } else {
1640       MiniLineInfo *pMiniLine=text_obj_ptr->detail.t->minilines.first;
1641 
1642       if (pMiniLine != NULL) {
1643          int need_to_free_tmp_buf=FALSE;
1644          char *tmp_buf=ConvertMiniLineToString(pMiniLine,
1645                &need_to_free_tmp_buf);
1646 
1647          DynStrSet(&attr_ptr->attr_value, tmp_buf);
1648          if (need_to_free_tmp_buf) UtilFree(tmp_buf);
1649       } else {
1650          DynStrSet(&attr_ptr->attr_value, "");
1651       }
1652    }
1653    attr_ptr->obj = text_obj_ptr;
1654    text_obj_ptr->detail.t->attr = attr_ptr;
1655 
1656    UpdAttr(attr_ptr);
1657    if (attr_ptr->shown) {
1658       AdjObjCache(attr_owner_obj);
1659       AdjObjBBox(attr_owner_obj);
1660    }
1661    RecordReplaceAnObj(attr_owner_obj);
1662    RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
1663          rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
1664          attr_owner_obj->bbox.ltx-GRID_ABS_SIZE(1),
1665          attr_owner_obj->bbox.lty-GRID_ABS_SIZE(1),
1666          attr_owner_obj->bbox.rbx+GRID_ABS_SIZE(1),
1667          attr_owner_obj->bbox.rby+GRID_ABS_SIZE(1));
1668    SetFileModified(TRUE);
1669 }
1670 
1671 static
ReturnInterruptedExec()1672 int ReturnInterruptedExec()
1673 {
1674    if (!execInterruptEnabled) {
1675       if (execInterruptQueued) {
1676          sprintf(gszMsgBox, TgLoadString(STID_USER_INTR_TOOL_WAIT_CLEANUP),
1677                TOOL_NAME);
1678          return (MsgBox(gszMsgBox, TOOL_NAME, YNC_MB) == MB_ID_YES);
1679       }
1680       execInterruptQueued = TRUE;
1681       return FALSE;
1682    }
1683    return TRUE;
1684 }
1685 
1686 static int execTightLoopWait=FALSE;
1687 static int execTightLoopOneLineStatus=FALSE;
1688 static char execTightLoopStatusBuf[MAX_STATUS_BTNS+1][MAXSTRING+1];
1689 
1690 static
ExitExecTightLoop()1691 void ExitExecTightLoop()
1692 {
1693    RestoreStatusStringsFromBuf(execTightLoopStatusBuf,
1694         execTightLoopOneLineStatus);
1695    execTightLoopWait = FALSE;
1696 }
1697 
1698 static
EnterExecTightLoop()1699 void EnterExecTightLoop()
1700 {
1701    SaveStatusStringsIntoBuf(execTightLoopStatusBuf,
1702          &execTightLoopOneLineStatus);
1703    execTightLoopWait = TRUE;
1704 }
1705 
1706 static
CheckExecInterrupt(orig_cmd)1707 int CheckExecInterrupt(orig_cmd)
1708    char *orig_cmd;
1709 {
1710    int check_any_button=execInterruptEnabled;
1711    XEvent ev;
1712 
1713    if (mainDisplay == NULL) return FALSE;
1714 
1715    while (XCheckMaskEvent(mainDisplay, StructureNotifyMask, &ev)) {
1716       if (iconWindowShown) {
1717          if ((ev.xany.window == iconBaseWindow && ev.type == UnmapNotify) ||
1718                (ev.xany.window == mainWindow && ev.type == MapNotify)) {
1719             XPutBackEvent(mainDisplay, &ev);
1720             return ReturnInterruptedExec();
1721          }
1722       } else if ((ev.xany.window == iconBaseWindow && ev.type == MapNotify) ||
1723             (ev.xany.window == mainWindow && ev.type == UnmapNotify)) {
1724          XPutBackEvent(mainDisplay, &ev);
1725          return ReturnInterruptedExec();
1726       } else if (ev.type == ConfigureNotify) {
1727          Reconfigure(FALSE);
1728       }
1729    }
1730    while (XCheckMaskEvent(mainDisplay, VisibilityChangeMask, &ev)) {
1731       if (iconWindowShown) {
1732          if (ev.xany.window == mainWindow && ev.type == VisibilityNotify &&
1733                ev.xvisibility.state == VisibilityUnobscured) {
1734             XPutBackEvent(mainDisplay, &ev);
1735             return ReturnInterruptedExec();
1736          } else {
1737             ExposeEventHandler(&ev, TRUE);
1738          }
1739       } else {
1740          if (ev.xany.window == iconBaseWindow && ev.type == VisibilityNotify &&
1741                ev.xvisibility.state == VisibilityUnobscured) {
1742             XPutBackEvent(mainDisplay, &ev);
1743             return ReturnInterruptedExec();
1744          } else {
1745             ExposeEventHandler(&ev, TRUE);
1746          }
1747       }
1748    }
1749    if (XCheckMaskEvent(mainDisplay, ExposureMask, &ev)) {
1750       ExposeEventHandler(&ev, TRUE);
1751       while (XCheckMaskEvent(mainDisplay, ExposureMask, &ev)) ;
1752    }
1753    if (ESCPressed() || (check_any_button && XCheckMaskEvent(mainDisplay,
1754          ButtonPressMask | KeyPressMask, &ev)) || CheckInterrupt(TRUE)) {
1755       if (orig_cmd == NULL) {
1756          sprintf(gszMsgBox, TgLoadString(STID_USER_INTR));
1757       } else {
1758          sprintf(gszMsgBox, TgLoadString(STID_FUNC_USER_INTR), orig_cmd);
1759       }
1760       Msg(gszMsgBox);
1761       return ReturnInterruptedExec();
1762    }
1763    if (execTightLoopWait) {
1764       while (XCheckWindowEvent(mainDisplay, dummyWindow1,
1765             EnterWindowMask|LeaveWindowMask, &ev)) {
1766          switch (ev.type) {
1767          case EnterNotify:
1768             SetMouseStatus(TgLoadCachedString(CSTID_INTERRUPT),
1769                   TgLoadCachedString(CSTID_INTERRUPT),
1770                   TgLoadCachedString(CSTID_INTERRUPT));
1771             break;
1772          case LeaveNotify:
1773             RestoreStatusStringsFromBuf(execTightLoopStatusBuf,
1774                  execTightLoopOneLineStatus);
1775             break;
1776          }
1777       }
1778    }
1779    if (!check_any_button) {
1780       while (XCheckMaskEvent(mainDisplay, ButtonPressMask|KeyPressMask, &ev)) ;
1781    }
1782    return FALSE;
1783 }
1784 
1785 static
IntExpression(expr,p_ival,orig_cmd)1786 int IntExpression(expr, p_ival, orig_cmd)
1787    char *expr, *orig_cmd;
1788    int *p_ival;
1789 {
1790    struct VRec v;
1791 
1792    if (EvalExpr(expr, &v)) {
1793       switch (v.vtype) {
1794       case NULL_VAL: break;
1795       case INT_VAL: if (p_ival != NULL) *p_ival = v.val.i; return TRUE;
1796       case DBL_VAL: break;
1797       case STR_VAL: break;
1798       default: break;
1799       }
1800    }
1801    sprintf(gszMsgBox, TgLoadString(STID_BAD_EVAL_INT_EXP_EXEC_CMD), expr,
1802          orig_cmd);
1803    MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1804    return FALSE;
1805 }
1806 
1807 static
FloatExpression(expr,p_dval,orig_cmd)1808 int FloatExpression(expr, p_dval, orig_cmd)
1809    char *expr, *orig_cmd;
1810    double *p_dval;
1811 {
1812    struct VRec v;
1813 
1814    if (EvalExpr(expr, &v)) {
1815       switch (v.vtype) {
1816       case NULL_VAL: break;
1817       case INT_VAL: if (p_dval != NULL) *p_dval = (double)v.val.i; return TRUE;
1818       case DBL_VAL: if (p_dval != NULL) *p_dval = v.val.d; return TRUE;
1819       case STR_VAL: break;
1820       default: break;
1821       }
1822    }
1823    sprintf(gszMsgBox, TgLoadString(STID_BAD_EVAL_FLOAT_EXP_EXEC_CMD), expr,
1824          orig_cmd);
1825    MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1826    return FALSE;
1827 }
1828 
1829 static
SelectAnObj(sub_obj,owner_obj,top_owner,pp_saved_top_sel,pp_saved_bot_sel)1830 void SelectAnObj(sub_obj, owner_obj, top_owner, pp_saved_top_sel,
1831       pp_saved_bot_sel)
1832    struct ObjRec *sub_obj, *owner_obj, *top_owner;
1833    struct SelRec **pp_saved_top_sel, **pp_saved_bot_sel;
1834 {
1835    if (pp_saved_top_sel != NULL && pp_saved_bot_sel != NULL) {
1836       *pp_saved_top_sel = topSel;
1837       *pp_saved_bot_sel = botSel;
1838    } else {
1839       if (topSel != NULL) RemoveAllSel();
1840    }
1841    topSel = botSel = (struct SelRec *)malloc(sizeof(struct SelRec));
1842    if (topSel == NULL) FailAllocMessage();
1843 
1844    topSel->next = topSel->prev = NULL;
1845    topSel->obj = (owner_obj==NULL ? sub_obj : top_owner);
1846    UpdSelBBox();
1847 }
1848 
1849 /* --------------------- Exec Routines --------------------- */
1850 
ExecLaunch(argv,obj_ptr,orig_cmd)1851 int ExecLaunch(argv, obj_ptr, orig_cmd)
1852    char **argv, *orig_cmd;
1853    struct ObjRec *obj_ptr;
1854    /* launch(attribute_to_launch); */
1855 {
1856    char *attr_name=argv[0];
1857    struct AttrRec *attr_ptr;
1858 
1859    UtilRemoveQuotes(attr_name);
1860    sprintf(execDummyStr, "%s=", attr_name);
1861    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, NULL);
1862    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
1863 
1864    return (DoLaunch(attr_ptr, obj_ptr));
1865 }
1866 
ExecExec(argv,obj_ptr,orig_cmd)1867 int ExecExec(argv, obj_ptr, orig_cmd)
1868    char **argv, *orig_cmd;
1869    struct ObjRec *obj_ptr;
1870    /* exec(attribute_to_exec); */
1871 {
1872    char *attr_name=argv[0];
1873    struct AttrRec *attr_ptr;
1874    struct ObjRec *attr_owner_obj=NULL;
1875 
1876    UtilRemoveQuotes(attr_name);
1877    sprintf(execDummyStr, "%s=", attr_name);
1878    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
1879    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
1880 
1881    return (DoExec(attr_ptr, attr_owner_obj));
1882 }
1883 
ExecMktemp(argv,obj_ptr,orig_cmd)1884 int ExecMktemp(argv, obj_ptr, orig_cmd)
1885    char **argv, *orig_cmd;
1886    struct ObjRec *obj_ptr;
1887    /* mktemp(str,result_attribute); */
1888 {
1889    char *file_name=argv[0], *attr_name=argv[1];
1890    struct AttrRec *attr_ptr;
1891    struct ObjRec *attr_owner_obj=NULL;
1892    int rc=TRUE;
1893 
1894    UtilRemoveQuotes(file_name);
1895    UtilRemoveQuotes(attr_name);
1896    UtilTrimBlanks(file_name);
1897    UtilTrimBlanks(attr_name);
1898    sprintf(execDummyStr, "%s=", attr_name);
1899    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
1900    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
1901 
1902 #ifndef _DONT_USE_MKTEMP
1903    if (mktemp(file_name) == NULL) {
1904       sprintf(gszMsgBox, TgLoadString(STID_FAIL_FUNC_CMD_EXEC_ABORT),
1905             "mktemp()");
1906       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1907       rc = FALSE;
1908    } else {
1909       char *psz=UtilStrRChr(file_name, DIR_SEP);
1910       int changed=FALSE;
1911 
1912       if (psz != NULL) {
1913          for (psz++; *psz != '\0'; psz++) {
1914             if ((*psz >= '0' && *psz <= '9') || (*psz >= 'a' && *psz <= 'z') ||
1915                   (*psz >= 'A' && *psz <= 'Z')) {
1916             } else {
1917                *psz = 'Q';
1918                changed = TRUE;
1919             }
1920          }
1921       }
1922       if (changed && mktemp(file_name) == NULL) {
1923          sprintf(gszMsgBox, TgLoadString(STID_FAIL_FUNC_CMD_EXEC_ABORT),
1924                "mktemp()");
1925          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1926          rc = FALSE;
1927       } else {
1928          unlink(file_name);
1929          ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, file_name);
1930       }
1931    }
1932 #else /* _DONT_USE_MKTEMP */
1933    {
1934       int fd=(-1);
1935       char *dup_fname=UtilStrDup(file_name), path[MAXPATHLENGTH];
1936 
1937       if (dup_fname == NULL) FailAllocMessage();
1938       if ((fd=mkstemp(dup_fname)) == (-1)) {
1939          sprintf(gszMsgBox, TgLoadString(STID_CANT_OBTAIN_TMP_FILE_NAME),
1940                file_name);
1941          if (PRTGIF) {
1942             fprintf(stderr, "%s\n", gszMsgBox);
1943          } else {
1944             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1945          }
1946          rc = FALSE;
1947       } else {
1948          close(fd);
1949          UtilStrCpyN(path, sizeof(path), dup_fname);
1950       }
1951       UtilFree(dup_fname);
1952       /*
1953        * int len=0;
1954        * char *psz=NULL, fname[MAXPATHLENGTH], path[MAXPATHLENGTH];
1955        *
1956        * UtilStrCpyN(fname, sizeof(fname), file_name);
1957        * len = strlen(fname);
1958        * while (len > 0 && fname[len-1] == 'X') {
1959        *    fname[--len] = '\0';
1960        * }
1961        * psz = UtilStrRChr(fname, DIR_SEP);
1962        * if (psz == NULL) {
1963        *    UtilStrCpyN(path, sizeof(path), (char*)tempnam(NULL, fname));
1964        * } else {
1965        *    *psz = '\0';
1966        *    UtilStrCpyN(path, sizeof(path), (char*)tempnam(fname, &psz[1]));
1967        *    *psz = DIR_SEP;
1968        * }
1969        */
1970       UtilTrimBlanks(path);
1971       unlink(path);
1972       ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, path);
1973    }
1974 #endif /* ~_DONT_USE_MKTEMP */
1975    return rc;
1976 }
1977 
ExecUseTemplate(argv,obj_ptr,orig_cmd)1978 int ExecUseTemplate(argv, obj_ptr, orig_cmd)
1979    char **argv, *orig_cmd;
1980    struct ObjRec *obj_ptr;
1981    /* create_file_using_simple_template(template_file, */
1982    /*      output_file,string_to_match,substitution_attribute); */
1983 {
1984    char *template_name=argv[0], *file_name=argv[1];
1985    char *match_str=argv[2], *attr_name=argv[3], msg[MAXSTRING+1];
1986    struct AttrRec *attr_ptr=NULL;
1987    struct TextRec *text_ptr=NULL;
1988    FILE *in_fp=NULL, *out_fp=NULL;
1989 
1990    UtilRemoveQuotes(template_name);
1991    UtilRemoveQuotes(file_name);
1992    UtilRemoveQuotes(match_str);
1993    UtilRemoveQuotes(attr_name);
1994    sprintf(execDummyStr, "%s=", attr_name);
1995    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, NULL);
1996    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
1997 
1998    if ((out_fp=fopen(file_name, "w")) != NULL &&
1999          (in_fp=fopen(template_name, "r")) != NULL) {
2000       int len_to_match=strlen(match_str), len, rc=TRUE;
2001       char tmp_buf[MAXSTRING+1];
2002 
2003       writeFileFailed = FALSE;
2004       while (fgets(tmp_buf, MAXSTRING, in_fp) != NULL) {
2005          len = strlen(tmp_buf);
2006          if (tmp_buf[len-1] == '\n') {
2007             tmp_buf[--len] = '\0';
2008             if (len==len_to_match && strcmp(tmp_buf, match_str)==0) {
2009                if (*attr_ptr->attr_value.s != '\0') {
2010                   if (fprintf(out_fp, "%s\n", attr_ptr->attr_value.s) == EOF) {
2011                      writeFileFailed = TRUE;
2012                   }
2013                }
2014                text_ptr = attr_ptr->obj->detail.t;
2015 
2016                if (text_ptr->minilines.first != NULL) {
2017                   MiniLineInfo *pMiniLine=NULL;
2018 
2019                   for (pMiniLine=text_ptr->minilines.first->next;
2020                         pMiniLine != NULL; pMiniLine = pMiniLine->next) {
2021                      int need_to_free_tmp_buf=FALSE;
2022                      char *tmp_buf=ConvertMiniLineToString(pMiniLine,
2023                            &need_to_free_tmp_buf);
2024 
2025                      if (fprintf(out_fp, "%s\n", tmp_buf) == EOF) {
2026                         writeFileFailed = TRUE;
2027                      }
2028                      if (need_to_free_tmp_buf) UtilFree(tmp_buf);
2029                      if (writeFileFailed) break;
2030                   }
2031                }
2032             } else if (fprintf(out_fp, "%s\n", tmp_buf) == EOF) {
2033                writeFileFailed = TRUE;
2034             }
2035          } else if (len==len_to_match && strcmp(tmp_buf, match_str)==0) {
2036             if (*attr_ptr->attr_value.s != '\0') {
2037                if (fprintf(out_fp, "%s\n", attr_ptr->attr_value.s) == EOF) {
2038                   writeFileFailed = TRUE;
2039                }
2040             }
2041             text_ptr = attr_ptr->obj->detail.t;
2042 
2043             if (text_ptr->minilines.first != NULL) {
2044                MiniLineInfo *pMiniLine=NULL;
2045 
2046                for (pMiniLine=text_ptr->minilines.first->next;
2047                      pMiniLine != NULL; pMiniLine = pMiniLine->next) {
2048                   int need_to_free_tmp_buf=FALSE;
2049                   char *tmp_buf=ConvertMiniLineToString(pMiniLine,
2050                         &need_to_free_tmp_buf);
2051 
2052                   if (fprintf(out_fp, "%s\n", tmp_buf) == EOF) {
2053                      writeFileFailed = TRUE;
2054                   }
2055                   if (need_to_free_tmp_buf) UtilFree(tmp_buf);
2056                   if (writeFileFailed) break;
2057                }
2058             }
2059          } else if (fprintf(out_fp, "%s\n", tmp_buf) == EOF) {
2060             writeFileFailed = TRUE;
2061          }
2062       }
2063       if (writeFileFailed) {
2064          FailToWriteFileMessage(file_name);
2065          rc = FALSE;
2066       }
2067       fclose(in_fp);
2068       fclose(out_fp);
2069       return rc;
2070    } else if (out_fp == NULL) {
2071       sprintf(msg, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_WRITING), file_name);
2072       MsgBox(msg, TOOL_NAME, INFO_MB);
2073    } else if (in_fp == NULL) {
2074       sprintf(msg, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_READING),
2075             template_name);
2076       MsgBox(msg, TOOL_NAME, INFO_MB);
2077    }
2078    if (out_fp != NULL) fclose(out_fp);
2079    if (in_fp != NULL) fclose(in_fp);
2080    return FALSE;
2081 }
2082 
2083 #define UPDATE_EPS_CHILD 0
2084 #define UPDATE_XBM_CHILD 1
2085 #define UPDATE_XPM_CHILD 2
2086 
2087 #define UPDATE_CHILD_NO_ALIGNMENT 0
2088 #define UPDATE_CHILD_NORMAL_ALIGNMENT 1
2089 #define UPDATE_CHILD_NO_OVERLAP_ALIGNMENT 2
2090 
2091 static int updateChildUsingAlignment=INVALID;
2092 
2093 static
ExecUpdChild(argv,obj_ptr,orig_cmd,upd_type)2094 int ExecUpdChild(argv, obj_ptr, orig_cmd, upd_type)
2095    char **argv, *orig_cmd;
2096    struct ObjRec *obj_ptr;
2097    int upd_type;
2098    /* update_eps_child(eps_file_name); */
2099    /* update_xbm_child(xbm_file_name); */
2100    /* update_xpm_child(xpm_file_name); */
2101 {
2102    struct XPmRec *xpm_ptr=NULL;
2103    char *file_name=argv[0], png_fname[MAXPATHLENGTH], ppm6_fname[MAXPATHLENGTH];
2104    char jpg_fname[MAXPATHLENGTH];
2105    char msg[MAXPATHLENGTH+1], deflated_fname[MAXPATHLENGTH];
2106    char **lines=NULL, write_date[32];
2107    struct ObjRec *sub_obj_ptr=NULL, *del_obj=NULL, *tmp_obj;
2108    int rc=BitmapOpenFailed, len=0, png_not_xpm=FALSE, jpg_not_xpm=FALSE;
2109    int num_lines=0, epsf_level=0, image_w=0, image_h=0;
2110    int del_obj_ltx=0, del_obj_lty=0, ltx=0, lty=0;
2111    int rbx=0, rby=0, x_hot, y_hot, w=0, h=0, ncolors=0;
2112    int chars_per_pixel=0, first_pixel_is_bg=0, *pixels=NULL;
2113    struct BBRec parent_obbox;
2114    unsigned int ui_image_w=0, ui_image_h=0;
2115    char *color_char=NULL, **color_str=NULL, *xpm_data=NULL;
2116    float llx=0, lly=0, urx=0, ury=0;
2117    Pixmap bitmap=None, pixmap=None;
2118    XImage *image=NULL, *bitmap_image=NULL;
2119 
2120    *png_fname = *jpg_fname = *ppm6_fname = '\0';
2121    if (obj_ptr == NULL) {
2122       sprintf(gszMsgBox, TgLoadString(STID_NO_OBJ_SPEC_WHILE_EXEC_CMD),
2123             orig_cmd);
2124       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2125       return FALSE;
2126    }
2127    UtilRemoveQuotes(file_name);
2128    if (updateChildUsingAlignment == INVALID) {
2129       char *c_ptr;
2130 
2131       updateChildUsingAlignment = UPDATE_CHILD_NO_ALIGNMENT;
2132       if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
2133             "UpdateChildUsingAlignment")) != NULL) {
2134          if (UtilStrICmp(c_ptr, "true") == 0) {
2135             updateChildUsingAlignment = UPDATE_CHILD_NORMAL_ALIGNMENT;
2136          } else if (UtilStrICmp(c_ptr, "no_overlap") == 0) {
2137             updateChildUsingAlignment = UPDATE_CHILD_NO_OVERLAP_ALIGNMENT;
2138          }
2139       }
2140    }
2141    switch (obj_ptr->type) {
2142    case OBJ_GROUP:
2143    case OBJ_ICON:
2144    case OBJ_SYM:
2145    case OBJ_PIN: break;
2146 
2147    default:
2148       sprintf(msg, TgLoadString(STID_FUNC_ONLY_WORK_COMPOSITE_OBJ), orig_cmd);
2149       MsgBox(msg, TOOL_NAME, INFO_MB);
2150       return FALSE;
2151    }
2152    parent_obbox.ltx = obj_ptr->obbox.rbx;
2153    parent_obbox.lty = obj_ptr->obbox.rby;
2154    parent_obbox.rbx = obj_ptr->obbox.ltx;
2155    parent_obbox.rby = obj_ptr->obbox.lty;
2156    switch (upd_type) {
2157    case UPDATE_EPS_CHILD:
2158       for (tmp_obj=obj_ptr->detail.r->last; tmp_obj!=NULL;
2159             tmp_obj=tmp_obj->prev) {
2160          if (tmp_obj->type==OBJ_XBM &&
2161                tmp_obj->detail.xbm->real_type!=XBM_XBM) {
2162             del_obj_ltx = tmp_obj->obbox.ltx;
2163             del_obj_lty = tmp_obj->obbox.lty;
2164             del_obj = tmp_obj;
2165             if (!updateChildUsingAlignment) break;
2166          } else if (updateChildUsingAlignment) {
2167             if (tmp_obj->obbox.ltx < parent_obbox.ltx)
2168                parent_obbox.ltx = tmp_obj->obbox.ltx;
2169             if (tmp_obj->obbox.lty < parent_obbox.lty)
2170                parent_obbox.lty = tmp_obj->obbox.lty;
2171             if (tmp_obj->obbox.rbx > parent_obbox.rbx)
2172                parent_obbox.rbx = tmp_obj->obbox.rbx;
2173             if (tmp_obj->obbox.rby > parent_obbox.rby)
2174                parent_obbox.rby = tmp_obj->obbox.rby;
2175          }
2176       }
2177       break;
2178    case UPDATE_XBM_CHILD:
2179       for (tmp_obj=obj_ptr->detail.r->last; tmp_obj!=NULL;
2180             tmp_obj=tmp_obj->prev) {
2181          if (tmp_obj->type==OBJ_XBM &&
2182                tmp_obj->detail.xbm->real_type==XBM_XBM) {
2183             del_obj_ltx = tmp_obj->obbox.ltx;
2184             del_obj_lty = tmp_obj->obbox.lty;
2185             del_obj = tmp_obj;
2186             if (!updateChildUsingAlignment) break;
2187          } else if (updateChildUsingAlignment) {
2188             if (tmp_obj->obbox.ltx < parent_obbox.ltx)
2189                parent_obbox.ltx = tmp_obj->obbox.ltx;
2190             if (tmp_obj->obbox.lty < parent_obbox.lty)
2191                parent_obbox.lty = tmp_obj->obbox.lty;
2192             if (tmp_obj->obbox.rbx > parent_obbox.rbx)
2193                parent_obbox.rbx = tmp_obj->obbox.rbx;
2194             if (tmp_obj->obbox.rby > parent_obbox.rby)
2195                parent_obbox.rby = tmp_obj->obbox.rby;
2196          }
2197       }
2198       break;
2199    case UPDATE_XPM_CHILD:
2200       for (tmp_obj=obj_ptr->detail.r->last; tmp_obj!=NULL;
2201             tmp_obj=tmp_obj->prev) {
2202          if (tmp_obj->type==OBJ_XPM) {
2203             del_obj_ltx = tmp_obj->obbox.ltx;
2204             del_obj_lty = tmp_obj->obbox.lty;
2205             del_obj = tmp_obj;
2206             if (!updateChildUsingAlignment) break;
2207          } else if (updateChildUsingAlignment) {
2208             if (tmp_obj->obbox.ltx < parent_obbox.ltx)
2209                parent_obbox.ltx = tmp_obj->obbox.ltx;
2210             if (tmp_obj->obbox.lty < parent_obbox.lty)
2211                parent_obbox.lty = tmp_obj->obbox.lty;
2212             if (tmp_obj->obbox.rbx > parent_obbox.rbx)
2213                parent_obbox.rbx = tmp_obj->obbox.rbx;
2214             if (tmp_obj->obbox.rby > parent_obbox.rby)
2215                parent_obbox.rby = tmp_obj->obbox.rby;
2216          }
2217       }
2218       len = strlen(file_name);
2219       if (len > 4 && UtilStrNCaseCmp(&file_name[len-4], ".png", 4) == 0) {
2220          png_not_xpm = TRUE;
2221          UtilStrCpyN(png_fname, sizeof(png_fname), file_name);
2222          strcpy(&file_name[len-4], ".xpm");
2223       } else if (len > 4 &&
2224             UtilStrNCaseCmp(&file_name[len-4], ".jpg", 4) == 0) {
2225          jpg_not_xpm = TRUE;
2226          UtilStrCpyN(jpg_fname, sizeof(jpg_fname), file_name);
2227          strcpy(&file_name[len-4], ".xpm");
2228       }
2229       break;
2230    default: return BadCmd(orig_cmd);
2231    }
2232    if (del_obj == NULL) {
2233       del_obj_ltx = obj_ptr->obbox.ltx;
2234       /*
2235        * Use lty to cover the invisible object.
2236        * Use to use rby to tile below the invisible object.
2237        */
2238       del_obj_lty = obj_ptr->obbox.lty;
2239    }
2240    importingFile = TRUE;
2241    switch (upd_type) {
2242    case UPDATE_EPS_CHILD:
2243       rc = MyReadEPSFile(file_name, &image_w, &image_h, &bitmap,
2244             &image, &num_lines, &lines, &epsf_level, &llx, &lly, &urx, &ury,
2245             write_date);
2246       break;
2247    case UPDATE_XBM_CHILD:
2248       rc = XReadBitmapFile(mainDisplay, mainWindow, file_name,
2249             &ui_image_w, &ui_image_h, &bitmap, &x_hot, &y_hot);
2250       image_w = ui_image_w; image_h = ui_image_h;
2251       break;
2252    case UPDATE_XPM_CHILD:
2253       if (png_not_xpm || jpg_not_xpm) {
2254          if (fullTrueColorMode && HasZlibSupport()) {
2255             if (png_not_xpm) {
2256                rc = ConvertPngToPpm6(png_fname, ppm6_fname, sizeof(ppm6_fname));
2257             } else if (jpg_not_xpm) {
2258                rc = ConvertJpegToPpm6(jpg_fname, ppm6_fname,
2259                      sizeof(ppm6_fname));
2260             } else {
2261                /* should not come here */
2262                rc = BitmapFileInvalid;
2263             }
2264             if (rc) {
2265                ResetPngHeaderInfo(&gPngHeaderInfo);
2266                sub_obj_ptr = CreatePpmTrueObjFromFile(ppm6_fname);
2267             }
2268             if (sub_obj_ptr != NULL &&
2269                   MkTempFile(deflated_fname, sizeof(deflated_fname), tmpDir,
2270                   TOOL_NAME) != NULL && DeflateFile(ppm6_fname,
2271                   deflated_fname)) {
2272                /* nothing to do here */
2273             } else {
2274                unlink(ppm6_fname);
2275                if (sub_obj_ptr != NULL) FreeObj(sub_obj_ptr);
2276                importingFile = FALSE;
2277                return FALSE;
2278             }
2279             unlink(ppm6_fname);
2280             xpm_ptr = sub_obj_ptr->detail.xpm;
2281             xpm_ptr->real_type = PPM_TRUE;
2282             xpm_ptr->ppm_data_compress = PPM_DATA_DEFLATED;
2283             xpm_ptr->ppm_data = ReadFileIntoBuf(deflated_fname,
2284                   &xpm_ptr->ppm_data_size);
2285             xpm_ptr->ppm_mask_data = NULL;
2286             xpm_ptr->ppm_mask_size = 0;
2287             unlink(deflated_fname);
2288             rc = BitmapSuccess;
2289          } else {
2290             if (png_not_xpm) {
2291                rc = ConvertPngToXpm(png_fname, file_name, strlen(file_name)+1);
2292             } else if (jpg_not_xpm) {
2293                rc = ConvertJpegToXpm(jpg_fname, file_name, strlen(file_name)+1);
2294             } else {
2295                /* should not come here */
2296                rc = BitmapFileInvalid;
2297             }
2298             if (rc) {
2299                rc = MyReadPixmapFile(file_name, &image_w, &image_h, &w, &h,
2300                      &pixmap, &image, &bitmap, &bitmap_image, &ncolors,
2301                      &chars_per_pixel, &first_pixel_is_bg, &color_char,
2302                      &color_str, &pixels, &xpm_data);
2303             } else {
2304                rc = BitmapFileInvalid;
2305             }
2306          }
2307       } else {
2308          rc = MyReadPixmapFile(file_name, &image_w, &image_h, &w, &h,
2309                &pixmap, &image, &bitmap, &bitmap_image, &ncolors,
2310                &chars_per_pixel, &first_pixel_is_bg, &color_char, &color_str,
2311                &pixels, &xpm_data);
2312       }
2313       break;
2314    }
2315    if (rc != BitmapSuccess) {
2316       importingFile = FALSE;
2317       sprintf(msg, TgLoadString(STID_FUNC_FAIL_TO_IMPORT_GIVEN), orig_cmd,
2318             file_name);
2319       MsgBox(msg, TOOL_NAME, INFO_MB);
2320       return FALSE;
2321    }
2322    ltx = obj_ptr->bbox.ltx; lty = obj_ptr->bbox.lty;
2323    rbx = obj_ptr->bbox.rbx; rby = obj_ptr->bbox.rby;
2324 
2325    PrepareToReplaceAnObj(obj_ptr);
2326 
2327    switch (upd_type) {
2328    case UPDATE_EPS_CHILD:
2329       saveEPSLines = TRUE;
2330       sub_obj_ptr = CreateEPSObj(file_name, image_w, image_h, bitmap,
2331             image, num_lines, lines, epsf_level, &llx, &lly, &urx, &ury,
2332             write_date);
2333       saveEPSLines = FALSE;
2334       if (strcmp(defaultEPSScalingStr,"1") != 0) {
2335          ScaleAnEPSObj(sub_obj_ptr, &defaultEPSScaling);
2336       }
2337       break;
2338    case UPDATE_XBM_CHILD:
2339       sub_obj_ptr = CreateXBmObj(image_w, image_h, image_w, image_h,
2340             bitmap, image);
2341       break;
2342    case UPDATE_XPM_CHILD:
2343       if (sub_obj_ptr == NULL) {
2344          sub_obj_ptr = CreateXPmObj(image_w, image_h, w, h, pixmap, image,
2345                bitmap, bitmap_image, ncolors, chars_per_pixel,
2346                first_pixel_is_bg, color_char, color_str, pixels, xpm_data);
2347       } else {
2348          /* already created */
2349       }
2350       break;
2351    }
2352    if (!PRTGIF && colorLayers && needToRedrawColorWindow) {
2353       RedrawColorWindow();
2354    }
2355    if (updateChildUsingAlignment != UPDATE_CHILD_NO_ALIGNMENT) {
2356       switch (horiAlign) {
2357       case ALIGN_N:
2358       case ALIGN_L:
2359          del_obj_ltx = parent_obbox.ltx;
2360          break;
2361       case ALIGN_C:
2362       case ALIGN_S:
2363          del_obj_ltx = ((parent_obbox.ltx+parent_obbox.rbx)>>1) -
2364                ((sub_obj_ptr->obbox.rbx-sub_obj_ptr->obbox.ltx)>>1);
2365          break;
2366       case ALIGN_R:
2367          del_obj_ltx = parent_obbox.rbx -
2368                (sub_obj_ptr->obbox.rbx-sub_obj_ptr->obbox.ltx);
2369          break;
2370       }
2371       switch (updateChildUsingAlignment) {
2372       case UPDATE_CHILD_NORMAL_ALIGNMENT:
2373          switch (vertAlign) {
2374          case ALIGN_T:
2375             del_obj_lty = parent_obbox.lty;
2376             break;
2377          case ALIGN_M:
2378          case ALIGN_S:
2379             del_obj_lty = ((parent_obbox.lty+parent_obbox.rby)>>1) -
2380                   ((sub_obj_ptr->obbox.rby-sub_obj_ptr->obbox.lty)>>1);
2381             break;
2382          case ALIGN_B:
2383             del_obj_lty = parent_obbox.rby -
2384                   (sub_obj_ptr->obbox.rby-sub_obj_ptr->obbox.lty);
2385             break;
2386          case ALIGN_N:
2387             del_obj_lty = parent_obbox.rby;
2388             break;
2389          }
2390          break;
2391       case UPDATE_CHILD_NO_OVERLAP_ALIGNMENT:
2392          switch (vertAlign) {
2393          case ALIGN_T:
2394             del_obj_lty = parent_obbox.lty -
2395                   (sub_obj_ptr->obbox.rby-sub_obj_ptr->obbox.lty);
2396             break;
2397          case ALIGN_M:
2398          case ALIGN_S:
2399             del_obj_lty = ((parent_obbox.lty+parent_obbox.rby)>>1) -
2400                   ((sub_obj_ptr->obbox.rby-sub_obj_ptr->obbox.lty)>>1);
2401             break;
2402          case ALIGN_B:
2403          case ALIGN_N:
2404             del_obj_lty = parent_obbox.rby;
2405             break;
2406          }
2407          break;
2408       }
2409    }
2410    MoveObj(sub_obj_ptr, del_obj_ltx-sub_obj_ptr->obbox.ltx,
2411          del_obj_lty-sub_obj_ptr->obbox.lty);
2412    if (del_obj != NULL) {
2413       if (del_obj == obj_ptr->detail.r->first) {
2414          obj_ptr->detail.r->first = del_obj->next;
2415       } else {
2416          del_obj->prev->next = del_obj->next;
2417       }
2418       if (del_obj == obj_ptr->detail.r->last) {
2419          obj_ptr->detail.r->last = del_obj->prev;
2420       } else {
2421          del_obj->next->prev = del_obj->prev;
2422       }
2423       FreeObj(del_obj);
2424    }
2425    sub_obj_ptr->prev = NULL;
2426    sub_obj_ptr->next = obj_ptr->detail.r->first;
2427    if (obj_ptr->detail.r->first == NULL) {
2428       obj_ptr->detail.r->last = sub_obj_ptr;
2429    } else {
2430       obj_ptr->detail.r->first->prev = sub_obj_ptr;
2431    }
2432    obj_ptr->detail.r->first = sub_obj_ptr;
2433    AdjObjBBox(obj_ptr);
2434 
2435    RecordReplaceAnObj(obj_ptr);
2436    RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
2437          rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
2438          obj_ptr->bbox.ltx-GRID_ABS_SIZE(1), obj_ptr->bbox.lty-GRID_ABS_SIZE(1),
2439          obj_ptr->bbox.rbx+GRID_ABS_SIZE(1),
2440          obj_ptr->bbox.rby+GRID_ABS_SIZE(1));
2441    SetFileModified(TRUE);
2442 
2443    importingFile = FALSE;
2444 
2445    return TRUE;
2446 }
2447 
ExecUpdEPSChild(argv,obj_ptr,orig_cmd)2448 int ExecUpdEPSChild(argv, obj_ptr, orig_cmd)
2449    char **argv, *orig_cmd;
2450    struct ObjRec *obj_ptr;
2451 {
2452    return ExecUpdChild(argv, obj_ptr, orig_cmd, UPDATE_EPS_CHILD);
2453 }
2454 
ExecUpdXBMChild(argv,obj_ptr,orig_cmd)2455 int ExecUpdXBMChild(argv, obj_ptr, orig_cmd)
2456    char **argv, *orig_cmd;
2457    struct ObjRec *obj_ptr;
2458 {
2459    return ExecUpdChild(argv, obj_ptr, orig_cmd, UPDATE_XBM_CHILD);
2460 }
2461 
ExecUpdXPMChild(argv,obj_ptr,orig_cmd)2462 int ExecUpdXPMChild(argv, obj_ptr, orig_cmd)
2463    char **argv, *orig_cmd;
2464    struct ObjRec *obj_ptr;
2465 {
2466    return ExecUpdChild(argv, obj_ptr, orig_cmd, UPDATE_XPM_CHILD);
2467 }
2468 
2469 static
ExecDelChild(argv,obj_ptr,orig_cmd,upd_type)2470 int ExecDelChild(argv, obj_ptr, orig_cmd, upd_type)
2471    char **argv, *orig_cmd;
2472    struct ObjRec *obj_ptr;
2473    int upd_type;
2474    /* delete_eps_child(obj_name); */
2475    /* delete_xbm_child(obj_name); */
2476    /* delete_xpm_child(obj_name); */
2477 {
2478    char *obj_name=argv[0];
2479    struct ObjRec *top_owner=NULL, *named_obj=NULL;
2480 
2481    struct ObjRec *del_obj=NULL, *tmp_obj=NULL;
2482    int ltx=0, lty=0, rbx=0, rby=0;
2483 
2484    UtilRemoveQuotes(obj_name);
2485    named_obj = FindObjWithName(botObj, obj_ptr, obj_name, FALSE,
2486          FALSE, NULL, &top_owner);
2487    if (named_obj == NULL) {
2488       return BadObjName(obj_name, orig_cmd);
2489    }
2490    switch (named_obj->type) {
2491    case OBJ_GROUP:
2492    case OBJ_ICON:
2493    case OBJ_SYM:
2494    case OBJ_PIN: break;
2495 
2496    default:
2497       sprintf(gszMsgBox, TgLoadString(STID_FUNC_ONLY_WORK_COMPOSITE_OBJ),
2498             orig_cmd);
2499       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2500       return FALSE;
2501    }
2502    ltx = top_owner->bbox.ltx; lty = top_owner->bbox.lty;
2503    rbx = top_owner->bbox.rbx; rby = top_owner->bbox.rby;
2504 
2505    switch (upd_type) {
2506    case UPDATE_EPS_CHILD:
2507       for (tmp_obj=named_obj->detail.r->last; tmp_obj!=NULL;
2508             tmp_obj=tmp_obj->prev) {
2509          if (tmp_obj->type==OBJ_XBM &&
2510                tmp_obj->detail.xbm->real_type!=XBM_XBM) {
2511             del_obj = tmp_obj;
2512             break;
2513          }
2514       }
2515       break;
2516    case UPDATE_XBM_CHILD:
2517       for (tmp_obj=named_obj->detail.r->last; tmp_obj!=NULL;
2518             tmp_obj=tmp_obj->prev) {
2519          if (tmp_obj->type==OBJ_XBM &&
2520                tmp_obj->detail.xbm->real_type==XBM_XBM) {
2521             del_obj = tmp_obj;
2522             break;
2523          }
2524       }
2525       break;
2526    case UPDATE_XPM_CHILD:
2527       for (tmp_obj=named_obj->detail.r->last; tmp_obj!=NULL;
2528             tmp_obj=tmp_obj->prev) {
2529          if (tmp_obj->type==OBJ_XPM) {
2530             del_obj = tmp_obj;
2531             break;
2532          }
2533       }
2534       break;
2535    default: return BadCmd(orig_cmd);
2536    }
2537    if (del_obj == NULL) {
2538       /* no child to delete, no problem */
2539       return TRUE;
2540    }
2541    PrepareToReplaceAnObj(top_owner);
2542 
2543    if (del_obj != NULL) {
2544       if (del_obj == named_obj->detail.r->first) {
2545          named_obj->detail.r->first = del_obj->next;
2546       } else {
2547          del_obj->prev->next = del_obj->next;
2548       }
2549       if (del_obj == named_obj->detail.r->last) {
2550          named_obj->detail.r->last = del_obj->prev;
2551       } else {
2552          del_obj->next->prev = del_obj->prev;
2553       }
2554       FreeObj(del_obj);
2555    }
2556    AdjObjBBox(top_owner);
2557 
2558    RecordReplaceAnObj(top_owner);
2559    RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
2560          rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
2561          top_owner->bbox.ltx-GRID_ABS_SIZE(1),
2562          top_owner->bbox.lty-GRID_ABS_SIZE(1),
2563          top_owner->bbox.rbx+GRID_ABS_SIZE(1),
2564          top_owner->bbox.rby+GRID_ABS_SIZE(1));
2565    SetFileModified(TRUE);
2566 
2567    return TRUE;
2568 }
2569 
ExecDelEPSChild(argv,obj_ptr,orig_cmd)2570 int ExecDelEPSChild(argv, obj_ptr, orig_cmd)
2571    char **argv, *orig_cmd;
2572    struct ObjRec *obj_ptr;
2573 {
2574    return ExecDelChild(argv, obj_ptr, orig_cmd, UPDATE_EPS_CHILD);
2575 }
2576 
ExecDelXBMChild(argv,obj_ptr,orig_cmd)2577 int ExecDelXBMChild(argv, obj_ptr, orig_cmd)
2578    char **argv, *orig_cmd;
2579    struct ObjRec *obj_ptr;
2580 {
2581    return ExecDelChild(argv, obj_ptr, orig_cmd, UPDATE_XBM_CHILD);
2582 }
2583 
ExecDelXPMChild(argv,obj_ptr,orig_cmd)2584 int ExecDelXPMChild(argv, obj_ptr, orig_cmd)
2585    char **argv, *orig_cmd;
2586    struct ObjRec *obj_ptr;
2587 {
2588    return ExecDelChild(argv, obj_ptr, orig_cmd, UPDATE_XPM_CHILD);
2589 }
2590 
2591 #ifndef _NO_GETTIMEOFDAY
2592 static
ms_time(tv)2593 long ms_time(tv)
2594    struct timeval *tv;
2595 {
2596    return ((long)(tv->tv_usec / 1000.0)) + ((long)(tv->tv_sec * 1000));
2597 }
2598 #endif /* ~_NO_GETTIMEOFDAY */
2599 
2600 #define FD_STYLE_LINEAR 0
2601 #define FD_STYLE_PINGPONG 1
2602 
2603 #define FD_FORWARD 0
2604 #define FD_REVERSE 1
2605 
ExecFlipDeck(argv,obj_ptr,orig_cmd)2606 int ExecFlipDeck(argv, obj_ptr, orig_cmd)
2607    char **argv, *orig_cmd;
2608    struct ObjRec *obj_ptr;
2609    /* flip_deck(times,frames_per_second,style); */
2610    /*       style=[linear | pingpong] */
2611 {
2612    char *times_str=argv[0];
2613    char *fps_str=argv[1], *style_str=argv[2];
2614    int num_bm, iteration, times, fps, style;
2615    int rc=TRUE;
2616    struct ObjRec *bm_obj=NULL, *cur_obj=NULL, *prev_obj=NULL, *next_obj=NULL;
2617    struct BBRec obbox;
2618    int select_width=XConnectionNumber(mainDisplay)+1;
2619 #ifdef _NO_GETTIMEOFDAY
2620    struct timeb start;
2621 #else /* ~_NO_GETTIMEOFDAY */
2622    struct timeval start;
2623    struct timezone zone;
2624 #endif /* _NO_GETTIMEOFDAY */
2625    long ms_start_time, ms_frame_interval;
2626    fd_set fdset;
2627 
2628    memset(&obbox, 0, sizeof(struct BBRec));
2629    if (obj_ptr == NULL) {
2630       sprintf(gszMsgBox, TgLoadString(STID_NO_OBJ_SPEC_WHILE_EXEC_CMD),
2631             orig_cmd);
2632       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2633       return FALSE;
2634    }
2635    UtilRemoveQuotes(times_str);
2636    UtilRemoveQuotes(fps_str);
2637    UtilRemoveQuotes(style_str);
2638    switch (obj_ptr->type) {
2639    case OBJ_GROUP:
2640    case OBJ_ICON:
2641    case OBJ_SYM:
2642    case OBJ_PIN: break;
2643 
2644    default:
2645       sprintf(execDummyStr, TgLoadString(STID_FUNC_ONLY_WORK_COMPOSITE_OBJ),
2646             orig_cmd);
2647       MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
2648       return FALSE;
2649    }
2650    num_bm = 0;
2651    for (bm_obj=obj_ptr->detail.r->last; bm_obj != NULL; bm_obj=bm_obj->prev) {
2652       if (bm_obj->type != OBJ_XBM && bm_obj->type != OBJ_XPM) {
2653          sprintf(gszMsgBox, TgLoadString(STID_FUNC_OBJ_NON_XBM_XPM_SUB_OBJS),
2654                orig_cmd);
2655          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2656          return (FALSE);
2657       } else if (num_bm++ == 0) {
2658          obbox.ltx = bm_obj->obbox.ltx; obbox.lty = bm_obj->obbox.lty;
2659          obbox.rbx = bm_obj->obbox.rbx; obbox.rby = bm_obj->obbox.rby;
2660       } else {
2661          if (obbox.ltx!=bm_obj->obbox.ltx || obbox.lty!=bm_obj->obbox.lty ||
2662                obbox.rbx!=bm_obj->obbox.rbx || obbox.rby!=bm_obj->obbox.rby) {
2663             sprintf(gszMsgBox, TgLoadString(STID_FUNC_DIFF_SZ_XBM_XPM_SUBOBJS),
2664                   orig_cmd);
2665             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2666             return FALSE;
2667          }
2668       }
2669    }
2670    if (num_bm < 2) {
2671       sprintf(gszMsgBox, TgLoadString(STID_FUNC_MORE_1_XBM_XPM_SUBOBJS),
2672             orig_cmd);
2673       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2674       return FALSE;
2675    }
2676    if (!IntExpression(fps_str, &fps, orig_cmd)) {
2677       return FALSE;
2678    }
2679    if (fps < 1 || fps > 60) {
2680       sprintf(gszMsgBox, TgLoadString(STID_FUNC_ARG_RANGE),
2681             orig_cmd, "frames_per_second", 1, 60, fps);
2682       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2683       return FALSE;
2684    }
2685    ms_frame_interval = round(1000 / fps) - 1;
2686    if (strcmp(style_str, "linear") == 0) {
2687       style = FD_STYLE_LINEAR;
2688    } else if (strcmp(style_str, "ping_pong") == 0) {
2689       style = FD_STYLE_PINGPONG;
2690    } else {
2691       sprintf(gszMsgBox, TgLoadString(STID_FUNC_UNDEFINED_ARG),
2692             orig_cmd, "style", 1, 60);
2693       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2694       return FALSE;
2695    }
2696    if (strcmp(times_str, "infinite") == 0) {
2697       times = (-1);
2698    } else {
2699       if (!IntExpression(times_str, &times, orig_cmd)) {
2700          return FALSE;
2701       }
2702    }
2703    iteration = 0;
2704 #ifdef _NO_GETTIMEOFDAY
2705    ftime(&start);
2706    ms_start_time = ((long)start.time * 1000) + ((long)start.millitm);
2707 #else /* ~_NO_GETTIMEOFDAY */
2708    gettimeofday(&start, &zone);
2709    ms_start_time = ms_time(&start);
2710 #endif /* _NO_GETTIMEOFDAY */
2711    while (rc == TRUE && (times < 0 || iteration < times)) {
2712       int looping=TRUE, direction=FD_FORWARD;
2713 
2714       if (times >= 0) iteration++;
2715       cur_obj = obj_ptr->detail.r->first;
2716       while (looping) {
2717          struct timeval timeout;
2718 #ifdef _NO_GETTIMEOFDAY
2719          struct timeb now;
2720 #else /* ~_NO_GETTIMEOFDAY */
2721          struct timeval now;
2722 #endif /* _NO_GETTIMEOFDAY */
2723          long ms_cur_time, ms_interval;
2724          int status;
2725 
2726          prev_obj = cur_obj->prev;
2727          next_obj = cur_obj->next;
2728          cur_obj->prev = cur_obj->next = NULL;
2729          switch (cur_obj->type) {
2730          case OBJ_XBM:
2731             if (iconWindowShown) {
2732                DrawXBmObj(iconWindow, 0, 0, cur_obj);
2733             } else {
2734                DrawXBmObj(drawWindow, drawOrigX, drawOrigY, cur_obj);
2735             }
2736             break;
2737          case OBJ_XPM:
2738             if (iconWindowShown) {
2739                DrawXPmObj(iconWindow, 0, 0, cur_obj);
2740             } else {
2741                DrawXPmObj(drawWindow, drawOrigX, drawOrigY, cur_obj);
2742             }
2743             break;
2744          }
2745          XSync(mainDisplay, FALSE);
2746          cur_obj->prev = prev_obj;
2747          cur_obj->next = next_obj;
2748          switch (style) {
2749          case FD_STYLE_LINEAR:
2750             if ((cur_obj=cur_obj->next) == NULL)
2751                looping = FALSE;
2752             break;
2753          case FD_STYLE_PINGPONG:
2754             switch (direction) {
2755             case FD_FORWARD:
2756                if (cur_obj->next == NULL) {
2757                   if ((cur_obj=cur_obj->prev) == obj_ptr->detail.r->first) {
2758                      looping = FALSE;
2759                   } else {
2760                      direction = FD_REVERSE;
2761                   }
2762                } else {
2763                   cur_obj = cur_obj->next;
2764                }
2765                break;
2766             case FD_REVERSE:
2767                if ((cur_obj=cur_obj->prev) == obj_ptr->detail.r->first) {
2768                   looping = FALSE;
2769                }
2770                break;
2771             }
2772             break;
2773          }
2774          EnterExecTightLoop();
2775          do
2776          {
2777             FD_ZERO(&fdset);
2778             FD_SET(select_width-1, &fdset);
2779 
2780 #ifdef _NO_GETTIMEOFDAY
2781             ftime(&now);
2782             ms_cur_time = ((long)now.time * 1000) + ((long)now.millitm);
2783 #else /* ~_NO_GETTIMEOFDAY */
2784             gettimeofday(&now, &zone);
2785             ms_cur_time = ms_time(&now);
2786 #endif /* _NO_GETTIMEOFDAY */
2787             ms_interval = ms_start_time + ms_frame_interval - ms_cur_time;
2788             while (ms_interval <= 0) {
2789                ms_start_time = ms_cur_time;
2790                ms_interval = ms_start_time + ms_frame_interval - ms_cur_time;
2791             }
2792             timeout.tv_sec = 0;
2793             timeout.tv_usec = 1000 * ms_interval;
2794 
2795 #ifdef __hpux
2796             status = select(select_width, (int*)&fdset, NULL, NULL, &timeout);
2797 #else /* !__hpux */
2798             status = select(select_width, &fdset, NULL, NULL, &timeout);
2799 #endif /* __hpux */
2800 
2801             if (status < 0) {
2802                if (errno == EINTR) {
2803                   /* interrupted by a system call, minor timing problem */
2804                   CheckInterrupt(TRUE);
2805                } else {
2806                   sprintf(gszMsgBox,
2807                         TgLoadString(STID_FUNC_SELECT_SYS_CALL_FAILED),
2808                         orig_cmd);
2809                   MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2810                   looping = FALSE;
2811                   rc = FALSE;
2812                   break;
2813                }
2814             } else if (status == 0) {
2815                /* timeout without any X events */
2816                CheckInterrupt(TRUE);
2817                break;
2818             } else {
2819                if (CheckExecInterrupt(orig_cmd)) {
2820                   looping = FALSE;
2821                   rc = FALSE;
2822                   userAbortExec = TRUE;
2823                   break;
2824                }
2825             }
2826          } while (looping && ms_interval > 0);
2827          ExitExecTightLoop();
2828       }
2829    }
2830 
2831 /* RedrawAnArea(botObj, obj_ptr->bbox.ltx-GRID_ABS_SIZE(1),
2832          obj_ptr->bbox.lty-GRID_ABS_SIZE(1), obj_ptr->bbox.rbx+GRID_ABS_SIZE(1),
2833          obj_ptr->bbox.rby+GRID_ABS_SIZE(1)); */
2834 
2835    cur_obj = obj_ptr->detail.r->first;
2836    prev_obj = cur_obj->prev;
2837    next_obj = cur_obj->next;
2838    cur_obj->prev = cur_obj->next = NULL;
2839    switch (cur_obj->type) {
2840    case OBJ_XBM:
2841       if (iconWindowShown) {
2842          DrawXBmObj(iconWindow, 0, 0, cur_obj);
2843       } else {
2844          DrawXBmObj(drawWindow, drawOrigX, drawOrigY, cur_obj);
2845       }
2846       break;
2847    case OBJ_XPM:
2848       if (iconWindowShown) {
2849          DrawXPmObj(iconWindow, 0, 0, cur_obj);
2850       } else {
2851          DrawXPmObj(drawWindow, drawOrigX, drawOrigY, cur_obj);
2852       }
2853       break;
2854    }
2855    XSync(mainDisplay, FALSE);
2856    cur_obj->prev = prev_obj;
2857    cur_obj->next = next_obj;
2858 
2859    return rc;
2860 }
2861 
2862 static
DoReadFileIntoAttr(attr_ptr,attr_owner_obj,file_name,orig_cmd)2863 int DoReadFileIntoAttr(attr_ptr, attr_owner_obj, file_name, orig_cmd)
2864    struct AttrRec *attr_ptr;
2865    struct ObjRec *attr_owner_obj;
2866    char *file_name, *orig_cmd;
2867 {
2868    FILE *fp=NULL;
2869 
2870    if (*file_name == '|') {
2871       if (inHyperSpace && !allowLaunchInHyperSpace) {
2872          XFlush(mainDisplay);
2873          XSync(mainDisplay, False);
2874          sprintf(gszMsgBox, TgLoadString(STID_LAUNCH_NOT_AUTO_IN_HYPER_EXEC),
2875                &file_name[1]);
2876          if (MsgBox(gszMsgBox, TOOL_NAME, YN_MB) != MB_ID_YES) {
2877             MsgBox(TgLoadString(STID_USER_ABORT_LAUNCH_IN_HYPER), TOOL_NAME,
2878                   INFO_MB);
2879             return FALSE;
2880          }
2881       }
2882       if (!FindProgramInPath(&file_name[1], NULL, FALSE)) {
2883          return FALSE;
2884       }
2885       sprintf(gszMsgBox, TgLoadCachedString(CSTID_EXECUTING_GIVEN_PROGRAM),
2886             &file_name[1]);
2887       SetStringStatus(gszMsgBox);
2888       if (!PRTGIF) XSync(mainDisplay, False);
2889       fp = (FILE*)popen(&file_name[1], "r");
2890    } else {
2891       fp = fopen(file_name, "r");
2892    }
2893    if (fp == NULL) {
2894       if (*file_name == '|') {
2895          sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_EXECUTE_CMD_EXEC_CMD),
2896                &file_name[1], orig_cmd);
2897       } else {
2898          sprintf(gszMsgBox, TgLoadString(STID_CANT_OPEN_FILE_READ_EXEC_CMD),
2899                file_name, orig_cmd);
2900       }
2901       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2902       return FALSE;
2903    }
2904    PrepareToReplaceAnObj(attr_owner_obj);
2905 
2906    JustReadFileIntoAttr(fp, attr_ptr, attr_owner_obj);
2907 
2908    if (*file_name == '|') {
2909       pclose(fp);
2910       SetStringStatus(TgLoadCachedString(CSTID_DOTS_DONE));
2911    } else {
2912       fclose(fp);
2913    }
2914    return TRUE;
2915 }
2916 
ExecReadFileIntoAttr(argv,obj_ptr,orig_cmd)2917 int ExecReadFileIntoAttr(argv, obj_ptr, orig_cmd)
2918    char **argv, *orig_cmd;
2919    struct ObjRec *obj_ptr;
2920    /* read_file_into_attr(file_name,result_attribute); */
2921 {
2922    char *file_name=argv[0], *attr_name=argv[1];
2923    struct AttrRec *attr_ptr;
2924    struct ObjRec *attr_owner_obj;
2925    int rc;
2926 
2927    UtilRemoveQuotes(file_name);
2928    UtilRemoveQuotes(attr_name);
2929    sprintf(execDummyStr, "%s=", attr_name);
2930    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
2931    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
2932 
2933    SaveStatusStrings();
2934    rc = DoReadFileIntoAttr(attr_ptr, attr_owner_obj, file_name, orig_cmd);
2935    RestoreStatusStrings();
2936    return rc;
2937 }
2938 
2939 static
ExecWriteOrAppendAttrIntoFile(argv,obj_ptr,orig_cmd,open_mode)2940 int ExecWriteOrAppendAttrIntoFile(argv, obj_ptr, orig_cmd, open_mode)
2941    char **argv, *orig_cmd, *open_mode;
2942    struct ObjRec *obj_ptr;
2943    /* write_attr_into_file(attribute,file_name); */
2944    /* append_attr_into_file(attribute,file_name); */
2945 {
2946    char *attr_name=argv[0], *file_name=argv[1];
2947    struct AttrRec *attr_ptr=NULL;
2948    FILE *fp=NULL;
2949 
2950    UtilRemoveQuotes(attr_name);
2951    UtilRemoveQuotes(file_name);
2952    sprintf(execDummyStr, "%s=", attr_name);
2953    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, NULL);
2954    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
2955 
2956    if (inHyperSpace && !allowLaunchInHyperSpace) {
2957       XFlush(mainDisplay);
2958       XSync(mainDisplay, False);
2959       sprintf(gszMsgBox, TgLoadString(STID_WRITE_NOT_AUTO_IN_HYPER_EXEC),
2960             file_name);
2961       if (MsgBox(gszMsgBox, TOOL_NAME, YN_MB) != MB_ID_YES) {
2962          MsgBox(TgLoadString(STID_USER_ABORT_WRITE_IN_HYPER), TOOL_NAME,
2963                INFO_MB);
2964          return FALSE;
2965       }
2966    }
2967    if ((fp=fopen(file_name, open_mode)) == NULL) {
2968       sprintf(execDummyStr, TgLoadString(STID_CANT_OPEN_FILE_READ_EXEC_CMD),
2969             file_name, orig_cmd);
2970       MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
2971       return FALSE;
2972    }
2973    writeFileFailed = FALSE;
2974 
2975    fprintf(fp, "%s\n", attr_ptr->attr_value.s);
2976    if (attr_ptr->obj->detail.t->minilines.first != NULL) {
2977       MiniLineInfo *pMiniLine=NULL;
2978 
2979       for (pMiniLine=attr_ptr->obj->detail.t->minilines.first->next;
2980             pMiniLine != NULL; pMiniLine=pMiniLine->next) {
2981          int need_to_free_tmp_buf=FALSE;
2982          char *tmp_buf=ConvertMiniLineToString(pMiniLine,
2983                &need_to_free_tmp_buf);
2984 
2985          if (fprintf(fp, "%s\n", tmp_buf) == EOF) {
2986             writeFileFailed = TRUE;
2987          }
2988          if (need_to_free_tmp_buf) UtilFree(tmp_buf);
2989          if (writeFileFailed) break;
2990       }
2991    }
2992    fclose(fp);
2993 
2994    if (writeFileFailed) return FailToWriteFileMessage(file_name);
2995    return TRUE;
2996 }
2997 
ExecWriteAttrIntoFile(argv,obj_ptr,orig_cmd)2998 int ExecWriteAttrIntoFile(argv, obj_ptr, orig_cmd)
2999    char **argv, *orig_cmd;
3000    struct ObjRec *obj_ptr;
3001    /* write_attr_into_file(attribute,file_name); */
3002 {
3003    return ExecWriteOrAppendAttrIntoFile(argv, obj_ptr, orig_cmd, "w");
3004 }
3005 
ExecAppendAttrIntoFile(argv,obj_ptr,orig_cmd)3006 int ExecAppendAttrIntoFile(argv, obj_ptr, orig_cmd)
3007    char **argv, *orig_cmd;
3008    struct ObjRec *obj_ptr;
3009    /* append_attr_into_file(attribute,file_name); */
3010 {
3011    return ExecWriteOrAppendAttrIntoFile(argv, obj_ptr, orig_cmd, "a");
3012 }
3013 
ExecSelectObjByName(argv,obj_ptr,orig_cmd)3014 int ExecSelectObjByName(argv, obj_ptr, orig_cmd)
3015    char **argv, *orig_cmd;
3016    struct ObjRec *obj_ptr;
3017    /* select_obj_by_name(obj_name); */
3018 {
3019    char *obj_name=argv[0];
3020    struct ObjRec *owner_obj=NULL, *named_obj;
3021 
3022    UtilRemoveQuotes(obj_name);
3023    named_obj = FindObjWithName(botObj, obj_ptr, obj_name, FALSE,
3024          FALSE, &owner_obj, NULL);
3025    if (topSel != NULL) RemoveAllSel();
3026    if (named_obj == NULL) {
3027       return BadObjName(obj_name, orig_cmd);
3028    }
3029    if (owner_obj != NULL) {
3030       sprintf(execDummyStr, TgLoadString(STID_BAD_NAME_TOP_LEVEL_ONLY_CMD),
3031             obj_name, orig_cmd);
3032       MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
3033       return FALSE;
3034    }
3035    AddNewSelObj(named_obj);
3036    UpdSelBBox();
3037 
3038    return TRUE;
3039 }
3040 
ExecSelectTopObj(obj_ptr,orig_cmd)3041 void ExecSelectTopObj(obj_ptr, orig_cmd)
3042    char *orig_cmd;
3043    struct ObjRec *obj_ptr;
3044    /* select_top_obj(); */
3045 {
3046    if (topObj == NULL) {
3047       sprintf(execDummyStr, TgLoadString(STID_NO_OBJ_SEL_WHILE_EXEC_CMD),
3048             orig_cmd);
3049       MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
3050       gnAbortExec = TRUE;
3051    } else {
3052       if (topSel != NULL) RemoveAllSel();
3053 
3054       SelectTopObj();
3055    }
3056 }
3057 
ExecDelAllSelObj(obj_ptr,orig_cmd)3058 void ExecDelAllSelObj(obj_ptr, orig_cmd)
3059    char *orig_cmd;
3060    struct ObjRec *obj_ptr;
3061    /* delete_selected_obj(); */
3062 {
3063    if (topSel == NULL) {
3064       sprintf(execDummyStr, TgLoadString(STID_NO_OBJ_SEL_WHILE_EXEC_CMD),
3065             orig_cmd);
3066       MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
3067       gnAbortExec = TRUE;
3068    } else {
3069       DelAllSelObj();
3070    }
3071 }
3072 
ExecUnSelectAllObj(obj_ptr,orig_cmd)3073 void ExecUnSelectAllObj(obj_ptr, orig_cmd)
3074    struct ObjRec *obj_ptr;
3075    char *orig_cmd;
3076    /* unselect_all_obj(); */
3077 {
3078    RemoveAllSel();
3079 }
3080 
ExecMoveSelObjRel(argv,obj_ptr,orig_cmd)3081 int ExecMoveSelObjRel(argv, obj_ptr, orig_cmd)
3082    char **argv, *orig_cmd;
3083    struct ObjRec *obj_ptr;
3084    /* move_selected_obj_relative(dx,dy); */
3085 {
3086    char *dx_str=argv[0], *dy_str=argv[1];
3087    int dx, dy;
3088 
3089    if (topSel == NULL) return BadSelectedObj(orig_cmd);
3090 
3091    UtilRemoveQuotes(dx_str);
3092    UtilRemoveQuotes(dy_str);
3093    if (!IntExpression(dx_str, &dx, orig_cmd) ||
3094          !IntExpression(dy_str, &dy, orig_cmd)) {
3095       return FALSE;
3096    }
3097    if (dx != 0 || dy != 0) {
3098       MoveAllSel(dx, dy);
3099       UpdSelBBox();
3100       SetFileModified(TRUE);
3101    }
3102    return TRUE;
3103 }
3104 
ExecRepeat(argv,obj_ptr,orig_cmd)3105 int ExecRepeat(argv, obj_ptr, orig_cmd)
3106    char **argv, *orig_cmd;
3107    struct ObjRec *obj_ptr;
3108    /* repeat(attr_name,times); */
3109 {
3110    char *attr_name=argv[0], *times_str=argv[1];
3111    int i, times=(-1), rc=TRUE;
3112    struct AttrRec *attr_ptr;
3113    struct ObjRec *attr_owner_obj=NULL;
3114 
3115    UtilRemoveQuotes(attr_name);
3116    UtilRemoveQuotes(times_str);
3117    sprintf(execDummyStr, "%s=", attr_name);
3118    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
3119    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
3120 
3121    if (strcmp(times_str, "infinite") != 0) {
3122       if (!IntExpression(times_str, &times, orig_cmd)) {
3123          return FALSE;
3124       }
3125    }
3126    for (i=0; times < 0 || i < times; i++) {
3127       rc = DoExec(attr_ptr, attr_owner_obj);
3128       if (!rc) break;
3129       if (times < 0) i--;
3130    }
3131    return rc;
3132 }
3133 
ExecHyperJump(argv,obj_ptr,orig_cmd)3134 int ExecHyperJump(argv, obj_ptr, orig_cmd)
3135    char **argv, *orig_cmd;
3136    struct ObjRec *obj_ptr;
3137    /* hyperjump(attr_name); */
3138 {
3139    char *attr_name=argv[0];
3140    struct AttrRec *attr_ptr;
3141 
3142    UtilRemoveQuotes(attr_name);
3143    sprintf(execDummyStr, "%s=", attr_name);
3144    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, NULL);
3145    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
3146 
3147    warpToAttr = attr_ptr;
3148    return TRUE;
3149 }
3150 
3151 /* do not translate -- program constants */
3152 static char *CGICharMap[] = {
3153    "                                ",
3154    "+         *  -. 0123456789      ",
3155    "@ABCDEFGHIJKLMNOPQRSTUVWXYZ    _",
3156    " abcdefghijklmnopqrstuvwxyz     ",
3157    NULL
3158 };
3159 
3160 static
MapCGIChars(buf,buf_sz,orig_str)3161 int MapCGIChars(buf, buf_sz, orig_str)
3162    char *buf, *orig_str;
3163    int buf_sz;
3164 {
3165    int count=0;
3166 
3167    for ( ; *orig_str != '\0'; orig_str++) {
3168       unsigned char orig_code=(unsigned char)(*orig_str);
3169       char code;
3170 
3171       if (orig_code < 0x20) {
3172          code = ' ';
3173       } else if (orig_code < 0x40) {
3174          code = CGICharMap[1][orig_code-0x20];
3175       } else if (orig_code < 0x60) {
3176          code = CGICharMap[2][orig_code-0x40];
3177       } else if (orig_code < 0x80) {
3178          code = CGICharMap[3][orig_code-0x60];
3179       } else {
3180          code = ' ';
3181       }
3182       if (code == ' ') {
3183          if (count+3 >= buf_sz) break;
3184          sprintf(&buf[count], "%%%02X", (int)orig_code);
3185          count += 3;
3186       } else {
3187          if (count+1 >= buf_sz) break;
3188          buf[count++] = code;
3189       }
3190    }
3191    buf[count] = '\0';
3192    return count;
3193 }
3194 
ExecMakeCGIQuery(argv,obj_ptr,orig_cmd)3195 int ExecMakeCGIQuery(argv, obj_ptr, orig_cmd)
3196    char **argv, *orig_cmd;
3197    struct ObjRec *obj_ptr;
3198    /* make_cgi_query(dest_attr_name,url_name,list_attr_name); */
3199 {
3200    char *dest_attr_name=argv[0], *url_name=argv[1], *list_attr_name=argv[2];
3201    struct AttrRec *dest_attr=NULL, *list_attr=NULL;
3202    struct ObjRec *dest_attr_owner_obj=NULL;
3203    MiniLineInfo *pMiniLine=NULL;
3204    char *buf=NULL, *c_ptr, *attr_names_buf=NULL;
3205    int buf_sz=0, buf_len=0, tmp_sz=0, num_attrs=0;
3206    int found_name=FALSE, seen_first_attr=FALSE, null_url=FALSE;
3207 
3208    UtilRemoveQuotes(dest_attr_name);
3209    UtilRemoveQuotes(url_name);
3210    UtilRemoveQuotes(list_attr_name);
3211 
3212    if (strcmp(url_name, "NULL") == 0) {
3213       null_url = TRUE;
3214       *url_name = '\0';
3215    }
3216    buf_sz = strlen(url_name);
3217    buf = (char*)malloc((buf_sz+1)*sizeof(char));
3218    if (buf == NULL) return FailAllocMessage();
3219 
3220    sprintf(buf, "%s", url_name);
3221    buf_len = buf_sz;
3222 
3223    sprintf(execDummyStr, "%s=", dest_attr_name);
3224    dest_attr = FindAttrWithName(obj_ptr, execDummyStr, &dest_attr_owner_obj);
3225    if (dest_attr == NULL) return BadAttr(execDummyStr, orig_cmd);
3226 
3227    sprintf(execDummyStr, "%s=", list_attr_name);
3228    list_attr = FindAttrWithName(obj_ptr, execDummyStr, NULL);
3229    if (list_attr == NULL) return BadAttr(execDummyStr, orig_cmd);
3230 
3231    tmp_sz = 0;
3232 
3233    for (pMiniLine=list_attr->obj->detail.t->minilines.first;
3234          pMiniLine != NULL; pMiniLine=pMiniLine->next) {
3235       int need_to_free_tmp_buf=FALSE;
3236       char *tmp_buf=ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
3237 
3238       tmp_sz += strlen(tmp_buf)+1;
3239       if (need_to_free_tmp_buf) UtilFree(tmp_buf);
3240    }
3241    attr_names_buf = (char*)malloc((tmp_sz+2)*sizeof(char));
3242    if (attr_names_buf == NULL) {
3243       free(buf);
3244       return FailAllocMessage();
3245    }
3246    tmp_sz = 0;
3247    found_name = (!list_attr->nameshown);
3248    for (pMiniLine=list_attr->obj->detail.t->minilines.first;
3249          pMiniLine != NULL; pMiniLine=pMiniLine->next) {
3250       int need_to_free_tmp_buf=FALSE;
3251       char *tmp_buf=ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
3252 
3253       if (found_name) {
3254          strcpy(&attr_names_buf[tmp_sz], tmp_buf);
3255          tmp_sz += strlen(tmp_buf);
3256       } else if ((c_ptr=strchr(tmp_buf, '=')) != NULL) {
3257          found_name = TRUE;
3258          strcpy(&attr_names_buf[tmp_sz], ++c_ptr);
3259          tmp_sz += strlen(c_ptr);
3260       } else {
3261          continue;
3262       }
3263       if (need_to_free_tmp_buf) UtilFree(tmp_buf);
3264 
3265       attr_names_buf[tmp_sz++] = '\n';
3266    }
3267    attr_names_buf[tmp_sz] = '\0';
3268    for (num_attrs=0, c_ptr=strtok(attr_names_buf, " ,\t\n\r"); c_ptr != NULL;
3269          num_attrs++, c_ptr=strtok(NULL, " ,\t\n\r")) {
3270       struct AttrRec *attr_ptr;
3271       int len, buf1_index;
3272       char *buf1=NULL;
3273 
3274       sprintf(execDummyStr, "%s=", c_ptr);
3275       attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, NULL);
3276       if (attr_ptr == NULL) {
3277          free(buf);
3278          free(attr_names_buf);
3279          return BadAttr(execDummyStr, orig_cmd);
3280       }
3281       len = strlen(execDummyStr);
3282       for (pMiniLine=attr_ptr->obj->detail.t->minilines.first;
3283             pMiniLine != NULL; pMiniLine=pMiniLine->next) {
3284          int need_to_free_tmp_buf=FALSE;
3285          char *tmp_buf=NULL;
3286 
3287          if (pMiniLine == attr_ptr->obj->detail.t->minilines.first) {
3288             char *attr_value=NULL;
3289 
3290             tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
3291             attr_value = UtilStrDup(tmp_buf);
3292             if (attr_value == NULL) FailAllocMessage();
3293             ParseAttrStr(tmp_buf, NULL, 0, attr_value, strlen(attr_value)+1);
3294             if (need_to_free_tmp_buf) UtilFree(tmp_buf);
3295             len += strlen(attr_value)+1;
3296             UtilFree(attr_value);
3297          } else {
3298             tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
3299             len += strlen(tmp_buf)+1;
3300             if (need_to_free_tmp_buf) UtilFree(tmp_buf);
3301          }
3302       }
3303       len = len*3;
3304       buf1 = (char*)malloc((len+1)*sizeof(char));
3305       if (buf1 == NULL) {
3306          free(buf);
3307          free(attr_names_buf);
3308          return FailAllocMessage();
3309       }
3310       if (seen_first_attr) {
3311          *buf1 = '&';
3312       } else {
3313          *buf1 = '?';
3314          seen_first_attr = TRUE;
3315       }
3316       buf1_index = 1+MapCGIChars(&buf1[1], len-1, c_ptr);
3317       buf1[buf1_index++] = '=';
3318       for (pMiniLine=attr_ptr->obj->detail.t->minilines.first;
3319             pMiniLine != NULL; pMiniLine=pMiniLine->next) {
3320          int need_to_free_tmp_buf=FALSE;
3321          char *tmp_buf=NULL;
3322 
3323          if (pMiniLine == attr_ptr->obj->detail.t->minilines.first) {
3324             char *attr_value=NULL;
3325 
3326             tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
3327             attr_value = UtilStrDup(tmp_buf);
3328             if (attr_value == NULL) FailAllocMessage();
3329             ParseAttrStr(tmp_buf, NULL, 0, attr_value, strlen(attr_value)+1);
3330             if (need_to_free_tmp_buf) UtilFree(tmp_buf);
3331             buf1_index += MapCGIChars(&buf1[buf1_index], len-buf1_index,
3332                   attr_value);
3333             UtilFree(attr_value);
3334          } else {
3335             tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
3336             buf1_index += MapCGIChars(&buf1[buf1_index], len-buf1_index,
3337                   tmp_buf);
3338             if (need_to_free_tmp_buf) UtilFree(tmp_buf);
3339          }
3340          if (pMiniLine->next != NULL && buf1_index < len-1) {
3341             buf1_index += MapCGIChars(&buf1[buf1_index], len-buf1_index, "\n");
3342          }
3343       }
3344       buf1[buf1_index] = '\0';
3345       if ((buf=(char*)realloc(buf, buf1_index+buf_sz+1)) == NULL) {
3346          free(buf);
3347          free(attr_names_buf);
3348          free(buf1);
3349          return FailAllocMessage();
3350       }
3351       strcpy(&buf[buf_sz], buf1);
3352       buf_sz += buf1_index;
3353       free(buf1);
3354    }
3355    if (null_url && *buf == '?') {
3356       char *psz=buf, *psz1=(&buf[1]);
3357 
3358       while (*psz1 != '\0') {
3359          *psz++ = *psz1++;
3360       }
3361       *psz = '\0';
3362    }
3363    ReplaceAttrFirstValue(dest_attr_owner_obj, dest_attr, buf);
3364    free(buf);
3365    free(attr_names_buf);
3366    return TRUE;
3367 }
3368 
3369 static XComposeStatus c_stat;
3370 
ExecWaitClick(argv,obj_ptr,orig_cmd)3371 int ExecWaitClick(argv, obj_ptr, orig_cmd)
3372    char **argv, *orig_cmd;
3373    struct ObjRec *obj_ptr;
3374    /* wait_click(cursor_name,grab,attr_name); */
3375 {
3376    char *cursor_name=argv[0], *grab_str=argv[1], *attr_name=argv[2], buf[80];
3377    struct AttrRec *attr_ptr;
3378    struct ObjRec *attr_owner_obj=NULL;
3379    Cursor cursor=(Cursor)0;
3380    int grab=FALSE, rc=TRUE, done=FALSE;
3381 
3382    UtilRemoveQuotes(cursor_name);
3383    UtilRemoveQuotes(grab_str);
3384    UtilRemoveQuotes(attr_name);
3385    grab = (strcmp(grab_str, "TRUE") == 0);
3386    if (strcmp(cursor_name, "NULL") != 0) {
3387       cursor = NewFontCursor(cursor_name);
3388       if (cursor == (Cursor)0) {
3389          sprintf(gszMsgBox, TgLoadString(STID_BAD_CURSOR_WHILE_EXEC_CMD),
3390                cursor_name, orig_cmd);
3391          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3392          return FALSE;
3393       }
3394    }
3395    sprintf(execDummyStr, "%s=", attr_name);
3396    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
3397    if (attr_ptr == NULL) {
3398       if (cursor != (Cursor)0) DeleteFontCursor(cursor);
3399       return BadAttr(execDummyStr, orig_cmd);
3400    }
3401    if (cursor != (Cursor)0) {
3402       SetWindowCursor(drawWindow, cursor);
3403       SetWindowCursor(mainWindow, cursor);
3404    }
3405    if (grab) {
3406       XGrabPointer(mainDisplay, rootWindow, False, ButtonPressMask,
3407             GrabModeAsync, GrabModeAsync, None,
3408             cursor==(Cursor)0 ? defaultCursor : cursor, CurrentTime);
3409    }
3410    while (!done) {
3411       XEvent input;
3412 
3413       XNextEvent(mainDisplay, &input);
3414       if (input.type == Expose || input.type == VisibilityNotify) {
3415          ExposeEventHandler(&input, TRUE);
3416       } else if (input.type == KeyPress) {
3417          char s[80];
3418          XKeyEvent *key_ev=(&(input.xkey));
3419          KeySym key_sym;
3420          int has_ch=FALSE;
3421 
3422          has_ch = XLookupString(key_ev, s, sizeof(s), &key_sym, &c_stat);
3423          TranslateKeys(s, &key_sym);
3424          if (CharIsESC(key_ev, s, key_sym, &has_ch)) {
3425             userAbortExec = TRUE;
3426             rc = FALSE;
3427             done = TRUE;
3428          } else {
3429             int button_num=INVALID;
3430 
3431             switch (key_sym) {
3432             case XK_Up:
3433             case XK_KP_Up: button_num = 0; break;
3434 
3435             case XK_Left:
3436             case XK_KP_Left: button_num = 1; break;
3437 
3438             case XK_space:
3439             case XK_KP_Space:
3440             case XK_Tab:
3441             case XK_Return:
3442             case XK_KP_Enter: button_num = 2; break;
3443 
3444             case XK_Right:
3445             case XK_KP_Right: button_num = 3; break;
3446 
3447             case XK_Down:
3448             case XK_KP_Down: button_num = 4; break;
3449 
3450             default: break;
3451             }
3452             if (button_num != INVALID) {
3453                sprintf(buf, "%1d", button_num);
3454                ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
3455                done = TRUE;
3456             }
3457          }
3458       } else if (input.type == ButtonPress) {
3459          int button_num=0;
3460 
3461          if (grab) {
3462             XUngrabPointer(mainDisplay, CurrentTime);
3463          }
3464          switch (input.xbutton.button) {
3465          case Button1: button_num = 1; break;
3466          case Button2: button_num = 2; break;
3467          case Button3: button_num = 3; break;
3468          default: button_num = (input.xbutton.button-Button1)+1; break;
3469          }
3470          sprintf(buf, "%1d", button_num);
3471          ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
3472          done = TRUE;
3473       }
3474    }
3475    if (cursor != (Cursor)0) {
3476       SetDefaultCursor(mainWindow);
3477       ShowCursor();
3478       DeleteFontCursor(cursor);
3479    }
3480    return rc;
3481 }
3482 
ExecSleep(argv,obj_ptr,orig_cmd)3483 int ExecSleep(argv, obj_ptr, orig_cmd)
3484    char **argv, *orig_cmd;
3485    struct ObjRec *obj_ptr;
3486    /* sleep(cursor_name,ms_interval); */
3487 {
3488    char *cursor_name=argv[0], *ms_interval_str=argv[1];
3489    Cursor cursor=(Cursor)0;
3490    int select_width=XConnectionNumber(mainDisplay)+1, rc=TRUE, val;
3491    long ms_start_time, ms_interval, ms_togo;
3492    struct timeval timeout;
3493 #ifdef _NO_GETTIMEOFDAY
3494    struct timeb now;
3495 #else /* ~_NO_GETTIMEOFDAY */
3496    struct timeval now;
3497    struct timezone zone;
3498 #endif /* _NO_GETTIMEOFDAY */
3499    fd_set fdset;
3500 
3501    UtilRemoveQuotes(cursor_name);
3502    UtilRemoveQuotes(ms_interval_str);
3503    if (!IntExpression(ms_interval_str, &val, orig_cmd)) {
3504       return FALSE;
3505    }
3506    ms_interval = (long)val;
3507    if (strcmp(cursor_name, "NULL") != 0) {
3508       cursor = NewFontCursor(cursor_name);
3509       if (cursor == (Cursor)0) {
3510          sprintf(gszMsgBox, TgLoadString(STID_BAD_CURSOR_WHILE_EXEC_CMD),
3511                cursor_name, orig_cmd);
3512          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3513          return FALSE;
3514       }
3515    }
3516    if (cursor != (Cursor)0) {
3517       SetWindowCursor(drawWindow, cursor);
3518       SetWindowCursor(mainWindow, cursor);
3519       XSync(mainDisplay, False);
3520    }
3521 #ifdef _NO_GETTIMEOFDAY
3522    ftime(&now);
3523    ms_start_time = ((long)now.time * 1000) + ((long)now.millitm);
3524 #else /* ~_NO_GETTIMEOFDAY */
3525    gettimeofday(&now, &zone);
3526    ms_start_time = ms_time(&now);
3527 #endif /* _NO_GETTIMEOFDAY */
3528    ms_togo = ms_interval;
3529 
3530    EnterExecTightLoop();
3531 
3532    while (rc && ms_togo > 0) {
3533       int status;
3534       long ms_cur_time;
3535 
3536       FD_ZERO(&fdset);
3537       FD_SET(select_width-1, &fdset);
3538       timeout.tv_sec = (long)(ms_togo/1000);
3539       timeout.tv_usec = 1000 * (ms_togo % 1000);
3540 #ifdef __hpux
3541       status = select(select_width, (int*)&fdset, NULL, NULL, &timeout);
3542 #else /* !__hpux */
3543       status = select(select_width, &fdset, NULL, NULL, &timeout);
3544 #endif /* __hpux */
3545       if (status < 0) {
3546          if (errno == EINTR) {
3547             /* interrupted by a system call, not a problem */
3548             CheckInterrupt(TRUE);
3549          } else {
3550             sprintf(gszMsgBox, TgLoadString(STID_INTERNAL_CMD_SELECT_FAILED),
3551                   orig_cmd);
3552             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3553             rc = FALSE;
3554          }
3555       } else if (status == 0) {
3556          /* good timeout */
3557          CheckInterrupt(TRUE);
3558          break;
3559       } else {
3560          rc = (!CheckExecInterrupt(orig_cmd));
3561          if (!rc) {
3562             userAbortExec = TRUE;
3563          }
3564       }
3565       if (rc) {
3566 #ifdef _NO_GETTIMEOFDAY
3567          ftime(&now);
3568          ms_cur_time = ((long)now.time * 1000) + ((long)now.millitm);
3569 #else /* ~_NO_GETTIMEOFDAY */
3570          gettimeofday(&now, &zone);
3571          ms_cur_time = ms_time(&now);
3572 #endif /* _NO_GETTIMEOFDAY */
3573          ms_togo = ms_start_time+ms_interval-ms_cur_time;
3574       }
3575    }
3576    ExitExecTightLoop();
3577 
3578    if (cursor != (Cursor)0) {
3579       SetDefaultCursor(mainWindow);
3580       ShowCursor();
3581       DeleteFontCursor(cursor);
3582    }
3583    return rc;
3584 }
3585 
ExecBeginAnimate(obj_ptr,orig_cmd)3586 void ExecBeginAnimate(obj_ptr, orig_cmd)
3587    struct ObjRec *obj_ptr;
3588    char *orig_cmd;
3589    /* begin_animate(); */
3590 {
3591    if (!BeginExecAnimate()) {
3592       gnAbortExec = TRUE;
3593    } else {
3594       ShowInterrupt(1);
3595    }
3596 }
3597 
ExecEndAnimate(obj_ptr,orig_cmd)3598 void ExecEndAnimate(obj_ptr, orig_cmd)
3599    struct ObjRec *obj_ptr;
3600    char *orig_cmd;
3601    /* end_animate(); */
3602 {
3603    EndExecAnimate();
3604    while (HideInterrupt() > 0) ;
3605 }
3606 
ExecSetRedraw(argv,obj_ptr,orig_cmd)3607 int ExecSetRedraw(argv, obj_ptr, orig_cmd)
3608    char **argv, *orig_cmd;
3609    struct ObjRec *obj_ptr;
3610    /* set_redraw(true_or_false); */
3611 {
3612    char *redraw_str=argv[0];
3613 
3614    UtilRemoveQuotes(redraw_str);
3615    if (strcmp(redraw_str, "TRUE") == 0) {
3616       execAnimateRedraw = TRUE;
3617    } else if (strcmp(redraw_str, "FALSE") == 0) {
3618       execAnimateRedraw = FALSE;
3619    } else {
3620       return BadArg("true_or_false", orig_cmd);
3621    }
3622    return TRUE;
3623 }
3624 
ExecSetSelObjColor(argv,obj_ptr,orig_cmd)3625 int ExecSetSelObjColor(argv, obj_ptr, orig_cmd)
3626    char **argv, *orig_cmd;
3627    struct ObjRec *obj_ptr;
3628    /* set_selected_obj_color(color_str); */
3629 {
3630    char *color_str=argv[0];
3631    int index, new_alloc;
3632 
3633    UtilRemoveQuotes(color_str);
3634    UtilTrimBlanks(color_str);
3635 
3636    if ((index=QuickFindColorIndex(NULL, color_str, &new_alloc, FALSE)) ==
3637          INVALID) {
3638       sprintf(gszMsgBox, TgLoadString(STID_BAD_COLOR_NAME_WHILE_EXEC_CMD),
3639             color_str, orig_cmd);
3640       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3641       return FALSE;
3642    }
3643    if (obj_ptr != NULL) {
3644       UtilStrCpyN(obj_ptr->color_str, sizeof(obj_ptr->color_str),
3645             colorMenuItems[index]);
3646    }
3647    ChangeAllSelColor(index, FALSE);
3648    return TRUE;
3649 }
3650 
ExecSetSelObjFill(argv,obj_ptr,orig_cmd)3651 int ExecSetSelObjFill(argv, obj_ptr, orig_cmd)
3652    char **argv, *orig_cmd;
3653    struct ObjRec *obj_ptr;
3654    /* set_selected_obj_fill(fill_index); */
3655 {
3656    char *index_str=argv[0];
3657    int index;
3658 
3659    UtilRemoveQuotes(index_str);
3660 
3661    if (!IntExpression(index_str, &index, orig_cmd)) {
3662       return FALSE;
3663    }
3664    if (index < 0 || index >= MAXPATTERNS) {
3665       sprintf(gszMsgBox, TgLoadString(STID_FUNC_ARG_RANGE),
3666             orig_cmd, "fill_index", 0, MAXPATTERNS-1, index);
3667       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3668       return FALSE;
3669    }
3670    ChangeAllSelFill(index, FALSE);
3671    return TRUE;
3672 }
3673 
ExecSetSelObjPen(argv,obj_ptr,orig_cmd)3674 int ExecSetSelObjPen(argv, obj_ptr, orig_cmd)
3675    char **argv, *orig_cmd;
3676    struct ObjRec *obj_ptr;
3677    /* set_selected_obj_pen(pen_index); */
3678 {
3679    char *index_str=argv[0];
3680    int index;
3681 
3682    UtilRemoveQuotes(index_str);
3683 
3684    if (!IntExpression(index_str, &index, orig_cmd)) {
3685       return FALSE;
3686    }
3687    if (index < 0 || index >= MAXPATTERNS) {
3688       sprintf(gszMsgBox, TgLoadString(STID_FUNC_ARG_RANGE),
3689             orig_cmd, "pen_index", 0, MAXPATTERNS-1, index);
3690       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3691       return FALSE;
3692    }
3693    ChangeAllSelPen(index, FALSE);
3694    return TRUE;
3695 }
3696 
ExecSetSelObjLineWidth(argv,obj_ptr,orig_cmd)3697 int ExecSetSelObjLineWidth(argv, obj_ptr, orig_cmd)
3698    char **argv, *orig_cmd;
3699    struct ObjRec *obj_ptr;
3700    /* set_selected_obj_line_width(width,aw,ah); */
3701 {
3702    char *width_str=argv[0], *aw_str=argv[1], *ah_str=argv[2];
3703    int width=0, aw=0, ah=0;
3704 
3705    UtilRemoveQuotes(width_str);
3706    UtilRemoveQuotes(aw_str);
3707    UtilRemoveQuotes(ah_str);
3708    if (!IntExpression(width_str, &width, orig_cmd) ||
3709          !IntExpression(aw_str, &aw, orig_cmd) ||
3710          !IntExpression(ah_str, &ah, orig_cmd)) {
3711       return FALSE;
3712    }
3713    if (width < 0) {
3714       sprintf(gszMsgBox, TgLoadString(STID_WIDTH_RANGE_WHILE_EXEC_CMD),
3715             width_str, orig_cmd);
3716       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3717       return FALSE;
3718    }
3719    if (topSel == NULL) {
3720       int index=GetBestLineWidthIndex(width, aw, ah);
3721 
3722       ChangeAllSelLineWidth(index, FALSE);
3723    } else {
3724       char width_spec[40], aw_spec[40], ah_spec[40];
3725 
3726       sprintf(width_spec, "%1d", width);
3727       sprintf(aw_spec, "%1d", aw);
3728       sprintf(ah_spec, "%1d", ah);
3729       ChangeAllSelRealLineWidth(CHANGE_LINE_ALL, width, aw, ah,
3730             width_spec, aw_spec, ah_spec, FALSE);
3731    }
3732    return TRUE;
3733 }
3734 
ExecSetSelObjSpline(argv,obj_ptr,orig_cmd)3735 int ExecSetSelObjSpline(argv, obj_ptr, orig_cmd)
3736    char **argv, *orig_cmd;
3737    struct ObjRec *obj_ptr;
3738    /* set_selected_obj_spline(spline_type); */
3739 {
3740    char *spline_spec=argv[0];
3741    int index;
3742 
3743    UtilRemoveQuotes(spline_spec);
3744    UtilTrimBlanks(spline_spec);
3745 
3746    if (strcmp(spline_spec,"straight") == 0) {
3747       index = LT_STRAIGHT;
3748    } else if (strcmp(spline_spec,"spline") == 0) {
3749       index = LT_SPLINE;
3750    } else if (strcmp(spline_spec,"interpolated") == 0) {
3751       index = LT_INTSPLINE;
3752    } else if (strcmp(spline_spec,"structured") == 0) {
3753       index = LT_STRUCT_SPLINE;
3754    } else {
3755       sprintf(gszMsgBox, TgLoadString(STID_SPLINE_TYPE_WHILE_EXEC_CMD),
3756             spline_spec, orig_cmd);
3757       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3758       return FALSE;
3759    }
3760    ChangeAllSelLineType(index, FALSE);
3761    return TRUE;
3762 }
3763 
ExecSetSelObjArrow(argv,obj_ptr,orig_cmd)3764 int ExecSetSelObjArrow(argv, obj_ptr, orig_cmd)
3765    char **argv, *orig_cmd;
3766    struct ObjRec *obj_ptr;
3767    /* set_selected_obj_arrow(arrow_type); */
3768 {
3769    char *arrow_spec=argv[0];
3770    int index;
3771 
3772    UtilRemoveQuotes(arrow_spec);
3773    UtilTrimBlanks(arrow_spec);
3774 
3775    if (strcmp(arrow_spec,"none") == 0) {
3776       index = LS_PLAIN;
3777    } else if (strcmp(arrow_spec,"right") == 0) {
3778       index = LS_RIGHT;
3779    } else if (strcmp(arrow_spec,"left") == 0) {
3780       index = LS_LEFT;
3781    } else if (strcmp(arrow_spec,"double") == 0) {
3782       index = LS_DOUBLE;
3783    } else {
3784       sprintf(gszMsgBox, TgLoadString(STID_ARROW_STYLE_WHILE_EXEC_CMD),
3785             arrow_spec, orig_cmd);
3786       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3787       return FALSE;
3788    }
3789    ChangeAllSelLineStyle(index, FALSE);
3790    return TRUE;
3791 }
3792 
ExecSetSelObjDash(argv,obj_ptr,orig_cmd)3793 int ExecSetSelObjDash(argv, obj_ptr, orig_cmd)
3794    char **argv, *orig_cmd;
3795    struct ObjRec *obj_ptr;
3796    /* set_selected_obj_dash(dash_index); */
3797 {
3798    char *index_str=argv[0];
3799    int index;
3800 
3801    UtilRemoveQuotes(index_str);
3802 
3803    if (!IntExpression(index_str, &index, orig_cmd)) {
3804       return FALSE;
3805    }
3806    if (index < 0 || index >= MAXDASHES) {
3807       sprintf(gszMsgBox, TgLoadString(STID_FUNC_ARG_RANGE),
3808             orig_cmd, "dash_index", 0, MAXDASHES-1, index);
3809       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3810       return FALSE;
3811    }
3812    ChangeAllSelLineDash(index, FALSE);
3813    return TRUE;
3814 }
3815 
ExecSetSelObjTransPat(argv,obj_ptr,orig_cmd)3816 int ExecSetSelObjTransPat(argv, obj_ptr, orig_cmd)
3817    char **argv, *orig_cmd;
3818    struct ObjRec *obj_ptr;
3819    /* set_selected_obj_trans_pat(trans_pat); */
3820 {
3821    char *trans_pat_str=argv[0];
3822    int trans_pat=0;
3823 
3824    UtilRemoveQuotes(trans_pat_str);
3825 
3826    if (!IntExpression(trans_pat_str, &trans_pat, orig_cmd)) {
3827       return FALSE;
3828    }
3829    if (trans_pat != 0) {
3830       trans_pat = TRANSPAT_MODE;
3831    } else {
3832       trans_pat = NO_TRANSPAT_MODE;
3833    }
3834    ChangeAllSelTransPat(trans_pat, FALSE);
3835    return TRUE;
3836 }
3837 
ExecSetSelObjRCBRadius(argv,obj_ptr,orig_cmd)3838 int ExecSetSelObjRCBRadius(argv, obj_ptr, orig_cmd)
3839    char **argv, *orig_cmd;
3840    struct ObjRec *obj_ptr;
3841    /* set_selected_obj_rcb_radius(rcb_radius); */
3842 {
3843    char *rcb_radius_str=argv[0];
3844    int rcb_radius=0;
3845 
3846    UtilRemoveQuotes(rcb_radius_str);
3847 
3848    if (!IntExpression(rcb_radius_str, &rcb_radius, orig_cmd)) {
3849       return FALSE;
3850    }
3851    if (rcb_radius < 4) {
3852       sprintf(gszMsgBox, TgLoadString(STID_RCB_RAD_RANGE_WHILE_EXEC_CMD),
3853             rcb_radius_str, orig_cmd);
3854       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3855       return FALSE;
3856    }
3857    ChangeAllSelRCBRadius(rcb_radius);
3858    return TRUE;
3859 }
3860 
ExecSetSelTextVSpace(argv,obj_ptr,orig_cmd)3861 int ExecSetSelTextVSpace(argv, obj_ptr, orig_cmd)
3862    char **argv, *orig_cmd;
3863    struct ObjRec *obj_ptr;
3864    /* set_selected_text_vspace(v_space); */
3865 {
3866    char *v_space_str=argv[0];
3867    int v_space=0;
3868 
3869    UtilRemoveQuotes(v_space_str);
3870 
3871    if (!IntExpression(v_space_str, &v_space, orig_cmd)) {
3872       return FALSE;
3873    }
3874    ChangeVSpace(v_space);
3875    return TRUE;
3876 }
3877 
ExecSetSelTextJust(argv,obj_ptr,orig_cmd)3878 int ExecSetSelTextJust(argv, obj_ptr, orig_cmd)
3879    char **argv, *orig_cmd;
3880    struct ObjRec *obj_ptr;
3881    /* set_selected_text_just(just_type); */
3882 {
3883    char *just_spec=argv[0];
3884    int just=JUST_L;
3885 
3886    UtilRemoveQuotes(just_spec);
3887    UtilTrimBlanks(just_spec);
3888 
3889    if (strcmp(just_spec,"left") == 0) {
3890       just = JUST_L;
3891    } else if (strcmp(just_spec,"center") == 0) {
3892       just = JUST_C;
3893    } else if (strcmp(just_spec,"right") == 0) {
3894       just = JUST_R;
3895    } else {
3896       sprintf(gszMsgBox, TgLoadString(STID_BAD_TEXT_JUST_WHILE_EXEC_CMD),
3897             just_spec, orig_cmd);
3898       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3899       return FALSE;
3900    }
3901    ChangeFontJust(just);
3902    return TRUE;
3903 }
3904 
ExecSetSelTextFont(argv,obj_ptr,orig_cmd)3905 int ExecSetSelTextFont(argv, obj_ptr, orig_cmd)
3906    char **argv, *orig_cmd;
3907    struct ObjRec *obj_ptr;
3908    /* set_selected_text_font(font_spec); */
3909 {
3910    char *font_spec=argv[0];
3911    int font=0, style=0;
3912 
3913    UtilRemoveQuotes(font_spec);
3914    UtilTrimBlanks(font_spec);
3915 
3916    if (!GetFontAndStyle(font_spec, &font, &style, TRUE)) {
3917       if (PRTGIF && !cmdLineOpenDisplay) {
3918          for (font=0; font < MAXFONTS; font++) {
3919             if (strcmp(font_spec, defFontMenuStr[font]) == 0) {
3920                ChangeFont(font, TRUE);
3921                return TRUE;
3922             }
3923          }
3924       } else {
3925          for (font=0; font < numFonts; font++) {
3926             if (strcmp(font_spec, fontMenuStr[font]) == 0) {
3927                ChangeFont(font, TRUE);
3928                return TRUE;
3929             }
3930          }
3931       }
3932       sprintf(gszMsgBox, TgLoadString(STID_BAD_FONT_NAME_WHILE_EXEC_CMD),
3933             font_spec, orig_cmd);
3934       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3935       return FALSE;
3936    }
3937    ChangeFont(font, TRUE);
3938    ChangeFontStyle(style);
3939 
3940    return TRUE;
3941 }
3942 
ExecSetSelTextStyle(argv,obj_ptr,orig_cmd)3943 int ExecSetSelTextStyle(argv, obj_ptr, orig_cmd)
3944    char **argv, *orig_cmd;
3945    struct ObjRec *obj_ptr;
3946    /* set_selected_text_style(textstyle); */
3947 {
3948    char *style_spec=argv[0];
3949    int style=0;
3950 
3951    UtilRemoveQuotes(style_spec);
3952    UtilTrimBlanks(style_spec);
3953 
3954    if (strcmp(style_spec, "r") == 0) {
3955       style = STYLE_NR;
3956    } else if (strcmp(style_spec, "b") == 0) {
3957       style = STYLE_BR;
3958    } else if (strcmp(style_spec, "i") == 0) {
3959       style = STYLE_NI;
3960    } else if (strcmp(style_spec, "bi") == 0) {
3961       style = STYLE_BI;
3962    } else {
3963       sprintf(gszMsgBox, TgLoadString(STID_BAD_STYLE_NAME_WHILE_EXEC_CMD),
3964             style_spec, orig_cmd);
3965       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
3966       return FALSE;
3967    }
3968    ChangeFontStyle(style);
3969 
3970    return TRUE;
3971 }
3972 
ExecSetSelTextSize(argv,obj_ptr,orig_cmd)3973 int ExecSetSelTextSize(argv, obj_ptr, orig_cmd)
3974    char **argv, *orig_cmd;
3975    struct ObjRec *obj_ptr;
3976    /* set_selected_text_size(size); */
3977 {
3978    char *size_spec=argv[0], *psz=NULL;
3979    int size=INVALID, sz_unit=INVALID, use_point_size=FALSE;
3980    int size_index=0, min_diff=0, min_size_index=0;
3981 
3982    UtilRemoveQuotes(size_spec);
3983 
3984    if ((psz=strstr(size_spec, "point")) != NULL ||
3985          (psz=strstr(size_spec, "pt")) != NULL) {
3986       *psz = '\0';
3987       use_point_size = TRUE;
3988    }
3989    if (!IntExpression(size_spec, &size, orig_cmd)) {
3990       return FALSE;
3991    }
3992    if (use_point_size) {
3993       sz_unit = PointSizeToSzUnit(size);
3994    } else {
3995       sz_unit = FontSizeToSzUnit(size);
3996    }
3997    if (topSel == NULL) {
3998       min_diff = abs(fontSzUnits[0] - sz_unit);
3999       for (size_index=1; size_index < numFontSizes; size_index++) {
4000          int diff=abs(fontSzUnits[size_index]-sz_unit);
4001 
4002          if (diff < min_diff) {
4003             min_diff = diff;
4004             min_size_index = size_index;
4005          }
4006       }
4007       ChangeFontSize(min_size_index);
4008    } else {
4009       ChangeAllSelRealSzUnit(sz_unit, FALSE);
4010    }
4011    return TRUE;
4012 }
4013 
ExecSetSelTextUnderline(argv,obj_ptr,orig_cmd)4014 int ExecSetSelTextUnderline(argv, obj_ptr, orig_cmd)
4015    char **argv, *orig_cmd;
4016    struct ObjRec *obj_ptr;
4017    /* set_selected_text_underline(underline); */
4018 {
4019    char *underline_on_str=argv[0];
4020    int underline_on=0;
4021 
4022    UtilRemoveQuotes(underline_on_str);
4023 
4024    if (!IntExpression(underline_on_str, &underline_on, orig_cmd)) {
4025       return FALSE;
4026    }
4027    ChangeFontUnderline(underline_on != 0);
4028    return TRUE;
4029 }
4030 
ExecSetSelTextOverline(argv,obj_ptr,orig_cmd)4031 int ExecSetSelTextOverline(argv, obj_ptr, orig_cmd)
4032    char **argv, *orig_cmd;
4033    struct ObjRec *obj_ptr;
4034    /* set_selected_text_overline(overline); */
4035 {
4036    char *overline_on_str=argv[0];
4037    int overline_on=0;
4038 
4039    UtilRemoveQuotes(overline_on_str);
4040 
4041    if (!IntExpression(overline_on_str, &overline_on, orig_cmd)) {
4042       return FALSE;
4043    }
4044    ChangeFontOverline(overline_on != 0);
4045    return TRUE;
4046 }
4047 
ExecInc(argv,obj_ptr,orig_cmd)4048 int ExecInc(argv, obj_ptr, orig_cmd)
4049    char **argv, *orig_cmd;
4050    struct ObjRec *obj_ptr;
4051    /* inc(attr_name,expr); */
4052 {
4053    char *attr_name=argv[0], *expr=argv[1], buf[40];
4054    int orig_ival, val;
4055    struct AttrRec *attr_ptr;
4056    struct ObjRec *attr_owner_obj=NULL;
4057 
4058    UtilRemoveQuotes(attr_name);
4059    UtilRemoveQuotes(expr);
4060    sprintf(execDummyStr, "%s=", attr_name);
4061    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4062    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4063 
4064    orig_ival = atoi(attr_ptr->attr_value.s);
4065    if (!IntExpression(expr, &val, orig_cmd)) return FALSE;
4066    if (val != 0) {
4067       sprintf(buf, "%1d", orig_ival+val);
4068       ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
4069    }
4070    return TRUE;
4071 }
4072 
ExecDec(argv,obj_ptr,orig_cmd)4073 int ExecDec(argv, obj_ptr, orig_cmd)
4074    char **argv, *orig_cmd;
4075    struct ObjRec *obj_ptr;
4076    /* dec(attr_name,expr); */
4077 {
4078    char *attr_name=argv[0], *expr=argv[1], buf[40];
4079    int orig_ival, val;
4080    struct AttrRec *attr_ptr;
4081    struct ObjRec *attr_owner_obj=NULL;
4082 
4083    UtilRemoveQuotes(attr_name);
4084    UtilRemoveQuotes(expr);
4085    sprintf(execDummyStr, "%s=", attr_name);
4086    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4087    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4088 
4089    orig_ival = atoi(attr_ptr->attr_value.s);
4090    if (!IntExpression(expr, &val, orig_cmd)) return FALSE;
4091    if (val != 0) {
4092       sprintf(buf, "%1d", orig_ival-val);
4093       ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
4094    }
4095    return TRUE;
4096 }
4097 
4098 #define SHUFFLE_TO_TOP (TRUE)
4099 #define SHUFFLE_TO_BOT (FALSE)
4100 
4101 static
DoShuffleObjToTopOrBottom(argv,obj_ptr,orig_cmd,to_top)4102 int DoShuffleObjToTopOrBottom(argv, obj_ptr, orig_cmd, to_top)
4103    char **argv, *orig_cmd;
4104    struct ObjRec *obj_ptr;
4105    int to_top;
4106    /* shuffle_obj_to_top(obj_name); */
4107    /* shuffle_obj_to_bottom(obj_name); */
4108 {
4109    char *obj_name=argv[0];
4110    struct ObjRec *owner_obj=NULL, *top_owner=NULL, *named_obj;
4111    int ltx, lty, rbx, rby;
4112    struct SelRec *saved_top_sel=topSel, *saved_bot_sel=botSel;
4113 
4114    UtilRemoveQuotes(obj_name);
4115    named_obj = FindObjWithName(botObj, obj_ptr, obj_name, FALSE,
4116          FALSE, &owner_obj, &top_owner);
4117    if (named_obj == NULL) return BadObjName(obj_name, orig_cmd);
4118 
4119    if (owner_obj == NULL) {
4120       if (to_top) {
4121          if (named_obj == topObj) return TRUE;
4122       } else {
4123          if (named_obj == botObj) return TRUE;
4124       }
4125       ltx = named_obj->bbox.ltx; lty = named_obj->bbox.lty;
4126       rbx = named_obj->bbox.rbx; rby = named_obj->bbox.rby;
4127    } else {
4128       if (to_top) {
4129          if (named_obj == owner_obj->detail.r->first) return TRUE;
4130       } else {
4131          if (named_obj == owner_obj->detail.r->last) return TRUE;
4132       }
4133       ltx = top_owner->bbox.ltx; lty = top_owner->bbox.lty;
4134       rbx = top_owner->bbox.rbx; rby = top_owner->bbox.rby;
4135    }
4136    topSel = botSel = (struct SelRec *)malloc(sizeof(struct SelRec));
4137    if (topSel == NULL) {
4138       FailAllocMessage();
4139       topSel = saved_top_sel;
4140       botSel = saved_bot_sel;
4141       return FALSE;
4142    }
4143    topSel->next = topSel->prev = NULL;
4144    topSel->obj = (owner_obj==NULL ? named_obj : top_owner);
4145    UpdSelBBox();
4146 
4147    if (owner_obj == NULL) {
4148       if (to_top) {
4149          MoveSelToTop();
4150       } else {
4151          MoveSelToBot();
4152       }
4153    } else {
4154       PrepareToRecord (CMD_REPLACE, topSel, botSel, numObjSelected);
4155 
4156       if (to_top) {
4157          named_obj->prev->next = named_obj->next;
4158          if (named_obj == owner_obj->detail.r->last) {
4159             owner_obj->detail.r->last = named_obj->prev;
4160          } else {
4161             named_obj->next->prev = named_obj->prev;
4162          }
4163          named_obj->prev = NULL;
4164          named_obj->next = owner_obj->detail.r->first;
4165          owner_obj->detail.r->first->prev = named_obj;
4166          owner_obj->detail.r->first = named_obj;
4167       } else {
4168          named_obj->next->prev = named_obj->prev;
4169          if (named_obj == owner_obj->detail.r->first) {
4170             owner_obj->detail.r->first = named_obj->next;
4171          } else {
4172             named_obj->prev->next = named_obj->next;
4173          }
4174          named_obj->next = NULL;
4175          named_obj->prev = owner_obj->detail.r->last;
4176          owner_obj->detail.r->last->next = named_obj;
4177          owner_obj->detail.r->last = named_obj;
4178       }
4179       RecordCmd (CMD_REPLACE, NULL, topSel, botSel, numObjSelected);
4180    }
4181    free(topSel);
4182    topSel = saved_top_sel;
4183    botSel = saved_bot_sel;
4184    UpdSelBBox();
4185 
4186    RedrawAnArea(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
4187          rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1));
4188    SetFileModified(TRUE);
4189 
4190    return TRUE;
4191 }
4192 
ExecShuffleObjToTop(argv,obj_ptr,orig_cmd)4193 int ExecShuffleObjToTop(argv, obj_ptr, orig_cmd)
4194    char **argv, *orig_cmd;
4195    struct ObjRec *obj_ptr;
4196    /* shuffle_obj_to_top(obj_name); */
4197 {
4198    return DoShuffleObjToTopOrBottom(argv, obj_ptr, orig_cmd, SHUFFLE_TO_TOP);
4199 }
4200 
ExecShuffleObjToBot(argv,obj_ptr,orig_cmd)4201 int ExecShuffleObjToBot(argv, obj_ptr, orig_cmd)
4202    char **argv, *orig_cmd;
4203    struct ObjRec *obj_ptr;
4204    /* shuffle_obj_to_bottom(obj_name); */
4205 {
4206    return DoShuffleObjToTopOrBottom(argv, obj_ptr, orig_cmd, SHUFFLE_TO_BOT);
4207 }
4208 
ExecDisableUndo(obj_ptr,orig_cmd)4209 void ExecDisableUndo(obj_ptr, orig_cmd)
4210    struct ObjRec *obj_ptr;
4211    char *orig_cmd;
4212    /* disable_undo(); */
4213 {
4214    if (historyDepth != 0) {
4215       sprintf(gszMsgBox, TgLoadString(STID_UNDO_BUF_FLUSHED_BY_CMD), orig_cmd);
4216       Msg(gszMsgBox);
4217    }
4218    DisableUndo();
4219 }
4220 
ExecEnableUndo(obj_ptr,orig_cmd)4221 void ExecEnableUndo(obj_ptr, orig_cmd)
4222    struct ObjRec *obj_ptr;
4223    char *orig_cmd;
4224    /* enable_undo(); */
4225 {
4226    EnableUndo();
4227 }
4228 
ExecGetDrawingArea(argv,obj_ptr,orig_cmd)4229 int ExecGetDrawingArea(argv, obj_ptr, orig_cmd)
4230    char **argv, *orig_cmd;
4231    struct ObjRec *obj_ptr;
4232    /* get_drawing_area(ltx_attr,lty_attr,rbx_attr,rby_attr); */
4233 {
4234    char *ltx_attr_name=argv[0], *lty_attr_name=argv[1];
4235    char *rbx_attr_name=argv[2], *rby_attr_name=argv[3], buf[40];
4236    struct AttrRec *ltx_attr_ptr, *lty_attr_ptr, *rbx_attr_ptr, *rby_attr_ptr;
4237    struct ObjRec *ltx_attr_owner_obj=NULL, *lty_attr_owner_obj=NULL;
4238    struct ObjRec *rbx_attr_owner_obj=NULL, *rby_attr_owner_obj=NULL;
4239 
4240    UtilRemoveQuotes(ltx_attr_name); UtilRemoveQuotes(lty_attr_name);
4241    UtilRemoveQuotes(rbx_attr_name); UtilRemoveQuotes(rby_attr_name);
4242    sprintf(execDummyStr, "%s=", ltx_attr_name);
4243    ltx_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &ltx_attr_owner_obj);
4244    if (ltx_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4245    sprintf(execDummyStr, "%s=", lty_attr_name);
4246    lty_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &lty_attr_owner_obj);
4247    if (lty_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4248    sprintf(execDummyStr, "%s=", rbx_attr_name);
4249    rbx_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &rbx_attr_owner_obj);
4250    if (rbx_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4251    sprintf(execDummyStr, "%s=", rby_attr_name);
4252    rby_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &rby_attr_owner_obj);
4253    if (rby_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4254 
4255    sprintf(buf, "%1d", drawOrigX);
4256    ReplaceAttrFirstValue(ltx_attr_owner_obj, ltx_attr_ptr, buf);
4257    sprintf(buf, "%1d", drawOrigY);
4258    ReplaceAttrFirstValue(lty_attr_owner_obj, lty_attr_ptr, buf);
4259    sprintf(buf, "%1d", drawOrigX+drawWinW);
4260    ReplaceAttrFirstValue(rbx_attr_owner_obj, rbx_attr_ptr, buf);
4261    sprintf(buf, "%1d", drawOrigY+drawWinH);
4262    ReplaceAttrFirstValue(rby_attr_owner_obj, rby_attr_ptr, buf);
4263 
4264    SetFileModified(TRUE);
4265    return TRUE;
4266 }
4267 
ExecGetSelObjBBox(argv,obj_ptr,orig_cmd)4268 int ExecGetSelObjBBox(argv, obj_ptr, orig_cmd)
4269    char **argv, *orig_cmd;
4270    struct ObjRec *obj_ptr;
4271    /* get_selected_obj_bbox(ltx_attr,lty_attr,rbx_attr,rby_attr); */
4272 {
4273    char *ltx_attr_name=argv[0], *lty_attr_name=argv[1];
4274    char *rbx_attr_name=argv[2], *rby_attr_name=argv[3], buf[40];
4275    struct AttrRec *ltx_attr_ptr, *lty_attr_ptr, *rbx_attr_ptr, *rby_attr_ptr;
4276    struct ObjRec *ltx_attr_owner_obj=NULL, *lty_attr_owner_obj=NULL;
4277    struct ObjRec *rbx_attr_owner_obj=NULL, *rby_attr_owner_obj=NULL;
4278 
4279    UtilRemoveQuotes(ltx_attr_name); UtilRemoveQuotes(lty_attr_name);
4280    UtilRemoveQuotes(rbx_attr_name); UtilRemoveQuotes(rby_attr_name);
4281    if (topSel == NULL) return BadSelectedObj(orig_cmd);
4282 
4283    sprintf(execDummyStr, "%s=", ltx_attr_name);
4284    ltx_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &ltx_attr_owner_obj);
4285    if (ltx_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4286    sprintf(execDummyStr, "%s=", lty_attr_name);
4287    lty_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &lty_attr_owner_obj);
4288    if (lty_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4289    sprintf(execDummyStr, "%s=", rbx_attr_name);
4290    rbx_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &rbx_attr_owner_obj);
4291    if (rbx_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4292    sprintf(execDummyStr, "%s=", rby_attr_name);
4293    rby_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &rby_attr_owner_obj);
4294    if (rby_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4295 
4296    sprintf(buf, "%1d", selObjLtX);
4297    ReplaceAttrFirstValue(ltx_attr_owner_obj, ltx_attr_ptr, buf);
4298    sprintf(buf, "%1d", selObjLtY);
4299    ReplaceAttrFirstValue(lty_attr_owner_obj, lty_attr_ptr, buf);
4300    sprintf(buf, "%1d", selObjRbX);
4301    ReplaceAttrFirstValue(rbx_attr_owner_obj, rbx_attr_ptr, buf);
4302    sprintf(buf, "%1d", selObjRbY);
4303    ReplaceAttrFirstValue(rby_attr_owner_obj, rby_attr_ptr, buf);
4304 
4305    SetFileModified(TRUE);
4306    return TRUE;
4307 }
4308 
ExecGetNamedObjBBox(argv,obj_ptr,orig_cmd)4309 int ExecGetNamedObjBBox(argv, obj_ptr, orig_cmd)
4310    char **argv, *orig_cmd;
4311    struct ObjRec *obj_ptr;
4312    /* get_named_obj_bbox(obj_name,ltx_attr,lty_attr,rbx_attr,rby_attr); */
4313 {
4314    char *obj_name=argv[0];
4315    char *ltx_attr_name=argv[1], *lty_attr_name=argv[2];
4316    char *rbx_attr_name=argv[3], *rby_attr_name=argv[4], buf[40];
4317    struct ObjRec *top_owner=NULL, *named_obj=NULL;
4318    struct AttrRec *ltx_attr_ptr, *lty_attr_ptr, *rbx_attr_ptr, *rby_attr_ptr;
4319    struct ObjRec *ltx_attr_owner_obj=NULL, *lty_attr_owner_obj=NULL;
4320    struct ObjRec *rbx_attr_owner_obj=NULL, *rby_attr_owner_obj=NULL;
4321 
4322    UtilRemoveQuotes(obj_name);
4323    UtilTrimBlanks(obj_name);
4324    UtilRemoveQuotes(ltx_attr_name); UtilRemoveQuotes(lty_attr_name);
4325    UtilRemoveQuotes(rbx_attr_name); UtilRemoveQuotes(rby_attr_name);
4326 
4327    named_obj = FindObjWithName(botObj, obj_ptr, obj_name, FALSE,
4328          FALSE, NULL, &top_owner);
4329    if (named_obj == NULL) {
4330       return BadObjName(obj_name, orig_cmd);
4331    }
4332    sprintf(execDummyStr, "%s=", ltx_attr_name);
4333    ltx_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &ltx_attr_owner_obj);
4334    if (ltx_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4335    sprintf(execDummyStr, "%s=", lty_attr_name);
4336    lty_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &lty_attr_owner_obj);
4337    if (lty_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4338    sprintf(execDummyStr, "%s=", rbx_attr_name);
4339    rbx_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &rbx_attr_owner_obj);
4340    if (rbx_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4341    sprintf(execDummyStr, "%s=", rby_attr_name);
4342    rby_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &rby_attr_owner_obj);
4343    if (rby_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4344 
4345    sprintf(buf, "%1d", named_obj->obbox.ltx);
4346    ReplaceAttrFirstValue(ltx_attr_owner_obj, ltx_attr_ptr, buf);
4347    sprintf(buf, "%1d", named_obj->obbox.lty);
4348    ReplaceAttrFirstValue(lty_attr_owner_obj, lty_attr_ptr, buf);
4349    sprintf(buf, "%1d", named_obj->obbox.rbx);
4350    ReplaceAttrFirstValue(rbx_attr_owner_obj, rbx_attr_ptr, buf);
4351    sprintf(buf, "%1d", named_obj->obbox.rby);
4352    ReplaceAttrFirstValue(rby_attr_owner_obj, rby_attr_ptr, buf);
4353 
4354    SetFileModified(TRUE);
4355    return TRUE;
4356 }
4357 
ExecMoveSelObjAbs(argv,obj_ptr,orig_cmd)4358 int ExecMoveSelObjAbs(argv, obj_ptr, orig_cmd)
4359    char **argv, *orig_cmd;
4360    struct ObjRec *obj_ptr;
4361    /* move_selected_obj_absolute(ltx,lty); */
4362 {
4363    char *ltx_str=argv[0], *lty_str=argv[1];
4364    int ltx, lty;
4365 
4366    UtilRemoveQuotes(ltx_str);
4367    UtilRemoveQuotes(lty_str);
4368    if (topSel == NULL) return BadSelectedObj(orig_cmd);
4369 
4370    if (!IntExpression(ltx_str, &ltx, orig_cmd) ||
4371          !IntExpression(lty_str, &lty, orig_cmd)) {
4372       return FALSE;
4373    }
4374    if (ltx != selObjLtX || lty != selObjLtY) {
4375       MoveAllSel(ltx-selObjLtX, lty-selObjLtY);
4376       UpdSelBBox();
4377       SetFileModified(TRUE);
4378    }
4379    return TRUE;
4380 }
4381 
ExecAssign(argv,obj_ptr,orig_cmd)4382 int ExecAssign(argv, obj_ptr, orig_cmd)
4383    char **argv, *orig_cmd;
4384    struct ObjRec *obj_ptr;
4385    /* assign(attr_name,expr); */
4386 {
4387    char *attr_name=argv[0], *expr=argv[1], buf[40];
4388    struct AttrRec *attr_ptr;
4389    struct ObjRec *attr_owner_obj=NULL;
4390    struct VRec v;
4391 
4392    UtilRemoveQuotes(attr_name);
4393    UtilRemoveQuotes(expr);
4394    UtilTrimBlanks(attr_name);
4395    sprintf(execDummyStr, "%s=", attr_name);
4396    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4397    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4398 
4399    if (!EvalExpr(expr, &v)) return FALSE;
4400 
4401    switch (v.vtype) {
4402    case INT_VAL:
4403       sprintf(buf, "%1d", v.val.i);
4404       ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
4405       break;
4406    case DBL_VAL:
4407       sprintf(buf, "%.12f", (float)(v.val.d));
4408       ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
4409       break;
4410    case NULL_VAL:
4411    case STR_VAL:
4412       sprintf(gszMsgBox, TgLoadString(STID_BAD_EVAL_NUM_EXP_EXEC_CMD),
4413             expr, orig_cmd);
4414       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4415       if (v.vtype == STR_VAL && v.val.s != NULL) free(v.val.s);
4416       return FALSE;
4417    }
4418    return TRUE;
4419 }
4420 
ExecStrCpy(argv,obj_ptr,orig_cmd)4421 int ExecStrCpy(argv, obj_ptr, orig_cmd)
4422    char **argv, *orig_cmd;
4423    struct ObjRec *obj_ptr;
4424    /* strcpy(attr_name,str); */
4425 {
4426    char *attr_name=argv[0], *the_str=argv[1];
4427    struct AttrRec *attr_ptr;
4428    struct ObjRec *attr_owner_obj=NULL;
4429 
4430    UtilRemoveQuotes(attr_name);
4431    UtilRemoveQuotes(the_str);
4432    UtilTrimBlanks(attr_name);
4433    sprintf(execDummyStr, "%s=", attr_name);
4434    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4435    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4436 
4437    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, the_str);
4438    return TRUE;
4439 }
4440 
ExecStrCat(argv,obj_ptr,orig_cmd)4441 int ExecStrCat(argv, obj_ptr, orig_cmd)
4442    char **argv, *orig_cmd;
4443    struct ObjRec *obj_ptr;
4444    /* strcat(attr_name,str); */
4445 {
4446    char *attr_name=argv[0], *the_str=argv[1], *new_str=NULL;
4447    int len=0;
4448    struct AttrRec *attr_ptr;
4449    struct ObjRec *attr_owner_obj=NULL;
4450 
4451    UtilRemoveQuotes(attr_name);
4452    UtilRemoveQuotes(the_str);
4453    UtilTrimBlanks(attr_name);
4454    sprintf(execDummyStr, "%s=", attr_name);
4455    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4456    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4457 
4458    len = strlen(attr_ptr->attr_value.s)+strlen(the_str);
4459    new_str = (char*)malloc(len+1);
4460    if (new_str == NULL) FailAllocMessage();
4461    sprintf(new_str, "%s%s", attr_ptr->attr_value.s, the_str);
4462    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, new_str);
4463    free(new_str);
4464 
4465    return TRUE;
4466 }
4467 
ExecCopyStrToCutBuffer(argv,obj_ptr,orig_cmd)4468 int ExecCopyStrToCutBuffer(argv, obj_ptr, orig_cmd)
4469    char **argv, *orig_cmd;
4470    struct ObjRec *obj_ptr;
4471    /* copy_string_to_cut_buffer(str); */
4472 {
4473    char *the_str=argv[0];
4474    int len=0;
4475 
4476    UtilRemoveQuotes(the_str);
4477 
4478    len = strlen(the_str);
4479    if (!WriteBufToCutBuffer(the_str, strlen(the_str), TRUE, FALSE, NULL)) {
4480       sprintf(gszMsgBox, TgLoadString(STID_WRITE_CUT_BUF_WHILE_EXEC_CMD),
4481             orig_cmd);
4482       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4483       return FALSE;
4484    }
4485    return TRUE;
4486 }
4487 
ExecWhile(argv,raw_argv,obj_ptr,orig_cmd)4488 int ExecWhile(argv, raw_argv, obj_ptr, orig_cmd)
4489    char **argv, **raw_argv, *orig_cmd;
4490    struct ObjRec *obj_ptr;
4491    /* while(expr,attr_to_exec); */
4492 {
4493    char *raw_expr=raw_argv[0], *attr_name=argv[1];
4494    struct AttrRec *attr_ptr;
4495    struct ObjRec *attr_owner_obj=NULL;
4496    int rc=TRUE;
4497 
4498    UtilRemoveQuotes(attr_name);
4499    sprintf(execDummyStr, "%s=", attr_name);
4500    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4501    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4502 
4503    while (rc) {
4504       int val;
4505       char *expr=convert_str(raw_expr, obj_ptr, TRUE);
4506 
4507       if (expr == NULL) {
4508          BadAttr(raw_expr, orig_cmd);
4509          return FALSE;
4510       } else if (!IntExpression(expr, &val, orig_cmd)) {
4511          free(expr);
4512          return FALSE;
4513       }
4514       free(expr);
4515       if (val == 0) break;
4516       if (!DoExec(attr_ptr, attr_owner_obj)) return FALSE;
4517       rc = (!CheckExecInterrupt(orig_cmd));
4518       if (!rc) {
4519          userAbortExec = TRUE;
4520       }
4521    }
4522    return rc;
4523 }
4524 
ExecIf(argv,obj_ptr,orig_cmd)4525 int ExecIf(argv, obj_ptr, orig_cmd)
4526    char **argv, *orig_cmd;
4527    struct ObjRec *obj_ptr;
4528    /* if(expr,then_attr_to_exec,else_attr_to_exec); */
4529 {
4530    char *expr=argv[0], *then_attr_name=argv[1], *else_attr_name=argv[2];
4531    int val=0;
4532 
4533    UtilRemoveQuotes(then_attr_name);
4534    UtilRemoveQuotes(else_attr_name);
4535 
4536    if (!IntExpression(expr, &val, orig_cmd)) return FALSE;
4537    if (val) {
4538       struct AttrRec *then_attr_ptr=NULL;
4539       struct ObjRec *then_attr_owner_obj=NULL;
4540 
4541       if (strcmp(then_attr_name, "NULL") != 0) {
4542          sprintf(execDummyStr, "%s=", then_attr_name);
4543          then_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr,
4544                &then_attr_owner_obj);
4545          if (then_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4546       }
4547       if (then_attr_ptr != NULL &&
4548             !DoExec(then_attr_ptr, then_attr_owner_obj)) {
4549          return FALSE;
4550       }
4551    } else {
4552       struct AttrRec *else_attr_ptr=NULL;
4553       struct ObjRec *else_attr_owner_obj=NULL;
4554 
4555       if (strcmp(else_attr_name, "NULL") != 0) {
4556          sprintf(execDummyStr, "%s=", else_attr_name);
4557          else_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr,
4558                &else_attr_owner_obj);
4559          if (else_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4560       }
4561       if (else_attr_ptr != NULL &&
4562             !DoExec(else_attr_ptr, else_attr_owner_obj)) {
4563          return FALSE;
4564       }
4565    }
4566    return TRUE;
4567 }
4568 
ExecGetCurrentFile(argv,obj_ptr,orig_cmd)4569 int ExecGetCurrentFile(argv, obj_ptr, orig_cmd)
4570    char **argv, *orig_cmd;
4571    struct ObjRec *obj_ptr;
4572    /* get_current_file(attr_name); */
4573 {
4574    char *attr_name=argv[0], *full_name=NULL;
4575    struct AttrRec *attr_ptr;
4576    struct ObjRec *attr_owner_obj=NULL;
4577 
4578    UtilRemoveQuotes(attr_name);
4579    UtilTrimBlanks(attr_name);
4580    sprintf(execDummyStr, "%s=", attr_name);
4581    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4582    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4583 
4584    if (curFileDefined) {
4585       if (*curSymDir == '\0') {
4586          sprintf(gszMsgBox, "%s%c%s", curDir, DIR_SEP, curFileName);
4587       } else {
4588          sprintf(gszMsgBox, "%s%c%s", curSymDir, DIR_SEP, curFileName);
4589       }
4590       full_name = UtilStrDup(gszMsgBox);
4591    }
4592    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr,
4593          (full_name==NULL ? "" : full_name));
4594    if (full_name != NULL) free(full_name);
4595    return TRUE;
4596 
4597 }
4598 
ExecGetCurrentExportFile(argv,obj_ptr,orig_cmd)4599 int ExecGetCurrentExportFile(argv, obj_ptr, orig_cmd)
4600    char **argv, *orig_cmd;
4601    struct ObjRec *obj_ptr;
4602    /* get_current_export_file(attr_name); */
4603 {
4604    char *attr_name=argv[0], *full_name=NULL;
4605    struct AttrRec *attr_ptr;
4606    struct ObjRec *attr_owner_obj=NULL;
4607 
4608    UtilRemoveQuotes(attr_name);
4609    UtilTrimBlanks(attr_name);
4610    sprintf(execDummyStr, "%s=", attr_name);
4611    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4612    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4613 
4614    if (curFileDefined) {
4615       char *psz=NULL;
4616 
4617       sprintf(gszMsgBox, "%s%c%s", curDir, DIR_SEP, curFileName);
4618       if ((psz=UtilStrRChr(gszMsgBox, '.')) == NULL) {
4619          sprintf(gszMsgBox, TgLoadString(STID_CANT_FIND_DOT_WHILE_EXEC_CMD),
4620                curDir, DIR_SEP, curFileName, orig_cmd);
4621          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
4622          return FALSE;
4623       }
4624       strcpy(++psz, GetExportExt(whereToPrint));
4625       full_name = UtilStrDup(gszMsgBox);
4626       if (full_name == NULL) FailAllocMessage();
4627    }
4628 
4629    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr,
4630          (full_name==NULL ? "" : full_name));
4631    if (full_name != NULL) free(full_name);
4632    return TRUE;
4633 }
4634 
ExecGetCurrentDir(argv,obj_ptr,orig_cmd)4635 int ExecGetCurrentDir(argv, obj_ptr, orig_cmd)
4636    char **argv, *orig_cmd;
4637    struct ObjRec *obj_ptr;
4638    /* get_current_dir(attr_name); */
4639 {
4640    char *attr_name=argv[0];
4641    struct AttrRec *attr_ptr;
4642    struct ObjRec *attr_owner_obj=NULL;
4643 
4644    UtilRemoveQuotes(attr_name);
4645    UtilTrimBlanks(attr_name);
4646    sprintf(execDummyStr, "%s=", attr_name);
4647    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4648    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4649 
4650    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, curDir);
4651    return TRUE;
4652 
4653 }
4654 
ExecGetEnv(argv,obj_ptr,orig_cmd)4655 int ExecGetEnv(argv, obj_ptr, orig_cmd)
4656    char **argv, *orig_cmd;
4657    struct ObjRec *obj_ptr;
4658    /* getenv(attr_name,env_var_name); */
4659 {
4660    char *attr_name=argv[0], *env_var_name=argv[1], *c_ptr, *env_var_value=NULL;
4661    struct AttrRec *attr_ptr;
4662    struct ObjRec *attr_owner_obj=NULL;
4663 
4664    UtilRemoveQuotes(attr_name);
4665    UtilRemoveQuotes(env_var_name);
4666    sprintf(execDummyStr, "%s=", attr_name);
4667    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4668    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4669 
4670    if ((c_ptr=getenv(env_var_name)) != NULL) {
4671       env_var_value = UtilStrDup(c_ptr);
4672    }
4673    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr,
4674          (env_var_value==NULL ? "" : env_var_value));
4675    if (env_var_value != NULL) free(env_var_value);
4676    return TRUE;
4677 }
4678 
ExecStrLen(argv,obj_ptr,orig_cmd)4679 int ExecStrLen(argv, obj_ptr, orig_cmd)
4680    char **argv, *orig_cmd;
4681    struct ObjRec *obj_ptr;
4682    /* strlen(attr_name,str); */
4683 {
4684    char *attr_name=argv[0], *the_str=argv[1], val_str[40];
4685    int len;
4686    struct AttrRec *attr_ptr;
4687    struct ObjRec *attr_owner_obj=NULL;
4688 
4689    UtilRemoveQuotes(attr_name);
4690    UtilRemoveQuotes(the_str);
4691    len = strlen(the_str);
4692    sprintf(execDummyStr, "%s=", attr_name);
4693    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4694    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4695 
4696    sprintf(val_str, "%1d", len);
4697    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, val_str);
4698    return TRUE;
4699 }
4700 
ExecSubStr(argv,obj_ptr,orig_cmd)4701 int ExecSubStr(argv, obj_ptr, orig_cmd)
4702    char **argv, *orig_cmd;
4703    struct ObjRec *obj_ptr;
4704    /* substr(attr_name,str,start_index,length); */
4705 {
4706    char *attr_name=argv[0], *the_str=argv[1];
4707    char *start_index_str=argv[2], *length_str=argv[3], *buf;
4708    int len, start_index=(-1), length=(-1);
4709    struct AttrRec *attr_ptr;
4710    struct ObjRec *attr_owner_obj=NULL;
4711 
4712    UtilRemoveQuotes(attr_name);
4713    UtilRemoveQuotes(the_str);
4714    UtilRemoveQuotes(start_index_str);
4715    len = strlen(the_str);
4716    sprintf(execDummyStr, "%s=", attr_name);
4717    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4718    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4719 
4720    if (!IntExpression(start_index_str, &start_index, orig_cmd) ||
4721          !IntExpression(length_str, &length, orig_cmd)) {
4722       return FALSE;
4723    }
4724    if (start_index < 0) start_index = 0;
4725    if (length+start_index > len) {
4726       length = len-start_index;
4727    }
4728    if (length < 0) length = 0;
4729    if ((buf=UtilStrDup(the_str)) == NULL) {
4730       FailAllocMessage();
4731    } else {
4732       strncpy(buf, &the_str[start_index], length);
4733       buf[length] = '\0';
4734    }
4735    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, (buf==NULL ? "" : buf));
4736    if (buf != NULL) free(buf);
4737    return TRUE;
4738 }
4739 
ExecStrStr(argv,obj_ptr,orig_cmd)4740 int ExecStrStr(argv, obj_ptr, orig_cmd)
4741    char **argv, *orig_cmd;
4742    struct ObjRec *obj_ptr;
4743    /* strstr(attr_name,str,substr); */
4744 {
4745    char *attr_name=argv[0], *the_str=argv[1], *sub_str=argv[2], *c_ptr;
4746    struct AttrRec *attr_ptr;
4747    struct ObjRec *attr_owner_obj=NULL;
4748 
4749    UtilRemoveQuotes(attr_name);
4750    UtilRemoveQuotes(the_str);
4751    UtilRemoveQuotes(sub_str);
4752    sprintf(execDummyStr, "%s=", attr_name);
4753    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4754    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4755 
4756    c_ptr = strstr(the_str, sub_str);
4757    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, (c_ptr==NULL ? "" : c_ptr));
4758    return TRUE;
4759 }
4760 
ExecStrRStr(argv,obj_ptr,orig_cmd)4761 int ExecStrRStr(argv, obj_ptr, orig_cmd)
4762    char **argv, *orig_cmd;
4763    struct ObjRec *obj_ptr;
4764    /* strrstr(attr_name,str,substr); */
4765 {
4766    char *attr_name=argv[0], *the_str=argv[1], *sub_str=argv[2];
4767    char *c_ptr, *last_match=NULL;
4768    struct AttrRec *attr_ptr;
4769    struct ObjRec *attr_owner_obj=NULL;
4770 
4771    UtilRemoveQuotes(attr_name);
4772    UtilRemoveQuotes(the_str);
4773    UtilRemoveQuotes(sub_str);
4774    sprintf(execDummyStr, "%s=", attr_name);
4775    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4776    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4777 
4778    for (c_ptr=strstr(the_str, sub_str); c_ptr != NULL;
4779          c_ptr=strstr(&last_match[1], sub_str)) {
4780       last_match = c_ptr;
4781    }
4782    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr,
4783          (last_match==NULL ? "" : last_match));
4784    return TRUE;
4785 }
4786 
ExecUnMakeSelObjIconic(obj_ptr,orig_cmd)4787 void ExecUnMakeSelObjIconic(obj_ptr, orig_cmd)
4788    struct ObjRec *obj_ptr;
4789    char *orig_cmd;
4790    /* unmake_selected_obj_iconic(); */
4791 {
4792    struct SelRec *sel_ptr;
4793    int modified=FALSE;
4794 
4795    if (topSel == NULL) {
4796       BadSelectedObj(orig_cmd);
4797       gnAbortExec = TRUE;
4798       return;
4799    }
4800    StartCompositeCmd();
4801    for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
4802       struct ObjRec *obj_ptr=sel_ptr->obj;
4803 
4804       if (obj_ptr->type == OBJ_ICON || obj_ptr->type == OBJ_PIN) {
4805          struct AttrRec *attr_ptr;
4806 
4807          modified = TRUE;
4808          PrepareToReplaceAnObj(obj_ptr);
4809          obj_ptr->type = OBJ_GROUP;
4810          attr_ptr = obj_ptr->fattr;
4811          for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next) {
4812             attr_ptr->inherited = FALSE;
4813          }
4814          AdjObjBBox(obj_ptr);
4815          RecordReplaceAnObj(obj_ptr);
4816       }
4817    }
4818    EndCompositeCmd();
4819    if (modified) {
4820       SetFileModified(TRUE);
4821    }
4822 }
4823 
ExecHyperJumpThenExec(argv,obj_ptr,orig_cmd)4824 int ExecHyperJumpThenExec(argv, obj_ptr, orig_cmd)
4825    char **argv, *orig_cmd;
4826    struct ObjRec *obj_ptr;
4827    /* hyperjump_then_exec(attr_name,attr_name_to_exec); */
4828 {
4829    char *attr_name=argv[0], *attr_name_to_exec=argv[1];
4830    struct AttrRec *attr_ptr;
4831 
4832    UtilRemoveQuotes(attr_name);
4833    UtilRemoveQuotes(attr_name_to_exec);
4834    sprintf(execDummyStr, "%s=", attr_name);
4835    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, NULL);
4836    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4837 
4838    warpToAttr = attr_ptr;
4839    if (cmdToExecAfterHyperJump != NULL) free(cmdToExecAfterHyperJump);
4840    sprintf(execDummyStr, "%s=", attr_name_to_exec);
4841    cmdToExecAfterHyperJump = UtilStrDup(execDummyStr);
4842 
4843    return TRUE;
4844 }
4845 
4846 #define SHOW_ATTR 0
4847 #define HIDE_ATTR 1
4848 #define SHOW_ATTR_NAME 2
4849 #define HIDE_ATTR_NAME 3
4850 #define SHOW_VALUE 4
4851 #define HIDE_VALUE 5
4852 
4853 static
ReplaceAttrShown(obj_ptr,attr_ptr,show_type)4854 void ReplaceAttrShown(obj_ptr, attr_ptr, show_type)
4855    struct ObjRec *obj_ptr;
4856    struct AttrRec *attr_ptr;
4857    int show_type;
4858    /* obj_ptr better be a top-level object */
4859 {
4860    int ltx, lty, rbx, rby, needs_redraw=FALSE;
4861 
4862    ltx = obj_ptr->bbox.ltx; lty = obj_ptr->bbox.lty;
4863    rbx = obj_ptr->bbox.rbx; rby = obj_ptr->bbox.rby;
4864    PrepareToReplaceAnObj(obj_ptr);
4865    switch (show_type) {
4866    case SHOW_ATTR:
4867    case SHOW_VALUE:
4868       attr_ptr->shown = TRUE;
4869       needs_redraw = TRUE;
4870       break;
4871    case HIDE_ATTR:
4872    case HIDE_VALUE:
4873       attr_ptr->shown = FALSE;
4874       needs_redraw = TRUE;
4875       break;
4876    case SHOW_ATTR_NAME:
4877       attr_ptr->nameshown = TRUE;
4878       if (attr_ptr->shown) needs_redraw = TRUE;
4879       UpdAttr(attr_ptr);
4880       break;
4881    case HIDE_ATTR_NAME:
4882       attr_ptr->nameshown = FALSE;
4883       if (attr_ptr->shown) needs_redraw = TRUE;
4884       UpdAttr(attr_ptr);
4885       break;
4886    }
4887    attr_ptr->obj->detail.t->cached_zoom = 0;
4888    if (attr_ptr->obj->detail.t->cached_bitmap != None) {
4889       XFreePixmap(mainDisplay, attr_ptr->obj->detail.t->cached_bitmap);
4890       attr_ptr->obj->detail.t->cached_bitmap = None;
4891    }
4892    if (attr_ptr->shown) {
4893       AdjObjCache(obj_ptr);
4894       AdjObjBBox(obj_ptr);
4895    }
4896    RecordReplaceAnObj(obj_ptr);
4897    if (needs_redraw) {
4898       RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
4899             rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
4900             obj_ptr->bbox.ltx-GRID_ABS_SIZE(1),
4901             obj_ptr->bbox.lty-GRID_ABS_SIZE(1),
4902             obj_ptr->bbox.rbx+GRID_ABS_SIZE(1),
4903             obj_ptr->bbox.rby+GRID_ABS_SIZE(1));
4904    }
4905    SetFileModified(TRUE);
4906 }
4907 
4908 static
ExecShowHideAttr(argv,obj_ptr,orig_cmd,show_type)4909 int ExecShowHideAttr(argv, obj_ptr, orig_cmd, show_type)
4910    char **argv, *orig_cmd;
4911    struct ObjRec *obj_ptr;
4912    int show_type;
4913    /* show_attr(attr_name); */
4914    /* hide_attr(attr_name); */
4915    /* show_attr_name(attr_name); */
4916    /* hide_attr_name(attr_name); */
4917 {
4918    char *attr_name=argv[0];
4919    struct AttrRec *attr_ptr;
4920    struct ObjRec *attr_owner_obj=NULL;
4921 
4922    UtilRemoveQuotes(attr_name);
4923    sprintf(execDummyStr, "%s=", attr_name);
4924    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4925    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4926    if (attr_owner_obj == tgifObj) {
4927       return FileAttrNotAllowed(execDummyStr, orig_cmd);
4928    }
4929    switch (show_type) {
4930    case SHOW_ATTR:
4931       if (attr_ptr->shown) return TRUE;
4932       break;
4933    case HIDE_ATTR:
4934       if (!attr_ptr->shown) return TRUE;
4935       break;
4936    case SHOW_ATTR_NAME:
4937       if (*attr_ptr->attr_name.s == '\0' || attr_ptr->nameshown) return TRUE;
4938       break;
4939    case HIDE_ATTR_NAME:
4940       if (*attr_ptr->attr_name.s == '\0' || !attr_ptr->nameshown) return TRUE;
4941       break;
4942    }
4943    ReplaceAttrShown(attr_owner_obj, attr_ptr, show_type);
4944 
4945    return TRUE;
4946 }
4947 
ExecShowAttr(argv,obj_ptr,orig_cmd)4948 int ExecShowAttr(argv, obj_ptr, orig_cmd)
4949    char **argv, *orig_cmd;
4950    struct ObjRec *obj_ptr;
4951    /* show_attr(attr_name); */
4952 {
4953    return ExecShowHideAttr(argv, obj_ptr, orig_cmd, SHOW_ATTR);
4954 }
4955 
ExecHideAttr(argv,obj_ptr,orig_cmd)4956 int ExecHideAttr(argv, obj_ptr, orig_cmd)
4957    char **argv, *orig_cmd;
4958    struct ObjRec *obj_ptr;
4959    /* hide_attr(attr_name); */
4960 {
4961    return ExecShowHideAttr(argv, obj_ptr, orig_cmd, HIDE_ATTR);
4962 }
4963 
ExecShowAttrName(argv,obj_ptr,orig_cmd)4964 int ExecShowAttrName(argv, obj_ptr, orig_cmd)
4965    char **argv, *orig_cmd;
4966    struct ObjRec *obj_ptr;
4967    /* show_attr_name(attr_name); */
4968 {
4969    return ExecShowHideAttr(argv, obj_ptr, orig_cmd, SHOW_ATTR_NAME);
4970 }
4971 
ExecHideAttrName(argv,obj_ptr,orig_cmd)4972 int ExecHideAttrName(argv, obj_ptr, orig_cmd)
4973    char **argv, *orig_cmd;
4974    struct ObjRec *obj_ptr;
4975    /* hide_attr_name(attr_name); */
4976 {
4977    return ExecShowHideAttr(argv, obj_ptr, orig_cmd, HIDE_ATTR_NAME);
4978 }
4979 
4980 static
ExecShowHideValue(argv,obj_ptr,orig_cmd,show_type)4981 int ExecShowHideValue(argv, obj_ptr, orig_cmd, show_type)
4982    char **argv, *orig_cmd;
4983    struct ObjRec *obj_ptr;
4984    int show_type;
4985    /* show_value(attr_value); */
4986    /* hide_value(attr_value); */
4987 {
4988    char *attr_value=argv[0];
4989    struct AttrRec *attr_ptr;
4990    struct ObjRec *attr_owner_obj=NULL;
4991 
4992    UtilRemoveQuotes(attr_value);
4993    sprintf(execDummyStr, "%s", attr_value);
4994    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
4995    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
4996    if (attr_owner_obj == tgifObj) {
4997       return FileAttrNotAllowed(execDummyStr, orig_cmd);
4998    }
4999    switch (show_type) {
5000    case SHOW_VALUE:
5001       if (attr_ptr->shown) return TRUE;
5002       break;
5003    case HIDE_VALUE:
5004       if (!attr_ptr->shown) return TRUE;
5005       break;
5006    }
5007    ReplaceAttrShown(attr_owner_obj, attr_ptr, show_type);
5008 
5009    return TRUE;
5010 }
5011 
ExecShowValue(argv,obj_ptr,orig_cmd)5012 int ExecShowValue(argv, obj_ptr, orig_cmd)
5013    char **argv, *orig_cmd;
5014    struct ObjRec *obj_ptr;
5015    /* show_value(attr_value); */
5016 {
5017    return ExecShowHideValue(argv, obj_ptr, orig_cmd, SHOW_VALUE);
5018 }
5019 
ExecHideValue(argv,obj_ptr,orig_cmd)5020 int ExecHideValue(argv, obj_ptr, orig_cmd)
5021    char **argv, *orig_cmd;
5022    struct ObjRec *obj_ptr;
5023    /* hide_value(attr_value); */
5024 {
5025    return ExecShowHideValue(argv, obj_ptr, orig_cmd, HIDE_VALUE);
5026 }
5027 
ExecGetAttrBBox(argv,obj_ptr,orig_cmd)5028 int ExecGetAttrBBox(argv, obj_ptr, orig_cmd)
5029    char **argv, *orig_cmd;
5030    struct ObjRec *obj_ptr;
5031    /* get_attr_bbox(ltx_attr,lty_attr,rbx_attr,rby_attr,attr_name); */
5032 {
5033    char *ltx_attr_name=argv[0], *lty_attr_name=argv[1];
5034    char *rbx_attr_name=argv[2], *rby_attr_name=argv[3], buf[40];
5035    char *attr_name=argv[4];
5036    struct AttrRec *ltx_attr_ptr, *lty_attr_ptr, *rbx_attr_ptr, *rby_attr_ptr;
5037    struct AttrRec *attr_ptr;
5038    struct ObjRec *ltx_attr_owner_obj=NULL, *lty_attr_owner_obj=NULL;
5039    struct ObjRec *rbx_attr_owner_obj=NULL, *rby_attr_owner_obj=NULL;
5040    struct ObjRec *attr_owner_obj=NULL;
5041 
5042    UtilRemoveQuotes(ltx_attr_name); UtilRemoveQuotes(lty_attr_name);
5043    UtilRemoveQuotes(rbx_attr_name); UtilRemoveQuotes(rby_attr_name);
5044    UtilRemoveQuotes(attr_name);
5045    sprintf(execDummyStr, "%s=", attr_name);
5046    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
5047    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
5048    if (attr_owner_obj == tgifObj) {
5049       return FileAttrNotAllowed(execDummyStr, orig_cmd);
5050    }
5051    sprintf(execDummyStr, "%s=", ltx_attr_name);
5052    ltx_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &ltx_attr_owner_obj);
5053    if (ltx_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
5054    sprintf(execDummyStr, "%s=", lty_attr_name);
5055    lty_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &lty_attr_owner_obj);
5056    if (lty_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
5057    sprintf(execDummyStr, "%s=", rbx_attr_name);
5058    rbx_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &rbx_attr_owner_obj);
5059    if (rbx_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
5060    sprintf(execDummyStr, "%s=", rby_attr_name);
5061    rby_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &rby_attr_owner_obj);
5062    if (rby_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
5063 
5064    sprintf(buf, "%1d", attr_ptr->obj->obbox.ltx);
5065    ReplaceAttrFirstValue(ltx_attr_owner_obj, ltx_attr_ptr, buf);
5066    sprintf(buf, "%1d", attr_ptr->obj->obbox.lty);
5067    ReplaceAttrFirstValue(lty_attr_owner_obj, lty_attr_ptr, buf);
5068    sprintf(buf, "%1d", attr_ptr->obj->obbox.rbx);
5069    ReplaceAttrFirstValue(rbx_attr_owner_obj, rbx_attr_ptr, buf);
5070    sprintf(buf, "%1d", attr_ptr->obj->obbox.rby);
5071    ReplaceAttrFirstValue(rby_attr_owner_obj, rby_attr_ptr, buf);
5072 
5073    SetFileModified(TRUE);
5074    return TRUE;
5075 }
5076 
ExecSizeSelObjAbs(argv,obj_ptr,orig_cmd)5077 int ExecSizeSelObjAbs(argv, obj_ptr, orig_cmd)
5078    char **argv, *orig_cmd;
5079    struct ObjRec *obj_ptr;
5080    /* size_selected_obj_absolute(abs_w,abs_h); */
5081 {
5082    char *abs_w_str=argv[0], *abs_h_str=argv[1];
5083    int abs_w, abs_h;
5084 
5085    UtilRemoveQuotes(abs_w_str);
5086    UtilRemoveQuotes(abs_h_str);
5087    if (topSel == NULL) return BadSelectedObj(orig_cmd);
5088 
5089    if (!IntExpression(abs_w_str, &abs_w, orig_cmd) ||
5090          !IntExpression(abs_h_str, &abs_h, orig_cmd)) {
5091       return FALSE;
5092    }
5093    if (abs_w < 0 || abs_h < 0) {
5094       if (abs_w < 0) {
5095          sprintf(gszMsgBox, TgLoadString(STID_BAD_WIDTH_WHILE_EXEC_CMD),
5096                abs_w_str, orig_cmd);
5097       } else {
5098          sprintf(gszMsgBox, TgLoadString(STID_BAD_HEIGHT_WHILE_EXEC_CMD),
5099                abs_h_str, orig_cmd);
5100       }
5101       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5102       return FALSE;
5103    }
5104    if (abs_w != selObjRbX-selObjLtX || abs_h != selObjRbY-selObjLtY) {
5105       SizeAllSelObj(abs_w, abs_h);
5106    }
5107    return TRUE;
5108 }
5109 
ExecSizeNamedObjAbs(argv,obj_ptr,orig_cmd)5110 int ExecSizeNamedObjAbs(argv, obj_ptr, orig_cmd)
5111    char **argv, *orig_cmd;
5112    struct ObjRec *obj_ptr;
5113    /* size_named_obj_absolute(obj_name,abs_w,abs_h); */
5114 {
5115    char *obj_name=argv[0], *abs_w_str=argv[1], *abs_h_str=argv[2];
5116    int abs_w=0, abs_h=0;
5117    struct ObjRec *top_owner=NULL, *named_obj=NULL;
5118 
5119    UtilRemoveQuotes(obj_name);
5120    UtilTrimBlanks(obj_name);
5121    UtilRemoveQuotes(abs_w_str);
5122    UtilRemoveQuotes(abs_h_str);
5123 
5124    named_obj = FindObjWithName(botObj, obj_ptr, obj_name, FALSE,
5125          FALSE, NULL, &top_owner);
5126    if (named_obj == NULL) {
5127       return BadObjName(obj_name, orig_cmd);
5128    }
5129    if (!IntExpression(abs_w_str, &abs_w, orig_cmd) ||
5130          !IntExpression(abs_h_str, &abs_h, orig_cmd)) {
5131       return FALSE;
5132    }
5133    if (abs_w < 0 || abs_h < 0) {
5134       if (abs_w < 0) {
5135          sprintf(gszMsgBox, TgLoadString(STID_BAD_WIDTH_WHILE_EXEC_CMD),
5136                abs_w_str, orig_cmd);
5137       } else {
5138          sprintf(gszMsgBox, TgLoadString(STID_BAD_HEIGHT_WHILE_EXEC_CMD),
5139                abs_h_str, orig_cmd);
5140       }
5141       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5142       return FALSE;
5143    }
5144    if (abs_w != named_obj->obbox.rbx-named_obj->obbox.ltx ||
5145          abs_h != named_obj->obbox.lty-named_obj->obbox.rby) {
5146       /* SizeAnObj() can only be called from within an internal command */
5147       SizeAnObj(named_obj, top_owner, abs_w, abs_h);
5148    }
5149    return TRUE;
5150 }
5151 
ExecMessageBox(argv,obj_ptr,orig_cmd)5152 int ExecMessageBox(argv, obj_ptr, orig_cmd)
5153    char **argv, *orig_cmd;
5154    struct ObjRec *obj_ptr;
5155    /* message_box(attr_name,msg,title,style); */
5156 {
5157    char *attr_name=argv[0], *msg=argv[1], *title=argv[2], *style_str=argv[3];
5158    char buf[MAXSTRING];
5159    struct AttrRec *attr_ptr=NULL;
5160    struct ObjRec *attr_owner_obj=NULL;
5161    int style=INFO_MB;
5162 
5163    UtilRemoveQuotes(attr_name);
5164    UtilRemoveQuotes(msg);
5165    UtilRemoveQuotes(title);
5166    UtilRemoveQuotes(style_str);
5167    if (strcmp(attr_name, "NULL") != 0) {
5168       sprintf(execDummyStr, "%s=", attr_name);
5169       attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
5170       if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
5171    }
5172    if (strcmp(title, "NULL") == 0) {
5173       title = TOOL_NAME;
5174    }
5175    if (strcmp(style_str, "NULL") == 0) {
5176       style = INFO_MB;
5177    } else if (strcmp(style_str, "info") == 0) {
5178       style = INFO_MB;
5179    } else if (strcmp(style_str, "ync") == 0) {
5180       style = YNC_MB;
5181    } else if (strcmp(style_str, "yn") == 0) {
5182       style = YN_MB;
5183    } else if (strcmp(style_str, "stop") == 0) {
5184       style = STOP_MB;
5185    } else {
5186       sprintf(gszMsgBox, TgLoadString(STID_BAD_STYLE_WHILE_EXEC_CMD),
5187             style_str, orig_cmd);
5188       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5189       return FALSE;
5190    }
5191    /* do not translate -- program constants */
5192    switch (MsgBox(msg, title, style)) {
5193    case MB_ID_FAILED: strcpy(buf, "FAILED"); break;
5194    case MB_ID_OK: strcpy(buf, "OK"); break;
5195    case MB_ID_CANCEL: strcpy(buf, "CANCEL"); break;
5196    case MB_ID_YES: strcpy(buf, "YES"); break;
5197    case MB_ID_NO: strcpy(buf, "NO"); break;
5198    case MB_ID_EXTRA: strcpy(buf, "EXTRA"); break;
5199    default: strcpy(buf, "(unknown)"); break;
5200    }
5201    if (attr_ptr != NULL) {
5202       ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
5203    }
5204    return TRUE;
5205 }
5206 
ExecGetUserInput(argv,obj_ptr,orig_cmd)5207 int ExecGetUserInput(argv, obj_ptr, orig_cmd)
5208    char **argv, *orig_cmd;
5209    struct ObjRec *obj_ptr;
5210    /* get_user_input(attr_name,msg1,msg2); */
5211 {
5212    char *attr_name=argv[0], *msg1=argv[1], *msg2=argv[2];
5213    char buf[MAXPATHLENGTH+1];
5214    struct AttrRec *attr_ptr;
5215    struct ObjRec *attr_owner_obj=NULL;
5216    int rc=INVALID;
5217 
5218    UtilRemoveQuotes(attr_name);
5219    UtilRemoveQuotes(msg1);
5220    UtilRemoveQuotes(msg2);
5221    sprintf(execDummyStr, "%s=", attr_name);
5222    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
5223    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
5224 
5225    *buf = '\0';
5226    if (strcmp(msg2, "USE_CURRENT_DIR") == 0) {
5227       if (curDirIsLocal) {
5228          sprintf(gszMsgBox, TgLoadString(STID_WORKING_DIRECTORY_IS), curDir);
5229       } else {
5230          sprintf(gszMsgBox, TgLoadString(STID_WORKING_DIRECTORY_IS),
5231                curLocalDir);
5232       }
5233       rc = Dialog(msg1, gszMsgBox, buf);
5234    } else if (strcmp(msg2, "NULL") == 0) {
5235       rc = Dialog(msg1, NULL, buf);
5236    } else {
5237       rc = Dialog(msg1, msg2, buf);
5238    }
5239    if (rc == INVALID) *buf = '\0';
5240    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
5241    return TRUE;
5242 }
5243 
ExecAddAttrToSelObj(argv,obj_ptr,orig_cmd)5244 int ExecAddAttrToSelObj(argv, obj_ptr, orig_cmd)
5245    char **argv, *orig_cmd;
5246    struct ObjRec *obj_ptr;
5247    /* add_attr_to_selected_obj(attr_name,attr_value,abs_x,abs_y); */
5248 {
5249    char *attr_name=argv[0], *attr_value=argv[1];
5250    char *abs_x_str=argv[2], *abs_y_str=argv[3];
5251    struct AttrRec *attr_ptr=NULL;
5252    struct ObjRec *selected_obj=NULL;
5253    int abs_x=0, abs_y=0, ignore_x=FALSE, ignore_y=FALSE;
5254 
5255    UtilRemoveQuotes(attr_name);
5256    UtilRemoveQuotes(attr_value);
5257    UtilRemoveQuotes(abs_x_str);
5258    UtilRemoveQuotes(abs_y_str);
5259    if (attr_name[0] == '!' && attr_name[1] == '.') {
5260       struct ObjRec *attr_owner_obj=NULL;
5261 
5262       sprintf(execDummyStr, "%s=", attr_name);
5263       attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
5264       if (attr_ptr == NULL) {
5265          AddObj(NULL, topObj, tgifObj);
5266          AddNewSelObj(topObj);
5267 
5268          PrepareToReplaceAnObj(tgifObj);
5269          attr_ptr = AddAttrByNameAndValue(tgifObj, &execDummyStr[2],
5270                attr_value);
5271          recordCmdIncludeTgifObj = TRUE;
5272          RecordReplaceAnObj(tgifObj);
5273          recordCmdIncludeTgifObj = FALSE;
5274 
5275          UnlinkObj(topObj);
5276          FreeTopSel();
5277          SetFileModified(TRUE);
5278       } else if (attr_owner_obj != tgifObj) {
5279          sprintf(gszMsgBox, TgLoadString(STID_BAD_ATTR_NAME_WHILE_EXEC_CMD),
5280                attr_name, orig_cmd);
5281          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5282          return FALSE;
5283       } else {
5284          ReplaceAttrFirstValue(tgifObj, attr_ptr, attr_value);
5285       }
5286       return TRUE;
5287    } else if (topSel == NULL) {
5288       return BadSelectedObj(orig_cmd);
5289    } else if (topSel != botSel) {
5290       sprintf(gszMsgBox, TgLoadString(STID_TOO_MANY_OBJ_WHILE_EXEC_CMD),
5291             orig_cmd);
5292       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5293       return FALSE;
5294    } else if (strchr(attr_name, '.') != NULL) {
5295       sprintf(gszMsgBox, TgLoadString(STID_BAD_ATTR_NAME_WHILE_EXEC_CMD),
5296             attr_name, orig_cmd);
5297       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5298       return FALSE;
5299    }
5300    if (strcmp(abs_x_str, "NULL") == 0) {
5301       ignore_x = TRUE;
5302    } else if (!IntExpression(abs_x_str, &abs_x, orig_cmd)) {
5303       return FALSE;
5304    }
5305    if (strcmp(abs_y_str, "NULL") == 0) {
5306       ignore_y = TRUE;
5307    } else if (!IntExpression(abs_y_str, &abs_y, orig_cmd)) {
5308       return FALSE;
5309    }
5310    selected_obj = topSel->obj;
5311 
5312    if (strcmp(attr_name, "NULL") == 0 || *attr_name == '\0') {
5313       *execDummyStr = '\0';
5314    } else {
5315       sprintf(execDummyStr, "%s=", attr_name);
5316    }
5317    attr_ptr = FindAttrWithName(selected_obj, execDummyStr, NULL);
5318    if (attr_ptr == NULL) {
5319       int ltx, lty, rbx, rby, x, y;
5320 
5321       ltx = selected_obj->bbox.ltx; lty = selected_obj->bbox.lty;
5322       rbx = selected_obj->bbox.rbx; rby = selected_obj->bbox.rby;
5323       x = (ignore_x ? selected_obj->obbox.ltx : abs_x);
5324       y = (ignore_y ? selected_obj->obbox.rby : abs_y);
5325       PrepareToReplaceAnObj(selected_obj);
5326       attr_ptr = AddAttrByNameAndValue(selected_obj, execDummyStr, attr_value);
5327       attr_ptr->shown = TRUE;
5328       attr_ptr->obj->color = colorIndex;
5329       if (mainDisplay != NULL) {
5330          UtilStrCpyN(attr_ptr->obj->color_str, sizeof(attr_ptr->obj->color_str),
5331                colorMenuItems[colorIndex]);
5332       }
5333       MoveObj(attr_ptr->obj, x-attr_ptr->obj->x, y-attr_ptr->obj->y);
5334       UpdTextBBox(attr_ptr->obj);
5335       AdjObjBBox(selected_obj);
5336       UpdSelBBox();
5337       RecordReplaceAnObj(selected_obj);
5338       RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
5339                rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
5340                selected_obj->bbox.ltx-GRID_ABS_SIZE(1),
5341                selected_obj->bbox.lty-GRID_ABS_SIZE(1),
5342                selected_obj->bbox.rbx+GRID_ABS_SIZE(1),
5343                selected_obj->bbox.rby+GRID_ABS_SIZE(1));
5344       SetFileModified(TRUE);
5345    } else {
5346       ReplaceAttrFirstValue(selected_obj, attr_ptr, attr_value);
5347    }
5348    return TRUE;
5349 }
5350 
ExecDelAttrFromSelObj(argv,obj_ptr,orig_cmd)5351 int ExecDelAttrFromSelObj(argv, obj_ptr, orig_cmd)
5352    char **argv, *orig_cmd;
5353    struct ObjRec *obj_ptr;
5354    /* delete_attr_from_selected_obj(attr_name); */
5355 {
5356    char *attr_name=argv[0];
5357    struct AttrRec *attr_ptr=NULL;
5358    struct ObjRec *attr_owner_obj=NULL;
5359    int ltx=0, lty=0, rbx=0, rby=0;
5360 
5361    UtilRemoveQuotes(attr_name);
5362    sprintf(execDummyStr, "%s=", attr_name);
5363    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
5364    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
5365 
5366    if (attr_owner_obj == tgifObj) {
5367       AddObj(NULL, topObj, tgifObj);
5368       AddNewSelObj(topObj);
5369 
5370       PrepareToReplaceAnObj(attr_owner_obj);
5371 
5372       UnlinkAttr(attr_ptr);
5373       FreeTextObj(attr_ptr->obj);
5374       FreeAttr(attr_ptr);
5375       AdjObjBBox(attr_owner_obj);
5376 
5377       recordCmdIncludeTgifObj = TRUE;
5378       RecordReplaceAnObj(attr_owner_obj);
5379       recordCmdIncludeTgifObj = FALSE;
5380 
5381       UnlinkObj(topObj);
5382       FreeTopSel();
5383       SetFileModified(TRUE);
5384 
5385       return TRUE;
5386    }
5387    ltx = attr_owner_obj->bbox.ltx;
5388    lty = attr_owner_obj->bbox.lty;
5389    rbx = attr_owner_obj->bbox.rbx;
5390    rby = attr_owner_obj->bbox.rby;
5391 
5392    PrepareToReplaceAnObj(attr_owner_obj);
5393 
5394    UnlinkAttr(attr_ptr);
5395    FreeTextObj(attr_ptr->obj);
5396    FreeAttr(attr_ptr);
5397    AdjObjBBox(attr_owner_obj);
5398    if (outerSel != NULL) AdjAncestorsBBox();
5399    UpdSelBBox();
5400 
5401    RecordReplaceAnObj(attr_owner_obj);
5402    RedrawAnArea(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
5403          rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1));
5404 
5405    SetFileModified(TRUE);
5406    return TRUE;
5407 }
5408 
ExecUserEndAnEdge(argv,obj_ptr,orig_cmd)5409 int ExecUserEndAnEdge(argv, obj_ptr, orig_cmd)
5410    char **argv, *orig_cmd;
5411    struct ObjRec *obj_ptr;
5412    /* user_end_an_edge(attr_name,abs_x,abs_y); */
5413 {
5414    char *attr_name=argv[0], *abs_x_str=argv[1], *abs_y_str=argv[2];
5415    struct AttrRec *attr_ptr=NULL;
5416    struct ObjRec *attr_owner_obj;
5417    int abs_x, abs_y, poly_created=FALSE, already_in_hyperspace=inHyperSpace;
5418    XEvent ev;
5419    XButtonEvent *button_ev_ptr;
5420 
5421    UtilRemoveQuotes(attr_name);
5422    UtilRemoveQuotes(abs_x_str);
5423    UtilRemoveQuotes(abs_y_str);
5424    if (strcmp(attr_name, "NULL") != 0) {
5425       sprintf(execDummyStr, "%s=", attr_name);
5426       attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
5427       if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
5428    }
5429    if (topSel != NULL) {
5430       RemoveAllSel();
5431    }
5432    if (!IntExpression(abs_x_str, &abs_x, orig_cmd) ||
5433          !IntExpression(abs_y_str, &abs_y, orig_cmd)) {
5434       return FALSE;
5435    }
5436    ResetWiringNodeInfo();
5437    SetCurChoice(DRAWPOLY);
5438    SetStringStatus(TgLoadString(STID_END_AN_EDGE_AT_A_PORT));
5439 
5440    ev.type = ButtonPress;
5441    button_ev_ptr = &(ev.xbutton);
5442    button_ev_ptr->button = Button1;
5443    button_ev_ptr->x = OFFSET_X(abs_x);
5444    button_ev_ptr->y = OFFSET_Y(abs_y);
5445 
5446    polyDrawn = FALSE;
5447    gstWiringInfo.num_ports_to_connect = 1;
5448    DrawPoly(&ev);
5449    gstWiringInfo.num_ports_to_connect = 0;
5450    poly_created = polyDrawn;
5451    SetCurChoice(NOTHING);
5452    if (already_in_hyperspace && !inHyperSpace) ToggleHyperSpace(TRUE);
5453 
5454    if (attr_ptr != NULL) {
5455       ReplaceAttrFirstValue(attr_owner_obj, attr_ptr,
5456             (poly_created ? gstWiringInfo.last_port_name : ""));
5457    }
5458    return TRUE;
5459 }
5460 
ExecUserDrawAnEdge(argv,obj_ptr,orig_cmd)5461 int ExecUserDrawAnEdge(argv, obj_ptr, orig_cmd)
5462    char **argv, *orig_cmd;
5463    struct ObjRec *obj_ptr;
5464    /* user_draw_an_edge(start_attr_name,end_attr_name); */
5465 {
5466    char *start_attr_name=argv[0], *end_attr_name=argv[1];
5467    struct AttrRec *start_attr_ptr=NULL, *end_attr_ptr=NULL;
5468    struct ObjRec *start_attr_owner_obj, *end_attr_owner_obj;
5469    int poly_created=FALSE, already_in_hyperspace=inHyperSpace;
5470    XGCValues values;
5471 
5472    UtilRemoveQuotes(start_attr_name);
5473    UtilRemoveQuotes(end_attr_name);
5474    if (strcmp(start_attr_name, "NULL") != 0) {
5475       sprintf(execDummyStr, "%s=", start_attr_name);
5476       start_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr,
5477             &start_attr_owner_obj);
5478       if (start_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
5479    }
5480    if (strcmp(end_attr_name, "NULL") != 0) {
5481       sprintf(execDummyStr, "%s=", end_attr_name);
5482       end_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr,
5483             &end_attr_owner_obj);
5484       if (end_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
5485    }
5486    if (topSel != NULL) {
5487       RemoveAllSel();
5488    }
5489    ResetWiringNodeInfo();
5490    connectingPortsByWire = TRUE;
5491    UseWireMenuItemInModeItem(TRUE);
5492 
5493    values.line_width = 3;
5494    XChangeGC(mainDisplay, revGrayGC, GCLineWidth, &values);
5495 
5496    SetCurChoice(DRAWPOLY);
5497    gstWiringInfo.num_ports_to_connect = 2;
5498    drawPolyHighlightedNode = NULL;
5499    SetStringStatus(TgLoadString(STID_DRAW_AN_EDGE_BETWEEN_PORTS));
5500    polyDrawn = FALSE;
5501    for (;;) {
5502       XEvent input;
5503 
5504       XNextEvent(mainDisplay, &input);
5505       if (input.type == Expose) {
5506          ExposeEventHandler(&input, TRUE);
5507       } else if (input.xany.window == drawWindow) {
5508          polyDrawn = FALSE;
5509          DrawingEventHandler(&input);
5510          if (curChoice == DRAWPOLY) {
5511             if (polyDrawn) {
5512                break;
5513             } else if (gstWiringInfo.num_ports_to_connect == (-1)) {
5514                break;
5515             }
5516          } else {
5517             polyDrawn = FALSE;
5518             break;
5519          }
5520       }
5521    }
5522    gstWiringInfo.num_ports_to_connect = 0;
5523    poly_created = polyDrawn;
5524    values.line_width = 1;
5525    XChangeGC(mainDisplay, revGrayGC, GCLineWidth, &values);
5526    connectingPortsByWire = FALSE;
5527    SetCurChoice(NOTHING);
5528    RedrawModeWindow();
5529    UseWireMenuItemInModeItem(FALSE);
5530    UpdatePinnedMenu(MENU_MODE);
5531 
5532    if (already_in_hyperspace && !inHyperSpace) ToggleHyperSpace(TRUE);
5533 
5534    if (start_attr_ptr != NULL) {
5535       ReplaceAttrFirstValue(start_attr_owner_obj, start_attr_ptr,
5536             (poly_created ? gstWiringInfo.first_port_name : ""));
5537    }
5538    if (end_attr_ptr != NULL) {
5539       ReplaceAttrFirstValue(end_attr_owner_obj, end_attr_ptr,
5540             (poly_created ? gstWiringInfo.last_port_name : ""));
5541    }
5542    return TRUE;
5543 }
5544 
ExecGetAPolyVertexAbs(argv,obj_ptr,orig_cmd)5545 int ExecGetAPolyVertexAbs(argv, obj_ptr, orig_cmd)
5546    char **argv, *orig_cmd;
5547    struct ObjRec *obj_ptr;
5548    /* get_a_poly_vertex_absolute(x_attr,y_attr,obj_name,v_index); */
5549 {
5550    char *x_attr_name=argv[0], *y_attr_name=argv[1], *obj_name=argv[2];
5551    char *v_index_str=argv[3], buf[40];
5552    int v_index=0, abs_x=0, abs_y=0;
5553    struct AttrRec *x_attr_ptr, *y_attr_ptr;
5554    struct ObjRec *x_attr_owner_obj=NULL, *y_attr_owner_obj=NULL;
5555    struct ObjRec *owner_obj=NULL, *named_obj;
5556 
5557    UtilRemoveQuotes(x_attr_name);
5558    UtilRemoveQuotes(y_attr_name);
5559    UtilRemoveQuotes(obj_name);
5560    UtilRemoveQuotes(v_index_str);
5561    named_obj = FindObjWithName(botObj, obj_ptr, obj_name, FALSE,
5562          FALSE, &owner_obj, NULL);
5563    if (named_obj == NULL) {
5564       return BadObjName(obj_name, orig_cmd);
5565    }
5566    if (!IntExpression(v_index_str, &v_index, orig_cmd)) return FALSE;
5567 
5568    switch (named_obj->type) {
5569    case OBJ_POLY:
5570       if (v_index < 0 || v_index >= named_obj->detail.p->n) {
5571          sprintf(execDummyStr, TgLoadString(STID_CANT_FIND_VRTX_WHILE_EXEC_CMD),
5572                v_index, obj_name, orig_cmd);
5573          MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
5574          return FALSE;
5575       }
5576       abs_x = (int)named_obj->detail.p->vlist[v_index].x;
5577       abs_y = (int)named_obj->detail.p->vlist[v_index].y;
5578       break;
5579    case OBJ_POLYGON:
5580       if (v_index < 0 || v_index >= named_obj->detail.g->n) {
5581          sprintf(execDummyStr, TgLoadString(STID_CANT_FIND_VRTX_WHILE_EXEC_CMD),
5582                v_index, obj_name, orig_cmd);
5583          MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
5584          return FALSE;
5585       }
5586       abs_x = (int)named_obj->detail.g->vlist[v_index].x;
5587       abs_y = (int)named_obj->detail.g->vlist[v_index].y;
5588       break;
5589    default:
5590       sprintf(execDummyStr, TgLoadString(STID_POLY_NOR_PGON_WHILE_EXEC_CMD),
5591             obj_name, orig_cmd);
5592       MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
5593       return FALSE;
5594    }
5595    sprintf(execDummyStr, "%s=", x_attr_name);
5596    x_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &x_attr_owner_obj);
5597    if (x_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
5598    sprintf(execDummyStr, "%s=", y_attr_name);
5599    y_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &y_attr_owner_obj);
5600    if (y_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
5601 
5602    sprintf(buf, "%1d", abs_x);
5603    ReplaceAttrFirstValue(x_attr_owner_obj, x_attr_ptr, buf);
5604    sprintf(buf, "%1d", abs_y);
5605    ReplaceAttrFirstValue(y_attr_owner_obj, y_attr_ptr, buf);
5606 
5607    SetFileModified(TRUE);
5608    return TRUE;
5609 }
5610 
ExecMoveAPolyVertexAbs(argv,obj_ptr,orig_cmd)5611 int ExecMoveAPolyVertexAbs(argv, obj_ptr, orig_cmd)
5612    char **argv, *orig_cmd;
5613    struct ObjRec *obj_ptr;
5614    /* move_a_poly_vertex_absolute(obj_name,v_index,abs_x,abs_y); */
5615 {
5616    char *obj_name=argv[0], *v_index_str=argv[1];
5617    char *abs_x_str=argv[2], *abs_y_str=argv[3];
5618    int v_index=0, abs_x=0, abs_y=0, cur_x=0, cur_y=0, ltx, lty, rbx, rby;
5619    int auto_center_attr;
5620    struct ObjRec *owner_obj=NULL, *top_owner=NULL, *named_obj;
5621    struct SelRec *saved_top_sel=topSel, *saved_bot_sel=botSel;
5622 
5623    UtilRemoveQuotes(obj_name);
5624    UtilRemoveQuotes(v_index_str);
5625    UtilRemoveQuotes(abs_x_str);
5626    UtilRemoveQuotes(abs_y_str);
5627    named_obj = FindObjWithName(botObj, obj_ptr, obj_name, FALSE,
5628          FALSE, &owner_obj, &top_owner);
5629    if (named_obj == NULL) {
5630       return BadObjName(obj_name, orig_cmd);
5631    }
5632    if (!IntExpression(v_index_str, &v_index, orig_cmd)) return FALSE;
5633    if (!IntExpression(abs_x_str, &abs_x, orig_cmd)) return FALSE;
5634    if (!IntExpression(abs_y_str, &abs_y, orig_cmd)) return FALSE;
5635 
5636    switch (named_obj->type) {
5637    case OBJ_POLY:
5638       if (v_index < 0 || v_index >= named_obj->detail.p->n) {
5639          sprintf(execDummyStr, TgLoadString(STID_CANT_FIND_VRTX_WHILE_EXEC_CMD),
5640                v_index, obj_name, orig_cmd);
5641          MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
5642          return FALSE;
5643       }
5644       cur_x = named_obj->detail.p->vlist[v_index].x;
5645       cur_y = named_obj->detail.p->vlist[v_index].y;
5646       break;
5647    case OBJ_POLYGON:
5648       if (v_index < 0 || v_index >= named_obj->detail.g->n) {
5649          sprintf(execDummyStr, TgLoadString(STID_CANT_FIND_VRTX_WHILE_EXEC_CMD),
5650                v_index, obj_name, orig_cmd);
5651          MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
5652          return FALSE;
5653       }
5654       cur_x = named_obj->detail.g->vlist[v_index].x;
5655       cur_y = named_obj->detail.g->vlist[v_index].y;
5656       break;
5657    default:
5658       sprintf(execDummyStr, TgLoadString(STID_POLY_NOR_PGON_WHILE_EXEC_CMD),
5659             obj_name, orig_cmd);
5660       MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
5661       return FALSE;
5662    }
5663    if (cur_x == abs_x && cur_y == abs_y) return TRUE;
5664    if (owner_obj == NULL) {
5665       ltx = named_obj->bbox.ltx; lty = named_obj->bbox.lty;
5666       rbx = named_obj->bbox.rbx; rby = named_obj->bbox.rby;
5667    } else {
5668       ltx = top_owner->bbox.ltx; lty = top_owner->bbox.lty;
5669       rbx = top_owner->bbox.rbx; rby = top_owner->bbox.rby;
5670    }
5671    SelectAnObj(named_obj, owner_obj, top_owner, &saved_top_sel, &saved_bot_sel);
5672 
5673    PrepareToRecord(CMD_REPLACE, topSel, botSel, numObjSelected);
5674    switch (named_obj->type) {
5675    case OBJ_POLY:
5676       named_obj->detail.p->vlist[v_index].x = abs_x;
5677       named_obj->detail.p->vlist[v_index].y = abs_y;
5678       AdjObjSplineVs(named_obj);
5679       if (named_obj->detail.p->curved != LT_INTSPLINE) {
5680          UpdPolyBBox(named_obj, named_obj->detail.p->n,
5681                named_obj->detail.p->vlist);
5682       } else {
5683          UpdPolyBBox(named_obj, named_obj->detail.p->intn,
5684                named_obj->detail.p->intvlist);
5685       }
5686       break;
5687    case OBJ_POLYGON:
5688       named_obj->detail.g->vlist[v_index].x = abs_x;
5689       named_obj->detail.g->vlist[v_index].y = abs_y;
5690       if (v_index == 0) {
5691          named_obj->detail.g->vlist[named_obj->detail.g->n-1].x = abs_x;
5692          named_obj->detail.g->vlist[named_obj->detail.g->n-1].y = abs_y;
5693       } else if (v_index == named_obj->detail.g->n-1) {
5694          named_obj->detail.g->vlist[0].x = abs_x;
5695          named_obj->detail.g->vlist[0].y = abs_y;
5696       }
5697       AdjObjSplineVs(named_obj);
5698       if (named_obj->detail.g->curved != LT_INTSPLINE) {
5699          UpdPolyBBox(named_obj, named_obj->detail.g->n,
5700                named_obj->detail.g->vlist);
5701       } else {
5702          UpdPolyBBox(named_obj, named_obj->detail.g->intn,
5703                named_obj->detail.g->intvlist);
5704       }
5705       break;
5706    }
5707    auto_center_attr = AutoCenterAttr(named_obj);
5708    if (auto_center_attr) {
5709       struct AttrRec *attr_ptr;
5710       int modified=FALSE;
5711 
5712       for (attr_ptr=named_obj->fattr; attr_ptr != NULL;
5713             attr_ptr=attr_ptr->next) {
5714          if (attr_ptr->shown) {
5715             struct BBRec bbox;
5716 
5717             CenterObjInOBBox(attr_ptr->obj, named_obj->obbox, &bbox);
5718             if (bbox.ltx < ltx) ltx = bbox.ltx;
5719             if (bbox.lty < lty) lty = bbox.lty;
5720             if (bbox.rbx > rbx) rbx = bbox.rbx;
5721             if (bbox.rby > rby) rby = bbox.rby;
5722             modified = TRUE;
5723          }
5724       }
5725       if (modified) AdjObjBBox(named_obj);
5726    }
5727    RecursivelyAdjObjBBox(named_obj, owner_obj, top_owner);
5728    RecordCmd(CMD_REPLACE, NULL, topSel, botSel, numObjSelected);
5729 
5730    UpdSelBBox();
5731    if (owner_obj == NULL) {
5732       if (named_obj->bbox.ltx < ltx) ltx = named_obj->bbox.ltx;
5733       if (named_obj->bbox.lty < lty) lty = named_obj->bbox.lty;
5734       if (named_obj->bbox.rbx > rbx) rbx = named_obj->bbox.rbx;
5735       if (named_obj->bbox.rby > rby) rby = named_obj->bbox.rby;
5736    } else {
5737       if (top_owner->bbox.ltx < ltx) ltx = top_owner->bbox.ltx;
5738       if (top_owner->bbox.lty < lty) lty = top_owner->bbox.lty;
5739       if (top_owner->bbox.rbx > rbx) rbx = top_owner->bbox.rbx;
5740       if (top_owner->bbox.rby > rby) rby = top_owner->bbox.rby;
5741    }
5742    free(topSel);
5743    topSel = saved_top_sel;
5744    botSel = saved_bot_sel;
5745    UpdSelBBox();
5746 
5747    RedrawAnArea(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
5748          rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1));
5749    SetFileModified(TRUE);
5750    return TRUE;
5751 }
5752 
ExecPostAttrAndGetCGI(argv,obj_ptr,orig_cmd)5753 int ExecPostAttrAndGetCGI(argv, obj_ptr, orig_cmd)
5754    char **argv, *orig_cmd;
5755    struct ObjRec *obj_ptr;
5756    /* post_attr_and_get_cgi_result(url_attr,query_attr,result_attr); */
5757 {
5758    char *url_attr_name=argv[0], *query_attr_name=argv[1];
5759    char *result_attr_name=argv[2];
5760    struct AttrRec *url_attr, *query_attr, *result_attr;
5761    struct ObjRec *result_attr_owner_obj=NULL;
5762    char *remote_buf=NULL, *tmp_remote_fname=NULL;
5763    int is_html=FALSE, remote_buf_sz=0, rc;
5764    FILE *fp;
5765 
5766    UtilRemoveQuotes(url_attr_name);
5767    UtilRemoveQuotes(query_attr_name);
5768    UtilRemoveQuotes(result_attr_name);
5769    sprintf(execDummyStr, "%s=", url_attr_name);
5770    url_attr = FindAttrWithName(obj_ptr, execDummyStr, NULL);
5771    if (url_attr == NULL) return BadAttr(execDummyStr, orig_cmd);
5772 
5773    sprintf(execDummyStr, "%s=", query_attr_name);
5774    query_attr = FindAttrWithName(obj_ptr, execDummyStr, NULL);
5775    if (query_attr == NULL) return BadAttr(execDummyStr, orig_cmd);
5776 
5777    sprintf(execDummyStr, "%s=", result_attr_name);
5778    result_attr = FindAttrWithName(obj_ptr, execDummyStr,
5779          &result_attr_owner_obj);
5780    if (result_attr == NULL) return BadAttr(execDummyStr, orig_cmd);
5781 
5782    if (!FileIsRemote(url_attr->attr_value.s)) {
5783       sprintf(gszMsgBox, TgLoadString(STID_BAD_REM_FNAME_WHILE_EXEC_CMD),
5784             url_attr->attr_value.s, orig_cmd);
5785       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5786       return FALSE;
5787    }
5788    fnameForPostingCGIQuery = (char*)malloc((strlen(tmpDir)+20)*sizeof(char));
5789    if (fnameForPostingCGIQuery == NULL) {
5790       FailAllocMessage();
5791       return FALSE;
5792    }
5793    if (MkTempFile(fnameForPostingCGIQuery, (strlen(tmpDir)+19)*sizeof(char),
5794          tmpDir, TOOL_NAME) == NULL) {
5795       free(fnameForPostingCGIQuery);
5796       fnameForPostingCGIQuery = NULL;
5797       return FALSE;
5798    }
5799    if ((fp=fopen(fnameForPostingCGIQuery, "w")) == NULL) {
5800       sprintf(gszMsgBox, TgLoadString(STID_CANT_OPEN_FILE_WRITE_EXEC_CMD),
5801             fnameForPostingCGIQuery, orig_cmd);
5802       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5803 
5804       free(fnameForPostingCGIQuery);
5805       fnameForPostingCGIQuery = NULL;
5806       return FALSE;
5807    }
5808    writeFileFailed = FALSE;
5809    fprintf(fp, "%s\r\n", query_attr->attr_value.s);
5810    if (query_attr->obj->detail.t->minilines.first != NULL) {
5811       MiniLineInfo *pMiniLine=NULL;
5812 
5813       for (pMiniLine=query_attr->obj->detail.t->minilines.first->next;
5814             pMiniLine != NULL; pMiniLine=pMiniLine->next) {
5815          int need_to_free_tmp_buf=FALSE;
5816          char *tmp_buf=ConvertMiniLineToString(pMiniLine,
5817                &need_to_free_tmp_buf);
5818 
5819          if (fprintf(fp, "%s\r\n", tmp_buf) == EOF) {
5820             writeFileFailed = TRUE;
5821          }
5822          if (need_to_free_tmp_buf) UtilFree(tmp_buf);
5823          if (writeFileFailed) break;
5824       }
5825    }
5826    fclose(fp);
5827    if (writeFileFailed) {
5828       FailToWriteFileMessage(fnameForPostingCGIQuery);
5829       unlink(fnameForPostingCGIQuery);
5830       free(fnameForPostingCGIQuery);
5831       fnameForPostingCGIQuery = NULL;
5832       return FALSE;
5833    }
5834    postingCGIQuery = TRUE;
5835    SaveStatusStrings();
5836    rc = LoadRemoteFileInMem(url_attr->attr_value.s, &remote_buf, NULL,
5837          &remote_buf_sz, &is_html, TRUE, NULL, 0);
5838    RestoreStatusStrings();
5839    postingCGIQuery = FALSE;
5840    unlink(fnameForPostingCGIQuery);
5841    free(fnameForPostingCGIQuery);
5842    fnameForPostingCGIQuery = NULL;
5843 
5844    if (!rc) {
5845       sprintf(gszMsgBox, TgLoadString(STID_UNEXP_ERR_EXEC_CMD_ABORT), orig_cmd);
5846       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5847       return FALSE;
5848    }
5849    tmp_remote_fname = WriteRemoteFileIntoTemp(remote_buf, remote_buf_sz, NULL);
5850    if (tmp_remote_fname == NULL) {
5851       return FALSE;
5852    }
5853    SaveStatusStrings();
5854    rc = DoReadFileIntoAttr(result_attr, result_attr_owner_obj,
5855          tmp_remote_fname, orig_cmd);
5856    RestoreStatusStrings();
5857 
5858    if (remote_buf != NULL) FreeRemoteBuf(remote_buf);
5859    if (tmp_remote_fname != NULL) {
5860       unlink(tmp_remote_fname);
5861       FreeRemoteBuf(tmp_remote_fname);
5862    }
5863    return rc;
5864 }
5865 
ExecNavigateBack(obj_ptr,orig_cmd)5866 void ExecNavigateBack(obj_ptr, orig_cmd)
5867    struct ObjRec *obj_ptr;
5868    char *orig_cmd;
5869    /* navigate_back(); */
5870 {
5871    execNavigateBack = TRUE;
5872 }
5873 
ExecStop(obj_ptr,orig_cmd)5874 void ExecStop(obj_ptr, orig_cmd)
5875    struct ObjRec *obj_ptr;
5876    char *orig_cmd;
5877    /* stop(); */
5878 {
5879    gnAbortExec = TRUE;
5880    gnStopCmdExecuted = TRUE;
5881    sprintf(gszMsgBox, TgLoadString(STID_GIVEN_CMD_EXECUTED), orig_cmd);
5882    Msg(gszMsgBox);
5883 }
5884 
ExecSqrt(argv,obj_ptr,orig_cmd)5885 int ExecSqrt(argv, obj_ptr, orig_cmd)
5886    char **argv, *orig_cmd;
5887    struct ObjRec *obj_ptr;
5888    /* sqrt(attr_name,expr); */
5889 {
5890    char *attr_name=argv[0], *expr=argv[1], buf[40];
5891    struct AttrRec *attr_ptr;
5892    struct ObjRec *attr_owner_obj=NULL;
5893    struct VRec v;
5894    double d_val=(double)0.0;
5895 
5896    UtilRemoveQuotes(attr_name);
5897    UtilRemoveQuotes(expr);
5898    sprintf(execDummyStr, "%s=", attr_name);
5899    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
5900    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
5901 
5902    if (!EvalExpr(expr, &v)) return FALSE;
5903 
5904    switch (v.vtype) {
5905    case INT_VAL: d_val = (double)v.val.i; break;
5906    case DBL_VAL: d_val = (double)v.val.d; break;
5907    case NULL_VAL:
5908    case STR_VAL:
5909       sprintf(gszMsgBox, TgLoadString(STID_BAD_EVAL_NUM_EXP_EXEC_CMD),
5910             expr, orig_cmd);
5911       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5912       if (v.vtype == STR_VAL && v.val.s != NULL) free(v.val.s);
5913       return FALSE;
5914    }
5915    if (d_val < (double)0.0) {
5916       sprintf(gszMsgBox, TgLoadString(STID_SQRT_NEG_NUM_WHILE_EXEC_CMD),
5917             orig_cmd);
5918       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5919       return FALSE;
5920    }
5921    d_val = (double)sqrt((double)d_val);
5922    sprintf(buf, "%.12f", (float)(d_val));
5923    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
5924    return TRUE;
5925 }
5926 
ExecRandom(argv,obj_ptr,orig_cmd)5927 int ExecRandom(argv, obj_ptr, orig_cmd)
5928    char **argv, *orig_cmd;
5929    struct ObjRec *obj_ptr;
5930    /* random(attr_name); */
5931 {
5932    static int snSeeded=FALSE;
5933    char *attr_name=argv[0], buf[40];
5934    struct AttrRec *attr_ptr;
5935    struct ObjRec *attr_owner_obj=NULL;
5936 
5937    UtilRemoveQuotes(attr_name);
5938    UtilTrimBlanks(attr_name);
5939    sprintf(execDummyStr, "%s=", attr_name);
5940    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
5941    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
5942 
5943    if (!snSeeded) {
5944       snSeeded = TRUE;
5945       srand(0);
5946    }
5947    sprintf(buf, "%1d", rand());
5948    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
5949    return TRUE;
5950 }
5951 
5952 #ifndef _NO_RAND48
5953 static int gnDRand48Seeded=FALSE;
5954 #endif /* ~_NO_RAND48 */
5955 
5956 #ifdef _NO_RAND48
5957 static
NoRand48(orig_cmd)5958 int NoRand48(orig_cmd)
5959    char *orig_cmd;
5960 {
5961    sprintf(gszMsgBox, TgLoadString(STID_CMD_NOT_AVAIL_ON_PLATFORM), orig_cmd);
5962    MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5963    return FALSE;
5964 }
5965 #endif /* _NO_RAND48 */
5966 
ExecSRand48(argv,obj_ptr,orig_cmd)5967 int ExecSRand48(argv, obj_ptr, orig_cmd)
5968    char **argv, *orig_cmd;
5969    struct ObjRec *obj_ptr;
5970    /* srand48(use_cur_time_as_seed); */
5971 {
5972 #ifndef _NO_RAND48
5973    char *use_cur_time_str=argv[0];
5974    int use_cur_time=0;
5975 
5976    UtilRemoveQuotes(use_cur_time_str);
5977    UtilTrimBlanks(use_cur_time_str);
5978    if (!IntExpression(use_cur_time_str, &use_cur_time, orig_cmd)) {
5979       return FALSE;
5980    }
5981    if (use_cur_time == 0) {
5982       srand48(0L);
5983    } else {
5984       time_t tloc;
5985 
5986       time(&tloc);
5987       srand48((long)tloc);
5988    }
5989    gnDRand48Seeded = TRUE;
5990 
5991    return TRUE;
5992 #else /* _NO_RAND48 */
5993    return NoRand48(orig_cmd);
5994 #endif /* ~_NO_RAND48 */
5995 }
5996 
ExecDRand48(argv,obj_ptr,orig_cmd)5997 int ExecDRand48(argv, obj_ptr, orig_cmd)
5998    char **argv, *orig_cmd;
5999    struct ObjRec *obj_ptr;
6000    /* drand48(attr_name); */
6001 {
6002 #ifndef _NO_RAND48
6003    char *attr_name=argv[0], buf[40];
6004    struct AttrRec *attr_ptr;
6005    struct ObjRec *attr_owner_obj=NULL;
6006    double d_val=(double)0;
6007 
6008    UtilRemoveQuotes(attr_name);
6009    UtilTrimBlanks(attr_name);
6010    sprintf(execDummyStr, "%s=", attr_name);
6011    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
6012    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6013 
6014    if (!gnDRand48Seeded) {
6015       gnDRand48Seeded = TRUE;
6016       srand48(0L);
6017    }
6018    d_val = (double)drand48();
6019    sprintf(buf, "%.12f", (float)(d_val));
6020    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
6021 
6022    return TRUE;
6023 #else /* _NO_RAND48 */
6024    return NoRand48(orig_cmd);
6025 #endif /* ~_NO_RAND48 */
6026 }
6027 
ExecRound(argv,obj_ptr,orig_cmd)6028 int ExecRound(argv, obj_ptr, orig_cmd)
6029    char **argv, *orig_cmd;
6030    struct ObjRec *obj_ptr;
6031    /* round(attr_name,expr); */
6032 {
6033    char *attr_name=argv[0], *expr=argv[1], buf[40];
6034    struct AttrRec *attr_ptr;
6035    struct ObjRec *attr_owner_obj=NULL;
6036    struct VRec v;
6037    double d_val=(double)0.0;
6038 
6039    UtilRemoveQuotes(attr_name);
6040    UtilRemoveQuotes(expr);
6041    sprintf(execDummyStr, "%s=", attr_name);
6042    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
6043    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6044 
6045    if (!EvalExpr(expr, &v)) return FALSE;
6046 
6047    switch (v.vtype) {
6048    case INT_VAL: d_val = (double)v.val.i; break;
6049    case DBL_VAL: d_val = (double)v.val.d; break;
6050    case NULL_VAL:
6051    case STR_VAL:
6052       sprintf(gszMsgBox, TgLoadString(STID_BAD_EVAL_NUM_EXP_EXEC_CMD),
6053             expr, orig_cmd);
6054       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
6055       if (v.vtype == STR_VAL && v.val.s != NULL) free(v.val.s);
6056       return FALSE;
6057    }
6058    sprintf(buf, "%1d", round(d_val));
6059    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
6060    return TRUE;
6061 }
6062 
ExecRedrawObj(argv,obj_ptr,orig_cmd)6063 int ExecRedrawObj(argv, obj_ptr, orig_cmd)
6064    char **argv, *orig_cmd;
6065    struct ObjRec *obj_ptr;
6066    /* redraw_obj(obj_name); */
6067 {
6068    char *obj_name=argv[0];
6069    struct ObjRec *owner_obj=NULL, *top_owner=NULL, *named_obj;
6070    int ltx, lty, rbx, rby;
6071 
6072    UtilRemoveQuotes(obj_name);
6073    named_obj = FindObjWithName(botObj, obj_ptr, obj_name, FALSE,
6074          FALSE, &owner_obj, &top_owner);
6075    if (named_obj == NULL) return BadObjName(obj_name, orig_cmd);
6076 
6077    ltx = named_obj->bbox.ltx; lty = named_obj->bbox.lty;
6078    rbx = named_obj->bbox.rbx; rby = named_obj->bbox.rby;
6079    RedrawAnArea(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
6080          rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1));
6081 
6082    return TRUE;
6083 }
6084 
ExecRedrawDrawingArea(obj_ptr,orig_cmd)6085 void ExecRedrawDrawingArea(obj_ptr, orig_cmd)
6086    struct ObjRec *obj_ptr;
6087    char *orig_cmd;
6088    /* redraw_drawing_area(); */
6089 {
6090    RedrawDrawWindow(botObj);
6091 }
6092 
ExecIntToHex(argv,obj_ptr,orig_cmd)6093 int ExecIntToHex(argv, obj_ptr, orig_cmd)
6094    char **argv, *orig_cmd;
6095    struct ObjRec *obj_ptr;
6096    /* itox(attr_name,digits,expr); */
6097 {
6098    char *attr_name=argv[0], *digits_str=argv[1], *expr=argv[2];
6099    char buf[40], buf1[40];
6100    struct AttrRec *attr_ptr;
6101    struct ObjRec *attr_owner_obj=NULL;
6102    struct VRec v;
6103    int digits=0, i_val=0;
6104 
6105    UtilRemoveQuotes(attr_name);
6106    UtilRemoveQuotes(digits_str);
6107    UtilRemoveQuotes(expr);
6108    sprintf(execDummyStr, "%s=", attr_name);
6109    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
6110    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6111 
6112    if (!IntExpression(digits_str, &digits, orig_cmd)) {
6113       return FALSE;
6114    }
6115    if (digits <= 0 || digits > 8) {
6116       sprintf(gszMsgBox, TgLoadString(STID_FUNC_ARG_RANGE),
6117             orig_cmd, "digits", 1, 8, digits);
6118       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
6119       return FALSE;
6120    }
6121 
6122    if (!EvalExpr(expr, &v)) return FALSE;
6123 
6124    switch (v.vtype) {
6125    case INT_VAL: i_val = v.val.i; break;
6126    case DBL_VAL: i_val = round(v.val.d); break;
6127    case NULL_VAL:
6128    case STR_VAL:
6129       sprintf(gszMsgBox, TgLoadString(STID_BAD_EVAL_NUM_EXP_EXEC_CMD),
6130             expr, orig_cmd);
6131       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
6132       if (v.vtype == STR_VAL && v.val.s != NULL) free(v.val.s);
6133       return FALSE;
6134    }
6135    sprintf(buf1, "%%0%1dx", digits);
6136    sprintf(buf, buf1, i_val);
6137    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
6138    return TRUE;
6139 }
6140 
ExecForI(argv,obj_ptr,orig_cmd)6141 int ExecForI(argv, obj_ptr, orig_cmd)
6142    char **argv, *orig_cmd;
6143    struct ObjRec *obj_ptr;
6144    /* for_i(attr_name,min_val,max_val,inc,attr_to_exec); */
6145 {
6146    char *attr_name=argv[0], *min_str=argv[1], *max_str=argv[2];
6147    char *inc_str=argv[3], *exec_attr_name=argv[4], num_buf[40];
6148    char *compare_buf=NULL, *assign_buf=NULL;
6149    struct AttrRec *attr_ptr=NULL, *exec_attr_ptr=NULL;
6150    struct ObjRec *attr_owner_obj=NULL, *exec_attr_owner_obj=NULL;
6151    int min_val=0, max_val=0, inc_val=1, ok=TRUE;
6152 
6153    UtilRemoveQuotes(attr_name);
6154    UtilRemoveQuotes(min_str);
6155    UtilRemoveQuotes(max_str);
6156    UtilRemoveQuotes(inc_str);
6157    UtilRemoveQuotes(exec_attr_name);
6158    if (strcmp(attr_name, "NULL") != 0) {
6159       sprintf(execDummyStr, "%s=", attr_name);
6160       attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
6161       if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6162    }
6163    sprintf(execDummyStr, "%s=", exec_attr_name);
6164    exec_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr,
6165          &exec_attr_owner_obj);
6166    if (exec_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6167 
6168    if (!IntExpression(min_str, &min_val, orig_cmd) ||
6169          !IntExpression(max_str, &max_val, orig_cmd) ||
6170          !IntExpression(inc_str, &inc_val, orig_cmd)) {
6171       return FALSE;
6172    }
6173    if (attr_ptr != NULL) {
6174       compare_buf = (char*)malloc((strlen(attr_name)+40)*sizeof(char));
6175       assign_buf = (char*)malloc((strlen(attr_name)+40)*sizeof(char));
6176       if (compare_buf == NULL || assign_buf == NULL) {
6177          FailAllocMessage();
6178          if (compare_buf != NULL) free(compare_buf);
6179          if (assign_buf != NULL) free(assign_buf);
6180          return FALSE;
6181       }
6182       sprintf(compare_buf, "$(%s) <= %1d", attr_name, max_val);
6183       sprintf(assign_buf, "$(%s)", attr_name);
6184 
6185       sprintf(num_buf, "%1d", min_val);
6186       ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, num_buf);
6187    }
6188    while (ok) {
6189       if (attr_ptr != NULL) {
6190          int val;
6191          char *expr=convert_str(compare_buf, obj_ptr, TRUE);
6192 
6193          if (expr == NULL) {
6194             BadAttr(compare_buf, orig_cmd);
6195             free(compare_buf);
6196             return FALSE;
6197          } else if (!IntExpression(expr, &val, orig_cmd)) {
6198             free(expr);
6199             free(compare_buf);
6200             return FALSE;
6201          }
6202          free(expr);
6203          if (val == 0) break;
6204       } else {
6205          if (min_val > max_val) break;
6206       }
6207       if (!DoExec(exec_attr_ptr, exec_attr_owner_obj)) return FALSE;
6208       if (attr_ptr != NULL) {
6209          int val;
6210          char *expr=convert_str(assign_buf, obj_ptr, TRUE);
6211 
6212          if (expr == NULL) {
6213             BadAttr(assign_buf, orig_cmd);
6214             free(assign_buf);
6215             return FALSE;
6216          } else if (!IntExpression(expr, &val, orig_cmd)) {
6217             free(expr);
6218             free(assign_buf);
6219             return FALSE;
6220          }
6221          free(expr);
6222          min_val = val + inc_val;
6223 
6224          sprintf(num_buf, "%1d", min_val);
6225          ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, num_buf);
6226       } else {
6227          min_val += inc_val;
6228       }
6229       ok = (!CheckExecInterrupt(orig_cmd));
6230       if (!ok) {
6231          userAbortExec = TRUE;
6232       }
6233    }
6234    if (compare_buf != NULL) free(compare_buf);
6235    if (assign_buf != NULL) free(assign_buf);
6236    return ok;
6237 }
6238 
ExecSetFileNotModified(obj_ptr,orig_cmd)6239 void ExecSetFileNotModified(obj_ptr, orig_cmd)
6240    struct ObjRec *obj_ptr;
6241    char *orig_cmd;
6242    /* set_file_not_modified(); */
6243 {
6244    justDupped = FALSE;
6245    SetFileModified(FALSE);
6246    RedrawTitleWindow();
6247 }
6248 
ExecNewId(argv,obj_ptr,orig_cmd)6249 int ExecNewId(argv, obj_ptr, orig_cmd)
6250    char **argv, *orig_cmd;
6251    struct ObjRec *obj_ptr;
6252    /* new_id(attr_name); */
6253 {
6254    char *attr_name=argv[0], buf[40];
6255    struct AttrRec *attr_ptr;
6256    struct ObjRec *attr_owner_obj=NULL;
6257 
6258    UtilRemoveQuotes(attr_name);
6259    sprintf(execDummyStr, "%s=", attr_name);
6260    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
6261    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6262 
6263    sprintf(buf, "%1d", objId++);
6264    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
6265    return TRUE;
6266 }
6267 
ExecRotateSelObj(argv,obj_ptr,orig_cmd)6268 int ExecRotateSelObj(argv, obj_ptr, orig_cmd)
6269    char **argv, *orig_cmd;
6270    struct ObjRec *obj_ptr;
6271    /* rotate_selected_obj(angle); */
6272 {
6273    char *expr=argv[0];
6274    struct VRec v;
6275    double d_val=(double)0.0;
6276 
6277    UtilRemoveQuotes(expr);
6278    if (topSel == NULL) return BadSelectedObj(orig_cmd);
6279 
6280    if (!EvalExpr(expr, &v)) return FALSE;
6281 
6282    switch (v.vtype) {
6283    case INT_VAL: d_val = (double)v.val.i; break;
6284    case DBL_VAL: d_val = (double)v.val.d; break;
6285    case NULL_VAL:
6286    case STR_VAL:
6287       sprintf(gszMsgBox, TgLoadString(STID_BAD_EVAL_NUM_EXP_EXEC_CMD),
6288             expr, orig_cmd);
6289       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
6290       if (v.vtype == STR_VAL && v.val.s != NULL) free(v.val.s);
6291       return FALSE;
6292    }
6293    RotateAllSelObj(d_val);
6294    return TRUE;
6295 }
6296 
ExecCallSimpleShortCut(argv,obj_ptr,orig_cmd)6297 int ExecCallSimpleShortCut(argv, obj_ptr, orig_cmd)
6298    char **argv, *orig_cmd;
6299    struct ObjRec *obj_ptr;
6300    /* call_simple_shortcut(shortcut_name); */
6301 {
6302    char *shortcut_name=argv[0], *func_name=NULL, *buf=NULL, code='\0';
6303    unsigned int state=0;
6304    int len, rc=TRUE;
6305 
6306    UtilRemoveQuotes(shortcut_name);
6307 
6308    if (!ValidShortCut(shortcut_name, 0, &code, &state)) {
6309       int found=FALSE;
6310 
6311       if (cmdLineTgrm2) {
6312          int actual_num_args=0;
6313          int index=ValidTangram2CmdName(shortcut_name, strlen(shortcut_name),
6314                &actual_num_args);
6315 
6316          if (index != 0 && actual_num_args == 0) {
6317             found = TRUE;
6318             DoTangram2ShortCut(index-CMDID_TANGRAM2_BASE, "");
6319          }
6320       }
6321       if (!found) {
6322          sprintf(gszMsgBox, TgLoadString(STID_BAD_SHORTCUT_WHILE_EXEC_CMD),
6323                shortcut_name, orig_cmd);
6324          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
6325       }
6326       return found;
6327    }
6328    len = strlen(shortcut_name);
6329    if ((func_name=(char*)malloc((len+3)*sizeof(char))) == NULL) {
6330       FailAllocMessage();
6331       return FALSE;
6332    }
6333    sprintf(func_name, "%s()", shortcut_name);
6334    if ((buf=UtilStrDup(func_name)) == NULL) {
6335       free(func_name);
6336       FailAllocMessage();
6337       return FALSE;
6338    }
6339    rc = CallShortCut(func_name, 1, &buf, &code, state);
6340    free(buf);
6341    free(func_name);
6342    if (!rc) {
6343       sprintf(gszMsgBox, TgLoadString(STID_BAD_SHORTCUT_WHILE_EXEC_CMD),
6344             shortcut_name, orig_cmd);
6345       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
6346    } else {
6347       /* do not translate -- program constants */
6348       if (UtilStrICmp(shortcut_name, "Quit") == 0) {
6349          gnAbortExec = TRUE;
6350       }
6351    }
6352    return rc;
6353 }
6354 
ExecCallOneArgShortCut(argv,obj_ptr,orig_cmd)6355 int ExecCallOneArgShortCut(argv, obj_ptr, orig_cmd)
6356    char **argv, *orig_cmd;
6357    struct ObjRec *obj_ptr;
6358    /* call_one_arg_shortcut(shortcut_name,arg); */
6359 {
6360    char *shortcut_name=argv[0], *arg=argv[1], **ppsz_buf=NULL, code='\0';
6361    char *func_name=NULL;
6362    unsigned int state;
6363    int len=0;
6364 
6365    UtilRemoveQuotes(shortcut_name);
6366    UtilRemoveQuotes(arg);
6367 
6368    /* do not translate -- program constants */
6369    if (strcmp(shortcut_name, "Quit") == 0 ||
6370          !ValidShortCut(shortcut_name, 1, &code, &state)) {
6371       int found=FALSE;
6372 
6373       if (cmdLineTgrm2) {
6374          int actual_num_args=0;
6375          int index=ValidTangram2CmdName(shortcut_name, strlen(shortcut_name),
6376                &actual_num_args);
6377 
6378          if (index != 0 && actual_num_args == 1) {
6379             found = TRUE;
6380             DoTangram2ShortCut(index-CMDID_TANGRAM2_BASE, arg);
6381          }
6382       }
6383       if (!found) {
6384          sprintf(gszMsgBox, TgLoadString(STID_BAD_SHORTCUT_WHILE_EXEC_CMD),
6385                shortcut_name, orig_cmd);
6386          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
6387       }
6388       return found;
6389    }
6390    len = strlen(shortcut_name);
6391    if ((func_name=(char*)malloc((len+3)*sizeof(char))) == NULL) {
6392       FailAllocMessage();
6393       return FALSE;
6394    }
6395    sprintf(func_name, "%s()", shortcut_name);
6396    if ((ppsz_buf=(char**)malloc(2*sizeof(char*))) == NULL) {
6397       free(func_name);
6398       FailAllocMessage();
6399       return FALSE;
6400    }
6401    if ((ppsz_buf[0]=UtilStrDup(func_name)) == NULL) {
6402       free(ppsz_buf);
6403       free(func_name);
6404       FailAllocMessage();
6405       return FALSE;
6406    }
6407    len = strlen(arg);
6408    if ((ppsz_buf[1]=(char*)malloc((len+2)*sizeof(char))) == NULL) {
6409       free(ppsz_buf[0]);
6410       free(ppsz_buf);
6411       free(func_name);
6412       FailAllocMessage();
6413       return FALSE;
6414    }
6415    sprintf(ppsz_buf[1], "%s)", arg);
6416    CallShortCut(func_name, 2, ppsz_buf, &code, state);
6417    free(ppsz_buf[1]);
6418    free(ppsz_buf[0]);
6419    free(ppsz_buf);
6420    free(func_name);
6421    return TRUE;
6422 }
6423 
ExecSubstituteAttr(argv,obj_ptr,orig_cmd)6424 int ExecSubstituteAttr(argv, obj_ptr, orig_cmd)
6425    char **argv, *orig_cmd;
6426    struct ObjRec *obj_ptr;
6427    /* substitute_attr(attr_name,src_attr_name,replace_attr_name,pattern_str); */
6428 {
6429    char *attr_name=argv[0], *src_attr_name=argv[1];
6430    char *replace_attr_name=argv[2], *pattern_str=argv[3];
6431    char tmp_fname[MAXPATHLENGTH+1];
6432    struct AttrRec *attr_ptr=NULL, *src_attr_ptr=NULL, *replace_attr_ptr=NULL;
6433    struct ObjRec *attr_owner_obj=NULL;
6434    MiniLineInfo *pMiniLine=NULL;
6435    int rc, pattern_len=0;
6436    FILE *fp;
6437 
6438    if (*pattern_str == '\0') return BadArg("pattern_str", orig_cmd);
6439 
6440    UtilRemoveQuotes(attr_name);
6441    UtilRemoveQuotes(src_attr_name);
6442    UtilRemoveQuotes(replace_attr_name);
6443    UtilRemoveQuotes(pattern_str);
6444    pattern_len = strlen(pattern_str);
6445 
6446    sprintf(execDummyStr, "%s=", attr_name);
6447    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
6448    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6449 
6450    sprintf(execDummyStr, "%s=", src_attr_name);
6451    src_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, NULL);
6452    if (src_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6453 
6454    sprintf(execDummyStr, "%s=", replace_attr_name);
6455    replace_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, NULL);
6456    if (replace_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6457 
6458    if (MkTempFile(tmp_fname, sizeof(tmp_fname), tmpDir, TOOL_NAME) == NULL) {
6459       return FALSE;
6460    }
6461    if ((fp=fopen(tmp_fname, "w")) == NULL) {
6462       sprintf(gszMsgBox, TgLoadString(STID_CANT_OPEN_FILE_WRITE_EXEC_CMD),
6463             tmp_fname, orig_cmd);
6464       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
6465       return FALSE;
6466    }
6467    writeFileFailed = FALSE;
6468 
6469    for (pMiniLine=src_attr_ptr->obj->detail.t->minilines.first;
6470          pMiniLine != NULL; pMiniLine=pMiniLine->next) {
6471       char *c_ptr, *buf=NULL;
6472       int need_to_free_tmp_buf=FALSE;
6473       char *tmp_buf=NULL;
6474 
6475       if (pMiniLine == src_attr_ptr->obj->detail.t->minilines.first) {
6476          char *attr_value=NULL;
6477 
6478          tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
6479          attr_value = UtilStrDup(tmp_buf);
6480          if (attr_value == NULL) FailAllocMessage();
6481          ParseAttrStr(tmp_buf, NULL, 0, attr_value, strlen(attr_value)+1);
6482          if (need_to_free_tmp_buf) UtilFree(tmp_buf);
6483          need_to_free_tmp_buf = TRUE;
6484          buf = tmp_buf = attr_value;
6485       } else {
6486          tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
6487          buf = tmp_buf;
6488       }
6489       for (c_ptr=strstr(buf, pattern_str); c_ptr != NULL;
6490             c_ptr=strstr(buf, pattern_str)) {
6491          char saved_ch=(*c_ptr);
6492          MiniLineInfo *pReplaceMiniLine=NULL;
6493 
6494          *c_ptr = '\0';
6495          if (fprintf(fp, "%s", buf) == EOF) {
6496             writeFileFailed = TRUE;
6497          }
6498          for (pReplaceMiniLine=replace_attr_ptr->obj->detail.t->minilines.first;
6499                pReplaceMiniLine != NULL;
6500                pReplaceMiniLine=pReplaceMiniLine->next) {
6501             char *buf1=NULL;
6502             int need_to_free_tmp_buf1=FALSE;
6503             char *tmp_buf1=ConvertMiniLineToString(pMiniLine,
6504                   &need_to_free_tmp_buf1);
6505 
6506             if (pReplaceMiniLine ==
6507                   replace_attr_ptr->obj->detail.t->minilines.first) {
6508                char *attr_value=NULL;
6509 
6510                tmp_buf1 = ConvertMiniLineToString(pReplaceMiniLine,
6511                      &need_to_free_tmp_buf1);
6512                attr_value = UtilStrDup(tmp_buf1);
6513                if (attr_value == NULL) FailAllocMessage();
6514                ParseAttrStr(tmp_buf1, NULL, 0, attr_value,
6515                      strlen(attr_value)+1);
6516                if (need_to_free_tmp_buf1) UtilFree(tmp_buf1);
6517                need_to_free_tmp_buf1 = TRUE;
6518                buf1 = tmp_buf1 = attr_value;
6519             } else {
6520                tmp_buf1 = ConvertMiniLineToString(pReplaceMiniLine,
6521                      &need_to_free_tmp_buf1);
6522                buf1 = tmp_buf1;
6523             }
6524             if (fprintf(fp, "%s%s", buf1,
6525                   pReplaceMiniLine->next==NULL ? "" : "\n") == EOF) {
6526                writeFileFailed = TRUE;
6527             }
6528             if (need_to_free_tmp_buf1) UtilFree(tmp_buf1);
6529             if (writeFileFailed) break;
6530          }
6531          *c_ptr = saved_ch;
6532          buf = (&c_ptr[pattern_len]);
6533       }
6534       if (buf != NULL) {
6535          if (fprintf(fp, "%s\n", buf) == EOF) {
6536             writeFileFailed = TRUE;
6537          }
6538       }
6539       if (need_to_free_tmp_buf) UtilFree(tmp_buf);
6540       if (writeFileFailed) break;
6541    }
6542    fclose(fp);
6543    if (writeFileFailed) {
6544       FailToWriteFileMessage(tmp_fname);
6545       unlink(tmp_fname);
6546       return FALSE;
6547    }
6548    SaveStatusStrings();
6549    rc = DoReadFileIntoAttr(attr_ptr, attr_owner_obj, tmp_fname, orig_cmd);
6550    RestoreStatusStrings();
6551    unlink(tmp_fname);
6552    return rc;
6553 }
6554 
ExecGetFileSize(argv,obj_ptr,orig_cmd)6555 int ExecGetFileSize(argv, obj_ptr, orig_cmd)
6556    char **argv, *orig_cmd;
6557    struct ObjRec *obj_ptr;
6558    /* get_file_size(attr_name,file_name); */
6559 {
6560    char *attr_name=argv[0], *file_name=argv[1], buf[40];
6561    struct AttrRec *attr_ptr=NULL;
6562    struct ObjRec *attr_owner_obj=NULL;
6563    struct stat stat_buf;
6564 
6565    UtilRemoveQuotes(attr_name);
6566    UtilRemoveQuotes(file_name);
6567 
6568    sprintf(execDummyStr, "%s=", attr_name);
6569    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
6570    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6571 
6572    if (stat(file_name, &stat_buf) != 0) {
6573       sprintf(gszMsgBox, TgLoadString(STID_STAT_FAILED_WHILE_EXEC_CMD),
6574             file_name, orig_cmd);
6575       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
6576       return FALSE;
6577    }
6578    sprintf(buf, "%ld", (long)stat_buf.st_size);
6579    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
6580    return TRUE;
6581 }
6582 
ExecIsFile(argv,obj_ptr,orig_cmd)6583 int ExecIsFile(argv, obj_ptr, orig_cmd)
6584    char **argv, *orig_cmd;
6585    struct ObjRec *obj_ptr;
6586    /* is_file(attr_name,file_name); */
6587 {
6588    char *attr_name=argv[0], *file_name=argv[1], buf[40];
6589    struct AttrRec *attr_ptr=NULL;
6590    struct ObjRec *attr_owner_obj=NULL;
6591    FILE *fp;
6592 
6593    UtilRemoveQuotes(attr_name);
6594    UtilRemoveQuotes(file_name);
6595 
6596    sprintf(execDummyStr, "%s=", attr_name);
6597    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
6598    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6599 
6600    if ((fp=fopen(file_name, "r")) != NULL) {
6601       fclose(fp);
6602       strcpy(buf, "1");
6603    } else {
6604       strcpy(buf, "0");
6605    }
6606    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
6607    return TRUE;
6608 }
6609 
ExecIndex(argv,obj_ptr,orig_cmd)6610 int ExecIndex(argv, obj_ptr, orig_cmd)
6611    char **argv, *orig_cmd;
6612    struct ObjRec *obj_ptr;
6613    /* index(attr_name,str,substr); */
6614 {
6615    char *attr_name=argv[0], *the_str=argv[1], *sub_str=argv[2], *c_ptr, buf[40];
6616    struct AttrRec *attr_ptr;
6617    struct ObjRec *attr_owner_obj=NULL;
6618 
6619    UtilRemoveQuotes(attr_name);
6620    UtilRemoveQuotes(the_str);
6621    UtilRemoveQuotes(sub_str);
6622    sprintf(execDummyStr, "%s=", attr_name);
6623    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
6624    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6625 
6626    c_ptr = strstr(the_str, sub_str);
6627    if (c_ptr == NULL) {
6628       strcpy(buf, "-1");
6629    } else {
6630       sprintf(buf, "%1d", (int)(c_ptr-the_str));
6631    }
6632    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
6633    return TRUE;
6634 }
6635 
ExecRIndex(argv,obj_ptr,orig_cmd)6636 int ExecRIndex(argv, obj_ptr, orig_cmd)
6637    char **argv, *orig_cmd;
6638    struct ObjRec *obj_ptr;
6639    /* rindex(attr_name,str,substr); */
6640 {
6641    char *attr_name=argv[0], *the_str=argv[1], *sub_str=argv[2];
6642    char *c_ptr, *last_match=NULL, buf[40];
6643    struct AttrRec *attr_ptr;
6644    struct ObjRec *attr_owner_obj=NULL;
6645 
6646    UtilRemoveQuotes(attr_name);
6647    UtilRemoveQuotes(the_str);
6648    UtilRemoveQuotes(sub_str);
6649    sprintf(execDummyStr, "%s=", attr_name);
6650    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
6651    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6652 
6653    for (c_ptr=strstr(the_str, sub_str); c_ptr != NULL;
6654          c_ptr=strstr(&last_match[1], sub_str)) {
6655       last_match = c_ptr;
6656    }
6657    if (last_match == NULL) {
6658       strcpy(buf, "-1");
6659    } else {
6660       sprintf(buf, "%1d", (int)(last_match-the_str));
6661    }
6662    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
6663    return TRUE;
6664 }
6665 
ExecGetNumberOfLines(argv,obj_ptr,orig_cmd)6666 int ExecGetNumberOfLines(argv, obj_ptr, orig_cmd)
6667    char **argv, *orig_cmd;
6668    struct ObjRec *obj_ptr;
6669    /* get_number_of_lines_in_attr(result_attr,attr_name); */
6670 {
6671    char *result_attr_name=argv[0], *attr_name=argv[1], buf[40];
6672    int count;
6673    MiniLineInfo *pMiniLine=NULL;
6674    struct AttrRec *result_attr_ptr, *attr_ptr;
6675    struct ObjRec *result_attr_owner_obj=NULL, *attr_owner_obj=NULL;
6676 
6677    UtilRemoveQuotes(result_attr_name);
6678    UtilRemoveQuotes(attr_name);
6679 
6680    sprintf(execDummyStr, "%s=", attr_name);
6681    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
6682    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6683 
6684    sprintf(execDummyStr, "%s=", result_attr_name);
6685    result_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr,
6686          &result_attr_owner_obj);
6687    if (result_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6688 
6689    count = 0;
6690    for (pMiniLine=attr_ptr->obj->detail.t->minilines.first;
6691          pMiniLine != NULL; pMiniLine=pMiniLine->next) {
6692       count++;
6693    }
6694    sprintf(buf, "%1d", count);
6695    ReplaceAttrFirstValue(result_attr_owner_obj, result_attr_ptr, buf);
6696 
6697    SetFileModified(TRUE);
6698    return TRUE;
6699 }
6700 
ExecGetLineInAttr(argv,obj_ptr,orig_cmd)6701 int ExecGetLineInAttr(argv, obj_ptr, orig_cmd)
6702    char **argv, *orig_cmd;
6703    struct ObjRec *obj_ptr;
6704    /* get_line_in_attr(result_attr,attr_name,line_number); */
6705 {
6706    char *result_attr_name=argv[0], *attr_name=argv[1];
6707    char *line_number_str=argv[2], *psz=NULL;
6708    int count, line_number=(-1);
6709    MiniLineInfo *pMiniLine=NULL;
6710    struct AttrRec *result_attr_ptr, *attr_ptr;
6711    struct ObjRec *result_attr_owner_obj=NULL, *attr_owner_obj=NULL;
6712 
6713    UtilRemoveQuotes(result_attr_name);
6714    UtilRemoveQuotes(attr_name);
6715    UtilRemoveQuotes(line_number_str);
6716 
6717    sprintf(execDummyStr, "%s=", attr_name);
6718    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
6719    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6720 
6721    sprintf(execDummyStr, "%s=", result_attr_name);
6722    result_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr,
6723          &result_attr_owner_obj);
6724    if (result_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6725 
6726    if (!IntExpression(line_number_str, &line_number, orig_cmd)) {
6727       return FALSE;
6728    }
6729    count = 0;
6730    for (pMiniLine=attr_ptr->obj->detail.t->minilines.first;
6731          pMiniLine != NULL; pMiniLine=pMiniLine->next) {
6732       if (count == line_number) {
6733          int need_to_free_tmp_buf=FALSE;
6734          char *tmp_buf=NULL;
6735 
6736          if (pMiniLine == attr_ptr->obj->detail.t->minilines.first) {
6737             char *attr_value=NULL;
6738 
6739             tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
6740             attr_value = UtilStrDup(tmp_buf);
6741             if (attr_value == NULL) FailAllocMessage();
6742             ParseAttrStr(tmp_buf, NULL, 0, attr_value, strlen(attr_value)+1);
6743             if (need_to_free_tmp_buf) UtilFree(tmp_buf);
6744             psz = UtilStrDup(attr_value);
6745             UtilFree(attr_value);
6746          } else {
6747             tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
6748             psz = UtilStrDup(tmp_buf);
6749             if (need_to_free_tmp_buf) UtilFree(tmp_buf);
6750          }
6751          if (psz == NULL) FailAllocMessage();
6752          break;
6753       }
6754       count++;
6755    }
6756    if (psz == NULL) psz = UtilStrDup("");
6757    ReplaceAttrFirstValue(result_attr_owner_obj, result_attr_ptr, psz);
6758    UtilFree(psz);
6759 
6760    SetFileModified(TRUE);
6761    return TRUE;
6762 }
6763 
ExecTrim(argv,obj_ptr,orig_cmd)6764 int ExecTrim(argv, obj_ptr, orig_cmd)
6765    char **argv, *orig_cmd;
6766    struct ObjRec *obj_ptr;
6767    /* trim(attr_name); */
6768 {
6769    char *attr_name=argv[0], *psz;
6770    struct AttrRec *attr_ptr;
6771    struct ObjRec *attr_owner_obj=NULL;
6772 
6773    UtilRemoveQuotes(attr_name);
6774    sprintf(execDummyStr, "%s=", attr_name);
6775    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
6776    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6777 
6778    psz = UtilStrDup(attr_ptr->attr_value.s);
6779    if (psz == NULL) FailAllocMessage();
6780    UtilTrimBlanks(psz);
6781    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, psz);
6782    UtilFree(psz);
6783    return TRUE;
6784 }
6785 
ExecIsAttr(argv,obj_ptr,orig_cmd)6786 int ExecIsAttr(argv, obj_ptr, orig_cmd)
6787    char **argv, *orig_cmd;
6788    struct ObjRec *obj_ptr;
6789    /* is_attr(result_attr,attr_name); */
6790 {
6791    char *result_attr_name=argv[0], *attr_name=argv[1], buf[40];
6792    struct AttrRec *result_attr_ptr, *attr_ptr;
6793    struct ObjRec *result_attr_owner_obj=NULL, *attr_owner_obj=NULL;
6794 
6795    UtilRemoveQuotes(result_attr_name);
6796    UtilRemoveQuotes(attr_name);
6797 
6798    sprintf(execDummyStr, "%s=", attr_name);
6799    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
6800    strcpy(buf, (attr_ptr==NULL ? "0" : "1"));
6801 
6802    sprintf(execDummyStr, "%s=", result_attr_name);
6803    result_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr,
6804          &result_attr_owner_obj);
6805    if (result_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6806 
6807    ReplaceAttrFirstValue(result_attr_owner_obj, result_attr_ptr, buf);
6808 
6809    SetFileModified(TRUE);
6810    return TRUE;
6811 }
6812 
ExecFindObjNames(argv,obj_ptr,orig_cmd)6813 int ExecFindObjNames(argv, obj_ptr, orig_cmd)
6814    char **argv, *orig_cmd;
6815    struct ObjRec *obj_ptr;
6816    /* find_obj_names(result_attr,obj_name,attr_name_value); */
6817 {
6818    char *result_attr_name=argv[0], *obj_name=argv[1], *attr_str=argv[2];
6819    char *psz=NULL, *attr_name=NULL, *attr_value=NULL;
6820    struct AttrRec *result_attr_ptr=NULL;
6821    struct ObjRec *result_attr_owner_obj=NULL, *optr=NULL;
6822    struct ObjRec *parent_obj_ptr=NULL, *first_obj_ptr=NULL;
6823    int ok=TRUE;
6824 
6825    UtilRemoveQuotes(result_attr_name);
6826    UtilRemoveQuotes(obj_name);
6827    UtilRemoveQuotes(attr_str);
6828 
6829    sprintf(execDummyStr, "%s=", result_attr_name);
6830    result_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr,
6831          &result_attr_owner_obj);
6832    if (result_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6833 
6834    if (*obj_name == '\0') {
6835       parent_obj_ptr = NULL;
6836    } else if ((parent_obj_ptr=FindObjWithName(botObj, obj_ptr, obj_name, FALSE,
6837          FALSE, NULL, NULL)) == NULL) {
6838       return BadObjName(obj_name, orig_cmd);
6839    } else {
6840       switch (parent_obj_ptr->type) {
6841       case OBJ_GROUP:
6842       case OBJ_ICON:
6843       case OBJ_SYM:
6844       case OBJ_PIN:
6845          break;
6846       default:
6847          sprintf(gszMsgBox, TgLoadString(STID_NON_GROUPED_WHILE_EXEC_CMD),
6848                obj_name, orig_cmd);
6849          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
6850          return FALSE;
6851       }
6852    }
6853    if (strcmp(attr_str, "") == 0) {
6854       attr_name = attr_value = NULL;
6855    } else if ((psz=strchr(attr_str,'=')) != NULL) {
6856       if (*(++psz) != '\0') {
6857          if (strcmp(psz, "*") == 0) {
6858             attr_value = NULL;
6859          } else {
6860             attr_value = UtilStrDup(psz);
6861             if (attr_value == NULL) FailAllocMessage();
6862          }
6863          *psz = '\0';
6864       } else {
6865          attr_value = UtilStrDup("");
6866          if (attr_value == NULL) FailAllocMessage();
6867       }
6868       attr_name = attr_str;
6869    } else {
6870       attr_name = NULL;
6871       attr_value = UtilStrDup(attr_str);
6872       if (attr_value == NULL) FailAllocMessage();
6873    }
6874    CleanTmpStr();
6875 
6876    if (parent_obj_ptr == NULL) {
6877       first_obj_ptr = topObj;
6878    } else {
6879       first_obj_ptr = parent_obj_ptr->detail.r->first;
6880    }
6881    for (optr=first_obj_ptr; optr != NULL; optr=optr->next) {
6882       struct AttrRec *name_attr=FindAttrWithName(optr,"name=",NULL);
6883 
6884       if (name_attr != NULL) {
6885          if (attr_name == NULL && attr_value == NULL) {
6886             if (!AppendToTmpStr(name_attr->attr_value.s)) {
6887                ok = FALSE;
6888                break;
6889             }
6890          } else {
6891             struct AttrRec *aptr=NULL;
6892 
6893             for (aptr=optr->fattr; aptr != NULL; aptr=aptr->next) {
6894                if (attr_name == NULL) {
6895                   if (*aptr->attr_name.s == '\0' &&
6896                         strcmp(aptr->attr_value.s, attr_value) == 0) {
6897                      break;
6898                   }
6899                } else if (attr_value == NULL) {
6900                   if (strcmp(aptr->attr_name.s, attr_name) == 0) {
6901                      break;
6902                   }
6903                } else {
6904                   if (strcmp(aptr->attr_name.s, attr_name) == 0 &&
6905                         strcmp(aptr->attr_value.s, attr_value) == 0) {
6906                      break;
6907                   }
6908                }
6909             }
6910             if (aptr != NULL && !AppendToTmpStr(name_attr->attr_value.s)) {
6911                ok = FALSE;
6912                break;
6913             }
6914          }
6915       }
6916    }
6917    if (ok) {
6918       int count=0;
6919       char *count_buf=(char*)malloc((strlen(result_attr_name)+40)*sizeof(char));
6920       struct StrRec *str_ptr;
6921 
6922       if (count_buf == NULL) FailAllocMessage();
6923       for (str_ptr=topTmpStr; str_ptr != NULL; str_ptr=str_ptr->next) {
6924          count++;
6925       }
6926       sprintf(count_buf, "%s=%d", result_attr_name, count);
6927       if (PrependToTmpStr(count_buf)) {
6928          ReplaceAttrAllValues(result_attr_owner_obj, result_attr_ptr,
6929                &topTmpStr, &botTmpStr);
6930       }
6931       free(count_buf);
6932    }
6933    CleanTmpStr();
6934    if (attr_value != NULL) UtilFree(attr_value);
6935    return TRUE;
6936 }
6937 
6938 static
FindObjNamesOnAllPgs(argv,obj_ptr,orig_cmd,tg2)6939 int FindObjNamesOnAllPgs(argv, obj_ptr, orig_cmd, tg2)
6940    char **argv, *orig_cmd;
6941    struct ObjRec *obj_ptr;
6942    int tg2;
6943    /*
6944     * find_obj_names_on_all_pages(result_attr,attr_name_value) or
6945     * tg2_find_obj_names_on_all_pages(result_attr,attr_name_value)
6946     */
6947 {
6948    char *result_attr_name=argv[0], *attr_str=argv[1];
6949    char *psz=NULL, *attr_name=NULL, *attr_value=NULL;
6950    struct AttrRec *result_attr_ptr=NULL;
6951    struct ObjRec *result_attr_owner_obj=NULL;
6952    struct PageRec *page_ptr=NULL;
6953    int ok=TRUE, page_num=0;
6954 
6955    UtilRemoveQuotes(result_attr_name);
6956    UtilRemoveQuotes(attr_str);
6957 
6958    sprintf(execDummyStr, "%s=", result_attr_name);
6959    result_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr,
6960          &result_attr_owner_obj);
6961    if (result_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
6962 
6963    if (strcmp(attr_str, "") == 0) {
6964       attr_name = attr_value = NULL;
6965    } else if ((psz=strchr(attr_str,'=')) != NULL) {
6966       if (*(++psz) != '\0') {
6967          if (strcmp(psz, "*") == 0) {
6968             attr_value = NULL;
6969          } else {
6970             attr_value = UtilStrDup(psz);
6971             if (attr_value == NULL) FailAllocMessage();
6972          }
6973          *psz = '\0';
6974       } else {
6975          attr_value = UtilStrDup("");
6976          if (attr_value == NULL) FailAllocMessage();
6977       }
6978       attr_name = attr_str;
6979    } else {
6980       attr_name = NULL;
6981       attr_value = UtilStrDup(attr_str);
6982       if (attr_value == NULL) FailAllocMessage();
6983    }
6984    CleanTmpStr();
6985 
6986    for (page_ptr=firstPage, page_num=1; page_ptr != NULL;
6987          page_ptr=page_ptr->next, page_num++) {
6988       char prefix[80];
6989       struct ObjRec *optr=NULL;
6990 
6991       if (tg2) {
6992          sprintf(prefix, "_Page%1d", page_num);
6993       } else {
6994          sprintf(prefix, "##%1d!", page_num);
6995       }
6996       for (optr=page_ptr->top; optr != NULL; optr=optr->next) {
6997          struct AttrRec *name_attr=FindAttrWithName(optr,"name=",NULL);
6998 
6999          if (name_attr != NULL) {
7000             if (attr_name == NULL && attr_value == NULL) {
7001                if (firstPage == lastPage) {
7002                   if (!AppendToTmpStr(name_attr->attr_value.s)) {
7003                      ok = FALSE;
7004                      break;
7005                   }
7006                } else {
7007                   if (!AppendToTmpStr2(prefix, name_attr->attr_value.s, tg2)) {
7008                      ok = FALSE;
7009                      break;
7010                   }
7011                }
7012             } else {
7013                struct AttrRec *aptr=NULL;
7014 
7015                for (aptr=optr->fattr; aptr != NULL; aptr=aptr->next) {
7016                   if (attr_name == NULL) {
7017                      if (*aptr->attr_name.s == '\0' &&
7018                            strcmp(aptr->attr_value.s, attr_value) == 0) {
7019                         break;
7020                      }
7021                   } else if (attr_value == NULL) {
7022                      if (strcmp(aptr->attr_name.s, attr_name) == 0) {
7023                         break;
7024                      }
7025                   } else {
7026                      if (strcmp(aptr->attr_name.s, attr_name) == 0 &&
7027                            strcmp(aptr->attr_value.s, attr_value) == 0) {
7028                         break;
7029                      }
7030                   }
7031                }
7032                if (aptr != NULL) {
7033                   if (firstPage == lastPage) {
7034                      if (!AppendToTmpStr(name_attr->attr_value.s)) {
7035                         ok = FALSE;
7036                         break;
7037                      }
7038                   } else {
7039                      if (!AppendToTmpStr2(prefix, name_attr->attr_value.s,
7040                            tg2)) {
7041                         ok = FALSE;
7042                         break;
7043                      }
7044                   }
7045                }
7046             }
7047          }
7048       }
7049    }
7050    if (ok) {
7051       int count=0;
7052       char *count_buf=(char*)malloc((strlen(result_attr_name)+40)*sizeof(char));
7053       struct StrRec *str_ptr;
7054 
7055       if (count_buf == NULL) FailAllocMessage();
7056       for (str_ptr=topTmpStr; str_ptr != NULL; str_ptr=str_ptr->next) {
7057          count++;
7058       }
7059       sprintf(count_buf, "%s=%d", result_attr_name, count);
7060       if (PrependToTmpStr(count_buf)) {
7061          ReplaceAttrAllValues(result_attr_owner_obj, result_attr_ptr,
7062                &topTmpStr, &botTmpStr);
7063       }
7064       free(count_buf);
7065    }
7066    CleanTmpStr();
7067    if (attr_value != NULL) UtilFree(attr_value);
7068    return TRUE;
7069 }
7070 
ExecFindObjNamesOnAllPgs(argv,obj_ptr,orig_cmd)7071 int ExecFindObjNamesOnAllPgs(argv, obj_ptr, orig_cmd)
7072    char **argv, *orig_cmd;
7073    struct ObjRec *obj_ptr;
7074    /* find_obj_names_on_all_pages(result_attr,attr_name_value); */
7075 {
7076    char *result_attr_name=argv[0], *attr_str=argv[1];
7077    struct AttrRec *result_attr_ptr=NULL;
7078    struct ObjRec *result_attr_owner_obj=NULL;
7079 
7080    UtilRemoveQuotes(result_attr_name);
7081    UtilRemoveQuotes(attr_str);
7082 
7083    sprintf(execDummyStr, "%s=", result_attr_name);
7084    result_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr,
7085          &result_attr_owner_obj);
7086    if (result_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
7087 
7088    return FindObjNamesOnAllPgs(argv, obj_ptr, orig_cmd, FALSE);
7089 }
7090 
ExecTg2FindObjNsOnAllPgs(argv,obj_ptr,orig_cmd)7091 int ExecTg2FindObjNsOnAllPgs(argv, obj_ptr, orig_cmd)
7092    char **argv, *orig_cmd;
7093    struct ObjRec *obj_ptr;
7094    /* tg2_find_obj_names_on_all_pages(result_attr,attr_name_value); */
7095 {
7096    char *result_attr_name=argv[0], *attr_str=argv[1];
7097    struct AttrRec *result_attr_ptr=NULL;
7098    struct ObjRec *result_attr_owner_obj=NULL;
7099 
7100    UtilRemoveQuotes(result_attr_name);
7101    UtilRemoveQuotes(attr_str);
7102 
7103    sprintf(execDummyStr, "%s=", result_attr_name);
7104    result_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr,
7105          &result_attr_owner_obj);
7106    if (result_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
7107 
7108    return FindObjNamesOnAllPgs(argv, obj_ptr, orig_cmd, TRUE);
7109 }
7110 
ExecTokenize(argv,obj_ptr,orig_cmd)7111 int ExecTokenize(argv, obj_ptr, orig_cmd)
7112    char **argv, *orig_cmd;
7113    struct ObjRec *obj_ptr;
7114    /* tokenize(result_attr,string,separator); */
7115 {
7116    char *result_attr_name=argv[0], *str=argv[1], *separator=argv[2], *psz;
7117    int ok=TRUE, just_got_sep=FALSE;
7118    struct AttrRec *result_attr_ptr;
7119    struct ObjRec *result_attr_owner_obj=NULL;
7120 
7121    UtilRemoveQuotes(result_attr_name);
7122    UtilRemoveQuotes(str);
7123    UtilRemoveQuotes(separator);
7124 
7125    sprintf(execDummyStr, "%s=", result_attr_name);
7126    result_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr,
7127          &result_attr_owner_obj);
7128    if (result_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
7129 
7130    if (strlen(separator) != 1) {
7131       sprintf(gszMsgBox, TgLoadString(STID_BAD_SEP_LONG_WHILE_EXEC_CMD),
7132             separator, orig_cmd);
7133       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7134       return FALSE;
7135    } else if (*separator == ' ' || *separator == '"' || *separator == '\'') {
7136       sprintf(gszMsgBox, TgLoadString(STID_BAD_SEP_WHILE_EXEC_CMD),
7137             separator, orig_cmd);
7138       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7139       return FALSE;
7140    }
7141    CleanTmpStr();
7142 
7143    psz = str;
7144    while (*psz != '\0') {
7145       char sep=(*separator), quote='\0', *start=NULL;
7146       int done=FALSE, inc=TRUE;
7147 
7148       while (*psz == ' ') psz++;
7149 
7150       start = psz;
7151       if (*psz == '\0') {
7152          if (just_got_sep) {
7153             UtilRightTrim(start);
7154             ok = AppendToTmpStr(start);
7155             just_got_sep = FALSE;
7156          }
7157          break;
7158       }
7159       if (*psz == '"' || *psz == '\'') {
7160          just_got_sep = FALSE;
7161          quote = (*psz);
7162          for (psz++; *psz != '\0' && *psz != quote; psz++) ;
7163          if (*psz == quote) {
7164             start = (&start[1]);
7165             *psz = '\0';
7166             ok = AppendToTmpStr(start);
7167             *psz = quote;
7168             if (ok) {
7169                psz++;
7170                while (*psz == ' ') psz++;
7171                if (*psz == '\0') {
7172                   done = TRUE;
7173                } else if (*psz == sep) {
7174                   just_got_sep = TRUE;
7175                } else {
7176                   inc = FALSE;
7177                }
7178             }
7179          } else {
7180             done = TRUE;
7181             UtilRightTrim(start);
7182             ok = AppendToTmpStr(start);
7183          }
7184       } else if (*psz == sep) {
7185          *psz = '\0';
7186          UtilRightTrim(start);
7187          ok = AppendToTmpStr(start);
7188          *psz = sep;
7189          just_got_sep = TRUE;
7190          if (!ok) break;
7191       } else {
7192          just_got_sep = FALSE;
7193          for (psz++; *psz != '\0' && *psz != sep; psz++) ;
7194          if (*psz == '\0') {
7195             if (start != psz) {
7196                char ch=(*psz);
7197 
7198                *psz = '\0';
7199                UtilRightTrim(start);
7200                ok = AppendToTmpStr(start);
7201                *psz = ch;
7202             }
7203             done = TRUE;
7204          } else if (*psz == sep) {
7205             *psz = '\0';
7206             UtilRightTrim(start);
7207             ok = AppendToTmpStr(start);
7208             *psz = sep;
7209             just_got_sep = TRUE;
7210          }
7211       }
7212       if (!ok || done) break;
7213       if (inc) psz++;
7214    }
7215    if (ok && just_got_sep) {
7216       ok = AppendToTmpStr("");
7217    }
7218    if (ok) {
7219       int count=0;
7220       char *count_buf=(char*)malloc((strlen(result_attr_name)+40)*sizeof(char));
7221       struct StrRec *str_ptr;
7222 
7223       if (count_buf == NULL) FailAllocMessage();
7224       for (str_ptr=topTmpStr; str_ptr != NULL; str_ptr=str_ptr->next) {
7225          count++;
7226       }
7227       sprintf(count_buf, "%s%d", result_attr_ptr->attr_name.s, count);
7228       if (PrependToTmpStr(count_buf)) {
7229          ReplaceAttrAllValues(result_attr_owner_obj, result_attr_ptr,
7230                &topTmpStr, &botTmpStr);
7231       }
7232       free(count_buf);
7233    }
7234    CleanTmpStr();
7235    return TRUE;
7236 }
7237 
ExecMoveAttrRel(argv,obj_ptr,orig_cmd)7238 int ExecMoveAttrRel(argv, obj_ptr, orig_cmd)
7239    char **argv, *orig_cmd;
7240    struct ObjRec *obj_ptr;
7241    /* move_attr_relative(attr_name,dx,dy); */
7242 {
7243    char *attr_name=argv[0];
7244    char *dx_str=argv[1], *dy_str=argv[2];
7245    int dx, dy;
7246    struct AttrRec *attr_ptr;
7247    struct ObjRec *attr_owner_obj=NULL;
7248 
7249    UtilRemoveQuotes(attr_name);
7250 
7251    sprintf(execDummyStr, "%s=", attr_name);
7252    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
7253    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
7254 
7255    UtilRemoveQuotes(dx_str);
7256    UtilRemoveQuotes(dy_str);
7257    if (!IntExpression(dx_str, &dx, orig_cmd) ||
7258          !IntExpression(dy_str, &dy, orig_cmd)) {
7259       return FALSE;
7260    }
7261    if (dx != 0 || dy != 0) {
7262       MoveAnAttr(attr_ptr, attr_owner_obj, dx, dy);
7263       SetFileModified(TRUE);
7264    }
7265    return TRUE;
7266 }
7267 
ExecGetNumberOfVs(argv,obj_ptr,orig_cmd)7268 int ExecGetNumberOfVs(argv, obj_ptr, orig_cmd)
7269    char **argv, *orig_cmd;
7270    struct ObjRec *obj_ptr;
7271    /* get_number_of_vertices(result_attr,obj_name); */
7272 {
7273    char *result_attr_name=argv[0], *obj_name=argv[1], buf[40];
7274    int count=0;
7275    struct AttrRec *result_attr_ptr=NULL;
7276    struct ObjRec *result_attr_owner_obj=NULL, *owner_obj=NULL, *named_obj=NULL;
7277 
7278    UtilRemoveQuotes(result_attr_name);
7279    UtilRemoveQuotes(obj_name);
7280 
7281    named_obj = FindObjWithName(botObj, obj_ptr, obj_name, FALSE,
7282          FALSE, &owner_obj, NULL);
7283    if (named_obj == NULL) return BadObjName(obj_name, orig_cmd);
7284 
7285    sprintf(execDummyStr, "%s=", result_attr_name);
7286    result_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr,
7287          &result_attr_owner_obj);
7288    if (result_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
7289 
7290    switch (named_obj->type) {
7291    case OBJ_POLY: count = named_obj->detail.p->n; break;
7292    case OBJ_POLYGON: count = named_obj->detail.g->n-1; break;
7293    default:
7294       sprintf(execDummyStr, TgLoadString(STID_POLY_NOR_PGON_WHILE_EXEC_CMD),
7295             obj_name, orig_cmd);
7296       MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
7297       return FALSE;
7298    }
7299    sprintf(buf, "%1d", count);
7300    ReplaceAttrFirstValue(result_attr_owner_obj, result_attr_ptr, buf);
7301 
7302    SetFileModified(TRUE);
7303    return TRUE;
7304 }
7305 
ExecIsObjTransformed(argv,obj_ptr,orig_cmd)7306 int ExecIsObjTransformed(argv, obj_ptr, orig_cmd)
7307    char **argv, *orig_cmd;
7308    struct ObjRec *obj_ptr;
7309    /* is_obj_transformed(result_attr,obj_name); */
7310 {
7311    char *result_attr_name=argv[0], *obj_name=argv[1], buf[40];
7312    struct AttrRec *result_attr_ptr=NULL;
7313    struct ObjRec *result_attr_owner_obj=NULL, *owner_obj=NULL, *named_obj=NULL;
7314 
7315    UtilRemoveQuotes(result_attr_name);
7316    UtilRemoveQuotes(obj_name);
7317 
7318    named_obj = FindObjWithName(botObj, obj_ptr, obj_name, FALSE,
7319          FALSE, &owner_obj, NULL);
7320    if (named_obj == NULL) return BadObjName(obj_name, orig_cmd);
7321    strcpy(buf, (named_obj->ctm==NULL ? "0" : "1"));
7322 
7323    sprintf(execDummyStr, "%s=", result_attr_name);
7324    result_attr_ptr = FindAttrWithName(obj_ptr, execDummyStr,
7325          &result_attr_owner_obj);
7326    if (result_attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
7327 
7328    ReplaceAttrFirstValue(result_attr_owner_obj, result_attr_ptr, buf);
7329 
7330    SetFileModified(TRUE);
7331    return TRUE;
7332 }
7333 
ExecMakeSelObjIconic(argv,obj_ptr,orig_cmd)7334 int ExecMakeSelObjIconic(argv, obj_ptr, orig_cmd)
7335    char **argv, *orig_cmd;
7336    struct ObjRec *obj_ptr;
7337    /* make_selected_obj_iconic(sym_path); */
7338 {
7339    char *sym_path=argv[0];
7340 
7341    UtilRemoveQuotes(sym_path);
7342 
7343    if (topSel == NULL) return BadSelectedObj(orig_cmd);
7344    if (topSel != botSel) {
7345       sprintf(execDummyStr, TgLoadString(STID_MORE_THAN_ONE_WHILE_EXEC_CMD),
7346             orig_cmd);
7347       MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
7348       return FALSE;
7349    }
7350    if (*sym_path != DIR_SEP) {
7351       sprintf(execDummyStr, TgLoadString(STID_MUST_FULL_PATH_WHILE_EXEC_CMD),
7352             sym_path, orig_cmd);
7353       MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
7354       return FALSE;
7355    }
7356    if (!MakeIconic(sym_path, TRUE)) {
7357       return FALSE;
7358    }
7359    return TRUE;
7360 }
7361 
ExecMoveNamedObjRel(argv,obj_ptr,orig_cmd)7362 int ExecMoveNamedObjRel(argv, obj_ptr, orig_cmd)
7363    char **argv, *orig_cmd;
7364    struct ObjRec *obj_ptr;
7365    /* move_named_obj_relative(obj_name,dx,dy); */
7366 {
7367    char *obj_name=argv[0], *dx_str=argv[1], *dy_str=argv[2];
7368    int dx=0, dy=0;
7369    struct ObjRec *top_owner=NULL, *named_obj=NULL;
7370 
7371    UtilRemoveQuotes(obj_name);
7372    UtilTrimBlanks(obj_name);
7373    UtilRemoveQuotes(dx_str);
7374    UtilRemoveQuotes(dy_str);
7375 
7376    named_obj = FindObjWithName(botObj, obj_ptr, obj_name, FALSE,
7377          FALSE, NULL, &top_owner);
7378    if (named_obj == NULL) {
7379       return BadObjName(obj_name, orig_cmd);
7380    }
7381    if (!IntExpression(dx_str, &dx, orig_cmd) ||
7382          !IntExpression(dy_str, &dy, orig_cmd)) {
7383       return FALSE;
7384    }
7385    if (dx == 0 && dy == 0) {
7386       return TRUE;
7387    }
7388    /* MoveAnObj() can only be called from within an internal command */
7389    MoveAnObj(named_obj, top_owner, dx, dy);
7390    SetFileModified(TRUE);
7391 
7392    return TRUE;
7393 }
7394 
ExecMoveNamedObjAbs(argv,obj_ptr,orig_cmd)7395 int ExecMoveNamedObjAbs(argv, obj_ptr, orig_cmd)
7396    char **argv, *orig_cmd;
7397    struct ObjRec *obj_ptr;
7398    /* move_named_obj_absolute(obj_name,ltx,lty); */
7399 {
7400    char *obj_name=argv[0], *ltx_str=argv[1], *lty_str=argv[2];
7401    int ltx=0, lty=0;
7402    struct ObjRec *top_owner=NULL, *named_obj=NULL;
7403 
7404    UtilRemoveQuotes(obj_name);
7405    UtilTrimBlanks(obj_name);
7406    UtilRemoveQuotes(ltx_str);
7407    UtilRemoveQuotes(lty_str);
7408 
7409    named_obj = FindObjWithName(botObj, obj_ptr, obj_name, FALSE,
7410          FALSE, NULL, &top_owner);
7411    if (named_obj == NULL) {
7412       return BadObjName(obj_name, orig_cmd);
7413    }
7414    if (!IntExpression(ltx_str, &ltx, orig_cmd) ||
7415          !IntExpression(lty_str, &lty, orig_cmd)) {
7416       return FALSE;
7417    }
7418    if (ltx == named_obj->obbox.ltx && lty == named_obj->obbox.lty) {
7419       return TRUE;
7420    }
7421    /* MoveAnObj() can only be called from within an internal command */
7422    MoveAnObj(named_obj, top_owner, ltx-named_obj->obbox.ltx,
7423          lty-named_obj->obbox.lty);
7424    SetFileModified(TRUE);
7425 
7426    return TRUE;
7427 }
7428 
ExecGetTgifVersion(argv,obj_ptr,orig_cmd)7429 int ExecGetTgifVersion(argv, obj_ptr, orig_cmd)
7430    char **argv, *orig_cmd;
7431    struct ObjRec *obj_ptr;
7432    /* get_tgif_version(major_attr,minor_attr,patchlevel_attr,build_attr); */
7433 {
7434    char *major_attr_name=argv[0], *minor_attr_name=argv[1];
7435    char *patchlevel_attr_name=argv[2], *build_attr_name=argv[3];
7436    char buf[40], *psz=NULL;
7437    struct AttrRec *attr_ptr;
7438    struct ObjRec *attr_owner_obj=NULL;
7439 
7440    UtilRemoveQuotes(major_attr_name);
7441    UtilRemoveQuotes(minor_attr_name);
7442    UtilRemoveQuotes(patchlevel_attr_name);
7443    UtilRemoveQuotes(build_attr_name);
7444    if (strcmp(major_attr_name, "NULL") != 0) {
7445       sprintf(execDummyStr, "%s=", major_attr_name);
7446       attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
7447       if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
7448       strcpy(buf, versionString);
7449       if ((psz=strchr(buf, '.')) != NULL) {
7450          *psz = '\0';
7451       }
7452       ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
7453    }
7454    if (strcmp(minor_attr_name, "NULL") != 0) {
7455       sprintf(execDummyStr, "%s=", minor_attr_name);
7456       attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
7457       if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
7458       strcpy(buf, versionString);
7459       if ((psz=strchr(buf, '.')) != NULL) {
7460          ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, ++psz);
7461       } else {
7462          ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, "");
7463       }
7464    }
7465    if (strcmp(patchlevel_attr_name, "NULL") != 0) {
7466       sprintf(execDummyStr, "%s=", patchlevel_attr_name);
7467       attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
7468       if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
7469       sprintf(buf, "%1d", TGIF_PATCHLEVEL);
7470       ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
7471    }
7472    if (strcmp(build_attr_name, "NULL") != 0) {
7473       sprintf(execDummyStr, "%s=", build_attr_name);
7474       attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
7475       if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
7476       ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, specialBuild);
7477    }
7478    return TRUE;
7479 }
7480 
ExecGetTgifDir(argv,obj_ptr,orig_cmd)7481 int ExecGetTgifDir(argv, obj_ptr, orig_cmd)
7482    char **argv, *orig_cmd;
7483    struct ObjRec *obj_ptr;
7484    /* get_tgif_dir(attr_name); */
7485 {
7486    char *attr_name=argv[0];
7487    struct AttrRec *attr_ptr;
7488    struct ObjRec *attr_owner_obj=NULL;
7489 
7490    UtilRemoveQuotes(attr_name);
7491    sprintf(execDummyStr, "%s=", attr_name);
7492    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
7493    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
7494 
7495    ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, tgifDir);
7496    return TRUE;
7497 }
7498 
ExecGetProfileString(argv,obj_ptr,orig_cmd)7499 int ExecGetProfileString(argv, obj_ptr, orig_cmd)
7500    char **argv, *orig_cmd;
7501    struct ObjRec *obj_ptr;
7502    /* get_profile_string(attr_name,section,key,def_value,ini_path); */
7503 {
7504    char *attr_name=argv[0], *section=argv[1], *key=argv[2], *def_value=argv[3];
7505    char *ini_path=argv[4];
7506    char *values=NULL;
7507    struct AttrRec *attr_ptr;
7508    struct ObjRec *attr_owner_obj=NULL;
7509 
7510    UtilRemoveQuotes(attr_name);
7511    UtilRemoveQuotes(section);
7512    UtilRemoveQuotes(key);
7513    UtilRemoveQuotes(ini_path);
7514    sprintf(execDummyStr, "%s=", attr_name);
7515    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
7516    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
7517 
7518    if (*ini_path != DIR_SEP) {
7519       sprintf(gszMsgBox, TgLoadString(STID_INVALID_GIVEN_PATH_MUST_FULL),
7520             ini_path);
7521       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7522       return FALSE;
7523    }
7524    values = tgGetProfileString((*section=='\0' ? NULL : section),
7525          (*key=='\0' ? NULL : key), ini_path);
7526 
7527    if (values != NULL) {
7528       if (*section == '\0' || *key == '\0') {
7529          int count=0, ok=TRUE;
7530          char *psz=NULL;
7531          char *count_buf=(char*)malloc((strlen(attr_name)+40)*sizeof(char));
7532 
7533          if (count_buf == NULL) FailAllocMessage();
7534          CleanTmpStr();
7535          for (psz=values; *psz != '\0'; psz++) {
7536             if (!AppendToTmpStr(psz)) {
7537                ok = FALSE;
7538                break;
7539             }
7540             psz += strlen(psz);
7541             count++;
7542          }
7543          if (ok) {
7544             sprintf(count_buf, "%s=%d", attr_name, count);
7545             if (PrependToTmpStr(count_buf)) {
7546                ReplaceAttrAllValues(attr_owner_obj, attr_ptr, &topTmpStr,
7547                      &botTmpStr);
7548             }
7549          }
7550          free(count_buf);
7551          CleanTmpStr();
7552       } else {
7553          ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, values);
7554       }
7555       tgFreeProfileString(values);
7556    } else {
7557       ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, def_value);
7558    }
7559    return TRUE;
7560 }
7561 
ExecWriteProfileString(argv,obj_ptr,orig_cmd)7562 int ExecWriteProfileString(argv, obj_ptr, orig_cmd)
7563    char **argv, *orig_cmd;
7564    struct ObjRec *obj_ptr;
7565    /* write_profile_string(section,key,value,ini_path); */
7566 {
7567    char *section=argv[0], *key=argv[1], *value=argv[2], *ini_path=argv[3];
7568 
7569    UtilRemoveQuotes(section);
7570    UtilRemoveQuotes(key);
7571    UtilRemoveQuotes(value);
7572    UtilRemoveQuotes(ini_path);
7573 
7574    if (inHyperSpace && !allowLaunchInHyperSpace) {
7575       XFlush(mainDisplay);
7576       XSync(mainDisplay, False);
7577       sprintf(gszMsgBox, TgLoadString(STID_WRITE_NOT_AUTO_IN_HYPER_EXEC),
7578             ini_path);
7579       if (MsgBox(gszMsgBox, TOOL_NAME, YN_MB) != MB_ID_YES) {
7580          MsgBox(TgLoadString(STID_USER_ABORT_WRITE_IN_HYPER), TOOL_NAME,
7581                INFO_MB);
7582          return FALSE;
7583       }
7584    }
7585    if (*ini_path != DIR_SEP) {
7586       sprintf(gszMsgBox, TgLoadString(STID_INVALID_GIVEN_PATH_MUST_FULL),
7587             ini_path);
7588       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7589       return FALSE;
7590    }
7591    if (tgWriteProfileString((*section=='\0' ? NULL : section),
7592          (*key=='\0' ? NULL : key), value, ini_path)) {
7593       tgWriteProfileString(NULL, NULL, NULL, ini_path);
7594    }
7595    return TRUE;
7596 }
7597 
ExecSelectAdditionalObj(argv,obj_ptr,orig_cmd)7598 int ExecSelectAdditionalObj(argv, obj_ptr, orig_cmd)
7599    char **argv, *orig_cmd;
7600    struct ObjRec *obj_ptr;
7601    /* select_additional_obj(obj_name); */
7602 {
7603    char *obj_name=argv[0];
7604    struct ObjRec *owner_obj=NULL, *named_obj=NULL;
7605 
7606    UtilRemoveQuotes(obj_name);
7607    UtilTrimBlanks(obj_name);
7608 
7609    named_obj = FindObjWithName(botObj, obj_ptr, obj_name, FALSE,
7610          FALSE, &owner_obj, NULL);
7611    if (named_obj == NULL) {
7612       return BadObjName(obj_name, orig_cmd);
7613    }
7614    if (owner_obj != NULL) {
7615       sprintf(execDummyStr, TgLoadString(STID_BAD_NAME_TOP_LEVEL_ONLY_CMD),
7616             obj_name, orig_cmd);
7617       MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
7618       return FALSE;
7619    }
7620    if (AlreadySelected(named_obj)) {
7621       sprintf(execDummyStr, TgLoadString(STID_OBJ_ALRDY_SEL_WHILE_EXEC_CMD),
7622             obj_name, orig_cmd);
7623       MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
7624       return FALSE;
7625    }
7626    AddNewSelObj(named_obj);
7627    UpdSelBBox();
7628 
7629    return TRUE;
7630 }
7631 
ExecOpenFile(argv,obj_ptr,orig_cmd)7632 int ExecOpenFile(argv, obj_ptr, orig_cmd)
7633    char **argv, *orig_cmd;
7634    struct ObjRec *obj_ptr;
7635    /* open_file(file_number,file_name,file_mode); */
7636 {
7637    char *file_number_str=argv[0], *file_name=argv[1], *file_mode=argv[2];
7638    int file_number=(-1);
7639 
7640    UtilRemoveQuotes(file_number_str);
7641    UtilRemoveQuotes(file_name);
7642    UtilRemoveQuotes(file_mode);
7643    UtilTrimBlanks(file_name);
7644    UtilTrimBlanks(file_mode);
7645 
7646    if (*file_name == '\0') {
7647       sprintf(gszMsgBox, TgLoadString(STID_INVALID_FNAME_WHILE_EXEC_CMD),
7648             file_name, orig_cmd);
7649       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7650       return FALSE;
7651    } else if (*file_mode == '\0') {
7652       sprintf(gszMsgBox, TgLoadString(STID_INVALID_FMODE_WHILE_EXEC_CMD),
7653             file_mode, orig_cmd);
7654       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7655       return FALSE;
7656    } else if (!IntExpression(file_number_str, &file_number, orig_cmd)) {
7657       return FALSE;
7658    }
7659    if (inHyperSpace && !allowLaunchInHyperSpace &&
7660          (*file_mode == 'w' || *file_mode == 'a')) {
7661       XFlush(mainDisplay);
7662       XSync(mainDisplay, False);
7663       sprintf(gszMsgBox, TgLoadString(STID_WRITE_NOT_AUTO_IN_HYPER_EXEC),
7664             file_name);
7665       if (MsgBox(gszMsgBox, TOOL_NAME, YN_MB) != MB_ID_YES) {
7666          MsgBox(TgLoadString(STID_USER_ABORT_WRITE_IN_HYPER), TOOL_NAME,
7667                INFO_MB);
7668          return FALSE;
7669       }
7670    }
7671    if (file_number == 0) {
7672       rewind(stdin);
7673    } else if (file_number < 0 || file_number == 1 || file_number == 2 ||
7674          file_number >= MAXEXECOPENFILES) {
7675       sprintf(gszMsgBox, TgLoadString(STID_INVALID_FNUM_WHILE_EXEC_CMD),
7676             file_number_str, orig_cmd);
7677       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7678       return FALSE;
7679    } else if (gaOpenFileInfo[file_number].fp != NULL) {
7680       sprintf(gszMsgBox, TgLoadString(STID_FNUM_ARDY_OPEN_WHILE_EXEC_CMD),
7681             file_number, orig_cmd);
7682       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7683       return FALSE;
7684    } else if ((gaOpenFileInfo[file_number].fp=fopen(file_name, file_mode)) ==
7685          NULL) {
7686       sprintf(gszMsgBox, TgLoadString(STID_CANT_OPEN_FMOD_WRITE_EXEC_CMD),
7687             file_name, file_mode, orig_cmd);
7688       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7689       return FALSE;
7690    } else if ((gaOpenFileInfo[file_number].fname=UtilStrDup(file_name)) ==
7691          NULL) {
7692       FailAllocMessage();
7693    }
7694    gaOpenFileInfo[file_number].eof = FALSE;
7695    return TRUE;
7696 }
7697 
ExecCloseFile(argv,obj_ptr,orig_cmd)7698 int ExecCloseFile(argv, obj_ptr, orig_cmd)
7699    char **argv, *orig_cmd;
7700    struct ObjRec *obj_ptr;
7701    /* close_file(file_number); */
7702 {
7703    char *file_number_str=argv[0];
7704    int file_number=(-1);
7705 
7706    UtilRemoveQuotes(file_number_str);
7707 
7708    if (!IntExpression(file_number_str, &file_number, orig_cmd)) {
7709       return FALSE;
7710    }
7711    if (file_number == 0) {
7712       rewind(stdin);
7713    } else if (file_number < 0 || file_number == 1 || file_number == 2 ||
7714          file_number >= MAXEXECOPENFILES) {
7715       sprintf(gszMsgBox, TgLoadString(STID_INVALID_FNUM_WHILE_EXEC_CMD),
7716             file_number_str, orig_cmd);
7717       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7718       return FALSE;
7719    } else if (gaOpenFileInfo[file_number].fp == NULL) {
7720       sprintf(gszMsgBox, TgLoadString(STID_FNUM_NOT_OPEN_WHILE_EXEC_CMD),
7721             file_number, orig_cmd);
7722       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7723       return FALSE;
7724    } else {
7725       fclose(gaOpenFileInfo[file_number].fp);
7726       UtilFree(gaOpenFileInfo[file_number].fname);
7727       gaOpenFileInfo[file_number].fp = NULL;
7728       gaOpenFileInfo[file_number].fname = NULL;
7729       gaOpenFileInfo[file_number].eof = FALSE;
7730    }
7731    return TRUE;
7732 }
7733 
ExecReadFile(argv,obj_ptr,orig_cmd)7734 int ExecReadFile(argv, obj_ptr, orig_cmd)
7735    char **argv, *orig_cmd;
7736    struct ObjRec *obj_ptr;
7737    /* read_file(file_number,result_attr); */
7738 {
7739    char *file_number_str=argv[0], *result_attr_name=argv[1], *buf=NULL;
7740    int file_number=(-1);
7741    struct AttrRec *result_attr=NULL;
7742    struct ObjRec *result_attr_owner_obj=NULL;
7743 
7744    UtilRemoveQuotes(file_number_str);
7745    UtilRemoveQuotes(result_attr_name);
7746    UtilTrimBlanks(result_attr_name);
7747 
7748    if (!IntExpression(file_number_str, &file_number, orig_cmd)) {
7749       return FALSE;
7750    }
7751    sprintf(execDummyStr, "%s=", result_attr_name);
7752    result_attr = FindAttrWithName(obj_ptr, execDummyStr,
7753          &result_attr_owner_obj);
7754    if (result_attr == NULL) return BadAttr(execDummyStr, orig_cmd);
7755 
7756    if (file_number < 0 || file_number == 1 || file_number == 2 ||
7757          file_number >= MAXEXECOPENFILES) {
7758       sprintf(gszMsgBox, TgLoadString(STID_INVALID_FNUM_WHILE_EXEC_CMD),
7759             file_number_str, orig_cmd);
7760       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7761       return FALSE;
7762    } else if (gaOpenFileInfo[file_number].fp == NULL) {
7763       sprintf(gszMsgBox, TgLoadString(STID_FNUM_NOT_OPEN_WHILE_EXEC_CMD),
7764             file_number, orig_cmd);
7765       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7766       return FALSE;
7767    } else if (gaOpenFileInfo[file_number].eof) {
7768       sprintf(gszMsgBox, TgLoadString(STID_EOF_FOR_FNUM_WHILE_EXEC_CMD),
7769             file_number, orig_cmd);
7770       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7771       return FALSE;
7772    } else {
7773       buf = UtilGetALine(gaOpenFileInfo[file_number].fp);
7774       if (buf == NULL) {
7775          gaOpenFileInfo[file_number].eof = TRUE;
7776          sprintf(gszMsgBox, TgLoadString(STID_EOF_FOR_FNUM_WHILE_EXEC_CMD),
7777                file_number, orig_cmd);
7778          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7779          return FALSE;
7780       }
7781    }
7782    ReplaceAttrFirstValue(result_attr_owner_obj, result_attr,
7783          (buf==NULL ? "" : buf));
7784    if (buf != NULL) UtilFree(buf);
7785 
7786    return TRUE;
7787 }
7788 
ExecWriteFile(argv,obj_ptr,orig_cmd)7789 int ExecWriteFile(argv, obj_ptr, orig_cmd)
7790    char **argv, *orig_cmd;
7791    struct ObjRec *obj_ptr;
7792    /* write_file(file_number,string); */
7793 {
7794    char *file_number_str=argv[0], *str=argv[1];
7795    int file_number=(-1);
7796 
7797    UtilRemoveQuotes(file_number_str);
7798    UtilRemoveQuotes(str);
7799 
7800    if (!IntExpression(file_number_str, &file_number, orig_cmd)) {
7801       return FALSE;
7802    }
7803    if (file_number < 0 || file_number >= MAXEXECOPENFILES) {
7804       sprintf(gszMsgBox, TgLoadString(STID_INVALID_FNUM_WHILE_EXEC_CMD),
7805             file_number_str, orig_cmd);
7806       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7807       return FALSE;
7808    } else if (gaOpenFileInfo[file_number].fp == NULL) {
7809       sprintf(gszMsgBox, TgLoadString(STID_FNUM_NOT_OPEN_WHILE_EXEC_CMD),
7810             file_number, orig_cmd);
7811       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7812       return FALSE;
7813    } else if (fprintf(gaOpenFileInfo[file_number].fp, "%s", str) == EOF) {
7814       if (file_number < 3) {
7815          sprintf(gszMsgBox, TgLoadString(STID_WRI_FNUM_FAIL_WHILE_EXEC_CMD),
7816                file_number, orig_cmd);
7817       } else {
7818          sprintf(gszMsgBox, TgLoadString(STID_WRI_FNN_FAIL_WHILE_EXEC_CMD),
7819                file_number, gaOpenFileInfo[file_number].fname, orig_cmd);
7820       }
7821       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7822       return FALSE;
7823    }
7824 
7825    return TRUE;
7826 }
7827 
ExecFlushFile(argv,obj_ptr,orig_cmd)7828 int ExecFlushFile(argv, obj_ptr, orig_cmd)
7829    char **argv, *orig_cmd;
7830    struct ObjRec *obj_ptr;
7831    /* flush_file(file_number); */
7832 {
7833    char *file_number_str=argv[0];
7834    int file_number=(-1);
7835 
7836    UtilRemoveQuotes(file_number_str);
7837 
7838    if (!IntExpression(file_number_str, &file_number, orig_cmd)) {
7839       return FALSE;
7840    }
7841    if (file_number <= 0 || file_number >= MAXEXECOPENFILES) {
7842       sprintf(gszMsgBox, TgLoadString(STID_INVALID_FNUM_WHILE_EXEC_CMD),
7843             file_number_str, orig_cmd);
7844       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7845       return FALSE;
7846    } else if (gaOpenFileInfo[file_number].fp == NULL) {
7847       sprintf(gszMsgBox, TgLoadString(STID_FNUM_NOT_OPEN_WHILE_EXEC_CMD),
7848             file_number, orig_cmd);
7849       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7850       return FALSE;
7851    }
7852    fflush(gaOpenFileInfo[file_number].fp);
7853 
7854    return TRUE;
7855 }
7856 
ExecAppendFile(argv,obj_ptr,orig_cmd)7857 int ExecAppendFile(argv, obj_ptr, orig_cmd)
7858    char **argv, *orig_cmd;
7859    struct ObjRec *obj_ptr;
7860    /* append_file(dest_file_name,src_file_name); */
7861 {
7862    char *dest_file_name=argv[0], *src_file_name=argv[1];
7863 
7864    UtilRemoveQuotes(dest_file_name);
7865    UtilRemoveQuotes(src_file_name);
7866    UtilTrimBlanks(dest_file_name);
7867    UtilTrimBlanks(src_file_name);
7868 
7869    if (!UtilPathExists(src_file_name)) {
7870       sprintf(gszMsgBox, TgLoadString(STID_INVALID_PATH_WHILE_EXEC_CMD),
7871             src_file_name, orig_cmd);
7872       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7873       return FALSE;
7874    }
7875    if (UtilPathExists(dest_file_name)) {
7876       char buf[0x1000];
7877       int fd1=(-1), fd2=(-1), failed=TRUE, bytes_read=0;
7878 
7879       if ((fd1=open(src_file_name, O_RDONLY)) != (-1) &&
7880             (fd2=open(dest_file_name, O_WRONLY|O_APPEND)) != (-1)) {
7881          failed = FALSE;
7882          while ((bytes_read=read(fd1, buf, sizeof(buf))) > 0) {
7883             if (write(fd2, buf, bytes_read) != bytes_read) {
7884                failed = TRUE;
7885                break;
7886             }
7887          }
7888       }
7889       if (fd1 != (-1)) close(fd1);
7890       if (fd2 != (-1)) close(fd2);
7891       if (failed) {
7892          sprintf(gszMsgBox, TgLoadString(STID_APPEND_FAILED_WHILE_EXEC_CMD),
7893                src_file_name, dest_file_name, orig_cmd);
7894          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7895          return FALSE;
7896       }
7897    } else if (UtilCopyFile(src_file_name, dest_file_name) !=
7898          TG_REMOTE_STATUS_OK) {
7899       sprintf(gszMsgBox, TgLoadString(STID_COPY_FAILED_WHILE_EXEC_CMD),
7900             src_file_name, dest_file_name, orig_cmd);
7901       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7902       return FALSE;
7903    }
7904    return TRUE;
7905 }
7906 
7907 /* do not translate -- program constants */
7908 static char *gaszOutputFormats[MAXDEFWHERETOPRINT+1] = {
7909    "Printer", "EPS", "PS", "Bitmap", "Text", "EPSI", "GIF", "HTML", "PDF",
7910    "TiffEPSI", "PNG", "JPEG", "PPM", "NetList", NULL
7911 };
7912 
ExecSetOutputFormat(argv,obj_ptr,orig_cmd)7913 int ExecSetOutputFormat(argv, obj_ptr, orig_cmd)
7914    char **argv, *orig_cmd;
7915    struct ObjRec *obj_ptr;
7916    /* set_output_format(format,color_output); */
7917 {
7918    char *format=argv[0], *color_output_str=argv[1];
7919    int i, color_output=(-1);
7920 
7921    UtilRemoveQuotes(format);
7922    UtilRemoveQuotes(color_output_str);
7923    UtilTrimBlanks(format);
7924 
7925    if (!IntExpression(color_output_str, &color_output, orig_cmd)) {
7926       return FALSE;
7927    }
7928    if (*format == '\0') {
7929       sprintf(gszMsgBox, TgLoadString(STID_INVALID_FORMAT_WHILE_EXEC_CMD),
7930             format, orig_cmd);
7931       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7932       return FALSE;
7933    }
7934    if (color_output != 0) color_output = TRUE;
7935 
7936    for (i=0; i < MAXDEFWHERETOPRINT; i++) {
7937       if (UtilStrICmp(format, gaszOutputFormats[i]) == 0) {
7938          SetWhereToPrint(i);
7939          if (color_output != colorDump) ToggleColorPostScript();
7940          return TRUE;
7941       }
7942    }
7943    if (color_output != colorDump) ToggleColorPostScript();
7944    for (i=MAXDEFWHERETOPRINT; i < maxWhereToPrint; i++) {
7945       if (UtilStrICmp(format, GetExportName(i, EXPORT_THIS)) == 0) {
7946          SetWhereToPrint(i);
7947          return TRUE;
7948       }
7949    }
7950    sprintf(gszMsgBox, TgLoadString(STID_INVALID_FORMAT_WHILE_EXEC_CMD),
7951          format, orig_cmd);
7952    MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7953    return FALSE;
7954 }
7955 
ExecSetExportClipRect(argv,obj_ptr,orig_cmd)7956 int ExecSetExportClipRect(argv, obj_ptr, orig_cmd)
7957    char **argv, *orig_cmd;
7958    struct ObjRec *obj_ptr;
7959    /* set_export_clip_rect(ltx,lty,rbx,rby); */
7960 {
7961    char *ltx_str=argv[0], *lty_str=argv[1], *rbx_str=argv[2], *rby_str=argv[3];
7962    int ltx=0, lty=0, rbx=0, rby=0;
7963 
7964    UtilRemoveQuotes(ltx_str);
7965    UtilRemoveQuotes(lty_str);
7966    UtilRemoveQuotes(rbx_str);
7967    UtilRemoveQuotes(rby_str);
7968 
7969    if (!IntExpression(ltx_str, &ltx, orig_cmd) ||
7970          !IntExpression(lty_str, &lty, orig_cmd) ||
7971          !IntExpression(rbx_str, &rbx, orig_cmd) ||
7972          !IntExpression(rby_str, &rby, orig_cmd)) {
7973       return FALSE;
7974    }
7975    if (ltx >= rbx || lty >= rby) {
7976       sprintf(gszMsgBox, TgLoadString(STID_INVALID_REC_WHILE_EXEC_CMD),
7977             ltx, lty, rbx, rby, orig_cmd);
7978       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
7979       return FALSE;
7980    }
7981    if (gpExportClipBBox == NULL) {
7982       gpExportClipBBox = (struct BBRec *)malloc(sizeof(struct BBRec));
7983       if (gpExportClipBBox == NULL) FailAllocMessage();
7984    }
7985    gpExportClipBBox->ltx = ltx;
7986    gpExportClipBBox->lty = lty;
7987    gpExportClipBBox->rbx = rbx;
7988    gpExportClipBBox->rby = rby;
7989 
7990    return TRUE;
7991 }
7992 
ExecImportFile(argv,obj_ptr,orig_cmd)7993 int ExecImportFile(argv, obj_ptr, orig_cmd)
7994    char **argv, *orig_cmd;
7995    struct ObjRec *obj_ptr;
7996    /* import_file(file_name,format,ltx,lty); */
7997 {
7998    char *file_name=argv[0], *format=argv[1], *ltx_str=argv[2], *lty_str=argv[3];
7999    int ltx=0, lty=0, import_type=INVALID, x_hot, y_hot, w=0, h=0, ncolors=0;
8000    unsigned int ui_image_w=0, ui_image_h=0;
8001    Pixmap bitmap=None, pixmap=None;
8002    XImage *image=NULL, *bitmap_image=NULL;
8003    char *color_char=NULL, **color_str=NULL, *xpm_data=NULL;
8004    char xpm_fname[MAXPATHLENGTH];
8005    int chars_per_pixel=0, first_pixel_is_bg=0, *pixels=NULL;
8006    int rc=BitmapOpenFailed, image_w=0, image_h=0;
8007    struct ObjRec *new_obj_ptr=NULL;
8008 
8009    UtilRemoveQuotes(file_name);
8010    UtilRemoveQuotes(format);
8011    UtilRemoveQuotes(ltx_str);
8012    UtilRemoveQuotes(lty_str);
8013    UtilTrimBlanks(file_name);
8014    UtilTrimBlanks(format);
8015 
8016    if (*file_name == '\0') {
8017       sprintf(gszMsgBox, TgLoadString(STID_INVALID_FNAME_WHILE_EXEC_CMD),
8018             file_name, orig_cmd);
8019       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8020       return FALSE;
8021    } else if (!IntExpression(ltx_str, &ltx, orig_cmd) ||
8022          !IntExpression(lty_str, &lty, orig_cmd)) {
8023       return FALSE;
8024    }
8025    if (topSel != NULL) RemoveAllSel();
8026 
8027    if (UtilStrICmp(format, "TGIF") == 0) {
8028       int dx=0, dy=0, saved_ltx=0, saved_lty=0, saved_rbx=0, saved_rby=0;
8029       int saved_move_mode=moveMode;
8030 
8031       import_type = FILE_IMPORT;
8032       StartCompositeCmd();
8033       importingFile = TRUE;
8034       importingFromExec = TRUE;
8035       rc = ImportGivenFile(file_name, FALSE, FALSE);
8036       importingFromExec = FALSE;
8037       importingFile = FALSE;
8038       if (rc != TRUE) {
8039          EndCompositeCmd();
8040          sprintf(gszMsgBox, TgLoadString(STID_IMPORT_FORMAT_WHILE_EXEC_CMD),
8041                file_name, format, orig_cmd);
8042          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8043          return FALSE;
8044       } else if (topSel == NULL) {
8045          EndCompositeCmd();
8046          sprintf(gszMsgBox, TgLoadString(STID_NO_OBJ_TO_IMP_WHILE_EXEC_CMD),
8047                file_name, orig_cmd);
8048          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8049          return FALSE;
8050       }
8051       UpdSelBBox();
8052       saved_ltx = selLtX; saved_lty = selLtY;
8053       saved_rbx = selRbX; saved_rby = selRbY;
8054       dx = ltx-selLtX;
8055       dy = lty-selLtY;
8056       moveMode = UNCONST_MOVE;
8057       MoveAllSel(dx, dy);
8058       moveMode = saved_move_mode;
8059       RedrawAreas(botObj,
8060             saved_ltx-GRID_ABS_SIZE(1), saved_lty-GRID_ABS_SIZE(1),
8061             saved_rbx+GRID_ABS_SIZE(1), saved_rby+GRID_ABS_SIZE(1),
8062             selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
8063             selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
8064       SetFileModified(TRUE);
8065       EndCompositeCmd();
8066 
8067       return TRUE;
8068    }
8069 
8070    if (UtilStrICmp(format, "XBM") == 0) {
8071       import_type = FILE_IMPORTXBM;
8072       rc = XReadBitmapFile(mainDisplay, mainWindow, file_name,
8073             &ui_image_w, &ui_image_h, &bitmap, &x_hot, &y_hot);
8074       image_w = ui_image_w; image_h = ui_image_h;
8075    } else if (UtilStrICmp(format, "XPM") == 0) {
8076       import_type = FILE_IMPORTXPM;
8077       rc = MyReadPixmapFile(file_name, &image_w, &image_h, &w, &h,
8078             &pixmap, &image, &bitmap, &bitmap_image, &ncolors, &chars_per_pixel,
8079             &first_pixel_is_bg, &color_char, &color_str, &pixels, &xpm_data);
8080    } else if (UtilStrICmp(format, "GIF") == 0) {
8081       import_type = FILE_IMPORTXPM;
8082       *xpm_fname = '\0';
8083       if (!ConvertGifToXpm(file_name, xpm_fname, sizeof(xpm_fname))) {
8084          sprintf(gszMsgBox, TgLoadString(STID_CONVERT_FORMAT_WHILE_EXEC_CMD),
8085                file_name, format, orig_cmd);
8086          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8087          return FALSE;
8088       } else {
8089          rc = MyReadPixmapFile(xpm_fname, &image_w, &image_h, &w, &h,
8090                &pixmap, &image, &bitmap, &bitmap_image, &ncolors,
8091                &chars_per_pixel, &first_pixel_is_bg, &color_char, &color_str,
8092                &pixels, &xpm_data);
8093          unlink(xpm_fname);
8094       }
8095    } else if (UtilStrICmp(format, "PNG") == 0) {
8096       import_type = FILE_IMPORTXPM;
8097       *xpm_fname = '\0';
8098       if (!ConvertPngToXpm(file_name, xpm_fname, sizeof(xpm_fname))) {
8099          sprintf(gszMsgBox, TgLoadString(STID_CONVERT_FORMAT_WHILE_EXEC_CMD),
8100                file_name, format, orig_cmd);
8101          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8102          return FALSE;
8103       } else {
8104          rc = MyReadPixmapFile(xpm_fname, &image_w, &image_h, &w, &h,
8105                &pixmap, &image, &bitmap, &bitmap_image, &ncolors,
8106                &chars_per_pixel, &first_pixel_is_bg, &color_char, &color_str,
8107                &pixels, &xpm_data);
8108          unlink(xpm_fname);
8109       }
8110    } else if (UtilStrICmp(format, "JPEG") == 0) {
8111       import_type = FILE_IMPORTXPM;
8112       *xpm_fname = '\0';
8113       if (!ConvertJpegToXpm(file_name, xpm_fname, sizeof(xpm_fname))) {
8114          sprintf(gszMsgBox, TgLoadString(STID_CONVERT_FORMAT_WHILE_EXEC_CMD),
8115                file_name, format, orig_cmd);
8116          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8117          return FALSE;
8118       } else {
8119          rc = MyReadPixmapFile(xpm_fname, &image_w, &image_h, &w, &h,
8120                &pixmap, &image, &bitmap, &bitmap_image, &ncolors,
8121                &chars_per_pixel, &first_pixel_is_bg, &color_char, &color_str,
8122                &pixels, &xpm_data);
8123          unlink(xpm_fname);
8124       }
8125    } else if (UtilStrICmp(format, "PPM") == 0) {
8126       import_type = FILE_IMPORTXPM;
8127       *xpm_fname = '\0';
8128       if (!ConvertPpmToXpm(file_name, xpm_fname, sizeof(xpm_fname))) {
8129          sprintf(gszMsgBox, TgLoadString(STID_CONVERT_FORMAT_WHILE_EXEC_CMD),
8130                file_name, format, orig_cmd);
8131          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8132          return FALSE;
8133       } else {
8134          rc = MyReadPixmapFile(xpm_fname, &image_w, &image_h, &w, &h,
8135                &pixmap, &image, &bitmap, &bitmap_image, &ncolors,
8136                &chars_per_pixel, &first_pixel_is_bg, &color_char, &color_str,
8137                &pixels, &xpm_data);
8138          unlink(xpm_fname);
8139       }
8140    } else if (UtilStrICmp(format, "PGM") == 0) {
8141       import_type = FILE_IMPORTXPM;
8142       *xpm_fname = '\0';
8143       if (!ConvertPgmToXpm(file_name, xpm_fname, sizeof(xpm_fname))) {
8144          sprintf(gszMsgBox, TgLoadString(STID_CONVERT_FORMAT_WHILE_EXEC_CMD),
8145                file_name, format, orig_cmd);
8146          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8147          return FALSE;
8148       } else {
8149          rc = MyReadPixmapFile(xpm_fname, &image_w, &image_h, &w, &h,
8150                &pixmap, &image, &bitmap, &bitmap_image, &ncolors,
8151                &chars_per_pixel, &first_pixel_is_bg, &color_char, &color_str,
8152                &pixels, &xpm_data);
8153          unlink(xpm_fname);
8154       }
8155    } else if (UtilStrICmp(format, "PBM") == 0) {
8156       import_type = FILE_IMPORTXBM;
8157       *xpm_fname = '\0';
8158       if (!ConvertPbmToXbm(file_name, xpm_fname, sizeof(xpm_fname))) {
8159          sprintf(gszMsgBox, TgLoadString(STID_CONVERT_TO_XBM_WHILE_EXEC_CMD),
8160                file_name, format, orig_cmd);
8161          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8162          return FALSE;
8163       } else {
8164          rc = XReadBitmapFile(mainDisplay, mainWindow, xpm_fname,
8165                &ui_image_w, &ui_image_h, &bitmap, &x_hot, &y_hot);
8166          image_w = ui_image_w; image_h = ui_image_h;
8167          unlink(xpm_fname);
8168       }
8169    } else {
8170       import_type = FILE_IMPORTXPM;
8171       *xpm_fname = '\0';
8172       if (!ConvertOtherToXpm(file_name, format, xpm_fname, sizeof(xpm_fname))) {
8173          sprintf(gszMsgBox, TgLoadString(STID_CONVERT_FORMAT_WHILE_EXEC_CMD),
8174                file_name, format, orig_cmd);
8175          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8176          return FALSE;
8177       } else {
8178          rc = MyReadPixmapFile(xpm_fname, &image_w, &image_h, &w, &h,
8179                &pixmap, &image, &bitmap, &bitmap_image, &ncolors,
8180                &chars_per_pixel, &first_pixel_is_bg, &color_char, &color_str,
8181                &pixels, &xpm_data);
8182          unlink(xpm_fname);
8183       }
8184    }
8185    importingFile = TRUE;
8186    if (rc != BitmapSuccess) {
8187       importingFile = FALSE;
8188       sprintf(gszMsgBox, TgLoadString(STID_IMPORT_FAILED_WHILE_EXEC_CMD),
8189             file_name, orig_cmd);
8190       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8191       return FALSE;
8192    }
8193    switch (import_type) {
8194    case FILE_IMPORTXBM:
8195       new_obj_ptr = CreateXBmObj(image_w, image_h, image_w, image_h,
8196             bitmap, image);
8197       break;
8198    case FILE_IMPORTXPM:
8199       new_obj_ptr = CreateXPmObj(image_w, image_h, w, h, pixmap, image, bitmap,
8200             bitmap_image, ncolors, chars_per_pixel, first_pixel_is_bg,
8201             color_char, color_str, pixels, xpm_data);
8202       break;
8203    default: importingFile = FALSE; return FALSE;
8204    }
8205    importingFile = FALSE;
8206 
8207    if (!PRTGIF && colorLayers && needToRedrawColorWindow) {
8208       RedrawColorWindow();
8209    }
8210    MoveObj(new_obj_ptr, ltx-new_obj_ptr->obbox.ltx, lty-new_obj_ptr->obbox.lty);
8211    AddObj(NULL, topObj, new_obj_ptr);
8212    SelectTopObj();
8213    UpdSelBBox();
8214 
8215    RecordNewObjCmd();
8216    RedrawAnArea(botObj,
8217          new_obj_ptr->bbox.ltx-GRID_ABS_SIZE(1),
8218          new_obj_ptr->bbox.lty-GRID_ABS_SIZE(1),
8219          new_obj_ptr->bbox.rbx+GRID_ABS_SIZE(1),
8220          new_obj_ptr->bbox.rby+GRID_ABS_SIZE(1));
8221    SetFileModified(TRUE);
8222 
8223    return TRUE;
8224 }
8225 
ExecSetXpmOutputVersion(argv,obj_ptr,orig_cmd)8226 int ExecSetXpmOutputVersion(argv, obj_ptr, orig_cmd)
8227    char **argv, *orig_cmd;
8228    struct ObjRec *obj_ptr;
8229    /* set_xpm_output_version(version_number); */
8230 {
8231    char *version_number_str=argv[0];
8232    int version_number=(-1);
8233 
8234    UtilRemoveQuotes(version_number_str);
8235 
8236    if (!IntExpression(version_number_str, &version_number, orig_cmd)) {
8237       return FALSE;
8238    }
8239    if (version_number != 1 && version_number != 3) {
8240       sprintf(gszMsgBox, TgLoadString(STID_BAD_VER_NUM_WHILE_EXEC_CMD),
8241             version_number, orig_cmd);
8242       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8243       return FALSE;
8244    }
8245    SetXpmOutputVersion(version_number);
8246    return TRUE;
8247 }
8248 
ExecEditIniSection(argv,obj_ptr,orig_cmd)8249 int ExecEditIniSection(argv, obj_ptr, orig_cmd)
8250    char **argv, *orig_cmd;
8251    struct ObjRec *obj_ptr;
8252    /* edit_ini_section(attr_name,title,section,ini_path); */
8253 {
8254    char *attr_name=argv[0], *title=argv[1], *section=argv[2], *ini_path=argv[3];
8255    char buf[40], *psz_keys=NULL;
8256    struct AttrRec *attr_ptr=NULL;
8257    struct ObjRec *attr_owner_obj=NULL;
8258 
8259    UtilRemoveQuotes(attr_name);
8260    UtilRemoveQuotes(title);
8261    UtilRemoveQuotes(section);
8262    UtilRemoveQuotes(ini_path);
8263    if (strcmp(attr_name, "NULL") != 0) {
8264       sprintf(execDummyStr, "%s=", attr_name);
8265       attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
8266       if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
8267    }
8268    if (strcmp(title, "NULL") == 0) {
8269       title = NULL;
8270    }
8271    if ((psz_keys=tgGetProfileString(section, NULL, ini_path)) == NULL) {
8272       sprintf(gszMsgBox, TgLoadString(STID_EMPTY_INI_SEC_WHILE_EXEC_CMD),
8273             section, ini_path, orig_cmd);
8274       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8275       return FALSE;
8276    } else {
8277       tgFreeProfileString(psz_keys);
8278    }
8279    if (EditIniSection(title, section, ini_path, NULL)) {
8280       strcpy(buf, "OK");
8281    } else {
8282       strcpy(buf, "CANCEL");
8283    }
8284    if (attr_ptr != NULL) {
8285       ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, buf);
8286    }
8287    return TRUE;
8288 }
8289 
ExecSelectFromIniSection(argv,obj_ptr,orig_cmd)8290 int ExecSelectFromIniSection(argv, obj_ptr, orig_cmd)
8291    char **argv, *orig_cmd;
8292    struct ObjRec *obj_ptr;
8293    /* select_from_ini_section(attr_name,title,section,ini_path); */
8294 {
8295    char *attr_name=argv[0], *title=argv[1], *section=argv[2], *ini_path=argv[3];
8296    char *psz_keys=NULL, *buf=NULL;
8297    struct AttrRec *attr_ptr=NULL;
8298    struct ObjRec *attr_owner_obj=NULL;
8299 
8300    UtilRemoveQuotes(attr_name);
8301    UtilRemoveQuotes(title);
8302    UtilRemoveQuotes(section);
8303    UtilRemoveQuotes(ini_path);
8304    if (strcmp(attr_name, "NULL") != 0) {
8305       sprintf(execDummyStr, "%s=", attr_name);
8306       attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
8307       if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
8308    }
8309    if (strcmp(title, "NULL") == 0) {
8310       title = NULL;
8311    }
8312    if ((psz_keys=tgGetProfileString(section, NULL, ini_path)) == NULL) {
8313       sprintf(gszMsgBox, TgLoadString(STID_EMPTY_INI_SEC_WHILE_EXEC_CMD),
8314             section, ini_path, orig_cmd);
8315       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8316       return FALSE;
8317    } else {
8318       tgFreeProfileString(psz_keys);
8319    }
8320    buf = SelectFromIniSection(title, section, ini_path);
8321    if (attr_ptr != NULL) {
8322       ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, (buf==NULL ? "" : buf));
8323    }
8324    UtilFree(buf);
8325 
8326    return TRUE;
8327 }
8328 
ExecAppendLineIntoAttr(argv,obj_ptr,orig_cmd)8329 int ExecAppendLineIntoAttr(argv, obj_ptr, orig_cmd)
8330    char **argv, *orig_cmd;
8331    struct ObjRec *obj_ptr;
8332    /* append_line_into_attr(attr_name,str); */
8333 {
8334    char *attr_name=argv[0], *the_str=argv[1];
8335    MiniLineInfo *pFirstMiniLine=NULL, *pLastMiniLine=NULL;
8336    struct AttrRec *attr_ptr=NULL;
8337    struct ObjRec *attr_owner_obj=NULL;
8338    struct TextRec *text_ptr=NULL;
8339 
8340    UtilRemoveQuotes(attr_name);
8341    UtilRemoveQuotes(the_str);
8342 
8343    sprintf(execDummyStr, "%s=", attr_name);
8344    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
8345    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
8346 
8347    PrepareToReplaceAnObj(attr_owner_obj);
8348 
8349    text_ptr = attr_ptr->obj->detail.t;
8350    CreateMiniLineFromString(the_str, &pFirstMiniLine, &pLastMiniLine);
8351    text_ptr->minilines.last->next = pFirstMiniLine;
8352    pFirstMiniLine->prev = text_ptr->minilines.last;
8353    text_ptr->minilines.last = pLastMiniLine;
8354    text_ptr->lines++;
8355    RecalcTextMetrics(text_ptr, attr_ptr->obj->x, text_ptr->baseline_y);
8356    UpdTextBBox(attr_ptr->obj);
8357    AdjObjBBox(attr_owner_obj);
8358 
8359    RecordReplaceAnObj(attr_owner_obj);
8360    RedrawAnArea(attr_ptr->obj, topObj->bbox.ltx-GRID_ABS_SIZE(1),
8361          attr_ptr->obj->bbox.lty-GRID_ABS_SIZE(1),
8362          attr_ptr->obj->bbox.rbx+GRID_ABS_SIZE(1),
8363          attr_ptr->obj->bbox.rby+GRID_ABS_SIZE(1));
8364 
8365    SetFileModified(TRUE);
8366    return TRUE;
8367 }
8368 
ExecInsertLineIntoAttr(argv,obj_ptr,orig_cmd)8369 int ExecInsertLineIntoAttr(argv, obj_ptr, orig_cmd)
8370    char **argv, *orig_cmd;
8371    struct ObjRec *obj_ptr;
8372    /* insert_line_into_attr(attr_name,str,line_number); */
8373 {
8374    char *attr_name=argv[0], *the_str=argv[1];
8375    char *line_number_str=argv[2];
8376    int count=0, line_number=(-1), ltx=0, lty=0, rbx=0, rby=0, found=FALSE;
8377    MiniLineInfo *pMiniLine=NULL, *pFirstMiniLine=NULL, *pLastMiniLine=NULL;
8378    struct AttrRec *attr_ptr=NULL;
8379    struct ObjRec *attr_owner_obj=NULL;
8380    struct TextRec *text_ptr=NULL;
8381 
8382    UtilRemoveQuotes(attr_name);
8383    UtilRemoveQuotes(the_str);
8384    UtilRemoveQuotes(line_number_str);
8385 
8386    sprintf(execDummyStr, "%s=", attr_name);
8387    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
8388    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
8389 
8390    if (!IntExpression(line_number_str, &line_number, orig_cmd)) {
8391       return FALSE;
8392    }
8393    if (line_number <= 0) {
8394       if (line_number == 0) {
8395          sprintf(gszMsgBox, TgLoadString(STID_BAD_LINENUM_WHILE_EXEC_CMD),
8396                line_number, orig_cmd);
8397       } else {
8398          sprintf(gszMsgBox, TgLoadString(STID_BAD_SMALL_LNUM_WHILE_EXEC_CMD),
8399                line_number, orig_cmd);
8400       }
8401       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8402       return FALSE;
8403    }
8404    ltx = attr_ptr->obj->bbox.ltx; lty = attr_ptr->obj->bbox.lty;
8405    rbx = attr_ptr->obj->bbox.rbx; rby = attr_ptr->obj->bbox.rby;
8406    PrepareToReplaceAnObj(attr_owner_obj);
8407 
8408    text_ptr = attr_ptr->obj->detail.t;
8409 
8410    count = 0;
8411    for (pMiniLine=attr_ptr->obj->detail.t->minilines.first;
8412          pMiniLine != NULL; pMiniLine=pMiniLine->next, count++) {
8413       if (count == line_number) {
8414          CreateMiniLineFromString(the_str, &pFirstMiniLine, &pLastMiniLine);
8415          pMiniLine->prev->next = pFirstMiniLine;
8416          pFirstMiniLine->prev = pMiniLine->prev;
8417          pFirstMiniLine->next = pMiniLine;
8418          pMiniLine->prev = pFirstMiniLine;
8419          text_ptr->lines++;
8420          found = TRUE;
8421          break;
8422       }
8423    }
8424    while (!found) {
8425       if (count++ == line_number) {
8426          CreateMiniLineFromString(the_str, &pFirstMiniLine, &pLastMiniLine);
8427          text_ptr->minilines.last->next = pFirstMiniLine;
8428          pFirstMiniLine->prev = text_ptr->minilines.last;
8429          text_ptr->minilines.last = pLastMiniLine;
8430          found = TRUE;
8431       } else {
8432          CreateMiniLineFromString("", &pFirstMiniLine, &pLastMiniLine);
8433          text_ptr->minilines.last->next = pFirstMiniLine;
8434          pFirstMiniLine->prev = text_ptr->minilines.last;
8435          text_ptr->minilines.last = pLastMiniLine;
8436          pFirstMiniLine = pLastMiniLine = NULL;
8437       }
8438       text_ptr->lines++;
8439    }
8440    RecalcTextMetrics(text_ptr, attr_ptr->obj->x, text_ptr->baseline_y);
8441    UpdTextBBox(attr_ptr->obj);
8442    AdjObjBBox(attr_owner_obj);
8443 
8444    RecordReplaceAnObj(attr_owner_obj);
8445    RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
8446          rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
8447          attr_ptr->obj->bbox.ltx-GRID_ABS_SIZE(1),
8448          attr_ptr->obj->bbox.lty-GRID_ABS_SIZE(1),
8449          attr_ptr->obj->bbox.rbx+GRID_ABS_SIZE(1),
8450          attr_ptr->obj->bbox.rby+GRID_ABS_SIZE(1));
8451 
8452    SetFileModified(TRUE);
8453    return TRUE;
8454 }
8455 
ExecClearAttr(argv,obj_ptr,orig_cmd)8456 int ExecClearAttr(argv, obj_ptr, orig_cmd)
8457    char **argv, *orig_cmd;
8458    struct ObjRec *obj_ptr;
8459    /* clear_attr(attr_name); */
8460 {
8461    char *attr_name=argv[0];
8462    struct AttrRec *attr_ptr=NULL;
8463    struct ObjRec *attr_owner_obj=NULL;
8464    struct TextRec *text_ptr=NULL;
8465    int changed=FALSE, ltx=0, lty=0, rbx=0, rby=0;
8466 
8467    UtilRemoveQuotes(attr_name);
8468 
8469    sprintf(execDummyStr, "%s=", attr_name);
8470    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
8471    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
8472 
8473    ltx = attr_ptr->obj->bbox.ltx; lty = attr_ptr->obj->bbox.lty;
8474    rbx = attr_ptr->obj->bbox.rbx; rby = attr_ptr->obj->bbox.rby;
8475 
8476    StartCompositeCmd();
8477 
8478    text_ptr = attr_ptr->obj->detail.t;
8479    if (text_ptr->minilines.first->next != NULL) {
8480       MiniLineInfo *pMiniLine=NULL, *pNextMiniLine=NULL;
8481 
8482       if (attr_owner_obj == tgifObj) {
8483          AddObj(NULL, topObj, tgifObj);
8484          AddNewSelObj(topObj);
8485       }
8486       PrepareToReplaceAnObj(attr_owner_obj);
8487       for (pMiniLine=text_ptr->minilines.first->next; pMiniLine != NULL;
8488             pMiniLine=pNextMiniLine) {
8489          pNextMiniLine = pMiniLine->next;
8490          UnlinkMiniLine(pMiniLine);
8491          FreeMiniLine(pMiniLine);
8492       }
8493       if (attr_owner_obj == tgifObj) recordCmdIncludeTgifObj = TRUE;
8494       RecordReplaceAnObj(attr_owner_obj);
8495       if (attr_owner_obj == tgifObj) {
8496          recordCmdIncludeTgifObj = FALSE;
8497          UnlinkObj(topObj);
8498          FreeTopSel();
8499       }
8500       changed = TRUE;
8501    }
8502    replaceAttrFirstValueRedraw = FALSE;
8503    if (ReplaceAttrFirstValue(attr_owner_obj, attr_ptr, "")) {
8504       changed = TRUE;
8505    }
8506    replaceAttrFirstValueRedraw = TRUE;
8507 
8508    if (changed) {
8509       RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
8510             rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
8511             attr_ptr->obj->bbox.ltx-GRID_ABS_SIZE(1),
8512             attr_ptr->obj->bbox.lty-GRID_ABS_SIZE(1),
8513             attr_ptr->obj->bbox.rbx+GRID_ABS_SIZE(1),
8514             attr_ptr->obj->bbox.rby+GRID_ABS_SIZE(1));
8515       SetFileModified(TRUE);
8516    }
8517    EndCompositeCmd();
8518 
8519    return TRUE;
8520 }
8521 
ExecCreateText(argv,obj_ptr,orig_cmd)8522 int ExecCreateText(argv, obj_ptr, orig_cmd)
8523    char **argv, *orig_cmd;
8524    struct ObjRec *obj_ptr;
8525    /* create_text_obj(abs_x,abs_baseline_y,str); */
8526 {
8527    char *abs_x_str=argv[0], *abs_baseline_y_str=argv[1];
8528    char *the_str=argv[2];
8529    int abs_x=0, abs_baseline_y=0;
8530 
8531    UtilRemoveQuotes(abs_x_str);
8532    UtilRemoveQuotes(abs_baseline_y_str);
8533    UtilRemoveQuotes(the_str);
8534    if (!IntExpression(abs_x_str, &abs_x, orig_cmd) ||
8535          !IntExpression(abs_baseline_y_str, &abs_baseline_y, orig_cmd)) {
8536       return FALSE;
8537    }
8538    if (*the_str == '\0') {
8539       sprintf(gszMsgBox, TgLoadString(STID_BAD_EMPTY_STR_WHILE_EXEC_CMD),
8540             orig_cmd);
8541       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8542       return FALSE;
8543    }
8544    MakeQuiescent();
8545 
8546    NewCurText();
8547    PrepareToReplaceAnObj(curTextObj);
8548    DynStrSet(&GetTextObjFirstStrSeg(topObj)->dyn_str, the_str);
8549    curTextModified = TRUE;
8550    CreateTextObj(TRUE, FALSE);
8551    curTextModified = FALSE;
8552    MoveObj(topObj, abs_x-topObj->x,
8553          abs_baseline_y-topObj->detail.t->baseline_y);
8554 
8555    RedrawAnArea(botObj, topObj->bbox.ltx-GRID_ABS_SIZE(1),
8556          topObj->bbox.lty-GRID_ABS_SIZE(1),
8557          topObj->bbox.rbx+GRID_ABS_SIZE(1),
8558          topObj->bbox.rby+GRID_ABS_SIZE(1));
8559 
8560    SetFileModified(TRUE);
8561    return TRUE;
8562 }
8563 
ExecCreateBox(argv,obj_ptr,orig_cmd)8564 int ExecCreateBox(argv, obj_ptr, orig_cmd)
8565    char **argv, *orig_cmd;
8566    struct ObjRec *obj_ptr;
8567    /* create_box_obj(abs_ltx,abs_lty,abs_rbx,abs_rby); */
8568 {
8569    char *abs_ltx_str=argv[0], *abs_lty_str=argv[1];
8570    char *abs_rbx_str=argv[2], *abs_rby_str=argv[3];
8571    int abs_ltx=0, abs_lty=0, abs_rbx=0, abs_rby=0;
8572 
8573    UtilRemoveQuotes(abs_ltx_str);
8574    UtilRemoveQuotes(abs_lty_str);
8575    UtilRemoveQuotes(abs_rbx_str);
8576    UtilRemoveQuotes(abs_rby_str);
8577    if (!IntExpression(abs_ltx_str, &abs_ltx, orig_cmd) ||
8578          !IntExpression(abs_lty_str, &abs_lty, orig_cmd) ||
8579          !IntExpression(abs_rbx_str, &abs_rbx, orig_cmd) ||
8580          !IntExpression(abs_rby_str, &abs_rby, orig_cmd)) {
8581       return FALSE;
8582    }
8583    MakeQuiescent();
8584 
8585    CreateBoxObj(abs_ltx, abs_lty, abs_rbx, abs_rby, TRUE);
8586 
8587    RecordNewObjCmd();
8588    RedrawAnArea(botObj, topObj->bbox.ltx-GRID_ABS_SIZE(1),
8589          topObj->bbox.lty-GRID_ABS_SIZE(1),
8590          topObj->bbox.rbx+GRID_ABS_SIZE(1),
8591          topObj->bbox.rby+GRID_ABS_SIZE(1));
8592 
8593    SetFileModified(TRUE);
8594    return TRUE;
8595 }
8596 
ExecCreateCornerOval(argv,obj_ptr,orig_cmd)8597 int ExecCreateCornerOval(argv, obj_ptr, orig_cmd)
8598    char **argv, *orig_cmd;
8599    struct ObjRec *obj_ptr;
8600    /* create_corner_oval_obj(abs_ltx,abs_lty,abs_rbx,abs_rby); */
8601 {
8602    char *abs_ltx_str=argv[0], *abs_lty_str=argv[1];
8603    char *abs_rbx_str=argv[2], *abs_rby_str=argv[3];
8604    int abs_ltx=0, abs_lty=0, abs_rbx=0, abs_rby=0;
8605    struct BBRec obbox;
8606 
8607    UtilRemoveQuotes(abs_ltx_str);
8608    UtilRemoveQuotes(abs_lty_str);
8609    UtilRemoveQuotes(abs_rbx_str);
8610    UtilRemoveQuotes(abs_rby_str);
8611    if (!IntExpression(abs_ltx_str, &abs_ltx, orig_cmd) ||
8612          !IntExpression(abs_lty_str, &abs_lty, orig_cmd) ||
8613          !IntExpression(abs_rbx_str, &abs_rbx, orig_cmd) ||
8614          !IntExpression(abs_rby_str, &abs_rby, orig_cmd)) {
8615       return FALSE;
8616    }
8617    MakeQuiescent();
8618 
8619    SetBBRec(&obbox, abs_ltx, abs_lty, abs_rbx, abs_rby);
8620    CreateOvalObj(&obbox, TRUE);
8621 
8622    RecordNewObjCmd();
8623    RedrawAnArea(botObj, topObj->bbox.ltx-GRID_ABS_SIZE(1),
8624          topObj->bbox.lty-GRID_ABS_SIZE(1),
8625          topObj->bbox.rbx+GRID_ABS_SIZE(1),
8626          topObj->bbox.rby+GRID_ABS_SIZE(1));
8627 
8628    SetFileModified(TRUE);
8629    return TRUE;
8630 }
8631 
ExecCreateCenterOval(argv,obj_ptr,orig_cmd)8632 int ExecCreateCenterOval(argv, obj_ptr, orig_cmd)
8633    char **argv, *orig_cmd;
8634    struct ObjRec *obj_ptr;
8635    /* create_center_oval_obj(abs_cx,abs_cy,radius); */
8636 {
8637    char *abs_cx_str=argv[0], *abs_cy_str=argv[1], *radius_str=argv[2];
8638    int abs_cx=0, abs_cy=0, radius=0;
8639    struct BBRec obbox;
8640 
8641    UtilRemoveQuotes(abs_cx_str);
8642    UtilRemoveQuotes(abs_cy_str);
8643    UtilRemoveQuotes(radius_str);
8644    if (!IntExpression(abs_cx_str, &abs_cx, orig_cmd) ||
8645          !IntExpression(abs_cy_str, &abs_cy, orig_cmd) ||
8646          !IntExpression(radius_str, &radius, orig_cmd)) {
8647       return FALSE;
8648    }
8649    MakeQuiescent();
8650 
8651    SetBBRec(&obbox, abs_cx-radius, abs_cy-radius, abs_cx+radius, abs_cy+radius);
8652    CreateOvalObj(&obbox, TRUE);
8653 
8654    RecordNewObjCmd();
8655    RedrawAnArea(botObj, topObj->bbox.ltx-GRID_ABS_SIZE(1),
8656          topObj->bbox.lty-GRID_ABS_SIZE(1),
8657          topObj->bbox.rbx+GRID_ABS_SIZE(1),
8658          topObj->bbox.rby+GRID_ABS_SIZE(1));
8659 
8660    SetFileModified(TRUE);
8661    return TRUE;
8662 }
8663 
ExecCreateEdgeOval(argv,obj_ptr,orig_cmd)8664 int ExecCreateEdgeOval(argv, obj_ptr, orig_cmd)
8665    char **argv, *orig_cmd;
8666    struct ObjRec *obj_ptr;
8667    /* create_edge_oval_obj(abs_ltx,abs_lty,abs_rbx,abs_rby); */
8668 {
8669    char *abs_ltx_str=argv[0], *abs_lty_str=argv[1];
8670    char *abs_rbx_str=argv[2], *abs_rby_str=argv[3];
8671    int abs_ltx=0, abs_lty=0, abs_rbx=0, abs_rby=0, cx=0, cy=0, w=0;
8672    double dx=(double)0, dy=(double)0, r=(double)0;
8673    struct BBRec obbox;
8674 
8675    UtilRemoveQuotes(abs_ltx_str);
8676    UtilRemoveQuotes(abs_lty_str);
8677    UtilRemoveQuotes(abs_rbx_str);
8678    UtilRemoveQuotes(abs_rby_str);
8679    if (!IntExpression(abs_ltx_str, &abs_ltx, orig_cmd) ||
8680          !IntExpression(abs_lty_str, &abs_lty, orig_cmd) ||
8681          !IntExpression(abs_rbx_str, &abs_rbx, orig_cmd) ||
8682          !IntExpression(abs_rby_str, &abs_rby, orig_cmd)) {
8683       return FALSE;
8684    }
8685    MakeQuiescent();
8686 
8687    cx = ((abs_rbx + abs_ltx) >> 1);
8688    cy = ((abs_rby + abs_lty) >> 1);
8689    dx = (double)(cx - abs_ltx);
8690    dy = (double)(cy - abs_lty);
8691    r = (double)sqrt(dx*dx+dy*dy);
8692    w = round(r);
8693    SetBBRec(&obbox, cx-w, cy-w, cx+w, cy+w);
8694    CreateOvalObj(&obbox, TRUE);
8695 
8696    RecordNewObjCmd();
8697    RedrawAnArea(botObj, topObj->bbox.ltx-GRID_ABS_SIZE(1),
8698          topObj->bbox.lty-GRID_ABS_SIZE(1),
8699          topObj->bbox.rbx+GRID_ABS_SIZE(1),
8700          topObj->bbox.rby+GRID_ABS_SIZE(1));
8701 
8702    SetFileModified(TRUE);
8703    return TRUE;
8704 }
8705 
ExecCreateRCBox(argv,obj_ptr,orig_cmd)8706 int ExecCreateRCBox(argv, obj_ptr, orig_cmd)
8707    char **argv, *orig_cmd;
8708    struct ObjRec *obj_ptr;
8709    /* create_rcbox_obj(abs_ltx,abs_lty,abs_rbx,abs_rby); */
8710 {
8711    char *abs_ltx_str=argv[0], *abs_lty_str=argv[1];
8712    char *abs_rbx_str=argv[2], *abs_rby_str=argv[3];
8713    int abs_ltx=0, abs_lty=0, abs_rbx=0, abs_rby=0;
8714 
8715    UtilRemoveQuotes(abs_ltx_str);
8716    UtilRemoveQuotes(abs_lty_str);
8717    UtilRemoveQuotes(abs_rbx_str);
8718    UtilRemoveQuotes(abs_rby_str);
8719    if (!IntExpression(abs_ltx_str, &abs_ltx, orig_cmd) ||
8720          !IntExpression(abs_lty_str, &abs_lty, orig_cmd) ||
8721          !IntExpression(abs_rbx_str, &abs_rbx, orig_cmd) ||
8722          !IntExpression(abs_rby_str, &abs_rby, orig_cmd)) {
8723       return FALSE;
8724    }
8725    MakeQuiescent();
8726 
8727    CreateRCBoxObj(abs_ltx, abs_lty, abs_rbx, abs_rby, TRUE);
8728 
8729    RecordNewObjCmd();
8730    RedrawAnArea(botObj, topObj->bbox.ltx-GRID_ABS_SIZE(1),
8731          topObj->bbox.lty-GRID_ABS_SIZE(1),
8732          topObj->bbox.rbx+GRID_ABS_SIZE(1),
8733          topObj->bbox.rby+GRID_ABS_SIZE(1));
8734 
8735    SetFileModified(TRUE);
8736    return TRUE;
8737 }
8738 
ExecCreateArc(argv,obj_ptr,orig_cmd)8739 int ExecCreateArc(argv, obj_ptr, orig_cmd)
8740    char **argv, *orig_cmd;
8741    struct ObjRec *obj_ptr;
8742    /* create_arc_obj(abs_cx,abs_cy,radius,dir,theta1,theta2); */
8743 {
8744    char *abs_cx_str=argv[0], *abs_cy_str=argv[1], *radius_str=argv[2];
8745    char *dir_str=argv[3], *theta1_str=argv[4], *theta2_str=argv[5];
8746    int abs_cx=0, abs_cy=0, radius=0, dir=0, x1=0, y1=0, x2=0, y2=0;
8747    double theta1=(double)0, theta2=(double)0;
8748    double angle_in_radian=(double)0, angle2=(double)0;
8749 
8750    UtilRemoveQuotes(abs_cx_str);
8751    UtilRemoveQuotes(abs_cy_str);
8752    UtilRemoveQuotes(radius_str);
8753    UtilRemoveQuotes(dir_str);
8754    UtilRemoveQuotes(theta1_str);
8755    UtilRemoveQuotes(theta2_str);
8756    if (!IntExpression(abs_cx_str, &abs_cx, orig_cmd) ||
8757          !IntExpression(abs_cy_str, &abs_cy, orig_cmd) ||
8758          !IntExpression(radius_str, &radius, orig_cmd) ||
8759          !FloatExpression(theta1_str, &theta1, orig_cmd) ||
8760          !FloatExpression(theta2_str, &theta2, orig_cmd)) {
8761       return FALSE;
8762    }
8763    UtilTrimBlanks(dir_str);
8764    switch (*dir_str) {
8765    case '+': dir = ARC_CW; break;
8766    case '-': dir = ARC_CCW; break;
8767    default:
8768       sprintf(gszMsgBox, TgLoadString(STID_BAD_DIRECTION_WHILE_EXEC_CMD),
8769             dir_str, orig_cmd);
8770       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8771       return FALSE;
8772    }
8773    if (radius < 1) {
8774       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_CREATE_ARC_WITH_RAD1),
8775             TOOL_NAME, radius);
8776       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8777       return FALSE;
8778    }
8779    MakeQuiescent();
8780 
8781    switch (dir) {
8782    case ARC_CCW:
8783       theta1 += (double)90;
8784       theta2 += (double)90;
8785       break;
8786    case ARC_CW:
8787       theta1 = -theta1+((double)90);
8788       theta2 = -theta2+((double)90);
8789       break;
8790    }
8791    angle_in_radian = theta1 * M_PI / ((double)180);
8792    x1 = round(((double)radius)*cos(angle_in_radian));
8793    y1 = -round(((double)radius)*sin(angle_in_radian));
8794    angle_in_radian = theta2 * M_PI / ((double)180);
8795    x2 = round(((double)radius)*cos(angle_in_radian));
8796    y2 = -round(((double)radius)*sin(angle_in_radian));
8797 
8798    while (theta1 < (double)0) theta1 += (double)360;
8799    while (theta2 > theta1) theta2 -= (double)360;
8800    while (theta2 < theta1) theta2 += (double)360;
8801 
8802    switch (dir) {
8803    case ARC_CCW:
8804       angle2 = theta2-theta1;
8805       if (angle2 == 0) angle2 = (double)360;
8806       break;
8807    case ARC_CW:
8808       angle2 = theta2-theta1-((double)360);
8809       break;
8810    }
8811    CreateArcObj(abs_cx, abs_cy, abs_cx+x1, abs_cy+y1, abs_cx+x2, abs_cy+y2, dir,
8812          -radius, -radius, (radius<<1), (radius<<1), round(theta1*((double)64)),
8813          round(angle2*((double)64)), TRUE);
8814 
8815    RecordNewObjCmd();
8816    RedrawAnArea(botObj, topObj->bbox.ltx-GRID_ABS_SIZE(1),
8817          topObj->bbox.lty-GRID_ABS_SIZE(1),
8818          topObj->bbox.rbx+GRID_ABS_SIZE(1),
8819          topObj->bbox.rby+GRID_ABS_SIZE(1));
8820 
8821    SetFileModified(TRUE);
8822    return TRUE;
8823 }
8824 
8825 static IntPoint firstVertexInCreate, lastVertexInCreate;
8826 
ExecCreateFirstVertex(argv,obj_ptr,orig_cmd)8827 int ExecCreateFirstVertex(argv, obj_ptr, orig_cmd)
8828    char **argv, *orig_cmd;
8829    struct ObjRec *obj_ptr;
8830    /* create_first_vertex(abs_x,abs_y); */
8831 {
8832    char *abs_x_str=argv[0], *abs_y_str=argv[1];
8833    int abs_x=0, abs_y=0;
8834 
8835    UtilRemoveQuotes(abs_x_str);
8836    UtilRemoveQuotes(abs_y_str);
8837    if (!IntExpression(abs_x_str, &abs_x, orig_cmd) ||
8838          !IntExpression(abs_y_str, &abs_y, orig_cmd)) {
8839       return FALSE;
8840    }
8841    MakeQuiescent();
8842 
8843    ResetCreatePoly();
8844    AddPtToCreatePoly(abs_x, abs_y);
8845    firstVertexInCreate.x = abs_x;
8846    firstVertexInCreate.y = abs_y;
8847 
8848    return TRUE;
8849 }
8850 
ExecCreateNextVertex(argv,obj_ptr,orig_cmd)8851 int ExecCreateNextVertex(argv, obj_ptr, orig_cmd)
8852    char **argv, *orig_cmd;
8853    struct ObjRec *obj_ptr;
8854    /* create_next_vertex(abs_x,abs_y); */
8855 {
8856    char *abs_x_str=argv[0], *abs_y_str=argv[1];
8857    int abs_x=0, abs_y=0;
8858 
8859    UtilRemoveQuotes(abs_x_str);
8860    UtilRemoveQuotes(abs_y_str);
8861    if (!IntExpression(abs_x_str, &abs_x, orig_cmd) ||
8862          !IntExpression(abs_y_str, &abs_y, orig_cmd)) {
8863       return FALSE;
8864    }
8865    if (numPtsInPoly == 0) {
8866       sprintf(gszMsgBox, TgLoadString(STID_NO_START_VRTX_WHILE_EXEC_CMD),
8867             orig_cmd);
8868       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8869       return FALSE;
8870    }
8871    AddPtToCreatePoly(abs_x, abs_y);
8872    lastVertexInCreate.x = abs_x;
8873    lastVertexInCreate.y = abs_y;
8874 
8875    return TRUE;
8876 }
8877 
ExecCreatePoly(obj_ptr,orig_cmd)8878 void ExecCreatePoly(obj_ptr, orig_cmd)
8879    struct ObjRec *obj_ptr;
8880    char *orig_cmd;
8881    /* create_poly_obj(); */
8882 {
8883    if (numPtsInPoly <= 1) {
8884       sprintf(gszMsgBox, TgLoadString(STID_TOO_FEW_VRTX_WHILE_EXEC_CMD),
8885             numPtsInPoly, orig_cmd);
8886       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8887       ResetCreatePoly();
8888       gnAbortExec = TRUE;
8889       return;
8890    }
8891    MakeQuiescent();
8892 
8893    CreatePolyObj(numPtsInPoly, TRUE);
8894 
8895    RecordNewObjCmd();
8896    RedrawAnArea(botObj, topObj->bbox.ltx-GRID_ABS_SIZE(1),
8897          topObj->bbox.lty-GRID_ABS_SIZE(1),
8898          topObj->bbox.rbx+GRID_ABS_SIZE(1),
8899          topObj->bbox.rby+GRID_ABS_SIZE(1));
8900 
8901    SetFileModified(TRUE);
8902 }
8903 
ExecCreatePolygon(obj_ptr,orig_cmd)8904 void ExecCreatePolygon(obj_ptr, orig_cmd)
8905    struct ObjRec *obj_ptr;
8906    char *orig_cmd;
8907    /* create_polygon_obj(); */
8908 {
8909    if (numPtsInPoly <= 2) {
8910       sprintf(gszMsgBox, TgLoadString(STID_TOO_FEW_VRTX_WHILE_EXEC_CMD),
8911             numPtsInPoly, orig_cmd);
8912       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8913       ResetCreatePoly();
8914    } else {
8915       MakeQuiescent();
8916 
8917       if (firstVertexInCreate.x != lastVertexInCreate.x ||
8918             firstVertexInCreate.y != lastVertexInCreate.y) {
8919          AddPtToCreatePoly(firstVertexInCreate.x, firstVertexInCreate.y);
8920          lastVertexInCreate.x = firstVertexInCreate.x;
8921          lastVertexInCreate.y = firstVertexInCreate.y;
8922       }
8923       CreatePolygonObj(numPtsInPoly, TRUE);
8924 
8925       RecordNewObjCmd();
8926       RedrawAnArea(botObj, topObj->bbox.ltx-GRID_ABS_SIZE(1),
8927             topObj->bbox.lty-GRID_ABS_SIZE(1),
8928             topObj->bbox.rbx+GRID_ABS_SIZE(1),
8929             topObj->bbox.rby+GRID_ABS_SIZE(1));
8930 
8931       SetFileModified(TRUE);
8932    }
8933 }
8934 
8935 static struct SelRec *topSelBeforeCreateGroup=NULL;
8936 static int createGroupDepth=0;
8937 
8938 static
ResetCreateGroup()8939 void ResetCreateGroup()
8940 {
8941    struct SelRec *next_sel=NULL;
8942 
8943    while (topSelBeforeCreateGroup != NULL) {
8944       next_sel = topSelBeforeCreateGroup->next;
8945       free(topSelBeforeCreateGroup);
8946       topSelBeforeCreateGroup = next_sel;
8947    }
8948    createGroupDepth = 0;
8949 }
8950 
ExecStartCreateGroup(obj_ptr,orig_cmd)8951 void ExecStartCreateGroup(obj_ptr, orig_cmd)
8952    struct ObjRec *obj_ptr;
8953    char *orig_cmd;
8954    /* start_create_group_obj(); */
8955 {
8956    struct SelRec *sel_ptr=NULL;
8957 
8958    MakeQuiescent();
8959    sel_ptr = SelectThisObject(topObj);
8960    sel_ptr->next = topSelBeforeCreateGroup;
8961    topSelBeforeCreateGroup = sel_ptr;
8962    createGroupDepth++;
8963 }
8964 
ExecCreateGroup(obj_ptr,orig_cmd)8965 void ExecCreateGroup(obj_ptr, orig_cmd)
8966    struct ObjRec *obj_ptr;
8967    char *orig_cmd;
8968    /* create_group_obj(); */
8969 {
8970    struct SelRec *next_sel=NULL;
8971    struct ObjRec *optr=NULL, *start_obj=NULL;
8972    int num_objs=0;
8973 
8974    if (createGroupDepth <= 0 || topSelBeforeCreateGroup == NULL) {
8975       sprintf(gszMsgBox, TgLoadString(STID_NO_START_OBJ_WHILE_EXEC_CMD),
8976             "start_create_group_obj", orig_cmd);
8977       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8978       ResetCreateGroup();
8979       gnAbortExec = TRUE;
8980       return;
8981    }
8982    MakeQuiescent();
8983 
8984    if (topSelBeforeCreateGroup->obj != NULL) {
8985       for (optr=topObj; optr != NULL; optr=optr->next) {
8986          if (optr == topSelBeforeCreateGroup->obj) {
8987             break;
8988          }
8989       }
8990       if (optr == NULL) {
8991          sprintf(gszMsgBox, TgLoadString(STID_CANT_FIND_MARK_WHILE_EXEC_CMD),
8992                "start_create_group_obj", orig_cmd);
8993          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
8994          ResetCreateGroup();
8995          gnAbortExec = TRUE;
8996          return;
8997       }
8998    }
8999    if (topSelBeforeCreateGroup->obj == NULL) {
9000       start_obj = botObj;
9001    } else {
9002       start_obj = topSelBeforeCreateGroup->obj->prev;
9003    }
9004    for (optr=start_obj, num_objs=0; optr != NULL; optr=optr->prev, num_objs++) {
9005    }
9006    if (num_objs == 0) {
9007       sprintf(gszMsgBox, TgLoadString(STID_NO_OBJ_GROUP_WHILE_EXEC_CMD),
9008             orig_cmd);
9009       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
9010       ResetCreateGroup();
9011       gnAbortExec = TRUE;
9012       return;
9013    } else if (num_objs == 1) {
9014       if (start_obj->type != OBJ_POLY && start_obj->type != OBJ_POLYGON) {
9015          sprintf(gszMsgBox, TgLoadString(STID_CANT_GRP_SNGL_WHILE_EXEC_CMD),
9016                orig_cmd);
9017          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
9018          ResetCreateGroup();
9019          gnAbortExec = TRUE;
9020          return;
9021       }
9022    }
9023    for (optr=start_obj; optr != NULL; optr=optr->prev) {
9024       struct SelRec *sel_ptr=SelectThisObject(optr);
9025 
9026       sel_ptr->next = topSel;
9027       sel_ptr->prev = NULL;
9028       if (topSel == NULL) {
9029          botSel = sel_ptr;
9030       } else {
9031          topSel->prev = sel_ptr;
9032       }
9033       topSel = sel_ptr;
9034    }
9035    UpdSelBBox();
9036    GroupSelObj(TRUE, TRUE, TRUE);
9037    RemoveAllSel();
9038    justDupped = FALSE;
9039 
9040    next_sel = topSelBeforeCreateGroup->next;
9041    free(topSelBeforeCreateGroup);
9042    topSelBeforeCreateGroup = next_sel;
9043    createGroupDepth--;
9044 }
9045 
ExecSetAllowInterrupt(argv,obj_ptr,orig_cmd)9046 int ExecSetAllowInterrupt(argv, obj_ptr, orig_cmd)
9047    char **argv, *orig_cmd;
9048    struct ObjRec *obj_ptr;
9049    /* set_allow_interrupt(true_or_false); */
9050 {
9051    char *allow_str=argv[0];
9052    int currently_enabled=execInterruptEnabled;
9053 
9054    UtilRemoveQuotes(allow_str);
9055    if (strcmp(allow_str, "TRUE") == 0) {
9056       execInterruptEnabled = TRUE;
9057    } else if (strcmp(allow_str, "FALSE") == 0) {
9058       execInterruptEnabled = FALSE;
9059    } else {
9060       return BadArg("true_or_false", orig_cmd);
9061    }
9062    if (!currently_enabled && execInterruptEnabled && execInterruptQueued) {
9063       gnAbortExec = TRUE;
9064       return FALSE;
9065    }
9066    return TRUE;
9067 }
9068 
9069 static
DoExecSelectEachObjAndExec(attr_name)9070 int DoExecSelectEachObjAndExec(attr_name)
9071    char *attr_name;
9072 {
9073    struct ObjRec *optr=NULL;
9074    int rc=TRUE;
9075 
9076    for (optr=botObj; rc && optr != NULL; optr=optr->prev) {
9077       struct AttrRec *attr_ptr=NULL;
9078 
9079       attr_ptr = FindAttrWithName(optr, attr_name, NULL);
9080       if (attr_ptr != NULL) {
9081          struct SelRec *sel_ptr=SelectThisObject(optr);
9082 
9083          AddSel(NULL, topSel, sel_ptr);
9084          UpdSelBBox();
9085          if (!DoExec(attr_ptr, optr)) {
9086             rc = FALSE;
9087          }
9088          RemoveAllSel();
9089       }
9090    }
9091    return rc;
9092 }
9093 
ExecSelectEachObjAndExec(argv,obj_ptr,orig_cmd)9094 int ExecSelectEachObjAndExec(argv, obj_ptr, orig_cmd)
9095    char **argv, *orig_cmd;
9096    struct ObjRec *obj_ptr;
9097    /* select_each_obj_and_exec(attr_name_to_exec); */
9098 {
9099    char *attr_name_to_exec=argv[0];
9100    int rc=TRUE;
9101 
9102    UtilRemoveQuotes(attr_name_to_exec);
9103 
9104    if (topSel != NULL) {
9105       struct AttrRec *attr_ptr=NULL;
9106 
9107       sprintf(execDummyStr, "%s=", attr_name_to_exec);
9108       attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, NULL);
9109       if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
9110 
9111       rc = DoExecSelectEachObjAndExec(execDummyStr);
9112    } else {
9113       char *attr_name=(char*)malloc(strlen(attr_name_to_exec)+2);
9114 
9115       if (attr_name == NULL) FailAllocMessage();
9116       sprintf(attr_name, "%s=", attr_name_to_exec);
9117 
9118       MakeQuiescent();
9119       StartCompositeCmd();
9120       if (lastPageNum == 1) {
9121          rc = DoExecSelectEachObjAndExec(attr_name);
9122       } else {
9123          int saved_cur_page_num=curPageNum, prev_page_num=curPageNum;
9124 
9125          for (curPageNum=1; rc && curPageNum <= lastPageNum; curPageNum++) {
9126             if (prev_page_num != curPageNum) {
9127                PrepareToRecord(CMD_GOTO_PAGE, NULL, NULL, prev_page_num);
9128                GotoPageNum(curPageNum);
9129                ShowPage();
9130                XSync(mainDisplay, False);
9131                RecordCmd(CMD_GOTO_PAGE, NULL, NULL, NULL, curPageNum);
9132                ClearAndRedrawDrawWindow();
9133                prev_page_num = curPageNum;
9134             }
9135             rc = DoExecSelectEachObjAndExec(attr_name);
9136          }
9137          if (prev_page_num != curPageNum) {
9138             PrepareToRecord(CMD_GOTO_PAGE, NULL, NULL, prev_page_num);
9139             GotoPageNum(saved_cur_page_num);
9140             ShowPage();
9141             RecordCmd(CMD_GOTO_PAGE, NULL, NULL, NULL, saved_cur_page_num);
9142             ClearAndRedrawDrawWindow();
9143             prev_page_num = curPageNum;
9144          }
9145       }
9146       EndCompositeCmd();
9147 
9148       UtilFree(attr_name);
9149    }
9150    return rc;
9151 }
9152 
ExecEditAttrInTextMode(argv,obj_ptr,orig_cmd)9153 int ExecEditAttrInTextMode(argv, obj_ptr, orig_cmd)
9154    char **argv, *orig_cmd;
9155    struct ObjRec *obj_ptr;
9156    /* edit_attr_in_text_mode(attr_name); */
9157 {
9158    char *attr_name=argv[0];
9159    struct AttrRec *attr_ptr=NULL;
9160    struct ObjRec *attr_owner_obj=NULL;
9161 
9162    UtilRemoveQuotes(attr_name);
9163 
9164    sprintf(execDummyStr, "%s=", attr_name);
9165    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
9166    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
9167 
9168    EditTextInAttr(attr_ptr);
9169 
9170    return TRUE;
9171 }
9172 
ExecSetFileUnSavable(obj_ptr,orig_cmd)9173 void ExecSetFileUnSavable(obj_ptr, orig_cmd)
9174    struct ObjRec *obj_ptr;
9175    char *orig_cmd;
9176    /* set_file_unsavable(); */
9177 {
9178    if (!IsFiletUnSavable()) {
9179       if (!fileModified) SetFileModified(TRUE);
9180       SetUnSavableFile(TRUE);
9181       RedrawTitleWindow();
9182    }
9183 }
9184 
9185 static
ExternalPsToEpsi(scale_val,src_file_name,dest_file_name)9186 void ExternalPsToEpsi(scale_val, src_file_name, dest_file_name)
9187    int scale_val;
9188    char *src_file_name, *dest_file_name;
9189 {
9190    char cmd[MAXSTRING<<1];
9191 
9192    switch (scale_val) {
9193    case 1:
9194       snprintf(cmd, sizeof(cmd), "pstoepsi %s %s", src_file_name,
9195             dest_file_name);
9196       break;
9197    case 2:
9198       snprintf(cmd, sizeof(cmd), "pstoepsi -2x %s %s", src_file_name,
9199             dest_file_name);
9200       break;
9201    }
9202    ExecuteCmd(cmd, FALSE);
9203 }
9204 
9205 #define GS_TYPE_GNU  0
9206 #define GS_TYPE_AFPL 1
9207 
9208 static
FindGsVersion(gs_copyright,pn_gs_type,pn_gs_version)9209 void FindGsVersion(gs_copyright, pn_gs_type, pn_gs_version)
9210    char *gs_copyright;
9211    int *pn_gs_type, *pn_gs_version;
9212 {
9213    char *psz_type=NULL, *psz_name=NULL, *psz_copy=UtilStrDup(gs_copyright);
9214 
9215    if (psz_copy == NULL) FailAllocMessage();
9216    psz_type = strtok(psz_copy, " \t\r\n");
9217    if (psz_type != NULL) {
9218       if (UtilStrICmp(psz_type, "GNU") == 0) {
9219          if (pn_gs_type != NULL) *pn_gs_type = GS_TYPE_GNU;
9220       } else if (UtilStrICmp(psz_type, "GPL") == 0) {
9221          if (pn_gs_type != NULL) *pn_gs_type = GS_TYPE_GNU;
9222       } else if (UtilStrICmp(psz_type, "AFPL") == 0) {
9223          if (pn_gs_type != NULL) *pn_gs_type = GS_TYPE_AFPL;
9224       } else if (UtilStrICmp(psz_type, "Aladdin") == 0) {
9225          if (pn_gs_type != NULL) *pn_gs_type = GS_TYPE_AFPL;
9226       } else {
9227          /* unrecognized type */
9228          psz_type = NULL;
9229       }
9230    }
9231    if (psz_type != NULL) {
9232       psz_name = strtok(NULL, " \t\r\n");
9233       if (UtilStrICmp(psz_name, "Ghostscript") != 0) {
9234          /* shouldn't come here */
9235          psz_name = NULL;
9236       }
9237    }
9238    if (psz_type != NULL && psz_name != NULL) {
9239       for (;;) {
9240          char *psz=strtok(NULL, " \t\r\n");
9241 
9242          if (psz == NULL) break;
9243          if (*psz >= '0' && *psz <= '9') {
9244             int gs_version=(-1);
9245 
9246             if (sscanf(psz, "%d", &gs_version) == 1) {
9247                if (pn_gs_version != NULL) *pn_gs_version = gs_version;
9248                break;
9249             }
9250          }
9251       }
9252    }
9253    UtilFree(psz_copy);
9254 }
9255 
9256 static
PbmToEpsi(d_scale,pbm_fname,out_fname,orig_cmd)9257 int PbmToEpsi(d_scale, pbm_fname, out_fname, orig_cmd)
9258    double d_scale;
9259    char *pbm_fname, *out_fname, *orig_cmd;
9260 {
9261    char xbm_fname[MAXPATHLENGTH];
9262    int rc=0, x_hot=0, y_hot=0, image_w=0, image_h=0;
9263    Pixmap bitmap=None;
9264    FILE *out_fp=NULL;
9265 
9266    *xbm_fname = '\0';
9267    out_fp = fopen(out_fname, "w");
9268    if (out_fp == NULL) {
9269       FailToOpenMessage(out_fname, "w", NULL);
9270       return FALSE;
9271    }
9272    if (!ConvertPbmToXbm(pbm_fname, xbm_fname, sizeof(xbm_fname))) {
9273       sprintf(gszMsgBox, TgLoadString(STID_CONVERT_TO_XBM_WHILE_EXEC_CMD),
9274             pbm_fname, "PBM", orig_cmd);
9275       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
9276       fclose(out_fp);
9277       return FALSE;
9278    }
9279    rc = XReadBitmapFile(mainDisplay, mainWindow, xbm_fname,
9280          (unsigned int *)(&image_w), (unsigned int *)(&image_h), &bitmap,
9281          &x_hot, &y_hot);
9282    unlink(xbm_fname);
9283 
9284    if (rc == BitmapSuccess) {
9285       int watch_cursor=watchCursorOnMainWindow;
9286       XImage *image=NULL;
9287 
9288       if (!watch_cursor) {
9289          SetWatchCursor(drawWindow);
9290          SetWatchCursor(mainWindow);
9291       }
9292       image = XGetImage(mainDisplay, bitmap, 0, 0, image_w, image_h, 1,
9293             ZPixmap);
9294       if (image == NULL) {
9295          MsgBox(TgLoadString(STID_XGETIMAGE_MAY_RUN_OUT_VMEM), TOOL_NAME,
9296                INFO_MB);
9297       } else {
9298          int row=0, col=0, llx=0, lly=0, urx=0, ury=0;
9299          int top=image_h+1, bottom=(-1), left=image_w+1, right=(-1);
9300          double dllx=(double)0, dlly=(double)0, durx=(double)0, dury=(double)0;
9301 
9302          for (row=0; row < image_h; row++) {
9303             for (col=0; col < image_w; col++) {
9304                if (XGetPixel(image, col, row)) {
9305                   if (row < top) top = row;
9306                   if (row > bottom) bottom = row;
9307                   if (col < left) left = col;
9308                   if (col > right) right = col;
9309                }
9310             }
9311          }
9312          dllx = ((double)(left))/d_scale;
9313          dlly = ((double)(image_h-bottom))/d_scale;
9314          durx = ((double)(right))/d_scale;
9315          dury = ((double)(image_h-top))/d_scale;
9316 
9317          llx = round(dllx); lly = round(dlly);
9318          urx = round(durx); ury = round(dury);
9319 
9320 #ifdef _NOT_DEFINED
9321          fprintf(stderr, "image_w = %1d\n", image_w);
9322          fprintf(stderr, "image_h = %1d\n", image_h);
9323          fprintf(stderr, "llx = %1d\n", left);
9324          fprintf(stderr, "lly = %1d\n", image_h-bottom);
9325          fprintf(stderr, "urx = %1d\n", right);
9326          fprintf(stderr, "ury = %1d\n", image_h-top);
9327          fprintf(stderr, "%%!PS-Adobe-2.0 EPSF-1.2\n");
9328          fprintf(stderr, "%%%%BoundingBox: %d %d %d %d\n", llx, lly, urx, ury);
9329          fprintf(stderr, "%%%%BeginPreview: %d %d 1 %d\n", right-left+1,
9330                bottom-top+1, bottom-top+1);
9331          fprintf(stderr, "%%%%EndImage\n");
9332          fprintf(stderr, "%%%%EndPreview\n");
9333 #endif /* _NOT_DEFINED */
9334 
9335          fprintf(out_fp, "%%!PS-Adobe-2.0 EPSF-1.2\n");
9336          fprintf(out_fp, "%%%%BoundingBox: %d %d %d %d\n", llx, lly, urx, ury);
9337          fprintf(out_fp, "%%%%BeginPreview: %d %d 1 %d\n", right-left+1,
9338                bottom-top+1, bottom-top+1);
9339 
9340          for (row=top; row <= bottom; row++) {
9341             int even=TRUE;
9342 
9343             fprintf(out_fp, "%% ");
9344             for (col=left; col <= right; col+=4) {
9345                int nibble=0;
9346 
9347                if (XGetPixel(image, col, row)) nibble |= 0x08;
9348                if (XGetPixel(image, col+1, row)) nibble |= 0x04;
9349                if (XGetPixel(image, col+2, row)) nibble |= 0x02;
9350                if (XGetPixel(image, col+3, row)) nibble |= 0x01;
9351                fprintf(out_fp, "%x", nibble);
9352                even = !even;
9353             }
9354             fprintf(out_fp, "%s\n", (even ? "" : "0"));
9355          }
9356          fprintf(out_fp, "%%%%EndImage\n");
9357          fprintf(out_fp, "%%%%EndPreview\n");
9358 
9359          if (!watch_cursor) {
9360             SetDefaultCursor(mainWindow);
9361             ShowCursor();
9362          }
9363          XDestroyImage(image);
9364       }
9365    } else {
9366       sprintf(gszMsgBox, TgLoadString(STID_IMPORT_FAILED_WHILE_EXEC_CMD),
9367             xbm_fname, orig_cmd);
9368       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
9369    }
9370    if (bitmap != None) XFreePixmap(mainDisplay, bitmap);
9371    fclose(out_fp);
9372 
9373    return TRUE;
9374 }
9375 
9376 static
InternalPsToEpsi(scale,src_file_name,dest_file_name,orig_cmd)9377 int InternalPsToEpsi(scale, src_file_name, dest_file_name, orig_cmd)
9378    double scale;
9379    char *src_file_name, *dest_file_name, *orig_cmd;
9380 {
9381    CVList list;
9382    CVListElem *elem=NULL;
9383    char cmd[MAXSTRING<<1], *gs_copyright=NULL;
9384    char tmp_fname1[MAXPATHLENGTH], tmp_pbm_fname[MAXPATHLENGTH];
9385    int gs_type=(-1), gs_version=(-1), ps_scale=0;
9386    double tmp_scale=(double)0;
9387 
9388    if (MkTempFile(tmp_fname1, sizeof(tmp_fname1), tmpDir, TOOL_NAME) == NULL) {
9389       return FALSE;
9390    }
9391    sprintf(tmp_pbm_fname, "%s.pbm", tmp_fname1);
9392    unlink(tmp_pbm_fname);
9393 
9394    CVListInit(&list);
9395    snprintf(cmd, sizeof(cmd), "%s -help | grep Ghostscript", gsPath);
9396    if (!ExecuteCmdGetResult(cmd, &list, 1)) {
9397       sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_EXECUTE_CMD_EXEC_CMD),
9398             cmd, orig_cmd);
9399       return FALSE;
9400    }
9401    for (elem=ListFirst(&list); elem != NULL; elem=ListNext(&list, elem)) {
9402       gs_copyright = UtilStrDup((char*)(elem->obj));
9403       FindGsVersion(gs_copyright, &gs_type, &gs_version);
9404       break;
9405    }
9406    if (gs_type == (-1) || gs_version == (-1)) {
9407       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_IDEN_GS), gs_copyright);
9408       Msg(gszMsgBox);
9409    }
9410    tmp_scale = ((double)72)*scale;
9411    ps_scale = round(tmp_scale);
9412    if (ps_scale < 1) ps_scale = 1;
9413 
9414    if (fabs(scale-((double)1)) < EQ_TOL) {
9415       snprintf(cmd, sizeof(cmd), "%s %s -sOutputFile=%s -- %s",
9416             gsPath, "-q -dBATCH -dNOPAUSE -sDEVICE=pbm", tmp_pbm_fname,
9417             src_file_name);
9418    } else {
9419       snprintf(cmd, sizeof(cmd), "%s %s -r%1dx%1d -sOutputFile=%s -- %s",
9420             gsPath, "-q -dBATCH -dNOPAUSE -sDEVICE=pbm", ps_scale, ps_scale,
9421             tmp_pbm_fname, src_file_name);
9422    }
9423    ExecuteCmd(cmd, FALSE);
9424    PbmToEpsi(scale, tmp_pbm_fname, tmp_fname1, orig_cmd);
9425    UtilConcatFile(tmp_fname1, src_file_name, dest_file_name);
9426 
9427    unlink(tmp_fname1);
9428    unlink(tmp_pbm_fname);
9429 
9430    /* clean up */
9431    for (elem=ListFirst(&list); elem != NULL; elem=ListNext(&list, elem)) {
9432       UtilFree((char*)(elem->obj));
9433    }
9434    ListUnlinkAll(&list);
9435    if (gs_copyright != NULL) UtilFree(gs_copyright);
9436 
9437    return TRUE;
9438 }
9439 
9440 static int externalPsToEpsi=INVALID;
9441 
ExecPsToEpsi(argv,obj_ptr,orig_cmd)9442 int ExecPsToEpsi(argv, obj_ptr, orig_cmd)
9443    char **argv, *orig_cmd;
9444    struct ObjRec *obj_ptr;
9445    /* pstoepsi(dest_file_name,src_file_name,scale); */
9446 {
9447    char *dest_file_name=argv[0], *src_file_name=argv[1], *scale_str=argv[2];
9448    double scale=(double)0;
9449 
9450    UtilRemoveQuotes(dest_file_name);
9451    UtilRemoveQuotes(src_file_name);
9452    UtilTrimBlanks(dest_file_name);
9453    UtilTrimBlanks(src_file_name);
9454 
9455    if (PRTGIF && !cmdLineOpenDisplay) {
9456       sprintf(gszMsgBox, TgLoadString(STID_TOOL_NOT_INTV_WHILE_EXEC_CMD),
9457             TOOL_NAME, orig_cmd);
9458       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
9459       return FALSE;
9460    }
9461    if (!UtilPathExists(src_file_name)) {
9462       sprintf(gszMsgBox, TgLoadString(STID_INVALID_PATH_WHILE_EXEC_CMD),
9463             src_file_name, orig_cmd);
9464       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
9465       return FALSE;
9466    }
9467    if (!FloatExpression(scale_str, &scale, orig_cmd)) {
9468       return FALSE;
9469    }
9470    if (scale < ((double)0.1) || scale > ((double)10)) {
9471       sprintf(gszMsgBox, TgLoadString(STID_FUNC_ARG_STRS_RANGE),
9472             orig_cmd, "scale", "0.1", "10", scale_str);
9473       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
9474       return FALSE;
9475    }
9476    if (externalPsToEpsi == INVALID) {
9477       char *c_ptr;
9478 
9479       externalPsToEpsi = FALSE;
9480       if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "ExternalPsToEpsi")) !=
9481             NULL && UtilStrICmp(c_ptr, "true") == 0) {
9482          externalPsToEpsi = TRUE;
9483       }
9484    }
9485    if (externalPsToEpsi) {
9486       int scale_val=round(scale);
9487 
9488       if (scale_val < 1 || scale_val > 2) {
9489          sprintf(gszMsgBox, TgLoadString(STID_FUNC_ARG_RANGE),
9490                orig_cmd, "scale", 1, 2, scale_val);
9491          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
9492          return FALSE;
9493       }
9494       ExternalPsToEpsi(scale_val, src_file_name, dest_file_name);
9495    } else {
9496       if (!InternalPsToEpsi(scale, src_file_name, dest_file_name,
9497             orig_cmd)) {
9498          /* failed, try external one? */
9499       }
9500    }
9501    return TRUE;
9502 }
9503 
ExecObjsBBoxIntersect(argv,obj_ptr,orig_cmd)9504 int ExecObjsBBoxIntersect(argv, obj_ptr, orig_cmd)
9505    char **argv, *orig_cmd;
9506    struct ObjRec *obj_ptr;
9507    /* objs_bbox_intersect(obj1_name,obj2_name,result_attr); */
9508 {
9509    char *obj1_name=argv[0], *obj2_name=argv[1], *result_attr_name=argv[2];
9510    char buf[40];
9511    struct ObjRec *named_obj1=NULL, *named_obj2=NULL;
9512    struct ObjRec *top_owner1=NULL, *top_owner2=NULL;
9513    struct ObjRec *result_attr_owner_obj=NULL;
9514    struct AttrRec *result_attr=NULL;
9515 
9516    UtilRemoveQuotes(obj1_name);
9517    UtilRemoveQuotes(obj2_name);
9518    UtilRemoveQuotes(result_attr_name);
9519    UtilTrimBlanks(obj1_name);
9520    UtilTrimBlanks(obj2_name);
9521    UtilTrimBlanks(result_attr_name);
9522 
9523    named_obj1 = FindObjWithName(botObj, obj_ptr, obj1_name, FALSE,
9524          FALSE, NULL, &top_owner1);
9525    if (named_obj1 == NULL) {
9526       return BadObjName(obj1_name, orig_cmd);
9527    }
9528    named_obj2 = FindObjWithName(botObj, obj_ptr, obj2_name, FALSE,
9529          FALSE, NULL, &top_owner2);
9530    if (named_obj2 == NULL) {
9531       return BadObjName(obj2_name, orig_cmd);
9532    }
9533    sprintf(execDummyStr, "%s=", result_attr_name);
9534    result_attr = FindAttrWithName(obj_ptr, execDummyStr,
9535          &result_attr_owner_obj);
9536    if (result_attr == NULL) return BadAttr(execDummyStr, orig_cmd);
9537 
9538    strcpy(buf, (BBoxIntersect(named_obj1->bbox, named_obj2->bbox) ?  "1" :
9539          "0"));
9540 
9541    ReplaceAttrFirstValue(result_attr_owner_obj, result_attr,
9542          (buf==NULL ? "" : buf));
9543 
9544    return TRUE;
9545 }
9546 
ExecDelAllAttrFromSelObj(obj_ptr,orig_cmd)9547 void ExecDelAllAttrFromSelObj(obj_ptr, orig_cmd)
9548    struct ObjRec *obj_ptr;
9549    char *orig_cmd;
9550    /* delete_all_attr_from_selected_objs(); */
9551 {
9552    struct SelRec *sel_ptr=NULL;
9553    int changed=FALSE;
9554 
9555    if (topSel == NULL) return;
9556 
9557    HighLightReverse();
9558    StartCompositeCmd();
9559    for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
9560       if (sel_ptr->obj->fattr != NULL) {
9561          changed = TRUE;
9562          PrepareToReplaceAnObj(sel_ptr->obj);
9563          DelAllAttrs(sel_ptr->obj->fattr);
9564          sel_ptr->obj->fattr = sel_ptr->obj->lattr = NULL;
9565          AdjObjBBox(sel_ptr->obj);
9566          RecordReplaceAnObj(sel_ptr->obj);
9567       }
9568    }
9569    EndCompositeCmd();
9570 
9571    if (changed) {
9572       SetFileModified(TRUE);
9573       RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
9574             selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
9575       UpdSelBBox();
9576       justDupped = FALSE;
9577    }
9578    HighLightForward();
9579 }
9580 
9581 typedef struct tagRandomPermutationInfo {
9582    int num_states;
9583    unsigned int *iv;
9584    unsigned int *state;
9585 } RandomPermutationInfo;
9586 
9587 static
Swap(psz,i,j)9588 void Swap(psz, i, j)
9589    unsigned int *psz;
9590    int i, j;
9591 {
9592     unsigned int t=psz[i];
9593 
9594     psz[i] = psz[j];
9595     psz[j] = t;
9596 }
9597 
9598 static
RandomPermutation(prpi,num_states)9599 void RandomPermutation(prpi, num_states)
9600    RandomPermutationInfo *prpi;
9601    int num_states;
9602 {
9603    int i=0, j=0;
9604    time_t tloc;
9605 
9606    memset(prpi, 0, sizeof(RandomPermutationInfo));
9607    prpi->num_states = num_states;
9608    prpi->iv = (unsigned int *)malloc(num_states*sizeof(unsigned int));
9609    prpi->state = (unsigned int *)malloc(num_states*sizeof(unsigned int));
9610    if (prpi->iv == NULL || prpi->state == NULL) FailAllocMessage();
9611    memset(prpi->iv, 0, num_states*sizeof(unsigned int));
9612    memset(prpi->state, 0, num_states*sizeof(unsigned int));
9613    for (i=0; i < num_states; i++) prpi->state[i] = i;
9614 
9615    time(&tloc);
9616 #ifndef _NO_RAND48
9617    srand48((long)tloc);
9618    for (i=0; i < num_states; i++) {
9619       double dval=drand48();
9620       int ival=0;
9621 
9622       if (num_states > 256) {
9623          ival = (unsigned int)(dval*((double)num_states));
9624          if (ival >= num_states) ival = num_states - 1;
9625          if (ival < 0) ival = 0;
9626       } else {
9627          ival = (unsigned int)(dval*((double)256));
9628          if (ival >= 256) ival = 255;
9629          if (ival < 0) ival = 0;
9630       }
9631       prpi->iv[i] = (unsigned int)ival;
9632    }
9633 #else /* _NO_RAND48 */
9634    srand((unsigned int)tloc);
9635    for (i=0; i < num_states; i++) {
9636       unsigned int uival=(rand() & 0x0ffff);
9637 
9638       uival *= 60013;
9639       if (num_states > 256) {
9640          uival = uival % num_states;
9641       } else {
9642          uival = (uival & 0x0ff);
9643       }
9644       prpi->iv[i] = uival;
9645    }
9646 #endif /* ~_NO_RAND48 */
9647 
9648    for (i=0, j=0; i < num_states; i++) {
9649       j = j + (int)(prpi->state[i]) + (int)(prpi->iv[i]);
9650       j = j % num_states;
9651       Swap(prpi->state, i, j);
9652    }
9653 }
9654 
ExecRndPermLinesInAttr(argv,obj_ptr,orig_cmd)9655 int ExecRndPermLinesInAttr(argv, obj_ptr, orig_cmd)
9656    char **argv, *orig_cmd;
9657    struct ObjRec *obj_ptr;
9658    /* random_permute_lines_in_attr(attr); */
9659 {
9660    char *attr_name=argv[0], *tmp_buf=NULL, **word_array=NULL;
9661    int i=0, count=0, index=0, need_to_free_tmp_buf=FALSE;
9662    MiniLinesInfo *minilines=NULL;
9663    MiniLineInfo *pMiniLine=NULL;
9664    struct AttrRec *attr_ptr=NULL;
9665    struct ObjRec *attr_owner_obj=NULL;
9666    RandomPermutationInfo rpi;
9667 
9668    UtilRemoveQuotes(attr_name);
9669 
9670    sprintf(execDummyStr, "%s=", attr_name);
9671    attr_ptr = FindAttrWithName(obj_ptr, execDummyStr, &attr_owner_obj);
9672    if (attr_ptr == NULL) return BadAttr(execDummyStr, orig_cmd);
9673 
9674    count = 0;
9675    for (pMiniLine=attr_ptr->obj->detail.t->minilines.first->next;
9676          pMiniLine != NULL; pMiniLine=pMiniLine->next) {
9677       count++;
9678    }
9679    if (count <= 0) return TRUE;
9680 
9681    word_array = (char**)malloc(count*sizeof(char*));
9682 
9683    if (word_array == NULL) FailAllocMessage();
9684    memset(word_array, 0, count*sizeof(char*));
9685 
9686    for (pMiniLine=attr_ptr->obj->detail.t->minilines.first->next;
9687          pMiniLine != NULL; pMiniLine=pMiniLine->next, index++) {
9688       need_to_free_tmp_buf = FALSE;
9689       tmp_buf = NULL;
9690       if (pMiniLine == attr_ptr->obj->detail.t->minilines.first) {
9691          char *attr_value=NULL;
9692 
9693          tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
9694          attr_value = UtilStrDup(tmp_buf);
9695          if (attr_value == NULL) FailAllocMessage();
9696          ParseAttrStr(tmp_buf, NULL, 0, attr_value, strlen(attr_value)+1);
9697          if (need_to_free_tmp_buf) UtilFree(tmp_buf);
9698          word_array[index] = UtilStrDup(attr_value);
9699          UtilFree(attr_value);
9700       } else {
9701          tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
9702          word_array[index] = UtilStrDup(tmp_buf);
9703          if (need_to_free_tmp_buf) UtilFree(tmp_buf);
9704       }
9705       if (word_array[index] == NULL) FailAllocMessage();
9706    }
9707    memset(&rpi, 0, sizeof(RandomPermutationInfo));
9708    RandomPermutation(&rpi, count);
9709 
9710    CleanTmpStr();
9711 
9712    need_to_free_tmp_buf = FALSE;
9713    tmp_buf = NULL;
9714    minilines = (&attr_ptr->obj->detail.t->minilines);
9715    tmp_buf = ConvertAttrNameFirstMiniLineToString(attr_ptr,
9716          &need_to_free_tmp_buf);
9717    if (!AppendToTmpStr(tmp_buf)) FailAllocMessage();
9718    if (need_to_free_tmp_buf) UtilFree(tmp_buf);
9719 
9720    for (i=0; i < count; i++) {
9721       AppendToTmpStr(word_array[rpi.state[i]]);
9722    }
9723    ReplaceAttrAllValues(attr_owner_obj, attr_ptr, &topTmpStr, &botTmpStr);
9724    CleanTmpStr();
9725 
9726    return TRUE;
9727 }
9728 
9729 /* --------------------- End of Exec Routines --------------------- */
9730 
9731 static
ExecFreeArgv(need_raw_argv,argc,p_argv,p_raw_argv)9732 char *ExecFreeArgv(need_raw_argv, argc, p_argv, p_raw_argv)
9733    int need_raw_argv, argc;
9734    char ***p_argv, ***p_raw_argv;
9735 {
9736    register int i;
9737 
9738    for (i=0; i < argc; i++) {
9739       if ((*p_argv)[i] == NULL) break;
9740       free((*p_argv)[i]);
9741    }
9742    if (*p_argv != NULL) free(*p_argv);
9743    if (need_raw_argv) {
9744       for (i=0; i < argc; i++) {
9745          if ((*p_raw_argv)[i] == NULL) break;
9746          free((*p_raw_argv)[i]);
9747       }
9748       if (*p_raw_argv != NULL) free(*p_raw_argv);
9749    }
9750    return NULL;
9751 }
9752 
9753 static
ShowExecStatus(need_raw_argv,argc,argv,raw_argv,func_name)9754 void ShowExecStatus(need_raw_argv, argc, argv, raw_argv, func_name)
9755    int need_raw_argv, argc;
9756    char **argv, **raw_argv, *func_name;
9757 {
9758    register int i, index;
9759 
9760    sprintf(execDummyStr, "EXEC: %s", func_name);
9761    index = strlen(execDummyStr);
9762    for (i=0; index < sizeof(execDummyStr)-7 && i < argc; i++) {
9763       int len=strlen(need_raw_argv ? raw_argv[i] : argv[i]);
9764 
9765       if (index+len+1 >= sizeof(execDummyStr)-7) {
9766          break;
9767       }
9768       if (i == 0) {
9769          execDummyStr[index++] = '(';
9770       } else {
9771          execDummyStr[index++] = ',';
9772       }
9773       strcpy(&execDummyStr[index], need_raw_argv ? raw_argv[i] : argv[i]);
9774       index += len;
9775    }
9776    if (i == argc) {
9777       if (argc == 0) execDummyStr[index++] = '(';
9778       execDummyStr[index++] = ')';
9779       execDummyStr[index] = '\0';
9780    } else {
9781       strcpy(&execDummyStr[index], ",...)");
9782    }
9783    SetStringStatus(execDummyStr);
9784    if (mainDisplay != NULL) XSync(mainDisplay, False);
9785 }
9786 
9787 static
ExecuteACommand(cmd_ptr,obj_ptr)9788 char *ExecuteACommand(cmd_ptr, obj_ptr)
9789    char * cmd_ptr;
9790    struct ObjRec * obj_ptr;
9791 {
9792    ExecInfo *pei=NULL;
9793    int i, tok_type, rc=TRUE, func_argc=0, need_raw_argv=FALSE;
9794    char buf[MAXSTRING<<2], **argv=NULL, **raw_argv=NULL;
9795    char *c_ptr=GetToken(cmd_ptr, buf, sizeof(buf), &tok_type);
9796 
9797    if (c_ptr == NULL) return NULL;
9798    if (*c_ptr == '\0') return c_ptr;
9799    for (pei=gExecInfo; pei->pfunc != NULL; pei++) {
9800       if (strcmp(pei->func_name, buf) == 0) {
9801          break;
9802       }
9803    }
9804    if (cmdLineTgrm2) {
9805       if (pei->pfunc == NULL) {
9806          pei = Tangram2GetExecInfo(buf);
9807       }
9808    }
9809    if (pei == NULL || pei->pfunc == NULL) {
9810       int len=strlen(buf);
9811 
9812       if (len > 0 && buf[len-1] == ' ') {
9813          sprintf(execDummyStr, TgLoadString(STID_UNRECOG_CMD_MAY_BE_BLANKS_ABT),
9814               buf);
9815       } else {
9816          sprintf(execDummyStr, TgLoadString(STID_UNRECOG_CMD_DOWNLOAD_TOOL),
9817               buf, TOOL_NAME, currentReleaseURL);
9818       }
9819       MsgBox(execDummyStr, TOOL_NAME, INFO_MB);
9820       return NULL;
9821    }
9822    func_argc = pei->func_argc;
9823    if (func_argc < 0) {
9824       func_argc = (-func_argc);
9825       need_raw_argv = TRUE;
9826    }
9827    if (func_argc > 0) {
9828       if (need_raw_argv) {
9829          raw_argv = (char**)malloc(func_argc*sizeof(char*));
9830          if (raw_argv == NULL) return (char*)(long)FailAllocMessage();
9831          for (i=0; i < func_argc; i++) raw_argv[i] = NULL;
9832       }
9833       argv = (char**)malloc(func_argc*sizeof(char*));
9834       if (argv == NULL) return (char*)(long)FailAllocMessage();
9835       for (i=0; i < func_argc; i++) argv[i] = NULL;
9836    }
9837    for (i=0; i < func_argc; i++) {
9838       if ((c_ptr=GetToken(c_ptr, buf, sizeof(buf), &tok_type)) == NULL ||
9839             tok_type == TOK_EMPTY) {
9840          BadCmd(pei->func_name);
9841          return ExecFreeArgv(need_raw_argv, func_argc, &argv, &raw_argv);
9842       }
9843       if (i == 0) {
9844          if (tok_type != TOK_LEFT_P) {
9845             BadCmd(pei->func_name);
9846             return ExecFreeArgv(need_raw_argv, func_argc, &argv, &raw_argv);
9847          }
9848       } else {
9849          if (tok_type != TOK_COMMA) {
9850             BadCmd(pei->func_name);
9851             return ExecFreeArgv(need_raw_argv, func_argc, &argv, &raw_argv);
9852          }
9853       }
9854       if ((c_ptr=GetToken(c_ptr, buf, sizeof(buf), &tok_type)) == NULL ||
9855             tok_type == TOK_EMPTY) {
9856          BadCmd(pei->func_name);
9857          return ExecFreeArgv(need_raw_argv, func_argc, &argv, &raw_argv);
9858       }
9859       if (tok_type != TOK_STR) {
9860          BadCmd(pei->func_name);
9861          return ExecFreeArgv(need_raw_argv, func_argc, &argv, &raw_argv);
9862       }
9863       if (need_raw_argv) {
9864          raw_argv[i] = UtilStrDup(buf);
9865          if (raw_argv[i] == NULL) {
9866             FailAllocMessage();
9867             return ExecFreeArgv(need_raw_argv, func_argc, &argv, &raw_argv);
9868          }
9869       }
9870       argv[i] = convert_str(buf, obj_ptr, pei->double_quotes_for_null);
9871 
9872       if (argv[i] == NULL) {
9873          BadAttr(buf, pei->func_name);
9874          return ExecFreeArgv(need_raw_argv, func_argc, &argv, &raw_argv);
9875       }
9876    }
9877    if (func_argc == 0) {
9878       if ((c_ptr=GetToken(c_ptr, buf, sizeof(buf), &tok_type)) == NULL ||
9879             tok_type == TOK_EMPTY) {
9880          BadCmd(pei->func_name);
9881          return ExecFreeArgv(need_raw_argv, func_argc, &argv, &raw_argv);
9882       }
9883       if (tok_type != TOK_LEFT_P) {
9884          BadCmd(pei->func_name);
9885          return ExecFreeArgv(need_raw_argv, func_argc, &argv, &raw_argv);
9886       }
9887    }
9888    if ((c_ptr=GetToken(c_ptr, buf, sizeof(buf), &tok_type)) == NULL ||
9889          tok_type == TOK_EMPTY) {
9890       BadCmd(pei->func_name);
9891       return ExecFreeArgv(need_raw_argv, func_argc, &argv, &raw_argv);
9892    }
9893    if (tok_type != TOK_RIGHT_P) {
9894       BadCmd(pei->func_name);
9895       return ExecFreeArgv(need_raw_argv, func_argc, &argv, &raw_argv);
9896    }
9897 
9898    ShowExecStatus(need_raw_argv, func_argc, argv, raw_argv, pei->func_name);
9899    if (func_argc > 0) {
9900       if (need_raw_argv) {
9901          rc = ((RawExecFunc*)(pei->pfunc))(argv, raw_argv, obj_ptr,
9902                pei->func_name);
9903       } else {
9904          rc = ((ExecFunc*)(pei->pfunc))(argv, obj_ptr, pei->func_name);
9905       }
9906    } else if (func_argc == 0) {
9907       gnAbortExec = FALSE;
9908       ((SimpleExecFunc*)(pei->pfunc))(obj_ptr, pei->func_name);
9909       if (gnAbortExec) rc = FALSE;
9910    }
9911    ExecFreeArgv(need_raw_argv, func_argc, &argv, &raw_argv);
9912    return (rc ? c_ptr : NULL);
9913 }
9914 
9915 static
ExecuteCommands(cmd,obj_ptr)9916 int ExecuteCommands(cmd, obj_ptr)
9917    char *cmd;
9918    struct ObjRec *obj_ptr;
9919 {
9920    int tok_type=TOK_INVALID, rc=TRUE;
9921    char *cmd_ptr=cmd;
9922 
9923    while (rc && *cmd_ptr != '\0') {
9924       gnSeenLeftParan = FALSE;
9925       if ((cmd_ptr=ExecuteACommand(cmd_ptr, obj_ptr)) == NULL) {
9926          rc = FALSE;
9927       } else if (*cmd_ptr != '\0') {
9928          char buf[MAXSTRING<<2];
9929 
9930          if (execNavigateBack) {
9931             break;
9932          } else if (warpToAttr != NULL) {
9933             break;
9934          } else if (OnlyBlanksLeft(cmd_ptr)) {
9935             break;
9936          } else if ((cmd_ptr=GetToken(cmd_ptr, buf, sizeof(buf), &tok_type)) ==
9937                NULL) {
9938             rc = FALSE;
9939          } else if (tok_type != TOK_SEMI) {
9940             MsgBox(TgLoadString(STID_UNRECOG_CMD_ABORT), TOOL_NAME, INFO_MB);
9941             rc = FALSE;
9942          }
9943       }
9944       if (rc && CheckExecInterrupt(NULL)) {
9945          Msg(TgLoadString(STID_USER_INTR));
9946          rc = FALSE;
9947          userAbortExec = TRUE;
9948       }
9949    }
9950    return rc;
9951 }
9952 
9953 static
CommentLine(buf)9954 int CommentLine(buf)
9955    char *buf;
9956 {
9957    while (*buf == ' ') buf++;
9958 
9959    return (buf[0] == '/' && buf[1] == '/');
9960 }
9961 
DoExec(exec_attr,obj_ptr)9962 int DoExec(exec_attr, obj_ptr)
9963    struct AttrRec *exec_attr;
9964    struct ObjRec *obj_ptr;
9965 {
9966    char *c_ptr, *cmd, *cmd_ptr;
9967    int cur_size=2*MAXSTRING, count=0, cmd_len=0, n;
9968    int first_time=TRUE, rc=TRUE;
9969    MiniLineInfo *pMiniLine=NULL;
9970 
9971    executingCommands = TRUE;
9972    escPressedWhileExecutingCommands = FALSE;
9973 
9974    cmd = (char*)malloc((cur_size+4)*sizeof(char));
9975    if (cmd == NULL) FailAllocMessage();
9976    cmd_ptr = cmd;
9977    for (pMiniLine=exec_attr->obj->detail.t->minilines.first;
9978          pMiniLine != NULL; pMiniLine=pMiniLine->next) {
9979       int need_to_free_tmp_buf=FALSE;
9980       char *tmp_buf=NULL;
9981 
9982       if (first_time) {
9983          char *attr_value=NULL;
9984 
9985          first_time = FALSE;
9986          tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
9987          attr_value = UtilStrDup(tmp_buf);
9988          if (attr_value == NULL) FailAllocMessage();
9989          ParseAttrStr(tmp_buf, NULL, 0, attr_value, strlen(attr_value)+1);
9990          if (need_to_free_tmp_buf) UtilFree(tmp_buf);
9991          need_to_free_tmp_buf = TRUE;
9992          c_ptr = tmp_buf = attr_value;
9993       } else {
9994          tmp_buf = ConvertMiniLineToString(pMiniLine, &need_to_free_tmp_buf);
9995          c_ptr = tmp_buf;
9996       }
9997       if (CommentLine(tmp_buf)) {
9998       } else if ((count=strlen(c_ptr)) != 0) {
9999          if (count+cmd_len >= cur_size) {
10000             n = cmd_ptr-cmd;
10001             cur_size += count+MAXSTRING;
10002             cmd = (char*)realloc(cmd, (cur_size+4)*sizeof(char));
10003             cmd_ptr = &cmd[n];
10004          }
10005          strncpy(cmd_ptr, c_ptr, count);
10006          cmd_ptr[count] = '\0';
10007          cmd_ptr += count;
10008          cmd_len += count;
10009          if (pMiniLine->next != NULL) {
10010             *cmd_ptr++ = ' ';
10011             *cmd_ptr = '\0';
10012             cmd_len++;
10013          }
10014       }
10015       if (need_to_free_tmp_buf) UtilFree(tmp_buf);
10016    }
10017    *cmd_ptr = '\0';
10018    justDupped = FALSE;
10019    execCurDepth++;
10020    StartCompositeCmd();
10021 
10022    rc = ExecuteCommands(cmd, obj_ptr);
10023 
10024    EndCompositeCmd();
10025    execCurDepth--;
10026    justDupped = FALSE;
10027    free(cmd);
10028 
10029    return rc;
10030 }
10031 
ResetExec(nBegin)10032 void ResetExec(nBegin)
10033    int nBegin;
10034 {
10035    static int sSavedXpmOutputVersion=(-1);
10036    static struct BBRec sTrimBBox;
10037    int i;
10038 
10039    executingCommands = FALSE;
10040    escPressedWhileExecutingCommands = FALSE;
10041 
10042    for (i=3; i < MAXEXECOPENFILES; i++) {
10043       if (gaOpenFileInfo[i].fp != NULL) {
10044          fclose(gaOpenFileInfo[i].fp);
10045          UtilFree(gaOpenFileInfo[i].fname);
10046       }
10047    }
10048    memset(gaOpenFileInfo, 0, MAXEXECOPENFILES*sizeof(struct OpenFileRec));
10049    gaOpenFileInfo[0].fp = stdin;
10050    gaOpenFileInfo[1].fp = stdout;
10051    gaOpenFileInfo[2].fp = stderr;
10052    rewind(stdin);
10053 
10054    if (gpExportClipBBox != NULL) {
10055       free(gpExportClipBBox);
10056       gpExportClipBBox = NULL;
10057    }
10058    if (nBegin) {
10059       userAbortExec = FALSE;
10060       execInterruptEnabled = TRUE;
10061       execInterruptQueued = FALSE;
10062       sSavedXpmOutputVersion = GetXpmOutputVersion();
10063       sTrimBBox.ltx = leftExportPixelTrim;
10064       sTrimBBox.lty = topExportPixelTrim;
10065       sTrimBBox.rbx = rightExportPixelTrim;
10066       sTrimBBox.rby = bottomExportPixelTrim;
10067       leftExportPixelTrim = topExportPixelTrim = rightExportPixelTrim =
10068             bottomExportPixelTrim = 0;
10069    } else {
10070       SetXpmOutputVersion(sSavedXpmOutputVersion);
10071       leftExportPixelTrim = sTrimBBox.ltx;
10072       topExportPixelTrim = sTrimBBox.lty;
10073       rightExportPixelTrim = sTrimBBox.rbx;
10074       bottomExportPixelTrim = sTrimBBox.rby;
10075    }
10076    ResetCreatePoly();
10077    ResetCreateGroup();
10078 }
10079 
10080 static
ReadACmdFromFile(fp,is_named_pipe,pn_quit)10081 char *ReadACmdFromFile(fp, is_named_pipe, pn_quit)
10082    FILE *fp;
10083    int is_named_pipe, *pn_quit;
10084 {
10085    char *buf=NULL;
10086 
10087    while (WaitForEvent(fp, FALSE, is_named_pipe, pn_quit, DO_ALL_X_EV, NULL,
10088          NULL) && (buf=UtilGetALine(fp)) != NULL) {
10089       int len=0;
10090 
10091       UtilTrimBlanks(buf);
10092       if (*buf == '\0') {
10093          UtilFree(buf);
10094          continue;
10095       } else if (strcmp(buf, ".\n") == 0) {
10096          UtilFree(buf);
10097          return NULL;
10098       }
10099       if (buf[0] == '/' && buf[1] == '/') {
10100          /* lines that start with "//" are comments */
10101          UtilFree(buf);
10102          continue;
10103       }
10104       len = strlen(buf);
10105       if (len > 0 && buf[len-1] == '\\') {
10106          char *buf1=NULL;
10107          int done=FALSE;
10108 
10109          buf[len-1] = ' ';
10110          while (!done && WaitForEvent(fp, FALSE, is_named_pipe, pn_quit,
10111                DO_ALL_X_EV, NULL, NULL) && (buf1=UtilGetALine(fp)) != NULL) {
10112             int len1=0;
10113 
10114             UtilTrimBlanks(buf1);
10115             len1 = strlen(buf1);
10116             if (len1 > 0 && buf1[len1-1] == '\\') {
10117                buf1[len1-1] = ' ';
10118             } else {
10119                done = TRUE;
10120             }
10121             buf = (char*)realloc(buf, len+len1+1);
10122             if (buf == NULL) FailAllocMessage();
10123             strcpy(&buf[len], buf1);
10124             len += len1;
10125             UtilFree(buf1);
10126          }
10127       }
10128       break;
10129    }
10130    if (buf == NULL && fp == stdin) {
10131       printf("\n");
10132    }
10133    return buf;
10134 }
10135 
10136 static
DoExecCmdsFromFile(fp,is_named_pipe,pn_quit)10137 void DoExecCmdsFromFile(fp, is_named_pipe, pn_quit)
10138    FILE *fp;
10139    int is_named_pipe, *pn_quit;
10140 {
10141    char prompt[MAXSTRING];
10142 
10143    if (fp == stdin) rewind(stdin);
10144    XSync(mainDisplay, False);
10145 
10146    executingCommands = TRUE;
10147    escPressedWhileExecutingCommands = FALSE;
10148    justDupped = FALSE;
10149    execCurDepth++;
10150 
10151    sprintf(prompt, "(%s) ", TOOL_NAME);
10152    UtilStrLower(prompt);
10153 
10154    while (!gnQuit && !gnStopCmdExecuted) {
10155       char *buf=NULL;
10156       int exec_rc=INVALID;
10157 
10158       if (fp == stdin) {
10159          printf("%s", prompt);
10160          fflush(stdout);
10161       }
10162       buf = ReadACmdFromFile(fp, is_named_pipe, pn_quit);
10163       if (buf == NULL) {
10164          if (fp == stdin) rewind(stdin);
10165          break;
10166       }
10167       if (fp == stdin || is_named_pipe) {
10168          gnDisableShortcuts = FALSE;
10169       }
10170       warpToAttr = NULL;
10171       exec_rc = ExecuteCommands(buf, NULL);
10172       if (exec_rc == TRUE && warpToAttr != NULL) {
10173          struct AttrRec *exec_attr=NULL;
10174 
10175          DoTeleport(warpToAttr);
10176          if ((exec_attr=FindFileAttrWithName("auto_exec=")) != NULL) {
10177             DoExecLoop(NULL, exec_attr);
10178          }
10179       }
10180       if (fp == stdin || is_named_pipe) {
10181          XSync(mainDisplay, False);
10182          gnDisableShortcuts = TRUE;
10183       }
10184       UtilFree(buf);
10185    }
10186    if (gnQuit) *pn_quit = TRUE;
10187 
10188    execCurDepth--;
10189    justDupped = FALSE;
10190 }
10191 
ExecCmdsFromFile(buf)10192 void ExecCmdsFromFile(buf)
10193    char *buf;
10194 {
10195    static int stnExecutingCmdsFromFile=FALSE;
10196    FILE *fp=NULL;
10197    char spec[MAXSTRING<<1], fname[MAXPATHLENGTH];
10198    int quit=FALSE, is_named_pipe=FALSE;
10199 
10200    *fname = '\0';
10201    gnStopCmdExecuted = FALSE;
10202    if (stnExecutingCmdsFromFile) {
10203       /* do not translate -- program constants */
10204       sprintf(gszMsgBox, TgLoadString(STID_TOOL_NOT_DONE_WITH_PREV_FUNC),
10205             TOOL_NAME, "ExecCmdsFromFile()");
10206       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
10207       return;
10208    }
10209    *spec = '\0';
10210    if (buf != NULL && strcmp(buf, "-1") != 0) {
10211       int len=0;
10212 
10213       UtilStrCpyN(spec, sizeof(spec), buf);
10214       UtilTrimBlanks(spec);
10215       len = strlen(spec);
10216       if (len > 0 && spec[len-1] == ')') spec[len-1] = '\0';
10217    } else {
10218       sprintf(gszMsgBox, TgLoadString(STID_ENTER_INTERN_CMD_FILE_NAME),
10219             TOOL_NAME);
10220       *spec = '\0';
10221       if (Dialog(gszMsgBox, NULL, spec) == INVALID) {
10222          return;
10223       }
10224    }
10225    UtilTrimBlanks(spec);
10226    if (strcmp(spec, "-") != 0) {
10227       struct stat stat_buf;
10228 
10229       if (*spec == DIR_SEP) {
10230          strcpy(fname, spec);
10231       } else {
10232          sprintf(fname, "%s%c%s", bootDir, DIR_SEP, spec);
10233       }
10234       if (stat(fname, &stat_buf) != 0) {
10235          int show_msg=TRUE;
10236 #ifndef _NO_LSTAT
10237          if (lstat(fname, &stat_buf) == 0 &&
10238                ((stat_buf.st_mode & S_IFLNK) == S_IFLNK)) {
10239             show_msg = FALSE;
10240          }
10241 #endif /* _NO_LSTAT */
10242          if (show_msg) {
10243             sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_STAT_GIVEN_FILE),
10244                   fname);
10245             Msg(gszMsgBox);
10246             /* ummm... continue below anyway */
10247          }
10248 #ifdef S_IFIFO
10249       } else if ((stat_buf.st_mode & S_IFIFO) == S_IFIFO) {
10250          is_named_pipe = TRUE;
10251 #endif /* S_IFIFO */
10252       }
10253       if ((fp=fopen(fname, (is_named_pipe ? "r+" : "r"))) == NULL) {
10254          sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_READING),
10255                fname);
10256          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
10257          return;
10258       }
10259    } else {
10260       fp = stdin;
10261    }
10262    MakeQuiescent();
10263 
10264    stnExecutingCmdsFromFile = TRUE;
10265    if (fp == stdin || is_named_pipe) {
10266       gnDisableShortcuts = TRUE;
10267       RedrawDummyWindow2();
10268    }
10269    ResetExec(TRUE);
10270    if (fp == stdin) {
10271       DoExecCmdsFromFile(fp, FALSE, &quit);
10272       fprintf(stdin, "%s\n", TgLoadString(STID_FINISH_EXEC_CMD_FROM_STDIN));
10273    } else if (is_named_pipe) {
10274       for (;;) {
10275          DoExecCmdsFromFile(fp, TRUE, &quit);
10276          if (quit || gnStopCmdExecuted) break;
10277          fclose(fp);
10278          if ((fp=fopen(fname, "r+")) == NULL) {
10279             sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_READING),
10280                   fname);
10281             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
10282             break;
10283          }
10284       }
10285       if (fp != NULL) fclose(fp);
10286    } else {
10287       DoExecCmdsFromFile(fp, FALSE, &quit);
10288       fclose(fp);
10289    }
10290    if (fp == stdin || is_named_pipe) {
10291       gnDisableShortcuts = FALSE;
10292       RedrawDummyWindow2();
10293    }
10294    stnExecutingCmdsFromFile = FALSE;
10295    if (quit) {
10296       SendCommandToSelf(CMDID_QUIT, 0);
10297    }
10298 }
10299 
ExecCmdsFromTmp(tmp_fname)10300 void ExecCmdsFromTmp(tmp_fname)
10301    char *tmp_fname;
10302 {
10303    static int stnExecutingCmdsFromTmp=FALSE;
10304    FILE *fp=NULL;
10305    int quit=FALSE;
10306 
10307    gnStopCmdExecuted = FALSE;
10308    if (stnExecutingCmdsFromTmp) {
10309       /* do not translate -- program constants */
10310       sprintf(gszMsgBox, TgLoadString(STID_TOOL_NOT_DONE_WITH_PREV_FUNC),
10311             TOOL_NAME, "ExecCmdsFromTmp()");
10312       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
10313       return;
10314    }
10315    if ((fp=fopen(tmp_fname, "r")) == NULL) {
10316       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_READING),
10317             tmp_fname);
10318       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
10319       return;
10320    }
10321    stnExecutingCmdsFromTmp = TRUE;
10322 
10323    ResetExec(TRUE);
10324    DoExecCmdsFromFile(fp, FALSE, &quit);
10325    fclose(fp);
10326 
10327    stnExecutingCmdsFromTmp = FALSE;
10328    if (quit) {
10329       SendCommandToSelf(CMDID_QUIT, 0);
10330    }
10331 }
10332 
StartExecCmdsFromFile()10333 void StartExecCmdsFromFile()
10334 {
10335    if (*cmdLineFileToExec == '\0') return;
10336 
10337    ExecCmdsFromFile(cmdLineFileToExec);
10338 }
10339 
BeginExecCommandsFromBuffer()10340 int BeginExecCommandsFromBuffer()
10341 {
10342    ResetExec(TRUE);
10343 
10344    executingCommands = TRUE;
10345    escPressedWhileExecutingCommands = FALSE;
10346    justDupped = FALSE;
10347    execCurDepth++;
10348 
10349    return TRUE;
10350 }
10351 
ExecACommandFromBuffer(buf,pn_quit)10352 int ExecACommandFromBuffer(buf, pn_quit)
10353    char *buf;
10354    int *pn_quit;
10355 {
10356    int exec_rc=INVALID;
10357 
10358    warpToAttr = NULL;
10359    exec_rc = ExecuteCommands(buf, NULL);
10360    if (exec_rc == TRUE && warpToAttr != NULL) {
10361       struct AttrRec *exec_attr=NULL;
10362 
10363       DoTeleport(warpToAttr);
10364       if ((exec_attr=FindFileAttrWithName("auto_exec=")) != NULL) {
10365          DoExecLoop(NULL, exec_attr);
10366       }
10367    }
10368    if (gnQuit) {
10369       if (pn_quit != NULL) *pn_quit = TRUE;
10370 
10371       execCurDepth--;
10372       justDupped = FALSE;
10373 
10374       SendCommandToSelf(CMDID_QUIT, 0);
10375 
10376       return FALSE;
10377    }
10378    return TRUE;
10379 }
10380 
EndExecCommandsFromBuffer()10381 void EndExecCommandsFromBuffer()
10382 {
10383    execCurDepth--;
10384    justDupped = FALSE;
10385    ShowCurChoiceMouseStatus(curChoice, 0, FALSE);
10386 }
10387 
CleanUpExec()10388 void CleanUpExec()
10389 {
10390    if (gpExportClipBBox != NULL) {
10391       free(gpExportClipBBox);
10392       gpExportClipBBox = NULL;
10393    }
10394    if (cmdToExecAfterHyperJump != NULL) {
10395       free(cmdToExecAfterHyperJump);
10396       cmdToExecAfterHyperJump = NULL;
10397    }
10398 }
10399 
10400 static char defGsPath[]="gs";
10401 
InitExec()10402 void InitExec()
10403 {
10404    char *c_ptr=NULL;
10405 
10406    gpExportClipBBox = NULL;
10407    executingCommands = FALSE;
10408    escPressedWhileExecutingCommands = FALSE;
10409    memset(gaOpenFileInfo, 0, MAXEXECOPENFILES*sizeof(struct OpenFileRec));
10410    cmdToExecAfterHyperJump = NULL;
10411 
10412    UtilStrCpyN(gsPath, sizeof(gsPath), defGsPath);
10413    if (!PRTGIF || cmdLineOpenDisplay) {
10414       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"GsPath")) != NULL) {
10415          if (!FindProgramInPath(c_ptr, NULL, TRUE)) {
10416             snprintf(gszMsgBox, sizeof(gszMsgBox),
10417                   TgLoadString(STID_INVALID_FILE_IN_X_DEFAULT),
10418                   c_ptr, TOOL_NAME, "GsPath");
10419             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
10420          } else {
10421             UtilStrCpyN(gsPath, sizeof(gsPath), c_ptr);
10422          }
10423       }
10424    }
10425 }
10426 
10427