Fix problem with title bar
[fsviewer.git] / src / FSViewer.c
blob759fce1531593f4caa2a32af5c2432d0da83478f
1 /* FSViewer.c */
3 #include <locale.h>
4 #include <X11/Xlib.h>
5 #include <X11/Xutil.h>
6 #include <X11/Xproto.h>
7 #include <WMaker.h>
8 #include <WINGs/WINGs.h>
9 #include <X11/Xlocale.h>
10 #include <X11/keysym.h>
11 #include <unistd.h> /* for access() */
13 #include "FSViewer.h"
14 #include "FSFileButton.h"
15 #include "filebrowser.h"
16 #include "FSFileView.h"
17 #include "FSUtils.h"
18 #include "FSMenu.h"
19 #include "FSFinder.h"
20 #include "xpm/FSViewer.xpm"
22 #define DEBUG 0
24 static FSViewer *fsViewer;
25 static Bool focusIn;
26 int ModifierFromKey(Display *dpy, char *key);
28 void
29 wAbort(Bool foo)
31 exit(1);
34 static void
35 FSLoadFSViewerConfigurations(FSViewer *fsViewer)
37 char *iconDir = NULL;
38 char *magicFile = NULL;
40 defaultsDB = WMGetStandardUserDefaults();
42 /*if there is no user database available, create one*/
43 if (WMGetUDStringForKey(defaultsDB, "DIRECTORY") == NULL)
45 InitFilesDB(fsViewer);
47 iconDir = FSGetStringForName("ICONDIR");
49 if (iconDir)
51 /* test for existing ICONDIR */
52 if (access(iconDir, F_OK) != 0) {
53 wwarning(_("User database entry for ICONDIR is not "
54 "valid: %s. Taking default value."), iconDir);
55 free(iconDir);
57 /*try compile time default value*/
58 WMSetUDStringForKey(defaultsDB, ICONDIR, "ICONDIR");
59 iconDir = FSGetStringForName("ICONDIR");
61 if (iconDir)
63 if (access(iconDir, F_OK) != 0) {
64 wwarning(_("Default ICONDIR not found: %s"), iconDir);
65 free(iconDir);
66 exit (1);
68 else {
69 WMSetResourcePath(iconDir);
70 free(iconDir);
73 else {
74 wwarning(_("No valid value for ICONDIR found. "
75 "Even default directory is broken!"));
76 exit (1);
81 else {
82 WMSetResourcePath(iconDir);
83 free(iconDir);
87 else {
88 wwarning(_("No value for ICONDIR found! May be your %s"
89 " preferences file is broken."), PACKAGE_NAME);
90 exit (1);
93 magicFile = FSGetStringForName("MAGICFILE");
94 if(magicFile)
96 magic_parse_file(magicFile);
97 free(magicFile);
99 else
100 magic_parse_file("");
103 static void
104 printHelp(char *progname)
106 printf(_("Usage: %s [options]\n"), progname);
107 puts(_("options:"));
108 puts(_(" -p <initial path> initial path to display"));
109 puts(_(" -v print version number and exit"));
112 Bool
113 FSIsFSViewerClipSet(FSViewer *fsViewer)
115 return fsViewer->clip ? True : False;
118 void
119 FSSetFSViewerClip(FSViewer *fsViewer, FileInfo *fileInfo)
121 /* Need to free previous clip???? */
122 /* Or need to copy fileInfo???? */
123 fsViewer->clip = fileInfo;
126 FileInfo *
127 FSGetFSViewerClip(FSViewer *fsViewer)
129 return fsViewer->clip;
132 void
133 FSSetFSViewerClipAction(FSViewer *fsViewer, ClipAction action)
135 fsViewer->clipAction = action;
138 ClipAction
139 FSGetFSViewerClipAction(FSViewer *fsViewer)
141 return fsViewer->clipAction;
144 void
145 FSSetFSViewerTransientWindow(FSViewer *fsViewer, Window window)
147 XWMHints *hints;
148 GNUstepWMAttributes attributes;
150 // WM_DELETE should be set here...
151 if ((hints = XAllocWMHints()))
153 hints->window_group = fsViewer->leader;
154 hints->flags = WindowGroupHint;
155 XSetWMHints(fsViewer->dpy, window, hints);
156 XFree((void *) hints);
159 memset((void *) &attributes, 0, sizeof(GNUstepWMAttributes));
160 attributes.window_style = (WMTitledWindowMask | WMClosableWindowMask);
161 attributes.window_level = WMFloatingWindowLevel;
162 attributes.extra_flags = GSFullKeyboardEventsFlag;
163 attributes.flags =
164 (/*GSWindowStyleAttr |*/ GSWindowLevelAttr | GSExtraFlagsAttr);
165 WMSetWindowAttributes(fsViewer->dpy, window, &attributes);
166 WMAppAddWindow(fsViewer->wmContext, window);
170 void
171 FSAddWindow(FSViewer *fsViewer, Window window)
173 XWMHints *hints;
174 GNUstepWMAttributes attributes;
176 // WM_DELETE should be set here...
177 if ((hints = XAllocWMHints()))
179 hints->window_group = fsViewer->leader;
180 /* hints->flags = WindowGroupHint; */
181 XSetWMHints(fsViewer->dpy, window, hints);
182 XFree((void *) hints);
185 memset((void *) &attributes, 0, sizeof(GNUstepWMAttributes));
186 attributes.window_style = (WMTitledWindowMask |
187 WMClosableWindowMask |
188 WMMiniaturizableWindowMask);
189 attributes.window_level = WMNormalWindowLevel;
190 attributes.extra_flags = GSFullKeyboardEventsFlag;
191 attributes.flags =
192 (/*GSWindowStyleAttr |*/ GSWindowLevelAttr | GSExtraFlagsAttr);
193 WMSetWindowAttributes(fsViewer->dpy, window, &attributes);
194 WMAppAddWindow(fsViewer->wmContext, window);
197 void
198 FSSetFSViewerConfirmWindow(FSViewer *fsViewer, Window window)
200 XWMHints *hints;
201 GNUstepWMAttributes attributes;
203 // WM_DELETE should be set here...
204 if ((hints = XAllocWMHints()))
206 hints->window_group = fsViewer->leader;
207 hints->flags = WindowGroupHint;
208 XSetWMHints(fsViewer->dpy, window, hints);
209 XFree((void *) hints);
212 // This is horrible: there must be a better way?
213 XStoreName(fsViewer->dpy, window, " ");
214 memset((void *) &attributes, 0, sizeof(GNUstepWMAttributes));
215 attributes.window_style = (WMTitledWindowMask);
216 attributes.window_level = WMFloatingWindowLevel;
217 attributes.extra_flags = GSFullKeyboardEventsFlag;
218 attributes.flags =
219 (/*GSWindowStyleAttr |*/ GSWindowLevelAttr | GSExtraFlagsAttr);
220 WMSetWindowAttributes(fsViewer->dpy, window, &attributes);
221 WMAppAddWindow(fsViewer->wmContext, window);
224 WMScreen *
225 FSGetFSViewerScreen(FSViewer *fsViewer)
227 return fsViewer->scr;
230 WMAppContext *
231 FSGetFSViewerWMContext(FSViewer *fsViewer)
233 return fsViewer->wmContext;
236 RContext *
237 FSGetFSViewerRContext(FSViewer *fsViewer)
239 return fsViewer->rcontext;
242 Display *
243 FSGetFSViewerDisplay(FSViewer *fsViewer)
245 return fsViewer->dpy;
248 XContext
249 FSGetFSViewerXContext(FSViewer *fsViewer)
251 return fsViewer->xContext;
254 Window
255 FSGetFSViewerLeader(FSViewer *fsViewer)
257 return fsViewer->leader;
260 void
261 FSAddViewToFSViewer(FSViewer *fsViewer, FSFileView *fView)
263 ++fsViewer->nviews;
264 fsViewer->current = fView;
267 void
268 FSRemoveViewFromFSViewer(FSViewer *fsViewer, FSFileView *fView)
270 --fsViewer->nviews;
273 void
274 FSSetFSViewerFinder(FSViewer *fsViewer, FSFinder *finder)
276 fsViewer->finder = finder;
279 FSFinder *
280 FSGetFSViewerFinder(FSViewer *fsViewer)
282 return fsViewer->finder;
285 void
286 FSSetFSViewerPath(FSViewer *fsViewer, char *path)
288 FSSetFileViewPath(fsViewer->current, path);
291 char *
292 FSGetFSViewerPath(FSViewer *fsViewer)
294 FileInfo *fileInfo = NULL;
295 FSFileView *fView;
297 fView = FSGetFSViewerCurrentView(fsViewer);
298 fileInfo = FSGetFileViewFileInfo(fView);
300 return GetPathnameFromPathName(fileInfo->path, fileInfo->name);
303 FSFileView *
304 FSGetFSViewerCurrentView(FSViewer *fsViewer)
306 return fsViewer->current;
309 void
310 FSUpdateCurrentFileViewTitles()
312 FSFileView *fView = NULL;
315 Make sure we're in a window, otherwise the app
316 could crash, especially if all windows are minimized,
317 then one is opened and closed. When another window is
318 opened, the current fileView references the one that
319 was just closed, so the app crashes as that fileView
320 isn't there. The current fileView isn't changed until
321 a window receives the focus, therefore we check to
322 see if the app is focused before unpdating the titles.
324 if(focusIn)
326 fView = FSGetFSViewerCurrentView(fsViewer);
327 FSUpdateFileViewTitles(fView);
332 FSGetFSViewerMetaMask(FSViewer *fsViewer)
334 return fsViewer->metaMask;
337 char *
338 parseArgs(int argc, char **argv)
340 char *initPath = NULL;
342 if (argc>1)
344 int i;
345 for (i=1; i<argc; i++)
347 if (strcmp(argv[i], "-v")==0)
349 printf("FSViewer %s\n", VERSION);
350 exit(0);
352 else if (strcmp(argv[i], "-p")==0)
354 i++;
355 if (i>=argc)
357 wwarning(_("too few arguments for %s"), argv[i-1]);
358 exit(0);
360 initPath = argv[i];
362 else
364 printHelp(argv[0]);
365 exit(0);
370 return initPath;
372 static void
373 FSCreateFSViewer(FSViewer *fsViewer, char **argv, int argc)
375 fsViewer->leader = XCreateSimpleWindow(fsViewer->dpy,
376 DefaultRootWindow(fsViewer->dpy),
377 10, 10, 10, 10, 0, 0, 0);
379 // Set standard X hints.
380 if ((fsViewer->class = XAllocClassHint()))
382 fsViewer->class->res_name = "fsviewer";
383 fsViewer->class->res_class = "FSViewer";
384 XSetClassHint(fsViewer->dpy, fsViewer->leader, fsViewer->class);
387 if ((fsViewer->hints = XAllocWMHints()))
389 fsViewer->hints->window_group = fsViewer->leader;
390 fsViewer->hints->flags = WindowGroupHint;
391 XSetWMHints(fsViewer->dpy, fsViewer->leader, fsViewer->hints);
392 XSetCommand(fsViewer->dpy, fsViewer->leader, argv, argc);
395 // Context for carrying a FileView*.
396 fsViewer->xContext = XUniqueContext();
399 * Create application descriptor.
401 WMInitializeApplication("FSViewer", &argc, argv);
402 fsViewer->scr = WMCreateScreen(fsViewer->dpy,
403 DefaultScreen(fsViewer->dpy));
405 // Create the WorkSpace menu context.
406 fsViewer->wmContext = WMAppCreateWithMain(fsViewer->dpy,
407 DefaultScreen(fsViewer->dpy),
408 fsViewer->leader);
409 fsViewer->initPath = parseArgs(argc, argv);
410 fsViewer->clip = NULL;
413 static void
414 FSCreateFSViewerIcons(FSViewer *fsViewer)
416 RContextAttributes attributes;
418 memset((void *) &attributes, 0, sizeof(RContextAttributes));
419 attributes.flags = (RC_RenderMode | RC_ColorsPerChannel);
420 attributes.render_mode = 0;
421 attributes.colors_per_channel = 4;
423 if (!(fsViewer->rcontext =
424 RCreateContext(fsViewer->dpy, DefaultScreen(fsViewer->dpy),
425 &attributes)))
427 /* Somethings broken here!! */
428 wfatal(_("Unable to get RContext: %s %s %d\n"),
429 "boo" /*RErrorString*/, __FILE__, __LINE__);
432 // The application icon.
433 if ((fsViewer->image = RGetImageFromXPMData(fsViewer->rcontext,
434 FSVIEWER_XPM)))
436 if ((RConvertImageMask(fsViewer->rcontext, fsViewer->image,
437 &fsViewer->appicon, &fsViewer->appmask, 0)))
439 fsViewer->hints->icon_pixmap = fsViewer->appicon;
440 fsViewer->hints->icon_mask = fsViewer->appmask;
441 fsViewer->hints->flags |= (IconPixmapHint | IconMaskHint);
442 XSetWMHints(fsViewer->dpy, fsViewer->leader, fsViewer->hints);
446 // The icon used in standard dialog panels.
447 if ((fsViewer->wmpixmap = WMCreatePixmapFromRImage(fsViewer->scr,
448 fsViewer->image, 0)))
450 WMSetApplicationIconPixmap(fsViewer->scr, fsViewer->wmpixmap);
454 static void
455 FSInitFSViewer(FSViewer *fsViewer)
457 int bit;
459 FSLoadFSViewerConfigurations(fsViewer);
460 FSInitSystemInfo(fsViewer);
461 FSInitInspector(fsViewer);
462 bit = ModifierFromKey(FSGetFSViewerDisplay(fsViewer), "META");
463 fsViewer->metaMask = 1<<bit;
466 int
467 main(int argc, char **argv)
469 FSFileView *fView;
470 focusIn = False;
472 setlocale(LC_ALL,"");
474 #ifdef ENABLE_NLS
475 if (getenv("NLSPATH"))
476 bindtextdomain("FSViewer", getenv("NLSPATH"));
477 else
478 bindtextdomain("FSViewer", LOCALEDIR);
479 bind_textdomain_codeset("FSViewer", "UTF-8");
480 textdomain("FSViewer");
482 if (!XSupportsLocale()) {
483 wwarning(_("X server does not support locale"));
485 if (XSetLocaleModifiers("") == NULL) {
486 wwarning(_("cannot set locale modifiers"));
488 #endif
490 /* wmessage("LOCALEDIR= %s", LOCALEDIR);*/
492 if (!(fsViewer = (FSViewer *) malloc(sizeof(FSViewer))))
494 wfatal(_("Unable to allocate memory for %s %s %d\n"),
495 argv[0], __FILE__, __LINE__);
497 memset((void *) fsViewer, 0, sizeof(FSViewer));
499 fsViewer->dpy = XOpenDisplay(NULL);
500 if (!fsViewer->dpy) {
501 wfatal(_("Unable to Open Display!"));
502 exit(0);
504 FSCreateFSViewer(fsViewer, argv, argc);
505 FSCreateFSViewerIcons(fsViewer);
506 FSInitFSViewer(fsViewer);
507 FSCreateMenu(fsViewer);
510 No path specified at start up, use home dir.
512 if(fsViewer->initPath == NULL)
513 fsViewer->initPath = FSGetHomeDir();
515 Unable to get home dir, must use `/`
517 if(fsViewer->initPath == NULL)
518 fsViewer->initPath = wstrdup("/");
520 if(!(fView = FSCreateFileView(fsViewer, fsViewer->initPath, True)))
522 wfatal(_("Unable to create a FileView instance %s %s %d"),
523 argv[0], __FILE__, __LINE__);
525 fsViewer->current = fView;
527 while (1)
529 XEvent event;
530 FSFileView *fView;
532 WMNextEvent(fsViewer->dpy, &event);
533 WMHandleEvent(&event);
534 WMProcessEvent(fsViewer->wmContext, &event);
536 switch (event.type)
538 case FocusIn:
539 if (!(XFindContext(fsViewer->dpy, event.xfocus.window,
540 fsViewer->xContext, (XPointer *) &fView)))
542 /* if((FSFinder *)fView == fsViewer->finder) */
543 /* break; */
544 fsViewer->current = fView;
545 FSUpdateFileViewShelf(fView);
547 focusIn = True;
548 break;
549 case FocusOut: focusIn = False;
550 break;
551 case ClientMessage:
552 // printf("arrgggg!\n");
553 break;