1 /*
2 * Copyright (c) 1997 Guylhem Aznar <guylhem@oeil.qc.ca>
3 * Copyright (c) 1994 Nobutaka Suzuki <nobuta-s@is.aist-nara.ac.jp>
4 * Copyright (c) 1994 Robert Nation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #define YES "Yes"
22 #define NO "No"
23
24 #include "../../configure.h"
25
26 #include <stdlib.h>
27
28 #include <X11/Xlib.h>
29 #include <X11/Xutil.h>
30 #include <X11/cursorfont.h>
31 #include <X11/Xmu/WinUtil.h>
32
33 #define IN_MODULE
34 #define MODULE_X_INTERFACE
35 #include "../../include/aftersteplib.h"
36 #include "../../include/module.h"
37 #include "Scroll.h"
38
39 int fd[2];
40
41 ScreenInfo Scr;
42
43 char *BackColor = "black";
44 char *ForeColor = "grey";
45
46 Window app_win;
47
48 #define MW_EVENTS (ExposureMask | ButtonReleaseMask | KeyReleaseMask)
49
50 void ParseOptions (const char *);
51
52 void
version(void)53 version (void)
54 {
55 printf ("%s version %s\n", MyName, VERSION);
56 exit (0);
57 }
58
59 void
usage(void)60 usage (void)
61 {
62 printf ("Usage:\n"
63 "%s [-v|--version] [-h|--help] [--window window-id] [x y]\n", MyName);
64 exit (0);
65 }
66
67 /***********************************************************************
68 *
69 * Procedure:
70 * main - start of module
71 *
72 ***********************************************************************/
73 int
main(int argc,char ** argv)74 main (int argc, char **argv)
75 {
76 char configfile[255];
77 char *realconfigfile;
78 char *temp;
79 int i;
80 char *global_config_file = NULL;
81
82 /* Save our program name - for error messages */
83 temp = strrchr (argv[0], '/');
84 MyName = temp ? temp + 1 : argv[0];
85 set_application_name( argv[0] );
86
87 for (i = 1; i < argc && *argv[i] == '-'; i++)
88 {
89 if (!strcmp (argv[i], "-h") || !strcmp (argv[i], "--help"))
90 usage ();
91 else if (!strcmp (argv[i], "-v") || !strcmp (argv[i], "--version"))
92 version ();
93 else if (!strcmp (argv[i], "-w") || !strcmp (argv[i], "--window"))
94 app_win = strtol (argv[++i], NULL, 16);
95 else if (!strcmp (argv[i], "-c") || !strcmp (argv[i], "--context"))
96 i++;
97 else if (!strcmp (argv[i], "-f") && i + 1 < argc)
98 global_config_file = argv[++i];
99 }
100
101 /* Dead pipe == dead AfterStep */
102 signal (SIGPIPE, DeadPipe);
103 set_signal_handler (SIGSEGV);
104
105 x_fd = ConnectX( ASDefaultScr, display_name, 0 );
106 /* connect to AfterStep */
107 fd[0] = fd[1] = ConnectAfterStep (0);
108
109 if (i < argc)
110 {
111 char *cptr = argv[i++];
112 extern int Reduction_H, Reduction_V;
113 Reduction_H = strtol (cptr, &cptr, 10);
114 Reduction_V = strtol (cptr, &cptr, 10);
115 if (Reduction_H < 2)
116 Reduction_H = 2;
117 if (Reduction_V < 2)
118 Reduction_V = 2;
119 }
120
121 /* scan config file for set-up parameters */
122 /* Colors and fonts */
123 if (global_config_file != NULL)
124 ParseOptions (global_config_file);
125 else
126 {
127 sprintf (configfile, "%s/scroll", AFTER_DIR);
128
129 realconfigfile = PutHome (configfile);
130
131 if ((CheckFile (realconfigfile)) == -1)
132 {
133 free (realconfigfile);
134 sprintf (configfile, "%s/scroll", AFTER_SHAREDIR);
135 realconfigfile = PutHome (configfile);
136 }
137 ParseOptions (realconfigfile);
138 free (realconfigfile);
139 }
140
141 if (app_win == 0)
142 GetTargetWindow (&app_win);
143
144 if (app_win == 0)
145 return 1;
146
147 fd_width = GetFdWidth ();
148
149 GrabWindow (app_win);
150 Loop (app_win);
151
152 return 0;
153 }
154
155
156 void
ParseOptions(const char * filename)157 ParseOptions (const char *filename)
158 {
159 FILE *file;
160 char *line, *tline;
161 int len;
162
163 if ((file = fopen (filename, "r")) != (FILE *) NULL)
164 {
165 line = (char *) safemalloc (MAXLINELENGTH);
166 len = strlen (MyName);
167 while ((tline = fgets (line, MAXLINELENGTH, file)) == NULL)
168 {
169 while (isspace (*tline))
170 tline++;
171 if ((*tline == '*') && (!mystrncasecmp (tline + 1, MyName, len)))
172 {
173 tline += len + 1;
174 if (!mystrncasecmp (tline, "Fore", 4))
175 ForeColor = stripcpy( tline + 4);
176 else if (!mystrncasecmp (tline, "Back", 4))
177 BackColor = stripcpy( tline + 4);
178 }
179 }
180 free (line);
181 fclose (file);
182 }
183 }
184
185 /***********************************************************************
186 *
187 * Detected a broken pipe - time to exit
188 *
189 **********************************************************************/
190 void
DeadPipe(int nonsense)191 DeadPipe (int nonsense)
192 {
193 extern Atom wm_del_win;
194
195 XReparentWindow (dpy, app_win, Scr.Root, 0, 0);
196 send_wm_protocol_request(app_win, wm_del_win, CurrentTime);
197 XSync (dpy, 0);
198 exit (0);
199 }
200
201
202 /**********************************************************************
203 *
204 * If no application window was indicated on the command line, prompt
205 * the user to select one
206 *
207 *********************************************************************/
208 void
GetTargetWindow(Window * app_win)209 GetTargetWindow (Window * app_win)
210 {
211 XEvent eventp;
212 int val = -10, trials;
213 Window target_win;
214
215 trials = 0;
216 while ((trials < 100) && (val != GrabSuccess))
217 {
218 val = XGrabPointer (dpy, Scr.Root, True,
219 ButtonReleaseMask,
220 GrabModeAsync, GrabModeAsync, Root,
221 XCreateFontCursor (dpy, XC_crosshair),
222 CurrentTime);
223 if (val != GrabSuccess)
224 {
225 sleep_a_little (1000);
226 }
227 trials++;
228 }
229 if (val != GrabSuccess)
230 {
231 fprintf (stderr, "%s: Couldn't grab the cursor!\n", MyName);
232 exit (1);
233 }
234 XMaskEvent (dpy, ButtonReleaseMask, &eventp);
235 XUngrabPointer (dpy, CurrentTime);
236 XSync (dpy, 0);
237 *app_win = eventp.xany.window;
238 if (eventp.xbutton.subwindow != None)
239 *app_win = eventp.xbutton.subwindow;
240
241 target_win = ClientWindow (*app_win);
242 if (target_win != None)
243 *app_win = target_win;
244 }
245
246
247 /****************************************************************************
248 *
249 * Find the actual application
250 *
251 ***************************************************************************/
252 Window
ClientWindow(Window input)253 ClientWindow (Window input)
254 {
255 Atom _XA_WM_STATE;
256 unsigned int nchildren;
257 Window root, parent, *children, target;
258 unsigned long nitems, bytesafter;
259 unsigned char *prop;
260 Atom atype;
261 int aformat;
262 int i;
263
264 _XA_WM_STATE = XInternAtom (dpy, "WM_STATE", False);
265
266 if (XGetWindowProperty (dpy, input, _XA_WM_STATE, 0L,
267 3L, False, _XA_WM_STATE, &atype,
268 &aformat, &nitems, &bytesafter,
269 &prop) == Success)
270 {
271 if (prop != NULL)
272 {
273 XFree (prop);
274 return input;
275 }
276 }
277
278 if (!XQueryTree (dpy, input, &root, &parent, &children, &nchildren))
279 return None;
280
281 for (i = 0; i < nchildren; i++)
282 {
283 target = ClientWindow (children[i]);
284 if (target != None)
285 {
286 XFree ((char *) children);
287 return target;
288 }
289 }
290 XFree ((char *) children);
291 return None;
292 }
293