1 /****************************************************************************
2 *
3 * Copyright (c) 1999 Sasha Vasko <sasha at aftercode.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 ****************************************************************************/
20
21 #define LOCAL_DEBUG
22 #include "../configure.h"
23
24 #include <stdarg.h>
25 #include <string.h>
26 #include <signal.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29
30 #include "asapp.h"
31 #include "afterstep.h"
32 #include "parser.h"
33 #include "screen.h"
34 #include "functions.h"
35 #include "session.h"
36 #include "balloon.h"
37 #include "mystyle.h"
38 #include "mylook.h"
39 #include "wmprops.h"
40 #include "desktop_category.h"
41 #include "../libAfterImage/asimage.h"
42 #include "../libAfterImage/xpm.h"
43 #include "../libAfterImage/char2uni.h"
44
45
46 ASProgArgs as_app_args = { 0, NULL, 0, NULL, NULL, NULL, 0, 0 }; /* some typical progy cmd line options - set by SetMyArgs( argc, argv ) */
47
48 ASProgArgs *MyArgsPtr = &as_app_args;
49 char *MyName = NULL; /* name are we known by */
50 char MyClass[MAX_MY_CLASS + 1] = "unknown"; /* application Class name ( Pager, Wharf, etc. ) - set by SetMyClass(char *) */
51 void (*MyVersionFunc) (void) = NULL;
52 void (*MyUsageFunc) (void) = NULL;
53
54 char *as_afterstep_dir_name = AFTER_DIR;
55 char *as_save_dir_name = AFTER_DIR "/" AFTER_SAVE;
56 char *as_start_dir_name = AFTER_DIR "/" START_DIR;
57 char *as_share_dir_name = AFTER_SHAREDIR;
58
59 char *as_background_dir_name = BACK_DIR;
60 char *as_look_dir_name = LOOK_DIR;
61 char *as_theme_dir_name = THEME_DIR;
62 char *as_theme_file_dir_name = THEME_FILE_DIR;
63 char *as_feel_dir_name = FEEL_DIR;
64 char *as_colorscheme_dir_name = COLORSCHEME_DIR;
65 char *as_font_dir_name = FONT_DIR;
66 char *as_icon_dir_name = ICON_DIR;
67 char *as_tile_dir_name = TILE_DIR;
68
69
70 int fd_width;
71
72 unsigned int nonlock_mods = 0; /* a mask for non-locking modifiers */
73 unsigned int lock_mods[MAX_LOCK_MODS] = { 0 }; /* all combinations of lock modifier masks */
74
75 /* Now for each display we may have one or several screens ; */
76 Display *dpy = NULL;
77 ScreenInfo *ASDefaultScr; /* ScreenInfo for the default screen */
78
79 //#define Scr (*DefaultScr);
80 int x_fd = 0; /* descriptor of the X Windows connection */
81
82
83 int SingleScreen = -1; /* if >= 0 then [points to the only ScreenInfo structure available */
84 int PointerScreen = 0; /* screen that currently has pointer */
85 unsigned int NumberOfScreens = 0; /* number of screens on display */
86
87 /* unused - future development : */
88 ScreenInfo **all_screens = NULL; /* all ScreenInfo structures for NumberOfScreens screens */
89 ASHashTable *screens_window_hash = NULL; /* so we can easily track what window is on what screen */
90
91 /* end of: unused - future development : */
92
93
94 struct ASFeel *DefaultFeel = NULL; /* unused - future development : */
95 struct MyLook *DefaultLook = NULL; /* unused - future development : */
96
97 void (*CloseOnExec) () = NULL;
98
99 struct ASSession *Session = NULL; /* filenames of look, feel and background */
100 struct ASEnvironment *Environment = NULL;
101
102 struct ASDatabase *Database = NULL;
103
104 struct ASCategoryTree *StandardCategories = NULL;
105 struct ASCategoryTree *AfterStepCategories = NULL;
106 struct ASCategoryTree *KDECategories = NULL;
107 struct ASCategoryTree *GNOMECategories = NULL;
108 struct ASCategoryTree *OtherCategories = NULL;
109 struct ASCategoryTree *CombinedCategories = NULL;
110
111
112
113 /* names of AS functions - used all over the place :*/
114
115 #define FUNC_TERM(keyword,func) {TF_NO_MYNAME_PREPENDING|TF_NAMED,keyword,sizeof(keyword)-1,TT_FUNCTION,func,NULL}
116 #define FUNC_TERM2(flags,keyword,func) {TF_NO_MYNAME_PREPENDING|TF_NAMED|(flags),keyword,sizeof(keyword)-1,TT_FUNCTION,func,NULL}
117
118 TermDef FuncTerms[F_FUNCTIONS_NUM + 1] = {
119 FUNC_TERM2 (NEED_NAME, "Nop", F_NOP), /* Nop "name"|"" */
120 FUNC_TERM2 (NEED_NAME, "Title", F_TITLE), /* Title "name" */
121 FUNC_TERM ("Beep", F_BEEP), /* Beep */
122 FUNC_TERM ("Quit", F_QUIT), /* Quit ["name"] */
123 FUNC_TERM2 (NEED_NAME | NEED_CMD, "Restart", F_RESTART), /* Restart "name" WindowManagerName */
124 FUNC_TERM ("SystemShutdown", F_SYSTEM_SHUTDOWN), /* Shutdown "name" | only available under gnome-session */
125 FUNC_TERM ("Logout", F_LOGOUT), /* Logout "name" | only available under gnome-session */
126 FUNC_TERM ("QuitWM", F_QUIT_WM), /* Will only work when not running under gnome-session */
127 FUNC_TERM ("Suspend", F_SUSPEND), /* If provided by UPower */
128 FUNC_TERM ("Hibernate", F_HIBERNATE), /* If provided by UPower */
129
130 FUNC_TERM ("Refresh", F_REFRESH), /* Refresh ["name"] */
131 #ifndef NO_VIRTUAL
132 FUNC_TERM2 (USES_NUMVALS, "Scroll", F_SCROLL), /* Scroll horiz vert */
133 FUNC_TERM2 (USES_NUMVALS, "GotoPage", F_GOTO_PAGE), /* GotoPage x y */
134 FUNC_TERM ("TogglePage", F_TOGGLE_PAGE), /* TogglePage ["name"] */
135 #endif
136 FUNC_TERM2 (USES_NUMVALS, "CursorMove", F_MOVECURSOR), /* CursorMove horiz vert */
137 FUNC_TERM2 (NEED_WINIFNAME, "WarpFore", F_WARP_F), /* WarpFore ["name" window_name] */
138 FUNC_TERM2 (NEED_WINIFNAME, "WarpBack", F_WARP_B), /* WarpBack ["name" window_name] */
139 FUNC_TERM2 (NEED_NAME | NEED_CMD, "Wait", F_WAIT), /* Wait "name" attributes */
140 FUNC_TERM2 (USES_NUMVALS, "Desk", F_DESK), /* Desk arg1 [arg2] */
141 FUNC_TERM2 (USES_NUMVALS, "GotoDeskViewport", F_GOTO_DESKVIEWPORT), /* GotoDeskViewport DESK+VX+VY */
142 #ifndef NO_WINDOWLIST
143 FUNC_TERM2 (USES_NUMVALS, "WindowList", F_WINDOWLIST), /* WindowList [arg1 arg2] */
144 #endif
145 FUNC_TERM ("StopModuleList", F_STOPMODULELIST), /* StopModuleList "name" */
146 FUNC_TERM ("RestartModuleList", F_RESTARTMODULELIST), /* RestartModuleList "name" */
147 FUNC_TERM2 (NEED_NAME, "PopUp", F_POPUP), /* PopUp "popup_name" [popup_name] */
148 FUNC_TERM2 (NEED_NAME, "Function", F_FUNCTION), /* Function "function_name" [function_name] */
149 FUNC_TERM2 (NEED_NAME | NEED_CMD, "Category", F_CATEGORY), /* Category "function_name" category_name */
150 FUNC_TERM2 (NEED_NAME | NEED_CMD, "CategoryTree", F_CATEGORY_TREE), /* CategoryTree "function_name" category_name */
151 FUNC_TERM ("MiniPixmap", F_MINIPIXMAP), /* MiniPixmap "name" */
152 FUNC_TERM ("SmallMiniPixmap", F_SMALL_MINIPIXMAP), /* SmallMiniPixmap "name" */
153 FUNC_TERM ("LargeMiniPixmap", F_SMALL_MINIPIXMAP), /* LargeMiniPixmap "name" */
154 FUNC_TERM ("Preview", F_Preview), /* Preview "name" */
155 FUNC_TERM2 (NEED_NAME, "DesktopEntry", F_DesktopEntry), /* DesktopEntry "name" */
156 FUNC_TERM2 (NEED_NAME | NEED_CMD, "Exec", F_EXEC), /* Exec "name" command */
157 FUNC_TERM2 (NEED_NAME | NEED_CMD, "ExecInDir", F_ExecInDir), /* Exec "name" [path command] */
158 FUNC_TERM2 (NEED_NAME | NEED_CMD, "Module", F_MODULE), /* Module "name" command */
159 FUNC_TERM2 (NEED_NAME | NEED_CMD, "ExecInTerm", F_ExecInTerm), /* ExecInTerm "name" command */
160 FUNC_TERM2 (NEED_NAME | NEED_CMD, "ExecBrowser", F_ExecBrowser), /* ExecBrowser "name" url */
161 FUNC_TERM2 (NEED_NAME | NEED_CMD, "ExecEditor", F_ExecEditor), /* ExecEditor "name" filename */
162 FUNC_TERM2 (NEED_NAME | NEED_CMD, "KillModuleByName", F_KILLMODULEBYNAME), /* KillModuleByName "name" module */
163 FUNC_TERM2 (NEED_NAME | NEED_CMD, "RestartModuleByName", F_RESTARTMODULEBYNAME), /* RestartModuleByName "name" module */
164 FUNC_TERM2 (NEED_NAME | NEED_CMD, "KillAllModulesByName", F_KILLALLMODULESBYNAME), /* KillAllModulesByName "name" module */
165 FUNC_TERM2 (NEED_NAME | NEED_CMD, "QuickRestart", F_QUICKRESTART), /* QuickRestart "name" what */
166 FUNC_TERM2 (NEED_NAME | NEED_CMD, "Background", F_CHANGE_BACKGROUND), /* Background "name" file_name */
167 FUNC_TERM2 (NEED_NAME | NEED_CMD, "BackgroundForeign", F_CHANGE_BACKGROUND_FOREIGN), /* BackgroundForeign "name" file_name */
168 FUNC_TERM2 (NEED_NAME | NEED_CMD, "ChangeLook", F_CHANGE_LOOK), /* ChangeLook "name" file_name */
169 FUNC_TERM2 (NEED_NAME | NEED_CMD, "ChangeFeel", F_CHANGE_FEEL), /* ChangeFeel "name" file_name */
170 FUNC_TERM2 (NEED_NAME | NEED_CMD, "ChangeTheme", F_CHANGE_THEME), /* ChangeTheme "name" file_name */
171 FUNC_TERM2 (NEED_NAME | NEED_CMD, "ChangeThemeFile", F_CHANGE_THEME_FILE), /* "name" file_name */
172 FUNC_TERM2 (NEED_NAME | NEED_CMD, "ChangeColorscheme", F_CHANGE_COLORSCHEME), /* ChangeColorscheme "name" file_name */
173 FUNC_TERM2 (NEED_NAME | NEED_CMD, "InstallLook", F_INSTALL_LOOK), /* "name" file_name */
174 FUNC_TERM2 (NEED_NAME | NEED_CMD, "InstallFeel", F_INSTALL_FEEL), /* "name" file_name */
175 FUNC_TERM2 (NEED_NAME | NEED_CMD, "InstallBackground", F_INSTALL_BACKGROUND), /* "name" file_name */
176 FUNC_TERM2 (NEED_NAME | NEED_CMD, "InstallFont", F_INSTALL_FONT), /* "name" file_name */
177 FUNC_TERM2 (NEED_NAME | NEED_CMD, "InstallIcon", F_INSTALL_ICON), /* "name" file_name */
178 FUNC_TERM2 (NEED_NAME | NEED_CMD, "InstallTile", F_INSTALL_TILE), /* "name" file_name */
179 FUNC_TERM2 (NEED_NAME | NEED_CMD, "InstallThemeFile", F_INSTALL_THEME_FILE), /* "name" file_name */
180 FUNC_TERM2 (NEED_NAME | NEED_CMD, "InstallColorscheme", F_INSTALL_COLORSCHEME), /* "name" file_name */
181 FUNC_TERM2 (NEED_NAME | NEED_CMD, "SaveWorkspace", F_SAVE_WORKSPACE), /* SaveWorkspace "name" file_name */
182 FUNC_TERM ("SignalReloadGTKRCFile", F_SIGNAL_RELOAD_GTK_RCFILE),
183 FUNC_TERM ("KIPCsendMessageAll", F_KIPC_SEND_MESSAGE_ALL),
184 FUNC_TERM2 (TF_SYNTAX_TERMINATOR, "EndFunction", F_ENDFUNC),
185 FUNC_TERM2 (TF_SYNTAX_TERMINATOR, "EndPopup", F_ENDPOPUP),
186 FUNC_TERM ("TakeScreenShot", F_TAKE_SCREENSHOT),
187
188 FUNC_TERM2 (NEED_CMD, "Set", F_SET), /* Set "name" <variable>=<value> */
189
190 FUNC_TERM2 (NEED_NAME | NEED_CMD, "Test", F_Test),
191 FUNC_TERM2 (NEED_NAME | NEED_CMD, "Remap", F_Remap),
192
193 /* this functions require window as aparameter */
194 FUNC_TERM ("&nonsense&", F_WINDOW_FUNC_START), /* not really a command */
195 FUNC_TERM2 (USES_NUMVALS, "Move", F_MOVE), /* Move ["name"] [whereX whereY] */
196 FUNC_TERM2 (USES_NUMVALS, "Resize", F_RESIZE), /* Resize ["name"] [toWidth toHeight] */
197 FUNC_TERM ("Raise", F_RAISE), /* Raise ["name"] */
198 FUNC_TERM ("Lower", F_LOWER), /* Lower ["name"] */
199 FUNC_TERM ("RaiseLower", F_RAISELOWER), /* RaiseLower ["name"] */
200 FUNC_TERM ("PutOnTop", F_PUTONTOP), /* PutOnTop */
201 FUNC_TERM ("PutOnBack", F_PUTONBACK), /* PutOnBack */
202 FUNC_TERM2 (USES_NUMVALS, "SetLayer", F_SETLAYER), /* SetLayer layer */
203 FUNC_TERM2 (USES_NUMVALS, "ToggleLayer", F_TOGGLELAYER), /* ToggleLayer layer1 layer2 */
204 FUNC_TERM ("Shade", F_SHADE), /* Shade ["name"] */
205 FUNC_TERM ("Delete", F_DELETE), /* Delete ["name"] */
206 FUNC_TERM ("Destroy", F_DESTROY), /* Destroy ["name"] */
207 FUNC_TERM ("Close", F_CLOSE), /* Close ["name"] */
208 FUNC_TERM ("Iconify", F_ICONIFY), /* Iconify ["name"] value */
209 FUNC_TERM2 (USES_NUMVALS, "Maximize", F_MAXIMIZE), /* Maximize ["name"] [hori vert] */
210 FUNC_TERM ("Fullscreen", F_FULLSCREEN), /* Maximize ["name"] [hori vert] */
211 FUNC_TERM ("Stick", F_STICK), /* Stick ["name"] */
212 FUNC_TERM ("Focus", F_FOCUS), /* Focus */
213 FUNC_TERM2 (NEED_WINIFNAME, "ChangeWindowUp", F_CHANGEWINDOW_UP), /* ChangeWindowUp ["name" window_name ] */
214 FUNC_TERM2 (NEED_WINIFNAME, "ChangeWindowDown", F_CHANGEWINDOW_DOWN), /* ChangeWindowDown ["name" window_name ] */
215 FUNC_TERM2 (NEED_WINIFNAME, "GoToBookmark", F_GOTO_BOOKMARK), /* GoToBookmark ["name" window_bookmark ] */
216 FUNC_TERM ("GetHelp", F_GETHELP), /* */
217 FUNC_TERM ("PasteSelection", F_PASTE_SELECTION), /* */
218 FUNC_TERM2 (USES_NUMVALS, "WindowsDesk", F_CHANGE_WINDOWS_DESK), /* WindowDesk "name" new_desk */
219 FUNC_TERM ("BookmarkWindow", F_BOOKMARK_WINDOW), /* BookmarkWindow "name" new_bookmark */
220 FUNC_TERM ("PinMenu", F_PIN_MENU), /* PinMenu ["name"] */
221 FUNC_TERM ("TakeWindowShot", F_TAKE_WINDOWSHOT),
222 FUNC_TERM ("TakeFrameShot", F_TAKE_FRAMESHOT),
223 FUNC_TERM ("SwallowWindow", F_SWALLOW_WINDOW), /* SwallowWindow "name" module_name */
224 /* end of window functions */
225 /* these are commands to be used only by modules */
226 FUNC_TERM ("&nonsense&", F_MODULE_FUNC_START), /* not really a command */
227 FUNC_TERM ("Send_WindowList", F_SEND_WINDOW_LIST), /* */
228 FUNC_TERM ("SET_MASK", F_SET_MASK), /* SET_MASK mask lock_mask */
229 FUNC_TERM2 (NEED_NAME, "SET_NAME", F_SET_NAME), /* SET_NAME name */
230 FUNC_TERM ("UNLOCK", F_UNLOCK), /* UNLOCK 1 */
231 FUNC_TERM ("SET_FLAGS", F_SET_FLAGS), /* SET_FLAGS flags */
232 /* these are internal commands */
233 FUNC_TERM ("&nonsense&", F_INTERNAL_FUNC_START), /* not really a command */
234 FUNC_TERM ("&raise_it&", F_RAISE_IT), /* should not be used by user */
235 /* wharf functions : */
236 {TF_NO_MYNAME_PREPENDING, "Folder", 6, TT_FUNCTION, F_Folder, NULL},
237 {TF_NO_MYNAME_PREPENDING | NEED_NAME | NEED_CMD | TF_NAMED, "Swallow", 7,
238 TT_FUNCTION, F_Swallow, NULL},
239 {TF_NO_MYNAME_PREPENDING | NEED_NAME | NEED_CMD | TF_NAMED, "MaxSwallow",
240 10, TT_FUNCTION, F_MaxSwallow, NULL},
241 {TF_NO_MYNAME_PREPENDING | NEED_NAME | NEED_CMD | TF_NAMED,
242 "SwallowModule", 13, TT_FUNCTION, F_SwallowModule,
243 NULL},
244 {TF_NO_MYNAME_PREPENDING | NEED_NAME | NEED_CMD | TF_NAMED,
245 "MaxSwallowModule", 16, TT_FUNCTION, F_MaxSwallowModule,
246 NULL},
247 {TF_NO_MYNAME_PREPENDING, "Size", 4, TT_FUNCTION, F_Size, NULL},
248 {TF_NO_MYNAME_PREPENDING, "Transient", 9, TT_FUNCTION, F_Transient,
249 NULL},
250
251 {0, NULL, 0, 0, 0}
252 };
253
254 struct SyntaxDef FuncSyntax = {
255 '\0', '\n', FuncTerms,
256 0, ' ', "", "\t",
257 "AfterStep Function",
258 "Functions",
259 "built in AfterStep functions",
260 NULL, 0
261 };
262
263 SyntaxDef PopupFuncSyntax = {
264 '\n', '\0', FuncTerms,
265 0, ' ', "\t", "\t",
266 "Popup/Complex function definition",
267 "Popup",
268 "",
269 NULL, 0
270 };
271
272
273
274 struct SyntaxDef *pFuncSyntax = &FuncSyntax;
275 struct SyntaxDef *pPopupFuncSyntax = &PopupFuncSyntax;
276
func2fterm(FunctionCode func,int quiet)277 TermDef *func2fterm (FunctionCode func, int quiet)
278 {
279 register int i;
280
281 /* in most cases that should work : */
282 if (func < F_FUNCTIONS_NUM)
283 if (FuncTerms[func].id == func)
284 return &(FuncTerms[func]);
285
286 /* trying fallback if it did not : */
287 for (i = 0; i < F_FUNCTIONS_NUM; i++)
288 if (FuncTerms[i].id == func)
289 return &(FuncTerms[i]);
290
291 /* something terribly wrong has happened : */
292 return NULL;
293 }
294
295 /************************************************************************************/
296 /* Command Line Processing/ App initialization here : */
297 /************************************************************************************/
SetMyClass(const char * app_class)298 void SetMyClass (const char *app_class)
299 {
300 if (app_class != NULL) {
301 strncpy (MyClass, (char *)app_class, MAX_MY_CLASS);
302 MyClass[MAX_MY_CLASS] = '\0';
303 }
304 }
305
SetMyName(char * argv0)306 void SetMyName (char *argv0)
307 {
308 char *temp = strrchr (argv0, '/');
309
310 /* Save our program name - for error messages */
311 MyName = temp ? temp + 1 : argv0;
312 set_application_name (argv0);
313 }
314
315 /* If you change/add options please change InitMyApp below and option flags in aftersteplib.h */
316
317 CommandLineOpts as_standard_cmdl_options[STANDARD_CMDL_OPTS_NUM] = {
318 #define SHOW_VERSION 0
319 #define SHOW_CONFIG 1
320 #define SHOW_USAGE 2
321 /* 0*/ {"v", "version", "Display version information and stop", NULL,
322 handler_show_info, NULL, SHOW_VERSION},
323 /* 1*/ {"c", "config", "Display Config information and stop", NULL,
324 handler_show_info, NULL, SHOW_CONFIG},
325 /* 2*/ {"h", "help", "Display uasge information and stop", NULL,
326 handler_show_info, NULL, SHOW_USAGE},
327 /* 3*/ {NULL, "debug", "Debugging: Run in Synchronous mode", NULL,
328 handler_set_flag, &(as_app_args.flags),
329 ASS_Debugging},
330 /* 4*/ {"s", "single", "Run on single screen only", NULL,
331 handler_set_flag, &(as_app_args.flags), ASS_SingleScreen},
332 /* 5*/ {"r", "restart", "Run as if it was restarted",
333 "same as regular startup, only \nruns RestartFunctioninstead of InitFunction",
334 handler_set_flag, &(as_app_args.flags), ASS_Restarting},
335 #define OPTION_HAS_ARGS 6
336 /* 6*/ {"d", "display", "Specify what X display we should connect to",
337 "Overrides $DISPLAY environment variable",
338 handler_set_string, &(as_app_args.display_name), 0, CMO_HasArgs},
339 /* 7*/ {"f", "config-file", "Read all config from requested file",
340 "Use it if you want to use .steprc\ninstead of standard config files",
341 handler_set_string, &(as_app_args.override_config), 0,
342 CMO_HasArgs},
343 /* 8*/ {"p", "user-dir", "Read all the config from requested dir",
344 "Use it to override config location\nrequested in compile time",
345 handler_set_string, &(as_app_args.override_home), 0, CMO_HasArgs},
346 /* 9*/ {"g", "global-dir", "Use requested dir as a shared config dir",
347 "Use it to override shared config location\nrequested in compile time",
348 handler_set_string, &(as_app_args.override_share), 0, CMO_HasArgs},
349 /*10*/ {"V", "verbosity-level",
350 "Change verbosity of the AfterStep output",
351 "0 - will disable any output;\n1 - will allow only error messages;\n5 - both errors and warnings(default)",
352 handler_set_int, &(as_app_args.verbosity_level), 0, CMO_HasArgs},
353 /*11*/ {NULL, "window", "Internal Use: Window in which action occured",
354 "interface part which has triggered our startup",
355 handler_set_int, &(as_app_args.src_window), 0, CMO_HasArgs},
356 /*12*/ {NULL, "context", "Internal Use: Context in which action occured",
357 "interface part which has triggered our startup",
358 handler_set_int, &(as_app_args.src_context), 0, CMO_HasArgs},
359 /*13*/ {NULL, "look", "Read look config from requested file",
360 "Use it if you want to use different look\ninstead of what was selected from the menu",
361 handler_set_string, &(as_app_args.override_look), 0, CMO_HasArgs},
362 /*14*/ {NULL, "feel", "Read feel config from requested file",
363 "Use it if you want to use different feel\ninstead of what was selected from the menu",
364 handler_set_string, &(as_app_args.override_feel), 0, CMO_HasArgs},
365 /*15*/ {NULL, "theme", "Read theme config from requested file",
366 "Use it if you want to use different theme\ninstead of what was selected from the menu",
367 handler_set_string, &(as_app_args.override_feel), 0, CMO_HasArgs},
368 #ifdef DEBUG_TRACE_X
369 /*16*/ {NULL, "trace-func",
370 "Debugging: Trace calls to a function with requested name", NULL,
371 handler_set_string, &(as_app_args.trace_calls), 0, CMO_HasArgs},
372 #endif
373 /*17*/ {"l", "log", "Save all output into the file",
374 "(instead of printing it to console)",
375 handler_set_string, &(as_app_args.log_file), 0, CMO_HasArgs},
376 /*18*/ {"L", "locale", "Set language locale",
377 "to be used while displaying text",
378 handler_set_dup_string, &(as_app_args.locale), 0, CMO_HasArgs},
379 /*19*/ {NULL, "myname", "Overrides module name",
380 "will be used while parsing config files\nand reporting to AfterStep",
381 handler_set_string, &(MyName), 0, CMO_HasArgs},
382 /*20*/ {NULL, "geometry", "Overrides module's geometry", NULL,
383 handler_set_geometry, &(as_app_args.geometry), 0, CMO_HasArgs},
384 /*21*/ {NULL, "gravity", "Overrides module's gravity", NULL,
385 handler_set_gravity, &(as_app_args.gravity), 0, CMO_HasArgs},
386 {NULL, NULL, NULL, NULL, NULL, NULL, 0}
387 };
388
standard_version(void)389 void standard_version (void)
390 {
391 show_debug (__FILE__, __FUNCTION__, __LINE__,
392 "version = \"%s\", MyVersionFunc = %p", VERSION,
393 MyVersionFunc);
394
395 if (MyVersionFunc)
396 MyVersionFunc ();
397 else
398 printf ("%s version %s\n", MyClass, VERSION);
399 }
400
401 void
print_command_line_opt(const char * prompt,CommandLineOpts * options,ASFlagType mask)402 print_command_line_opt (const char *prompt, CommandLineOpts * options,
403 ASFlagType mask)
404 {
405 register int i;
406 ASFlagType bit = 0x01;
407
408 if (options == NULL)
409 options = as_standard_cmdl_options;
410 printf ("%s:\n", prompt);
411
412 for (i = 0; options[i].handler != NULL; i++) {
413 if (!get_flags (bit, mask)) {
414 if (options[i].short_opt)
415 printf (OPTION_SHORT_FORMAT, options[i].short_opt);
416 else
417 printf (OPTION_NOSHORT_FORMAT);
418
419 if (!get_flags (options[i].flags, CMO_HasArgs))
420 printf (OPTION_DESCR1_FORMAT_NOVAL, options[i].long_opt,
421 options[i].descr1);
422 else
423 printf (OPTION_DESCR1_FORMAT_VAL, options[i].long_opt,
424 options[i].descr1);
425
426 if (options[i].descr2) {
427 register char *start = options[i].descr2;
428 register char *end;
429
430 do {
431 end = strchr (start, '\n');
432 if (end == NULL)
433 printf (OPTION_DESCR2_FORMAT, start);
434 else {
435 static char buffer[81];
436 register int len = (end > start + 80) ? 80 : end - start;
437
438 strncpy (buffer, start, len);
439 buffer[len] = '\0';
440 printf (OPTION_DESCR2_FORMAT, buffer);
441 start = end + 1;
442 }
443 }
444 while (end != NULL);
445 }
446 }
447 bit = bit << 1;
448 }
449 }
450
standard_usage()451 void standard_usage ()
452 {
453 standard_version ();
454 if (MyUsageFunc)
455 MyUsageFunc ();
456 else
457 printf (OPTION_USAGE_FORMAT "\n", MyName);
458 print_command_line_opt ("standard_options are :",
459 as_standard_cmdl_options, as_app_args.mask);
460 }
461
handler_show_info(char * argv,void * trg,long param)462 void handler_show_info (char *argv, void *trg, long param)
463 {
464 switch (param) {
465 case SHOW_VERSION:
466 standard_version ();
467 break;
468 case SHOW_CONFIG:
469 standard_version ();
470 printf ("BinDir %s\n", AFTER_BIN_DIR);
471 printf ("ManDir %s\n", AFTER_MAN_DIR);
472 printf ("DocDir %s\n", AFTER_DOC_DIR);
473 printf ("ShareDir %s\n", AFTER_SHAREDIR);
474 printf ("AfterDir %s\n", AFTER_DIR);
475 break;
476 case SHOW_USAGE:
477 standard_usage ();
478 break;
479 }
480 exit (0);
481 }
482
handler_set_flag(char * argv,void * trg,long param)483 void handler_set_flag (char *argv, void *trg, long param)
484 {
485 register ASFlagType *f = trg;
486
487 set_flags (*f, param);
488 }
489
handler_set_string(char * argv,void * trg,long param)490 void handler_set_string (char *argv, void *trg, long param)
491 {
492 register char **s = trg;
493
494 if (argv)
495 *s = argv;
496 }
497
handler_set_dup_string(char * argv,void * trg,long param)498 void handler_set_dup_string (char *argv, void *trg, long param)
499 {
500 register char **s = trg;
501
502 if (argv) {
503 if (*s)
504 free (*s);
505 *s = mystrdup (argv);
506 }
507 }
508
handler_set_int(char * argv,void * trg,long param)509 void handler_set_int (char *argv, void *trg, long param)
510 {
511 register int *i = trg;
512
513 if (argv)
514 *i = atoi (argv);
515 }
516
handler_set_geometry(char * argv,void * trg,long param)517 void handler_set_geometry (char *argv, void *trg, long param)
518 {
519 register ASGeometry *geom = trg;
520
521 if (argv) {
522 memset (geom, 0x00, sizeof (ASGeometry));
523 parse_geometry (argv, &(geom->x), &(geom->y), &(geom->width),
524 &(geom->height), &(geom->flags));
525 }
526 }
527
handler_set_gravity(char * argv,void * trg,long param)528 void handler_set_gravity (char *argv, void *trg, long param)
529 {
530 register int *i = trg;
531
532 *i = ForgetGravity;
533 if (argv) {
534
535 if (mystrncasecmp (argv, "NorthWest", 9) == 0)
536 *i = NorthWestGravity;
537 else if (mystrncasecmp (argv, "SouthWest", 9) == 0)
538 *i = SouthWestGravity;
539 else if (mystrncasecmp (argv, "NorthEasth", 10) == 0)
540 *i = NorthEastGravity;
541 else if (mystrncasecmp (argv, "SouthEast", 9) == 0)
542 *i = SouthEastGravity;
543 else if (mystrncasecmp (argv, "Center", 6) == 0)
544 *i = CenterGravity;
545 else if (mystrncasecmp (argv, "Static", 6) == 0)
546 *i = StaticGravity;
547 else
548 show_warning
549 ("unknown gravity type \"%s\". Use one of: NorthWest, SouthWest, NorthEast, SouthEast, Center, Static",
550 argv);
551 }
552 }
553
554
match_command_line_opt(char * argvi,CommandLineOpts * options)555 int match_command_line_opt (char *argvi, CommandLineOpts * options)
556 {
557 register char *ptr = argvi;
558 register int opt;
559
560 if (ptr == NULL)
561 return -1;
562 show_debug (__FILE__, __FUNCTION__, __LINE__, "ptr = \"%s\"", ptr);
563 if (*ptr == '-') {
564 ++ptr;
565 if (*ptr == '-') {
566 ++ptr;
567 show_debug (__FILE__, __FUNCTION__, __LINE__, "ptr = \"%s\"", ptr);
568 for (opt = 0; options[opt].handler; ++opt)
569 if (strcmp (options[opt].long_opt, ptr) == 0)
570 break;
571 } else {
572 show_debug (__FILE__, __FUNCTION__, __LINE__, "ptr = \"%s\"", ptr);
573 for (opt = 0; options[opt].handler; ++opt)
574 if (options[opt].short_opt)
575 if (strcmp (options[opt].short_opt, ptr) == 0)
576 break;
577 }
578 } else
579 opt = -1;
580 if (options[opt].handler == NULL)
581 opt = -1;
582 return opt;
583 }
584
585 static DeadPipe_handler _as_dead_pipe_handler = NULL;
586
set_DeadPipe_handler(DeadPipe_handler new_handler)587 DeadPipe_handler set_DeadPipe_handler (DeadPipe_handler new_handler)
588 {
589 DeadPipe_handler old = _as_dead_pipe_handler;
590
591 _as_dead_pipe_handler = new_handler;
592 return old;
593 }
594
ASDeadPipe(int nonsense)595 void ASDeadPipe (int nonsense)
596 {
597 if (_as_dead_pipe_handler)
598 _as_dead_pipe_handler (nonsense);
599 else
600 exit (0);
601 }
602
603 static char **AS_environ = NULL;
604
override_environ(char ** envp)605 void override_environ (char **envp)
606 {
607 AS_environ = envp;
608 }
609
610 void
InitMyApp(const char * app_class,int argc,char ** argv,void (* version_func)(void),void (* custom_usage_func)(void),ASFlagType opt_mask)611 InitMyApp (const char *app_class, int argc, char **argv,
612 void (*version_func) (void), void (*custom_usage_func) (void),
613 ASFlagType opt_mask)
614 {
615 /* first of all let's set us some nice signal handlers */
616 #ifdef HAVE_SIGSEGV_HANDLING
617 set_signal_handler (SIGSEGV);
618 #endif
619
620 set_signal_handler (SIGUSR2);
621 signal (SIGPIPE, ASDeadPipe); /* don't forget DeadPipe should be provided by the app */
622
623 SetMyClass (app_class);
624 MyVersionFunc = version_func;
625 MyUsageFunc = custom_usage_func;
626
627 memset (&as_app_args, 0x00, sizeof (ASProgArgs));
628 as_app_args.locale = mystrdup (AFTER_LOCALE);
629 if (as_app_args.locale[0] == '\0') {
630 free (as_app_args.locale);
631 as_app_args.locale = mystrdup (getenv ("LANG"));
632 }
633
634 as_app_args.mask = opt_mask;
635 as_app_args.gravity = ForgetGravity;
636 #ifndef NO_DEBUG_OUTPUT
637 as_app_args.verbosity_level = OUTPUT_VERBOSE_THRESHOLD;
638 #else
639 as_app_args.verbosity_level = OUTPUT_DEFAULT_THRESHOLD;
640 #endif
641
642 /* Uncomment this to enable cmd line args tracing/debugging :
643 * set_output_threshold(20); */
644
645 ASDefaultScr = safecalloc (1, sizeof (ScreenInfo));
646 init_ScreenInfo (ASDefaultScr);
647 show_debug (__FILE__, __FUNCTION__, __LINE__, "argc = %d", argc);
648
649 if (argc > 0 && argv) {
650 int i;
651
652 as_app_args.saved_argc = argc;
653 as_app_args.saved_argv = safecalloc (argc, sizeof (char *));
654 for (i = 0; i < argc; ++i)
655 as_app_args.saved_argv[i] = mystrdup (argv[i]);
656
657 SetMyName (argv[0]);
658
659 for (i = 1; i < argc; i++) {
660 register int opt;
661
662 show_debug (__FILE__, __FUNCTION__, __LINE__,
663 "i = %d, argv[i] = 0x%p", i, argv[i]);
664 if ((opt =
665 match_command_line_opt (&(argv[i][0]),
666 as_standard_cmdl_options)) < 0)
667 continue;
668 if (get_flags ((0x01 << opt), as_app_args.mask))
669 continue;
670 if (get_flags (as_standard_cmdl_options[opt].flags, CMO_HasArgs)) {
671 argv[i] = NULL;
672 if (++i >= argc)
673 continue;
674 else
675 as_standard_cmdl_options[opt].handler (argv[i],
676 as_standard_cmdl_options
677 [opt].trg,
678 as_standard_cmdl_options
679 [opt].param);
680 } else
681 as_standard_cmdl_options[opt].handler (NULL,
682 as_standard_cmdl_options
683 [opt].trg,
684 as_standard_cmdl_options
685 [opt].param);
686 argv[i] = NULL;
687 }
688 }
689
690 set_output_threshold (as_app_args.verbosity_level);
691 if (as_app_args.log_file)
692 if (freopen (as_app_args.log_file,
693 /*get_flags( as_app_args.flags, ASS_Restarting)? */
694 "a" /*:"w" */ , stderr)
695 == NULL)
696 show_system_error ("failed to redirect output into file \"%s\"",
697 as_app_args.log_file);
698
699
700 fd_width = get_fd_width ();
701
702 if (FuncSyntax.term_hash == NULL)
703 PrepareSyntax (&FuncSyntax);
704 if (as_app_args.locale == NULL)
705 as_app_args.locale = mystrdup ("");
706 if (as_app_args.locale && strlen (as_app_args.locale) > 0) {
707 as_set_charset (parse_charset_name (as_app_args.locale));
708 #ifdef I18N
709 if (strlen (as_app_args.locale) > 0)
710 if (setlocale (LC_CTYPE, as_app_args.locale) == NULL) {
711 show_error ("unable to set locale");
712 }
713 #endif
714 } else {
715 #ifdef I18N
716 show_warning
717 ("LANG environment variable is not set - use -L \"locale\" command line option to define locale");
718 #endif
719 }
720
721 #ifdef DEBUG_TRACE_X
722 trace_enable_function (as_app_args.trace_calls);
723 #endif
724
725 asxml_var_insert (ASXMLVAR_IconButtonWidth, 64);
726 asxml_var_insert (ASXMLVAR_IconButtonHeight, 64);
727 asxml_var_insert (ASXMLVAR_IconWidth, 48);
728 asxml_var_insert (ASXMLVAR_IconHeight, 48);
729 asxml_var_insert (ASXMLVAR_MinipixmapWidth, 24);
730 asxml_var_insert (ASXMLVAR_MinipixmapHeight, 24);
731 asxml_var_insert (ASXMLVAR_TitleFontSize, 14);
732 asxml_var_insert (ASXMLVAR_MenuFontSize, 16);
733 asxml_var_insert (ASXMLVAR_MenuShowMinipixmaps, 1);
734 asxml_var_insert (ASXMLVAR_MenuShowUnavailable, 1);
735
736 }
737
free_func_hash()738 void free_func_hash ()
739 {
740 if (FuncSyntax.term_hash) {
741 FreeSyntaxHash (&FuncSyntax);
742 }
743 }
744
745 /*********** end command line parsing **************************/
746 static char *_as_known_terms[] = {
747 "x-terminal-emulator",
748 "urxvt",
749 "aterm",
750 "rxvt -tr -fg yellow -bg black",
751 "Eterm -tr -tint blue -fg yellow -bg black",
752 "xterm -fg yellow -bg blue",
753 NULL
754 };
755
756 static char *_as_known_browsers[] = {
757 "$BROWSER",
758 "sensible-browser",
759 "x-www-browser", /* don't like default debian selection of konqueror */
760 "firefox",
761 "mozilla-firefox",
762 "mozilla",
763 "opera",
764 NULL
765 };
766
767 static char *_as_known_editors[] = {
768 "editor",
769 "$EDITOR",
770 "nedit",
771 "xemacs",
772 "gedit",
773 "kedit",
774 "kate",
775 NULL
776 };
777
778 static char **_as_known_tools[ASTool_Count] = {
779 _as_known_terms,
780 _as_known_browsers,
781 _as_known_editors
782 };
783
784 static char *_as_tools_name[ASTool_Count] = {
785 "Terminal",
786 "Browser",
787 "Editor"
788 };
789
790
as_get_default_tool(ASToolType type)791 char *as_get_default_tool (ASToolType type)
792 {
793 int i;
794
795 for (i = 0; _as_known_tools[type][i]; ++i) {
796 char *tmp = _as_known_tools[type][i];
797 char *fullname = NULL;
798 int res;
799
800 if (tmp[0] == '$')
801 tmp = copy_replace_envvar (tmp);
802 res = get_executable_in_path (tmp, &fullname);
803 if (tmp != _as_known_tools[type][i])
804 free (tmp);
805 if (res > 0)
806 return fullname;
807 }
808 return NULL;
809 }
810
811 void
set_environment_tool_from_list(ASEnvironment * e,ASToolType type,char ** list,int list_len)812 set_environment_tool_from_list (ASEnvironment * e, ASToolType type,
813 char **list, int list_len)
814 {
815 int i;
816
817 destroy_string (&(e->tool_command[type]));
818 for (i = 0; i < list_len; ++i)
819 if (list[i]) {
820 char *tmp = list[i];
821 char *fullname = NULL;
822
823 if (tmp[0] == '$')
824 tmp = copy_replace_envvar (tmp);
825 if (get_executable_in_path (tmp, &fullname)) {
826 e->tool_command[type] = fullname;
827 break;
828 } else
829 show_warning ("%s command %s is not in the path",
830 _as_tools_name[type], tmp);
831 if (tmp != list[i])
832 free (tmp);
833 }
834 if (e->tool_command[type] == NULL)
835 e->tool_command[type] = as_get_default_tool (type);
836 show_progress ("%s is set to: \"%s\"", _as_tools_name[type],
837 e->tool_command[type] ? e->tool_command[type] : "none");
838 }
839
make_themed_icon_category_path(const char * category,int desired_size_idx,Bool fallback)840 static char *make_themed_icon_category_path (const char *category,
841 int desired_size_idx,
842 Bool fallback)
843 {
844 char *tmp, *tmp2, *theme_path;
845 static char *standard_sizes[] =
846 { "16x16", "32x32", "48x48", "64x64", "128x128", NULL };
847
848 if (!fallback && Environment->IconTheme == NULL)
849 return NULL;
850 if (fallback && Environment->IconThemeFallback == NULL)
851 return NULL;
852
853 tmp =
854 make_file_name (fallback ? Environment->
855 IconThemeFallback : Environment->IconTheme,
856 standard_sizes[desired_size_idx]);
857 tmp2 = make_file_name (Environment->IconThemePath, tmp);
858 free (tmp);
859 theme_path = make_file_name (tmp2, category);
860 free (tmp2);
861
862 return theme_path;
863 }
864
is_themable_icon(const char * name)865 Bool is_themable_icon (const char *name)
866 {
867 return (Environment && Environment->IconTheme
868 && Environment->IconThemePath && strchr (name, '/') == NULL);
869 }
870
load_environment_icon(const char * category,const char * name,int desired_size)871 ASImage *load_environment_icon (const char *category, const char *name,
872 int desired_size)
873 {
874 ASImage *icon = NULL;
875 char *png_name = NULL;
876 char *svg_name = NULL;
877 Bool add_to_man = False;
878 int len;
879 int desired_size_idx;
880
881 if (name == NULL || ASDefaultScr == NULL)
882 return NULL;
883
884 desired_size_idx = (desired_size + 15) / 16 - 1;
885 if (desired_size_idx > 4)
886 desired_size_idx = 4;
887 else if (desired_size_idx < 0)
888 desired_size_idx = 0;
889
890 show_debug (__FILE__, __FUNCTION__, __LINE__, "IconTheme = %s",
891 Environment->IconTheme);
892
893 len = strlen (name);
894 if (len < 4 || name[len - 4] != '.') {
895 png_name = add_file_extension (name, "png");
896 svg_name = add_file_extension (name, "svg");
897 }
898 /* we maybe already loaded so try with just the name : */
899 icon = fetch_asimage (ASDefaultScr->image_manager, name);
900
901 /* nope we are not, so try loading as themed icon first: */
902 if (icon == NULL && is_themable_icon (name) && category) {
903 int fallback;
904 for (fallback = 0; fallback <= 1; fallback++) {
905 int try, try_size_idx = desired_size_idx;
906 for (try = 0; icon == NULL && try < 3; ++try) {
907 char *theme_path =
908 make_themed_icon_category_path (category, try_size_idx,
909 fallback);
910 if (theme_path == NULL)
911 break;
912
913 if (icon == NULL && png_name) {
914 char *themed_name = make_file_name (theme_path, png_name);
915 icon =
916 get_asimage_quiet (ASDefaultScr->image_manager, themed_name,
917 ASFLAGS_EVERYTHING, 100);
918 free (themed_name);
919 }
920 if (icon == NULL && svg_name) {
921 char *themed_name = make_file_name (theme_path, svg_name);
922 icon =
923 get_asimage_quiet (ASDefaultScr->image_manager, themed_name,
924 ASFLAGS_EVERYTHING, 100);
925 free (themed_name);
926 }
927 if (icon == NULL) {
928 char *themed_name = make_file_name (theme_path, name);
929 icon =
930 get_asimage_quiet (ASDefaultScr->image_manager, themed_name,
931 ASFLAGS_EVERYTHING, 100);
932 free (themed_name);
933 }
934 free (theme_path);
935 switch (try) {
936 case 0:
937 try_size_idx =
938 desired_size_idx <
939 4 ? desired_size_idx + 1 : desired_size_idx - 1;
940 break;
941 case 1:
942 try_size_idx = desired_size_idx == 0
943 || desired_size_idx == 4 ? 2 : desired_size_idx - 1;
944 break;
945 default:
946 break;
947 }
948 }
949 }
950 add_to_man = True;
951 }
952
953 /* finally, try loading straight (for native AS icons primarily): */
954 if (icon == NULL) {
955 icon =
956 get_asimage_quiet (ASDefaultScr->image_manager, name,
957 ASFLAGS_EVERYTHING, 100);
958 if (icon == NULL) {
959 add_to_man = True;
960 if (png_name)
961 icon =
962 get_asimage_quiet (ASDefaultScr->image_manager, png_name,
963 ASFLAGS_EVERYTHING, 100);
964 if (icon == NULL && svg_name)
965 icon =
966 get_asimage_quiet (ASDefaultScr->image_manager, svg_name,
967 ASFLAGS_EVERYTHING, 100);
968 }
969 }
970
971 if (icon && add_to_man && icon->ref_count == 1) {
972 forget_asimage (icon);
973 if (icon->imageman == NULL)
974 store_asimage (ASDefaultScr->image_manager, icon, name);
975 }
976 if (png_name)
977 free (png_name);
978 if (svg_name)
979 free (svg_name);
980 return icon;
981 }
982
load_environment_icon_any(const char * filename,int desired_size)983 ASImage *load_environment_icon_any (const char *filename, int desired_size)
984 {
985 ASImage *icon = NULL;
986 if (filename) {
987 Bool possibly_themed = is_themable_icon (filename);
988 icon = load_environment_icon ("apps", filename, desired_size);
989 if (!icon && possibly_themed)
990 icon = load_environment_icon ("actions", filename, desired_size);
991 if (!icon && possibly_themed)
992 icon = load_environment_icon ("places", filename, desired_size);
993 if (!icon && possibly_themed)
994 icon = load_environment_icon ("categories", filename, desired_size);
995 if (!icon && possibly_themed)
996 icon = load_environment_icon ("devices", filename, desired_size);
997 }
998 return icon;
999 }
1000
make_default_environment()1001 ASEnvironment *make_default_environment ()
1002 {
1003 int i;
1004 ASEnvironment *e = safecalloc (1, sizeof (ASEnvironment));
1005 static const char *default_pixmap_path_format =
1006 "%s/desktop/icons/:"
1007 "%s/desktop/icons/:"
1008 "%s/desktop/:"
1009 "%s/desktop/:" "%s/desktop/buttons/:" "%s/desktop/buttons/:"
1010 "%s/backgrounds/:" "%s/backgrounds/:" "%s";
1011
1012 static const char *default_font_path_format =
1013 "%s/desktop/fonts/:" "%s/desktop/fonts/:"
1014 "/usr/share/fonts/default/TrueType/:" "%s";
1015
1016 static const char *default_cursor_path_format =
1017 "%s/desktop/cursors:" "%s/desktop/cursors";
1018
1019 e->desk_scale = 24;
1020 e->desk_pages_h = 2;
1021 e->desk_pages_v = 2;
1022 e->module_path = mystrdup (AFTER_BIN_DIR);
1023 e->icon_path = mystrdup (DEFAULT_ICON_DIR);
1024 e->pixmap_path =
1025 safemalloc (strlen ((char *)default_pixmap_path_format) +
1026 strlen (AFTER_DIR) * 4 + strlen (AFTER_SHAREDIR) * 4 +
1027 strlen (DEFAULT_PIXMAP_DIR) + 1);
1028 sprintf (e->pixmap_path, default_pixmap_path_format, AFTER_DIR,
1029 AFTER_SHAREDIR, AFTER_DIR, AFTER_SHAREDIR, AFTER_DIR,
1030 AFTER_SHAREDIR, AFTER_DIR, AFTER_SHAREDIR, DEFAULT_PIXMAP_DIR);
1031
1032 e->font_path = safemalloc (strlen ((char *)default_font_path_format) +
1033 strlen (AFTER_DIR) + strlen (AFTER_SHAREDIR) +
1034 strlen (DEFAULT_TTF_DIR) + 1);
1035 sprintf (e->font_path, default_font_path_format, AFTER_DIR,
1036 AFTER_SHAREDIR, DEFAULT_TTF_DIR);
1037
1038 e->cursor_path =
1039 safemalloc (strlen ((char *)default_cursor_path_format) +
1040 strlen (AFTER_DIR) + strlen (AFTER_SHAREDIR) + 1);
1041 sprintf (e->cursor_path, default_cursor_path_format, AFTER_DIR,
1042 AFTER_SHAREDIR);
1043
1044 for (i = 0; i < ASTool_Count; ++i)
1045 e->tool_command[i] = as_get_default_tool (i);
1046
1047 /* by default - don't do overwrite gtkrc files so to not aggrave people */
1048 e->gtkrc_path = NULL; /* make_session_rc_file(Session, GTKRC_FILE); */
1049 e->gtkrc20_path = NULL; /* make_session_rc_file(Session, GTKRC20_FILE) ; */
1050 e->IconTheme = mystrdup ("oxygen");
1051 e->IconThemePath = mystrdup ("/usr/chare/icons");
1052 e->IconThemeFallback = mystrdup ("hicolor");
1053 return e;
1054 }
1055
destroy_asenvironment(ASEnvironment ** penv)1056 void destroy_asenvironment (ASEnvironment ** penv)
1057 {
1058 if (penv) {
1059 ASEnvironment *e = *penv;
1060
1061 if (e) {
1062 int i;
1063
1064 if (e->module_path)
1065 free (e->module_path);
1066 if (e->sound_path)
1067 free (e->sound_path);
1068 if (e->icon_path)
1069 free (e->icon_path);
1070 if (e->pixmap_path)
1071 free (e->pixmap_path);
1072 if (e->font_path)
1073 free (e->font_path);
1074 if (e->cursor_path)
1075 free (e->cursor_path);
1076 for (i = 0; i < ASTool_Count; ++i)
1077 destroy_string (&(e->tool_command[i]));
1078
1079 destroy_string (&(e->gtkrc_path));
1080 destroy_string (&(e->gtkrc20_path));
1081 destroy_string (&(e->IconTheme));
1082 destroy_string (&(e->IconThemePath));
1083 destroy_string (&(e->IconThemeFallback));
1084
1085 free (e);
1086 *penv = NULL;
1087 }
1088 }
1089 }
1090
1091 /*
1092 * Initialize database variables
1093 */
1094
destroy_asdatabase()1095 void destroy_asdatabase ()
1096 {
1097 if (Database)
1098 destroy_asdb (&Database);
1099 /* XResources : */
1100 destroy_user_database ();
1101 }
1102
name2desktop_category_tree(const char * name,int * tree_name_len)1103 static ASCategoryTree *name2desktop_category_tree (const char *name,
1104 int *tree_name_len)
1105 {
1106 ASCategoryTree *ct = CombinedCategories;
1107 int offset = 0;
1108
1109 /* fprintf( stderr, __FUNCTION__ ": checking \"%s\" (AfterSTep categories = %p)\n", name, AfterStepCategories );*/
1110
1111 if (!mystrncasecmp (name, "AfterStep:", 10)) {
1112 ct = AfterStepCategories;
1113 offset = 10;
1114 } else if (!mystrncasecmp (name, "KDE:", 4)) {
1115 ct = KDECategories;
1116 offset = 4;
1117 } else if (!mystrncasecmp (name, "GNOME:", 6)) {
1118 ct = GNOMECategories;
1119 offset = 6;
1120 } else if (!mystrncasecmp (name, "OTHER:", 7)) {
1121 ct = OtherCategories;
1122 offset = 7;
1123 } else if (!mystrncasecmp (name, "COMBINED:", 9)) {
1124 ct = CombinedCategories;
1125 offset = 9;
1126 }
1127 if (tree_name_len)
1128 *tree_name_len = offset;
1129 return ct;
1130 }
1131
name2desktop_category(const char * name,ASCategoryTree ** tree_return)1132 ASDesktopCategory *name2desktop_category (const char *name,
1133 ASCategoryTree ** tree_return)
1134 {
1135 int offset = 0;
1136 ASCategoryTree *ct = name2desktop_category_tree (name, &offset);
1137
1138 if (tree_return)
1139 *tree_return = ct;
1140
1141 return fetch_desktop_category (ct, name + offset);
1142 }
1143
name2desktop_entry(const char * name,ASCategoryTree ** tree_return)1144 ASDesktopEntry *name2desktop_entry (const char *name,
1145 ASCategoryTree ** tree_return)
1146 {
1147 int offset = 0;
1148 ASCategoryTree *ct = name2desktop_category_tree (name, &offset);
1149
1150 if (tree_return)
1151 *tree_return = ct;
1152
1153 return fetch_desktop_entry (ct, name + offset);
1154 }
1155
InitSession()1156 void InitSession ()
1157 {
1158 /* initializing our dirs names */
1159 if (Session == NULL) {
1160 Session =
1161 GetNCASSession (ASDefaultScr, as_app_args.override_home,
1162 as_app_args.override_share);
1163 if (as_app_args.override_config)
1164 set_session_override (Session, as_app_args.override_config, 0);
1165 if (as_app_args.override_look)
1166 set_session_override (Session, as_app_args.override_look,
1167 F_CHANGE_LOOK);
1168 if (as_app_args.override_feel)
1169 set_session_override (Session, as_app_args.override_feel,
1170 F_CHANGE_FEEL);
1171 }
1172 }
1173
free_as_app_args()1174 void free_as_app_args ()
1175 {
1176 int i;
1177
1178 for (i = 0; i < as_app_args.saved_argc; ++i)
1179 if (as_app_args.saved_argv[i])
1180 free (as_app_args.saved_argv[i]);
1181 free (as_app_args.saved_argv);
1182 as_app_args.saved_argv = NULL;
1183
1184 destroy_string (&(as_app_args.locale));
1185
1186 }
1187
FreeMyAppResources()1188 void FreeMyAppResources ()
1189 {
1190 cleanup_default_balloons ();
1191 destroy_asdatabase ();
1192 mystyle_destroy_all ();
1193 mylook_init (&(ASDefaultScr->Look), True, ASFLAGS_EVERYTHING);
1194 destroy_image_manager (ASDefaultScr->image_manager, False);
1195 destroy_font_manager (ASDefaultScr->font_manager, False);
1196 clientprops_cleanup ();
1197 destroy_wmprops (ASDefaultScr->wmprops, False);
1198 wmprops_cleanup ();
1199 free_func_hash ();
1200 flush_keyword_ids ();
1201 purge_asimage_registry ();
1202 asxml_var_cleanup ();
1203 custom_color_cleanup ();
1204 build_xpm_colormap (NULL);
1205 destroy_screen_gcs (ASDefaultScr);
1206 if (ASDefaultScr->RootImage) {
1207 safe_asimage_destroy (ASDefaultScr->RootImage);
1208 ASDefaultScr->RootImage = NULL;
1209 }
1210 destroy_asvisual (ASDefaultScr->asv, False);
1211 free_as_app_args ();
1212 destroy_assession (Session);
1213 Session = NULL;
1214 destroy_asenvironment (&Environment);
1215 is_executable_in_path (NULL);
1216 #ifdef XSHMIMAGE
1217 flush_shm_cache ();
1218 #endif
1219 free (ASDefaultScr);
1220 flush_default_asstorage ();
1221 flush_asbidirlist_memory_pool ();
1222 flush_ashash_memory_pool ();
1223
1224 }
1225
1226
1227 /************ child process spawning ***************************/
1228 /***********************************************************************
1229 * Procedure:
1230 * general purpose child launcher - spawn child.
1231 * Pass along all the cmd line args if needed.
1232 * returns PID of the spawned process
1233 ************************************************************************/
1234 static int as_singletons[MAX_SINGLETONS_NUM];
1235 static Bool as_init_singletons = True;
1236
as_sigchild_handler(int signum)1237 void as_sigchild_handler (int signum)
1238 {
1239 int pid;
1240 int status;
1241
1242 signal (SIGCHLD, as_sigchild_handler);
1243 DEBUG_OUT ("Entering SigChild_handler(%lu)", time (NULL));
1244 if (as_init_singletons)
1245 return;
1246 while ((pid = WAIT_CHILDREN (&status)) > 0) {
1247 register int i;
1248
1249 LOCAL_DEBUG_OUT ("pid = %d", pid);
1250 for (i = 0; i < MAX_SINGLETONS_NUM; i++)
1251 if (pid == as_singletons[i]) {
1252 as_singletons[i] = 0;
1253 break;
1254 }
1255 }
1256 DEBUG_OUT ("Exiting SigChild_handler(%lu)", time (NULL));
1257 }
1258
1259 /*
1260 * This should return 0 if process of running external app to draw background completed or killed.
1261 * otherwise it returns > 0
1262 */
check_singleton_child(int singleton_id,Bool kill_it_to_death)1263 int check_singleton_child (int singleton_id, Bool kill_it_to_death)
1264 {
1265 int i;
1266 int pid, status;
1267
1268 if (as_init_singletons || singleton_id < 0)
1269 return -1;
1270
1271 if (singleton_id >= MAX_SINGLETONS_NUM)
1272 singleton_id = MAX_SINGLETONS_NUM - 1;
1273
1274 DEBUG_OUT ("CheckingForDrawChild(%lu)....", time (NULL));
1275 if ((pid = as_singletons[singleton_id]) > 0) {
1276 DEBUG_OUT ("checking on singleton child #%d started with PID (%d)",
1277 singleton_id, pid);
1278 if (kill_it_to_death) {
1279 kill (pid, SIGTERM);
1280 for (i = 0; i < 100; i++) { /* give it 10 sec to terminate */
1281 sleep_a_millisec (100);
1282 if (WAIT_CHILDREN (&status) == pid
1283 || as_singletons[singleton_id] <= 0)
1284 break;
1285 }
1286 if (i >= 100)
1287 kill (pid, SIGKILL); /* no more mercy */
1288 as_singletons[singleton_id] = 0;
1289 }
1290 } else if (as_singletons[singleton_id] < 0)
1291 as_singletons[singleton_id] = 0;
1292
1293 DEBUG_OUT ("Done(%lu). Child PID on exit = %d.", time (NULL),
1294 as_singletons[singleton_id]);
1295 return as_singletons[singleton_id];
1296 }
1297
1298 int
spawn_child(const char * cmd,int singleton_id,int screen,const char * orig_display,Window w,int context,Bool do_fork,Bool pass_args,...)1299 spawn_child (const char *cmd, int singleton_id, int screen,
1300 const char *orig_display, Window w, int context, Bool do_fork,
1301 Bool pass_args, ...)
1302 {
1303 int pid = 0;
1304
1305 if (cmd == NULL)
1306 return 0;
1307 if (as_init_singletons) {
1308 register int i;
1309
1310 for (i = 0; i < MAX_SINGLETONS_NUM; i++)
1311 as_singletons[i] = 0;
1312 signal (SIGCHLD, as_sigchild_handler);
1313 as_init_singletons = False;
1314 }
1315
1316 if (singleton_id >= 0) {
1317 if (singleton_id >= MAX_SINGLETONS_NUM)
1318 singleton_id = MAX_SINGLETONS_NUM - 1;
1319 if (as_singletons[singleton_id] > 0)
1320 check_singleton_child (singleton_id, True);
1321 }
1322
1323 if (do_fork)
1324 pid = fork ();
1325
1326 if (pid != 0) {
1327 /* there is a possibility of the race condition here
1328 * but it really is not worse the trouble to try and avoid it.
1329 */
1330 if (singleton_id >= 0)
1331 as_singletons[singleton_id] = pid;
1332 return pid;
1333 } else { /* we get here only in child process. We now need to spawn new proggy here: */
1334 int len;
1335 char *display = mystrdup (XDisplayString (dpy));
1336 char **envp;
1337 register char *ptr;
1338
1339 char *cmdl;
1340 char *arg, *screen_str = NULL, *w_str = NULL, *context_str = NULL;
1341 int env_s = 0;
1342 char **envvars = AS_environ;
1343 int font_path_slot = -1, image_path_slot = -1;
1344
1345 va_list ap;
1346
1347 LOCAL_DEBUG_OUT ("dpy = %p, DisplayString = \"%s\"", dpy, display);
1348 LOCAL_DEBUG_OUT ("pid(%d), entered child process to spawn ...", pid);
1349
1350 #if HAVE_DECL_ENVIRON
1351 if (envvars == NULL) {
1352 envvars = environ;
1353 }
1354 #else
1355 /* how the hell could we get environment otherwise ? */
1356 #endif
1357 if (envvars) {
1358 int font_path_len = strlen (ASFONT_PATH_ENVVAR);
1359 int image_path_len = strlen (ASIMAGE_PATH_ENVVAR);
1360
1361 for (env_s = 0; envvars[env_s] != NULL; ++env_s) {
1362 if (font_path_slot < 0 && strlen (envvars[env_s]) > font_path_len)
1363 if (strncmp (envvars[env_s], ASFONT_PATH_ENVVAR, font_path_len)
1364 == 0)
1365 font_path_slot = env_s;
1366 if (image_path_slot < 0
1367 && strlen (envvars[env_s]) > image_path_len)
1368 if (strncmp (envvars[env_s], ASIMAGE_PATH_ENVVAR, image_path_len)
1369 == 0)
1370 image_path_slot = env_s;
1371 }
1372 }
1373 if (font_path_slot < 0)
1374 ++env_s;
1375 if (image_path_slot < 0)
1376 ++env_s;
1377 envp = safecalloc (env_s + 2, sizeof (char *));
1378
1379 /* environment variabless to pass to child process */
1380 if (envvars) {
1381 int dst = 0;
1382
1383 for (env_s = 0; envvars[env_s] != NULL; ++env_s) {
1384 /* don't want to path DESKTOP_AUTOSTART_ID to our children -
1385 its set by gnome-session for AfterStep proper specifically,
1386 otherwise children will attempt to re-use it for SessionManagement registration, failing miserably */
1387 if (strlen (envvars[env_s]) < sizeof (SESSION_ID_ENVVAR)
1388 || strncmp (envvars[env_s], SESSION_ID_ENVVAR,
1389 sizeof (SESSION_ID_ENVVAR) - 1) != 0)
1390 envp[dst++] = envvars[env_s];
1391 }
1392 env_s = dst;
1393 }
1394
1395 envp[env_s] =
1396 safemalloc (8 + strlen (orig_display ? orig_display : display) +
1397 1);
1398 sprintf (envp[env_s], "DISPLAY=%s",
1399 orig_display ? orig_display : display);
1400 ++env_s;
1401 if (Environment) {
1402 if (Environment->pixmap_path != NULL) {
1403 int slot_no = image_path_slot;
1404
1405 if (slot_no < 0)
1406 slot_no = env_s++;
1407
1408 envp[slot_no] =
1409 safemalloc (strlen (ASIMAGE_PATH_ENVVAR) + 1 +
1410 strlen (Environment->pixmap_path) + 1);
1411 sprintf (envp[slot_no], "%s=%s", ASIMAGE_PATH_ENVVAR,
1412 Environment->pixmap_path);
1413 }
1414 if (Environment->font_path) {
1415 int slot_no = font_path_slot;
1416
1417 if (slot_no < 0)
1418 slot_no = env_s++;
1419 envp[slot_no] =
1420 safemalloc (strlen (ASFONT_PATH_ENVVAR) + 1 +
1421 strlen (Environment->font_path) + 1);
1422 sprintf (envp[slot_no], "%s=%s", ASFONT_PATH_ENVVAR,
1423 Environment->font_path);
1424 }
1425 }
1426
1427 len = strlen ((char *)cmd);
1428 if (pass_args) {
1429 register int i = 0;
1430
1431 while (display[i])
1432 ++i;
1433
1434 while (i > 0 && isdigit (display[--i])) ;
1435 if (display[i] == '.')
1436 display[i + 1] = '\0';
1437 /*
1438 This bit of code seems to break AS restarting
1439 on Fedora 8. causing DISPLAY=":0.0" to
1440 become DISPLAY=":0.". -- Jeremy
1441 */
1442 if (screen >= 0)
1443 screen_str = string_from_int (screen);
1444 if (w != None)
1445 w_str = string_from_int (w);
1446 if (context != C_NO_CONTEXT)
1447 context_str = string_from_int (context);
1448
1449 len += 1 + 2 + 1 + strlen (orig_display ? orig_display : display);
1450 if (screen_str)
1451 len += strlen (screen_str);
1452 len += 3; /* for "-s " */
1453 if (get_flags (as_app_args.flags, ASS_Debugging))
1454 len += 8;
1455 if (get_flags (as_app_args.flags, ASS_Restarting))
1456 len += 3;
1457 if (as_app_args.override_config)
1458 len += 4 + strlen (as_app_args.override_config);
1459 if (as_app_args.override_home)
1460 len += 4 + strlen (as_app_args.override_home);
1461 if (as_app_args.override_share)
1462 len += 4 + strlen (as_app_args.override_share);
1463
1464 if (as_app_args.locale)
1465 len += 4 + strlen (as_app_args.locale);
1466
1467 if (as_app_args.verbosity_level != OUTPUT_DEFAULT_THRESHOLD)
1468 len += 4 + 32;
1469 #ifdef DEBUG_TRACE_X
1470 if (as_app_args.trace_calls)
1471 len += 13 + strlen (as_app_args.trace_calls);
1472 #endif
1473 if (w_str)
1474 len += 1 + 8 + 1 + strlen (w_str);
1475 if (context_str)
1476 len += 1 + 9 + 1 + strlen (context_str);
1477 }
1478 /* now we want to append arbitrary number of arguments to the end of command line : */
1479 va_start (ap, pass_args);
1480 while ((arg = va_arg (ap, char *)) != NULL)
1481 len += 1 + strlen (arg);
1482
1483 va_end (ap);
1484
1485 len += 4;
1486
1487 ptr = cmdl = safemalloc (len);
1488 strcpy (cmdl, (char *)cmd);
1489 while (*ptr)
1490 ptr++;
1491 if (pass_args) {
1492 if (orig_display)
1493 ptr += sprintf (ptr, " -d %s -s", orig_display);
1494 else if (screen_str)
1495 ptr += sprintf (ptr, " -d %s.%s -s", display, screen_str);
1496 else
1497 ptr += sprintf (ptr, " -d %s -s", display);
1498
1499
1500 if (get_flags (as_app_args.flags, ASS_Debugging)) {
1501 strcpy (ptr, " --debug");
1502 ptr += 8;
1503 }
1504 if (get_flags (as_app_args.flags, ASS_Restarting)) {
1505 strcpy (ptr, " -r");
1506 ptr += 3;
1507 }
1508 if (as_app_args.override_config)
1509 ptr += sprintf (ptr, " -f %s", as_app_args.override_config);
1510 if (as_app_args.override_home)
1511 ptr += sprintf (ptr, " -p %s", as_app_args.override_home);
1512 if (as_app_args.override_share)
1513 ptr += sprintf (ptr, " -g %s", as_app_args.override_share);
1514 if (as_app_args.verbosity_level != OUTPUT_DEFAULT_THRESHOLD)
1515 ptr += sprintf (ptr, " -V %d", as_app_args.verbosity_level);
1516 LOCAL_DEBUG_OUT
1517 ("len = %d, cmdl = \"%s\" strlen = %d, locale = \"%s\", ptr-cmdl = %d",
1518 len, cmdl, (int)strlen (cmdl), as_app_args.locale,
1519 (int)(ptr - cmdl));
1520 if (as_app_args.locale && as_app_args.locale[0]
1521 && !isspace (as_app_args.locale[0]))
1522 ptr += sprintf (ptr, " -L %s", as_app_args.locale);
1523
1524 #ifdef DEBUG_TRACE_X
1525 if (as_app_args.trace_calls)
1526 ptr += sprintf (ptr, " --trace-func %s", as_app_args.trace_calls);
1527 #endif
1528 if (w_str)
1529 ptr += sprintf (ptr, " --window %s", w_str);
1530 if (context_str)
1531 ptr += sprintf (ptr, " --context %s", context_str);
1532 }
1533
1534 va_start (ap, pass_args);
1535 while ((arg = va_arg (ap, char *)) != NULL) {
1536 *(ptr++) = ' ';
1537 strcpy (ptr, arg);
1538 while (*ptr)
1539 ptr++;
1540 LOCAL_DEBUG_OUT ("len = %d, cmdl = \"%s\" strlen = %d", len, cmdl,
1541 (int)strlen (cmdl));
1542
1543 }
1544 va_end (ap);
1545 if (do_fork) {
1546 int i = ptr - cmdl;
1547
1548 while (--i >= 0)
1549 if (!isspace (cmdl[i]))
1550 break;
1551 do_fork = (i < 0 || cmdl[i] != '&');
1552 }
1553 strcpy (ptr, do_fork ? " &\n" : "\n");
1554
1555 LOCAL_DEBUG_OUT ("len = %d, cmdl = \"%s\" strlen = %d", len, cmdl,
1556 (int)strlen (cmdl));
1557 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
1558 {
1559 FILE *fff = fopen ("/tmp/afterstep.exec.log", "a");
1560
1561 if (fff) {
1562 fprintf (fff, "%s:%ld: [%s]", MyName, time (NULL), cmdl);
1563 fclose (fff);
1564 }
1565 }
1566 #endif
1567
1568 LOCAL_DEBUG_OUT ("execle(\"%s\")", cmdl);
1569 /* fprintf( stderr, "len=%d: execl(\"%s\")", len, cmdl ); */
1570
1571 /* CYGWIN does not handle close-on-exec gracefully - whave to do it ourselves : */
1572 if (CloseOnExec)
1573 CloseOnExec ();
1574
1575 {
1576 const char *shell;
1577 char *argv0;
1578
1579 if ((shell = getenv ("SHELL")) == NULL || *shell == '\0')
1580 shell = mystrdup ("/bin/sh");
1581
1582 parse_file_name (shell, NULL, &argv0);
1583 /* argv0 = basename(shell); */
1584
1585 execle (shell, argv0, "-c", cmdl, (char *)0, envp);
1586 }
1587
1588 if (screen >= 0)
1589 show_error ("failed to start %s on the screen %d", cmd, screen);
1590 else
1591 show_error ("failed to start %s", cmd);
1592 show_system_error (" complete command line: \"%s\"\n", cmdl);
1593 exit (128);
1594 }
1595 }
1596
1597 /******************************************************************************/
1598 /* web download functions : */
1599 /******************************************************************************/
is_url(const char * url)1600 Bool is_url (const char *url)
1601 {
1602 return (strncmp (url, "http://", 7) == 0
1603 || strncmp (url, "ftp://", 6) == 0);
1604 }
1605
make_log_name(const char * cachedFileName)1606 char *make_log_name (const char *cachedFileName)
1607 {
1608 char *logName = safemalloc (strlen (cachedFileName) + 4 + 1);
1609
1610 sprintf (logName, "%s.log", cachedFileName);
1611 return logName;
1612 }
1613
spawn_download(const char * url,const char * cachedFileName)1614 int spawn_download (const char *url, const char *cachedFileName)
1615 {
1616 /* cmdl: wget -b -nv -o <escaped_url>.log -O <cache_file> <url> */
1617 #define WGET_CMDL_HEADER "wget -b -nv -o "
1618 int cacheFNLen = strlen (cachedFileName);
1619 char *wget_cmdl =
1620 safemalloc (sizeof (WGET_CMDL_HEADER) + cacheFNLen + 4 + 1 + 2 + 1 +
1621 cacheFNLen + 1 + strlen (url) + 1);
1622 int res;
1623
1624 sprintf (wget_cmdl, WGET_CMDL_HEADER "%s.log -O %s %s", cachedFileName,
1625 cachedFileName, url);
1626 LOCAL_DEBUG_OUT ("spawning \"%s\"", wget_cmdl);
1627 res =
1628 spawn_child (wget_cmdl, -1, -1, NULL, None, C_NO_CONTEXT, True,
1629 False, NULL);
1630 free (wget_cmdl);
1631 return res;
1632 }
1633
1634 Bool
check_download_complete(int pid,const char * cachedFileName,int * sizeDownloaded,int * size)1635 check_download_complete (int pid, const char *cachedFileName,
1636 int *sizeDownloaded, int *size)
1637 {
1638 if (pid != 0) {
1639 /* TODO : possibly check if process exited ? */
1640
1641 }
1642 /* verify log file */
1643 {
1644 char *logName = make_log_name (cachedFileName);
1645 char *log = logName ? load_file (logName) : NULL;
1646
1647 if (log && log[0] != '\0') {
1648 int s1 = 0, s2 = 1;
1649
1650 char *openBracket = strchr (log, '[');
1651
1652 LOCAL_DEBUG_OUT ("Open Bracket:%s", openBracket);
1653 if (openBracket) {
1654 sscanf (openBracket + 1, "%d/%d", &s1, &s2);
1655 LOCAL_DEBUG_OUT ("s1 = %d, s2 = %d", s1, s2);
1656 }
1657 if (sizeDownloaded)
1658 *sizeDownloaded = s1;
1659 if (size)
1660 *size = s2;
1661 free (log);
1662 return True;
1663 }
1664 }
1665 return False;
1666 }
1667
1668
1669 /************ end child process spawning ***************************/
1670