Enable silent-rules for compilation
[fsviewer.git] / src / FSFileView.c
blobded5d84e9f8ada0c7dd9fc6810a57f8a94f7d9db
1 #include <limits.h>
2 #include <stdlib.h>
3 #include <X11/Xlib.h>
4 #include <X11/Xutil.h>
5 #include <X11/Xproto.h>
6 #include <WMaker.h>
7 #include <WINGs/WINGsP.h>
8 #include <X11/Xlocale.h>
9 #include <X11/keysym.h>
10 #include <sys/stat.h>
11 #include <unistd.h>
12 #include <X11/cursorfont.h>
14 #include "files.h"
15 #include "filebrowser.h"
16 #include "FSFileButton.h"
17 #include "FSViewer.h"
18 #include "FSFileView.h"
19 #include "DnD.h"
20 #include "FSUtils.h"
22 #define MIN_UPPER_HEIGHT 90
23 #define MIN_LOWER_HEIGHT 200
24 #define FILE_ICON_WIDTH 95
25 #define FILE_ICON_HEIGHT 80
26 #define PADX 10
27 #define PADY 10
28 #define PADDED_WIDTH 115
29 #define PADDED_HEIGHT 100
31 static void notificationObserver(void *self, WMNotification *notif);
32 static void FSAddFileViewShelfItem(FSFileView *fView, FileInfo *fileInfo);
33 static void handleShelfButtonActions(WMWidget *self, void *data);
34 static void handleShelfEventActions(XEvent *event, void *data);
35 static void FSAddFileViewItemIntoShelf(FSViewer *fView);
36 static void FSRemoveFileViewItemFromShelf(FSFileView *fView,
37 FSFileIcon *fileIcon);
38 static void FSSetupFileViewShelfItems(FSFileView *fView);
39 static void FSReorganiseShelf(FSFileView *fView);
40 static void handleScrollViewDoubleClick(WMWidget *self, void *clientData);
41 static Bool FSAddFileViewShelfItemIntoProplist(FSFileView *fView,
42 FileInfo *fileInfo);
43 static void handleShelfDrop(XEvent *ev, void *clientData);
44 static void handleBtnDrop(XEvent *ev, void *clientData);
45 static void handleBtnDrag(XEvent *ev, void *clientData);
46 static FSFileIcon *FSFindFileIconWithFileInfo(FSFileView *fView,
47 FileInfo *fileInfo);
49 static void
50 splitViewConstrainCallback(WMSplitView *sPtr, int divIndex, int *min, int *max)
52 *min = 1;
53 *max = WMWidgetHeight(sPtr)-WMGetSplitViewDividerThickness(sPtr)-MIN_UPPER_HEIGHT;
56 static void
57 handleScrollViewDoubleClick(WMWidget *self, void *clientData)
59 char *pathname;
60 FileInfo *fileInfo;
61 FileBrowser *bPtr = (FileBrowser *)self;
62 FSFileView *fView = (FSFileView *)clientData;
64 if( (fileInfo = FSGetFileBrowserSelectedFileInfo(bPtr)) == NULL )
65 return;
67 pathname = (char *)wmalloc(strlen(fileInfo->path)+
68 strlen(fileInfo->name)+1);
69 strcpy(pathname, fileInfo->path);
70 strcat(pathname, fileInfo->name);
72 if(access(pathname, X_OK) == 0)
73 LaunchApp(fView->fsViewer, fileInfo, AppExec);
74 else if(access(pathname, R_OK) == 0)
75 LaunchApp(fView->fsViewer, fileInfo, AppView);
76 else if(access(pathname, W_OK) == 0)
77 LaunchApp(fView->fsViewer, fileInfo, AppEdit);
79 if(pathname)
80 free(pathname);
83 static void
84 notificationObserver(void *self, WMNotification *notif)
86 FSFileView *fView = (FSFileView*)self;
87 void *object = WMGetNotificationObject(notif);
88 int divThickness = WMGetSplitViewDividerThickness(fView->split);
90 if (WMGetNotificationName(notif) == WMViewSizeDidChangeNotification)
92 if (object == WMWidgetView(fView->fileView))
94 fView->h = WMWidgetHeight(fView->fileView);
95 fView->w = WMWidgetWidth(fView->fileView);
97 WMResizeWidget(fView->split, fView->w, fView->h);
99 else if (object == WMWidgetView(fView->shelfF))
101 int w = WMWidgetWidth(fView->shelfF);
103 if(fView->shelfW != w)
105 FSReorganiseShelf(fView);
106 fView->shelfW = w;
109 else if (object == WMWidgetView(fView->fileBrowserF))
111 WMResizeWidget(fView->fileBrowser,
112 WMWidgetWidth(fView->fileBrowserF)-10,
113 WMWidgetHeight(fView->fileBrowserF)-5);
118 static void
119 handleKeyPressEvents(XEvent *event, void *data)
121 char buffer[64];
122 KeySym ksym;
123 int count;
124 Bool meta_pressed = False;
125 FSViewer *fsViewer = (FSViewer *) data;
126 FSFileView *fView = FSGetFSViewerCurrentView(fsViewer);
128 if (event->xkey.state & FSGetFSViewerMetaMask(fsViewer))
129 meta_pressed = True;
130 else
131 return;
133 /* FSFileBrowserKeyPress(fView->fileBrowser, event); */
135 count = XLookupString(&event->xkey, buffer, 63, &ksym, NULL);
136 buffer[count] = '\0';
139 switch (ksym)
141 /* Lower Case */
142 case XK_a :
143 FSSelectAllCB(fsViewer, 0, 0);
144 break;
145 case XK_c :
146 FSCopyCB(fsViewer, 0, 0);
147 break;
148 case XK_d :
149 FSCopyCB(fsViewer, 0, 0);
150 break;
151 /* case XK_e : */
152 /* FSEjectDisksCB(fsViewer, 0, 0); */
153 /* break; */
154 case XK_f :
155 FSFilterViewCB(fsViewer, 0, 0);
156 break;
157 case XK_h :
158 FSHideCB(NULL, 0, 0);
159 break;
160 case XK_i :
161 FSInspectorCB(fsViewer, 0, 0);
162 break;
163 case XK_l :
164 FSLinkCB(fsViewer, 0, 0);
165 break;
166 case XK_m :
167 FSMiniaturizeCB(fsViewer, 0, 0);
168 break;
169 case XK_n :
170 FSNewDirCB(fsViewer, 0, 0);
171 break;
172 case XK_o :
173 FSViewCB(fsViewer, 0, 0);
174 break;
175 case XK_q :
176 FSQuitCB(NULL, NULL);
177 break;
178 case XK_r :
179 /* Should be Destroy */
180 FSDeleteCB(fsViewer, 0, 0);
181 break;
182 case XK_s :
183 FSSortOrderCB(fsViewer, 0, 0);
184 break;
185 case XK_u :
186 FSUpdateViewCB(fsViewer, 0, 0);
187 break;
188 case XK_v :
189 FSPasteCB(fsViewer, 0, 0);
190 break;
191 case XK_w :
192 FSCloseWindowCB(fsViewer, 0, 0);
193 break;
194 case XK_x :
195 FSCutCB(fsViewer, 0, 0);
196 break;
197 case XK_question :
198 FSHelpCB(fsViewer, 0, 0);
199 break;
201 /* Upper Case */
202 case XK_B :
203 FSBrowseCB(fsViewer, 0, 0);
204 break;
205 case XK_C :
206 FSConsoleCB(fsViewer, 0, 0);
207 break;
208 case XK_D :
209 FSDotFilesCB(fsViewer, 0, 0);
210 break;
211 case XK_E :
212 FSEditCB(fsViewer, 0, 0);
213 break;
214 case XK_F :
215 FSFinderCB(fsViewer, 0, 0);
216 break;
217 case XK_I :
218 FSIconCB(fsViewer, 0, 0);
219 break;
220 case XK_L :
221 FSListCB(fsViewer, 0, 0);
222 break;
223 case XK_N :
224 FSNewViewCB(fsViewer, 0, 0);
225 break;
226 case XK_O :
227 FSOpenAsFolderCB(fsViewer, 0, 0);
228 break;
229 case XK_P :
230 FSProcessCB(fsViewer, 0, 0);
231 break;
232 case XK_R :
233 FSRunCB(fsViewer, 0, 0);
234 break;
235 case XK_S :
236 FSViewCB(fsViewer, 0, 0);
237 break;
239 default: /* Do Nothing */
240 break;
244 FSFileView *
245 FSCreateFileView(FSViewer *fsViewer, char *path, Bool primary)
247 int divThickness;
248 WMPropList* array = NULL;
249 FSFileView *fView;
250 GNUstepWMAttributes attributes;
252 if (!path)
253 return NULL;
255 if (!(fView = (FSFileView *) malloc(sizeof(FSFileView))))
256 return NULL;
258 memset((void *) fView, 0, sizeof(FSFileView));
260 if (!(fView->path = wstrdup(path)))
262 free((void *) fView);
263 return NULL;
266 fView->dpy = FSGetFSViewerDisplay(fsViewer);
267 fView->scr = FSGetFSViewerScreen(fsViewer);
268 fView->fsViewer = fsViewer;
269 fView->ctrlKey = False;
270 fView->fileIcons = NULL;
271 fView->dirtyFileIcon = NULL;
273 default values from property list:
274 164, "XPOS"
275 164, "YPOS"
276 520, "WSIZE"
277 390, "HSIZE"
279 fView->x = FSGetIntegerForName("XPOS");
280 if (fView->x < 0)
282 wwarning(_("Wrong XPOS value: %d. Using default."), fView->x);
283 fView->x = 164;
285 fView->y = FSGetIntegerForName("YPOS");
286 if (fView->y < 0)
288 wwarning(_("Wrong YPOS value: %d. Using default."), fView->y);
289 fView->y = 164;
291 fView->w = FSGetIntegerForName("WSIZE");
292 if (fView->w <= 0)
294 wwarning(_("Wrong WSIZE value: %d. Using default."), fView->w);
295 fView->w = 520;
297 fView->h = FSGetIntegerForName("HSIZE");
298 if (fView->h <= 0)
300 wwarning(_("Wrong HSIZE value: %d. Using default."), fView->h);
301 fView->h = 390;
304 fView->xcontext = FSGetFSViewerXContext(fsViewer);
305 fView->primary = primary;
307 fView->fileView = WMCreateWindow(fView->scr, "fileView");
308 WMSetWindowTitle(fView->fileView, _("FileView"));
309 if ((fView->primary == False))
311 WMSetWindowCloseAction(fView->fileView, FSDestroyFileView,
312 (void *) fView);
315 WMSetViewNotifySizeChanges(WMWidgetView(fView->fileView), True);
317 WMResizeWidget(fView->fileView, fView->w, fView->h);
318 WMMoveWidget(fView->fileView, fView->x, fView->y);
320 fView->split = WMCreateSplitView(fView->fileView);
321 WMResizeWidget(fView->split, fView->w, fView->h);
322 WMSetSplitViewConstrainProc(fView->split, splitViewConstrainCallback);
324 divThickness = WMGetSplitViewDividerThickness(fView->split);
326 /* Initialise the FileButton Widget */
327 InitFSFileButton(fView->scr);
329 /* Initialize drag'n'drop */
330 DndInitialize(fView->fileView);
332 fView->shelfF = WMCreateFrame(fView->fileView);
333 WMSetViewNotifySizeChanges(WMWidgetView(fView->shelfF), True);
334 WMSetFrameRelief(fView->shelfF, WRFlat);
336 fView->fileBrowserF = WMCreateFrame(fView->fileView);
337 WMSetViewNotifySizeChanges(WMWidgetView(fView->fileBrowserF), True);
338 WMSetFrameRelief(fView->fileBrowserF, WRFlat);
341 WMAddSplitViewSubview(fView->split, W_VIEW(fView->shelfF));
342 WMAddSplitViewSubview(fView->split, W_VIEW(fView->fileBrowserF));
344 InitFileBrowser(fView->scr);
345 fView->fileBrowser = FSCreateFileBrowser(fView->fileBrowserF);
346 WMRealizeWidget(fView->fileView);
347 WMMoveWidget(fView->fileBrowser, 5, 0);
348 /* watch values for w and h, should not be to small */
349 WMResizeWidget(fView->fileBrowser,
350 fView->w-10, fView->h-5-MIN_UPPER_HEIGHT-divThickness);
352 int cw = FSGetIntegerForName("ColumnWidth");
353 if (cw < 169)
354 cw = 169;
355 FSSetFileBrowserColumnWidth(fView->fileBrowser, cw);
357 WMResizeWidget(fView->shelfF, fView->w, MIN_UPPER_HEIGHT);
358 FSSetupFileViewShelfItems(fView);
360 fView->shelfW = fView->w;
361 fView->shelfH = MIN_UPPER_HEIGHT;
362 WMResizeWidget(fView->fileBrowserF,
363 fView->w, fView->h-MIN_UPPER_HEIGHT-divThickness);
364 WMMoveWidget(fView->fileBrowserF, 0, MIN_UPPER_HEIGHT+divThickness);
366 /* WMRealizeWidget(fView->fileView); */
368 /* WMRealizeWidget(fView->split); */
370 /* Initialise the FileButton Widget */
371 /* InitFSFileButton(fView->scr); */
372 /* Initialize drag'n'drop */
373 /* DndInitialize(fView->fileView); */
374 /* Initialize Shelf */
375 /* initShelf(fView); */
376 /* Initialize File Browser */
377 /* initFileBrowser(fView); */
378 /* WMAdjustSplitViewSubviews(fView->split); */
380 /* register notification observers */
381 /* WMAddNotificationObserver(notificationObserver, fView, */
382 /* WMViewSizeDidChangeNotification, */
383 /* WMWidgetView(fView->fileView)); */
385 if ((fView->hints = XAllocWMHints()))
387 fView->hints->window_group = FSGetFSViewerLeader(fsViewer);
388 fView->hints->flags = WindowGroupHint;
389 XSetWMHints(fView->dpy, WMWidgetXID(fView->fileView),
390 fView->hints);
393 if ((fView->class = XAllocClassHint()))
395 fView->class->res_name = "fileViewer";
396 fView->class->res_class = "FileViewer";
397 XSetClassHint(fView->dpy, WMWidgetXID(fView->fileView),
398 fView->class);
401 if ((fView->size = XAllocSizeHints()))
403 fView->size->width = fView->w;
404 fView->size->height = fView->h;
405 fView->size->min_width = fView->w;
406 fView->size->max_width =
407 DisplayWidth(fView->dpy, DefaultScreen(fView->dpy));
408 fView->size->min_height = 250;
409 fView->size->max_height =
410 DisplayHeight(fView->dpy, DefaultScreen(fView->dpy));
411 fView->size->width_inc = 171;
412 fView->size->height_inc = 1;
413 fView->size->flags = (USSize | PSize | PMinSize |
414 PMaxSize | PResizeInc);
415 if ((fView->primary == True))
417 fView->size->x = fView->x;
418 fView->size->y = fView->y;
419 fView->size->flags |= (USPosition | PPosition);
421 XSetWMNormalHints(fView->dpy, WMWidgetXID(fView->fileView),
422 fView->size);
425 if ((fView->primary))
427 memset((void *) &attributes, 0, sizeof(GNUstepWMAttributes));
428 attributes.window_style = (WMTitledWindowMask |
429 WMMiniaturizableWindowMask |
430 WMResizableWindowMask);
431 attributes.window_level = WMNormalWindowLevel;
432 attributes.extra_flags = GSFullKeyboardEventsFlag;
433 attributes.flags = (GSWindowStyleAttr | GSWindowLevelAttr |
434 GSExtraFlagsAttr);
435 WMSetWindowAttributes(fView->dpy, WMWidgetXID(fView->fileView),
436 &attributes);
439 WMAppAddWindow(FSGetFSViewerWMContext(fsViewer),
440 WMWidgetXID(fView->fileView));
442 FSSetFileBrowserPath(fView->fileBrowser, fView->path);
443 FSSetFileBrowserDoubleAction(fView->fileBrowser,
444 handleScrollViewDoubleClick,
445 (void *)fView);
447 /* Drag'n'Drop handles */
448 DndRegisterDropWidget(fView->shelfF, handleShelfDrop, fView);
450 WMMapSubwidgets(fView->fileView);
451 WMMapWidget(fView->shelfF);
452 WMMapWidget(fView->fileBrowserF);
453 WMMapWidget(fView->fileBrowser);
454 WMMapWidget(fView->fileView);
456 XSaveContext(fView->dpy, WMWidgetXID(fView->fileView),
457 fView->xcontext,
458 (XPointer) fView);
459 FSAddViewToFSViewer(fsViewer, fView);
461 WMCreateEventHandler(WMWidgetView(fView->fileView), KeyPressMask,
462 handleKeyPressEvents, fsViewer);
464 /* register notification observers */
465 WMAddNotificationObserver(notificationObserver, fView,
466 WMViewSizeDidChangeNotification,
467 WMWidgetView(fView->fileView));
468 WMAddNotificationObserver(notificationObserver, fView,
469 WMViewSizeDidChangeNotification,
470 WMWidgetView(fView->shelfF));
471 WMAddNotificationObserver(notificationObserver, fView,
472 WMViewSizeDidChangeNotification,
473 WMWidgetView(fView->fileBrowserF));
475 WMSetWindowMiniwindowPixmap(fView->fileView,
476 WMGetApplicationIconPixmap(fView->scr));
478 array = FSGetUDObjectForKey(defaultsDB, "SHELF");
479 if(array && WMIsPLArray(array))
481 fView->shelf = WMDeepCopyPropList(array);
484 FSUpdateFileViewTitles(fView);
486 return fView;
489 void
490 FSDestroyFileView(WMWidget *self, void *client)
492 WMPoint pos;
493 WMSize size;
494 FSFileView *fileView = (FSFileView *) client;
496 size = WMGetViewSize(W_VIEW(fileView->fileView));
497 pos = WMGetViewScreenPosition(W_VIEW(fileView->fileView));
499 FSSetIntegerForName("XPOS", pos.x);
500 FSSetIntegerForName("YPOS", pos.y);
501 FSSetIntegerForName("WSIZE", size.width);
502 FSSetIntegerForName("HSIZE", size.height);
504 XDeleteContext(fileView->dpy, WMWidgetXID(fileView->fileView),
505 fileView->xcontext);
506 WMUnmapWidget(fileView->fileView);
508 while(fileView->fileIcons != NULL)
510 WMUnmapWidget(fileView->fileIcons->btn);
511 WMDestroyWidget(fileView->fileIcons->btn);
512 fileView->fileIcons = fileView->fileIcons->next;
514 fileView->fileIcons = NULL;
515 fileView->fileIconCnt = 0;
517 if(fileView->dirtyFileIcon)
519 WMUnmapWidget(fileView->dirtyFileIcon->btn);
520 WMDestroyWidget(fileView->dirtyFileIcon->btn);
521 fileView->dirtyFileIcon = NULL;
524 WMDestroyWidget(fileView->fileView);
525 FSRemoveViewFromFSViewer(fileView->fsViewer, fileView);
526 free(fileView);
528 fileView = NULL;
531 Bool
532 FSIsFileViewPrimary(FSFileView *fileView)
534 return fileView->primary;
537 WMWidget *
538 FSFileViewWMWidget(FSFileView *fileView)
540 return fileView->fileView;
543 char *
544 FSGetFileViewPath(FSFileView *fileView)
546 return FSGetFileBrowserPath(fileView->fileBrowser);
549 FileInfo *
550 FSGetFileViewFileInfo(FSFileView *fileView)
552 return FSGetFileInfo(FSGetFileViewPath(fileView));
555 void
556 FSUpdateFileViewPath(FSFileView *fileView, FileAction action,
557 FileInfo *src, FileInfo *dest)
559 char *path = NULL;
560 FileInfo *fileInfo = NULL;
561 FSFileIcon *fileIcon = NULL;
563 switch(action)
565 case FileCopy :
566 FSUpdateFileBrowser(fileView->fileBrowser, action, src, dest);
567 break;
568 case FileMove :
569 case FileDelete :
570 FSUpdateFileBrowser(fileView->fileBrowser, action, src, dest);
571 fileIcon = FSFindFileIconWithFileInfo(fileView, src);
572 FSRemoveFileViewItemFromShelf(fileView, fileIcon);
573 break;
574 case FileRename :
575 FSUpdateFileBrowser(fileView->fileBrowser, action, src, dest);
576 fileIcon = FSFindFileIconWithFileInfo(fileView, src);
577 FSRemoveFileViewItemFromShelf(fileView, fileIcon);
578 fileInfo = FSGetFileInfo(GetPathnameFromPathName(dest->path,
579 dest->name));
580 if(fileInfo && fileIcon)
582 if(FSAddFileViewShelfItemIntoProplist(fileView, fileInfo))
583 FSAddFileViewShelfItem(fileView, fileInfo);
584 FSFreeFileInfo(fileInfo);
586 break;
587 case FileSync :
588 FSUpdateFileViewShelf(fileView);
589 path = FSGetFileViewPath(fileView);
590 FSSetFileBrowserPath(fileView->fileBrowser, path);
591 break;
594 if(path)
595 free(path);
598 void
599 FSSetFileViewPath(FSFileView *fileView, char *path)
601 FSSetFileBrowserPath(fileView->fileBrowser, path);
604 void
605 FSUpdateFileViewTitles(FSFileView *fView)
607 char *title = NULL;
608 char *path = NULL;
610 path = FSGetFileViewPath(fView);
611 if(path)
613 title = (char *) wmalloc(strlen(path)+12);
614 snprintf(title, strlen(path)+12, "FSViewer - %s", path);
616 else
618 title = (char *) wmalloc(33);
619 snprintf(title, 33, _("FSViewer - we've got a problem!"));
622 WMSetWindowMiniwindowTitle(fView->fileView, title);
623 WMSetWindowTitle(fView->fileView, title);
625 if(path)
626 free(path);
627 if(title)
628 free(title);
631 WMWindow *
632 FSGetFileViewWindow(FSFileView *fView)
634 return fView->fileView;
637 void
638 FSSetFileViewFilter(FSFileView *fView, char *filter)
640 FSSetFileBrowserFilter(fView->fileBrowser, filter);
641 FSUpdateFileViewPath(fView, FileSync, NULL, NULL);
644 char *
645 FSGetFileViewFilter(FSFileView *fView)
647 return FSGetFileBrowserFilter(fView->fileBrowser);
650 /****************************************************************************
652 * Shelf Related Functions Below
654 ****************************************************************************/
656 static void
657 handleShelfDrop(XEvent *ev, void *clientData)
659 FSFileView *fView = (FSFileView *) clientData;
660 FileInfo *fileInfo = NULL;
661 unsigned char *data=NULL;
662 unsigned long Size;
663 unsigned int Type;
665 Type=DndDataType(ev);
666 if( (Type != DndFile) && (Type != DndDir) &&
667 (Type != DndLink) && (Type!=DndExe) )
669 return;
671 DndGetData(&data,&Size);
673 fileInfo = FSGetFileInfo(data);
674 if(fileInfo)
677 * If fileInfo was successfully entered into the
678 * array, place it on the shelf
680 if(FSAddFileViewShelfItemIntoProplist(fView, fileInfo))
681 FSAddFileViewShelfItem(fView, fileInfo);
686 static void
687 handleShelfEventActions(XEvent *event, void *data)
689 FSFileView *fView = (FSFileView *)data;
691 if(event->xkey.state & ControlMask)
693 fView->ctrlKey = True;
698 static void
699 handleShelfButtonActions(WMWidget *self, void *data)
701 int i;
702 Bool found = False;
703 FSFileButton *btn = (FSFileButton *)self;
704 FSFileView *fView = (FSFileView *)data;
705 FSFileIcon *fileIcon = fView->fileIcons;
707 while(fileIcon != NULL)
709 if(btn == fileIcon->btn)
711 found = True;
712 break;
714 fileIcon = fileIcon->next;
717 if(found)
719 if(fView->ctrlKey)
721 FSRemoveFileViewItemFromShelf(fView, fileIcon);
722 fView->ctrlKey = False;
724 else
726 char *pathname;
727 FileInfo *fileInfo = FSGetFileButtonFileInfo(fileIcon->btn);
729 if(fileInfo == NULL)
730 return;
732 pathname = (char *)malloc(strlen(fileInfo->path)+
733 strlen(fileInfo->name)+1);
734 strcpy(pathname, fileInfo->path);
735 strcat(pathname, fileInfo->name);
737 if(isDirectory(fileInfo->fileType))
738 FSSetFileBrowserPath(fView->fileBrowser, pathname);
739 else if(access(pathname, X_OK) == 0)
740 LaunchApp(fView->fsViewer, fileInfo, AppExec);
741 else if(access(pathname, R_OK) == 0)
742 LaunchApp(fView->fsViewer, fileInfo, AppView);
743 else if(access(pathname, W_OK) == 0)
744 LaunchApp(fView->fsViewer, fileInfo, AppEdit);
749 /* Drag'n'Drop */
750 /* Drop handle for Shelf icon */
751 static void
752 handleShelfButtonDrop(XEvent *ev, void *clientData)
754 unsigned long Size;
755 unsigned int Type,Keys;
756 unsigned char *data = NULL;
757 FSFileIcon *fileIcon = (FSFileIcon *) clientData;
758 FileInfo *src = NULL;
759 FileInfo *dest = FSGetFileButtonFileInfo(fileIcon->btn);
760 FSFileView *fView = WMGetHangedData(fileIcon->btn);
762 Type = DndDataType(ev);
763 if( (Type!=DndFile) && (Type!=DndFiles) &&
764 (Type!=DndExe) && (Type!=DndDir) && (Type!=DndLink))
766 return;
769 Keys=DndDragButtons(ev);
771 DndGetData(&data,&Size);
772 if(!data)
773 return;
775 if(Type!=DndFiles)
777 char *srcPath = NULL;
778 char *destPath = NULL;
780 src=FSGetFileInfo(data);
782 srcPath = GetPathnameFromPathName(src->path, src->name);
783 destPath = GetPathnameFromPathName(dest->path, dest->name);
785 if(strcmp(srcPath, destPath) != 0)
787 if(Keys & ShiftMask) /* Copy */
789 wwarning("%s %d", __FILE__, __LINE__);
790 FSCopy(src, dest);
792 else
794 /* FSFileIcon *fileIcon = NULL; */
796 FSMove(src, dest);
797 /* fileIcon = FSFindFileIconWithFileInfo(fView, src); */
798 /* if(fileIcon) */
799 /* FSRemoveFileViewItemFromShelf(fView, fileIcon); */
802 if(srcPath)
803 free(srcPath);
804 if(destPath)
805 free(destPath);
809 /* Drag handle for Shelf icon */
810 static void
811 handleShelfButtonDrag(XEvent *ev, void *clientData)
813 int type;
814 char *path = NULL;
815 WMPixmap *pixmap = NULL;
816 FSFileIcon *fileIcon = (FSFileIcon *) clientData;
817 FileInfo *fileInfo = FSGetFileButtonFileInfo(fileIcon->btn);
819 if (!DragStarted)
820 return;
822 if(!fileInfo)
823 return;
825 path = GetPathnameFromPathName(fileInfo->path, fileInfo->name);
826 type = FSGetDNDType(fileInfo);
828 DndSetData(type, path, (unsigned long)(strlen(path)+1));
830 pixmap = FSCreateBlurredPixmapFromFile(WMWidgetScreen(fileIcon->btn),
831 fileInfo->imgName);
832 DndHandleDragging(fileIcon->btn, ev, pixmap);
834 if(path)
835 free(path);
836 if(pixmap)
837 WMReleasePixmap(pixmap);
841 * Place the fileIcon in the next free slot on the shelf.
842 * all very orderly!!
844 static void
845 FSPositionItemInShelf(FSFileView *fView, FSFileIcon *fileIcon, int num)
847 int w, h;
848 int row, col;
849 int numCol = 0;
850 int width = 0;
852 w = WMWidgetWidth(fView->shelfF)-25;
853 h = WMWidgetHeight(fView->shelfF);
855 numCol = (int) (w / PADDED_WIDTH);
856 row = (int) (num/numCol);
857 col = num-(numCol*row);
859 WMMoveWidget(fileIcon->btn, 25+(PADDED_WIDTH*(col)),
860 PADY+(PADDED_HEIGHT*row));
865 FSReorganiseShelf: Local Function to reorganise shelf layout if
866 the contents changed.
868 static void
869 FSReorganiseShelf(FSFileView *fView)
871 int cnt = 0;
872 FSFileIcon *tmp = fView->fileIcons;
874 if(fView->dirtyFileIcon)
876 WMUnmapWidget(fView->dirtyFileIcon->btn);
877 WMDestroyWidget(fView->dirtyFileIcon->btn);
878 fView->dirtyFileIcon = NULL;
881 if(tmp == NULL)
882 return;
883 else
885 while(tmp->next)
887 FSPositionItemInShelf(fView, tmp, cnt);
888 cnt++;
889 tmp = tmp->next;
891 FSPositionItemInShelf(fView, tmp, cnt);
896 * FSAddFileViewShelfItem:
897 * Create a fileIcon, add it to FileView->fileIcons
898 * and add it to the shelf after the last fileIcon
900 static void
901 FSAddFileViewShelfItem(FSFileView *fView, FileInfo *fileInfo)
903 char *pathname;
904 FSFileIcon *fileIcon;
905 FSFileIcon *tmp = fView->fileIcons;
907 if(fileInfo == NULL)
908 return;
910 fileIcon = (FSFileIcon *) wmalloc(sizeof(FSFileIcon));
911 memset(fileIcon, 0, sizeof(FSFileIcon));
912 fileIcon->next = NULL;
914 /* Create a FileButton */
915 fileIcon->btn = FSCreateFileButton(fView->shelfF);
916 pathname = GetPathnameFromPathName(fileInfo->path, fileInfo->name);
917 FSSetFileButtonPathname(fileIcon->btn, pathname, 0);
918 FSSetFileButtonAction(fileIcon->btn, handleShelfButtonActions, fView);
919 WMHangData(fileIcon->btn, fView);
920 WMRealizeWidget(fileIcon->btn);
921 WMMapWidget(fileIcon->btn);
924 /* Drag'n'Drop */
925 DndRegisterDropWidget(fileIcon->btn, handleShelfButtonDrop, fileIcon);
926 DndRegisterDragWidget(fileIcon->btn, handleShelfButtonDrag, fileIcon);
928 /* Add the new Btn to the fileIcon linked list */
929 if(fView->fileIcons == NULL)
930 fView->fileIcons = fileIcon;
931 else
933 while(tmp->next)
934 tmp = tmp->next;
936 fileIcon->next = tmp->next;
937 tmp->next = fileIcon;
940 /* Position the btn in the shelf */
941 FSPositionItemInShelf(fView, fileIcon, fView->fileIconCnt);
942 fView->fileIconCnt++;
945 * Add a Button Press handler,
946 * used to check for control key presses
948 WMCreateEventHandler(WMWidgetView(fileIcon->btn),
949 ButtonPressMask,
950 handleShelfEventActions, fView);
954 * FSAddFileViewItemIntoShelf:
955 * Add the selected path to the shelf and
956 * update the SHELF entry in the user defaults DB
958 static void
959 FSAddFileViewItemIntoShelf(FSViewer *fsViewer)
961 FSFileView *fView = NULL;
962 FileInfo *fileInfo = NULL;
964 /* Get the current path fileInfo */
965 fView = FSGetFSViewerCurrentView(fsViewer);
966 fileInfo = FSGetFileBrowserSelectedFileInfo(fView->fileBrowser);
968 if(fileInfo == NULL)
969 return;
971 if(FSAddFileViewShelfItemIntoProplist(fView, fileInfo))
974 * If fileInfo was successfully entered into the
975 * array, place it on the shelf
977 FSAddFileViewShelfItem(fView, fileInfo);
982 * FSAddFileViewShelfItemIntoProplist:
983 * Add the fileInfo into the user DC, if it was successfully
984 * entered return False, if the fileInfo is already in there
985 * return true.
987 static Bool
988 FSAddFileViewShelfItemIntoProplist(FSFileView *fView, FileInfo *fileInfo)
990 Bool notFound;
991 char *pathname = NULL;
992 WMPropList* val = NULL;
993 WMPropList* array = NULL;
996 * Get the Shelf entry and insert the pathname into
997 * the array
999 pathname = GetPathnameFromPathName(fileInfo->path, fileInfo->name);
1000 val = WMCreatePLString(pathname);
1001 array = FSGetUDObjectForKey(defaultsDB, "SHELF");
1002 if (!array)
1004 array = WMCreatePLArray(WMCreatePLString(wgethomedir()), NULL );
1005 WMSetUDObjectForKey(defaultsDB, array, "SHELF");
1007 notFound = InsertArrayElement(array, val);
1010 * If val hasn't been found in the original array
1011 * it is inserted, therefore we want to update the
1012 * shelf array.
1014 if(notFound)
1016 WMSetUDObjectForKey(defaultsDB, array, "SHELF");
1018 WMReleasePropList(fView->shelf);
1019 fView->shelf = WMDeepCopyPropList(array);
1022 if(pathname)
1023 free(pathname);
1025 return notFound;
1029 * Remove the fileIcon from the shelf and the proplist entry
1031 static void
1032 FSRemoveFileViewItemFromShelf(FSFileView *fView, FSFileIcon *fileIcon)
1034 char *pathname = NULL;
1035 WMPropList* key = NULL;
1036 WMPropList* val = NULL;
1037 WMPropList* array = NULL;
1038 FileInfo *fileInfo = NULL;
1039 FSFileIcon *tmp = fView->fileIcons;
1041 if(fileIcon == NULL)
1042 return;
1044 The following code is needed to remove the btn to
1045 prevent a seg fault when the btn widget is destroyed
1046 and the calling function exits. The procedure is as follows:
1047 a) unmap the btn and remove it from the list
1048 b) Remove the shelf item from the proplist entry
1049 c) Reorganise the shelf with the updated list.
1050 d) Set dirtyFileIcon so that it will be removed on the next
1051 reorganise shelf call or when the FileViewer is destroyed.
1053 To check that it seg faults at the end of this function insert
1054 WMWidgetDestroy(fileIcon->btn);
1056 /* Required by dirtyIcon...*/
1057 WMUnmapWidget(fileIcon->btn);
1058 if(tmp != fileIcon)
1060 while(tmp->next != fileIcon)
1061 tmp = tmp->next;
1062 tmp->next = tmp->next->next;
1064 else
1066 tmp = tmp->next;
1067 fView->fileIcons = tmp;
1069 fView->fileIconCnt--;
1070 /*...dirtyIcon*/
1072 fileInfo = FSGetFileButtonFileInfo(fileIcon->btn);
1073 pathname = GetPathnameFromPathName(fileInfo->path, fileInfo->name);
1074 val = WMCreatePLString(pathname);
1075 array = FSGetUDObjectForKey(defaultsDB, "SHELF");
1077 if (array && WMIsPLArray(array))
1079 FSRemoveArrayElement(array, val);
1081 WMSetUDObjectForKey(defaultsDB, array, "SHELF");
1083 WMReleasePropList(fView->shelf);
1084 fView->shelf = WMDeepCopyPropList(array);
1086 FSReorganiseShelf(fView);
1087 fView->dirtyFileIcon = fileIcon;
1089 if(key)
1090 WMReleasePropList(key);
1091 if(pathname)
1092 free(pathname);
1096 Read the proplist entry for SHELf and add the necessary fileIcons to
1097 the shelf
1099 static void
1100 FSSetupFileViewShelfItems(FSFileView *fView)
1102 WMPropList* key = NULL;
1103 WMPropList* array = NULL;
1105 array = FSGetUDObjectForKey(defaultsDB, "SHELF");
1106 if(array && WMIsPLArray(array))
1108 char *path;
1109 FileInfo *fileInfo = NULL;
1110 int numElem, i;
1112 numElem = WMGetPropListItemCount(array);
1113 for(i = 0; i < numElem; i++)
1115 path = WMGetFromPLString(WMGetFromPLArray(array, i));
1116 fileInfo = FSGetFileInfo(path);
1117 FSAddFileViewShelfItem(fView, fileInfo);
1122 Update the Shelf. This is used when the focus moves between FileView
1123 windows. The local proplist shelf copy is compared with the filesDB copy,
1124 if they are different, the shelf and fileIcons list is regenerated.
1126 The local shelf copy provides a method to check if the global shelf is
1127 dirty. The local copy has no other function.
1129 void
1130 FSUpdateFileViewShelf(FSFileView *fView)
1132 WMPropList* key = NULL;
1133 WMPropList* array = NULL;
1134 FSFileIcon *tmp = fView->fileIcons;
1136 /* rid ourselves of the dirty File Icon */
1137 if(fView->dirtyFileIcon)
1139 WMUnmapWidget(fView->dirtyFileIcon->btn);
1140 WMDestroyWidget(fView->dirtyFileIcon->btn);
1141 fView->dirtyFileIcon = NULL;
1144 /* get the global array */
1145 array = FSGetUDObjectForKey(defaultsDB, "SHELF");
1146 if(array && WMIsPLArray(array))
1148 char *path;
1149 FileInfo *fileInfo = NULL;
1150 int numElem, i;
1152 /* Check to see if they are different */
1153 if(WMIsPropListEqualTo(array, fView->shelf) == False)
1155 /* they are, so clear the shelf */
1156 while(tmp != NULL)
1158 WMUnmapWidget(tmp->btn);
1159 WMDestroyWidget(tmp->btn);
1160 tmp = tmp->next;
1162 fView->fileIcons = NULL;
1163 fView->fileIconCnt = 0;
1165 /* reload the shelf */
1166 numElem = WMGetPropListItemCount(array);
1167 for(i = 0; i < numElem; i++)
1169 path = WMGetFromPLString(WMGetFromPLArray(array, i));
1170 fileInfo = FSGetFileInfo(path);
1171 FSAddFileViewShelfItem(fView, fileInfo);
1174 WMReleasePropList(fView->shelf);
1175 fView->shelf = WMDeepCopyPropList(array);
1181 * Find the fileIcon with the given fileInfo
1183 static FSFileIcon *
1184 FSFindFileIconWithFileInfo(FSFileView *fView, FileInfo *fileInfo)
1186 FileInfo *fI = NULL;
1187 FSFileIcon *tmp = fView->fileIcons;
1188 FSFileIcon *theOne = NULL;
1190 while(tmp)
1192 fI = FSGetFileButtonFileInfo(tmp->btn);
1193 if( strcmp(fileInfo->name, fI->name) == 0 &&
1194 strcmp(fileInfo->path, fI->path) == 0 )
1196 /* found the right fileIcon */
1197 theOne = tmp;
1198 break;
1200 else
1201 tmp = tmp->next;
1204 return theOne;
1207 void
1208 FSSetFileViewMode(FSFileView *fView, FSFileViewType mode)
1211 switch(mode)
1213 case Browser : FSSetFileBrowserMode(fView->fileBrowser, 0);
1214 break;
1215 case Icon : FSSetFileBrowserMode(fView->fileBrowser, 1);
1216 break;
1217 case List : FSSetFileBrowserMode(fView->fileBrowser, 2);
1218 break;
1219 default : FSSetFileBrowserMode(fView->fileBrowser, 0);
1220 break;