aboutsummaryrefslogtreecommitdiffstats
path: root/filelist.c
diff options
context:
space:
mode:
authorkraxel <kraxel>2004-03-28 11:31:57 +0000
committerkraxel <kraxel>2004-03-28 11:31:57 +0000
commite9e9684117719204929821028ba9dbb7915ea119 (patch)
tree6dd2d71940b33a9f960945335e9124ef4fea9fe7 /filelist.c
downloadfbida-e9e9684117719204929821028ba9dbb7915ea119.tar.gz
Initial revision
Diffstat (limited to 'filelist.c')
-rw-r--r--filelist.c619
1 files changed, 619 insertions, 0 deletions
diff --git a/filelist.c b/filelist.c
new file mode 100644
index 0000000..317e3b1
--- /dev/null
+++ b/filelist.c
@@ -0,0 +1,619 @@
+/*
+ * file list management ("virtual photo album").
+ * (c) 2003 Gerd Knorr <kraxel@bytesex.org>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+#include <fnmatch.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <X11/Xlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/extensions/XShm.h>
+#include <Xm/Xm.h>
+#include <Xm/Form.h>
+#include <Xm/Label.h>
+#include <Xm/RowColumn.h>
+#include <Xm/PushB.h>
+#include <Xm/CascadeB.h>
+#include <Xm/ScrolledW.h>
+#include <Xm/SelectioB.h>
+#include <Xm/Transfer.h>
+#include <Xm/TransferP.h>
+#include <Xm/Container.h>
+#include <Xm/FileSB.h>
+#include <Xm/Separator.h>
+
+#include "RegEdit.h"
+#include "ida.h"
+#include "readers.h"
+#include "viewer.h"
+#include "browser.h"
+#include "filter.h"
+#include "x11.h"
+#include "dither.h"
+#include "selections.h"
+#include "filebutton.h"
+#include "filelist.h"
+#include "xdnd.h"
+#include "idaconfig.h"
+
+/*----------------------------------------------------------------------*/
+
+struct list_handle;
+
+struct list_handle {
+ char *filename;
+ struct list_head files;
+
+ Widget shell;
+ Widget scroll;
+ Widget container;
+ Widget status;
+ XmString details[DETAIL_COUNT+1];
+
+ Widget loadbox;
+ Widget savebox;
+
+ XtWorkProcId wproc;
+};
+
+/* ---------------------------------------------------------------------- */
+
+static void filelist_add(struct list_handle *h, char *filename)
+{
+ struct file_button *file;
+ char *tmp;
+
+ /* fixup filename */
+ if (0 == strncmp(filename,"file:",5))
+ filename += 5;
+ if (NULL != (tmp = strchr(filename,'\n')))
+ *tmp = 0;
+ if (NULL != (tmp = strchr(filename,'\r')))
+ *tmp = 0;
+ if (0 == strlen(filename))
+ return;
+
+ /* add file */
+ file = malloc(sizeof(*file));
+ memset(file,0,sizeof(*file));
+
+ tmp = strrchr(filename,'/');
+ if (!tmp)
+ goto oops;
+ file->basename = strdup(tmp+1);
+ file->filename = strdup(filename);
+
+ if (-1 == stat(file->filename,&file->st)) {
+ fprintf(stderr,"stat %s: %s\n",file->filename,strerror(errno));
+ goto oops;
+ }
+ if (!S_ISREG(file->st.st_mode)) {
+ fprintf(stderr,"%s: not a regular file\n",file->filename);
+ goto oops;
+ }
+
+ list_add_tail(&file->window,&h->files);
+ file_createwidgets(h->container, file);
+ XtManageChild(file->widget);
+ fileinfo_queue(file);
+ container_relayout(h->container);
+ return;
+
+ oops:
+ if (file->filename)
+ free(file->filename);
+ if (file->basename)
+ free(file->basename);
+ free(file);
+}
+
+static void filelist_file(struct list_handle *h, char *filename)
+{
+ if (h->filename == filename)
+ return;
+ if (h->filename)
+ free(h->filename);
+ h->filename = strdup(filename);
+ XtVaSetValues(h->shell,XtNtitle,h->filename,NULL);
+}
+
+static void filelist_read(struct list_handle *h, char *filename)
+{
+ FILE *fp;
+ char line[128];
+
+ fp = fopen(filename,"r");
+ if (NULL == fp) {
+ fprintf(stderr,"open %s: %s\n",filename,strerror(errno));
+ return;
+ }
+ while (NULL != fgets(line, sizeof(line), fp)) {
+ filelist_add(h, line);
+ }
+ fclose(fp);
+ filelist_file(h,filename);
+ container_relayout(h->container);
+}
+
+static void filelist_write(struct list_handle *h, char *filename)
+{
+ struct file_button *file;
+ struct list_head *item;
+ FILE *fp;
+
+ fp = fopen(filename,"w");
+ if (NULL == fp) {
+ fprintf(stderr,"open %s: %s\n",filename,strerror(errno));
+ return;
+ }
+ list_for_each(item, &h->files) {
+ file = list_entry(item, struct file_button, window);
+ fprintf(fp,"%s\n",file->filename);
+ }
+ fclose(fp);
+ filelist_file(h,filename);
+}
+
+static void filelist_delall(struct list_handle *h)
+{
+ struct file_button *file;
+ struct list_head *item;
+
+ list_for_each(item, &h->files) {
+ file = list_entry(item, struct file_button, window);
+ XtUnmanageChild(file->widget);
+ XtDestroyWidget(file->widget);
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* receive data (drops, paste) */
+
+static Atom targets[16];
+static Cardinal ntargets;
+
+static void
+filelist_xfer(Widget widget, XtPointer clientdata, XtPointer call_data)
+{
+ struct list_handle *h = clientdata;
+ XmSelectionCallbackStruct *scs = call_data;
+ unsigned char *cdata = scs->value;
+ unsigned long *ldata = scs->value;
+ Atom target = 0;
+ unsigned int i,j,pending;
+ char *file;
+
+ if (debug) {
+ char *y = !scs->type ? NULL : XGetAtomName(dpy,scs->type);
+ char *t = !scs->target ? NULL : XGetAtomName(dpy,scs->target);
+ char *s = !scs->selection ? NULL : XGetAtomName(dpy,scs->selection);
+ fprintf(stderr,"list: id=%p target=%s type=%s selection=%s\n",
+ scs->transfer_id,t,y,s);
+ if (y) XFree(y);
+ if (t) XFree(t);
+ if (s) XFree(s);
+ }
+
+ pending = scs->remaining;
+ if (scs->target == XA_TARGETS) {
+ /* look if we find a target we can deal with ... */
+ for (i = 0; !target && i < scs->length; i++) {
+ for (j = 0; j < ntargets; j++) {
+ if (ldata[i] == targets[j]) {
+ target = ldata[i];
+ break;
+ }
+ }
+ }
+ if (target) {
+ XmTransferValue(scs->transfer_id, target, filelist_xfer,
+ clientdata, XtLastTimestampProcessed(dpy));
+ pending++;
+ }
+ if (debug) {
+ fprintf(stderr,"list: available targets: ");
+ for (i = 0; i < scs->length; i++) {
+ char *name = !ldata[i] ? NULL : XGetAtomName(dpy,ldata[i]);
+ fprintf(stderr,"%s%s", i != 0 ? ", " : "", name);
+ XFree(name);
+ }
+ fprintf(stderr,"\n");
+ if (0 == scs->length)
+ fprintf(stderr,"list: Huh? no TARGETS available?\n");
+ }
+ }
+
+ if (scs->target == XA_FILE_NAME ||
+ scs->target == XA_FILE) {
+ /* load file */
+ if (debug)
+ fprintf(stderr,"list: => \"%s\"\n",cdata);
+ filelist_add(h,cdata);
+ }
+
+ if (scs->target == _NETSCAPE_URL) {
+ /* load file */
+ if (debug)
+ fprintf(stderr,"list: => \"%s\"\n",cdata);
+ filelist_add(h,cdata);
+ }
+
+ if (scs->target == MIME_TEXT_URI_LIST) {
+ /* load file(s) */
+ for (file = strtok(cdata,"\r\n");
+ NULL != file;
+ file = strtok(NULL,"\r\n")) {
+ if (debug)
+ fprintf(stderr,"list: => \"%s\"\n",file);
+ filelist_add(h,file);
+ }
+ }
+
+ XFree(scs->value);
+ if (1 == pending) {
+ /* all done -- clean up */
+ if (debug)
+ fprintf(stderr,"list: all done\n");
+ XmTransferDone(scs->transfer_id, XmTRANSFER_DONE_SUCCEED);
+ XdndDropFinished(widget,scs);
+ }
+}
+
+static void
+filelist_dest_cb(Widget w, XtPointer clientdata, XtPointer call_data)
+{
+ XmDestinationCallbackStruct *dcs = call_data;
+
+ if (debug)
+ fprintf(stderr,"list: xfer id=%p\n",dcs->transfer_id);
+ XmTransferValue(dcs->transfer_id, XA_TARGETS, filelist_xfer,
+ clientdata, XtLastTimestampProcessed(dpy));
+}
+
+/*----------------------------------------------------------------------*/
+
+static void
+filelist_new_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
+{
+ struct list_handle *h = clientdata;
+
+ filelist_delall(h);
+ if (h->filename) {
+ free(h->filename);
+ h->filename = NULL;
+ }
+ XtVaSetValues(h->shell,XtNtitle,"new list",NULL);
+}
+
+static void
+init_file_box(Widget box, char *filename)
+{
+ char *dir,*file;
+ XmString s1;
+
+ if (NULL == filename) {
+ dir = strdup(ida_lists);
+ } else {
+ dir = strdup(filename);
+ file = strrchr(dir,'/');
+ if (NULL == file)
+ return;
+ *file = 0;
+ file++;
+ }
+
+ s1 = XmStringGenerate(dir, NULL, XmMULTIBYTE_TEXT, NULL);
+ XtVaSetValues(box,
+ XmNdirectory, s1,
+ XmNpattern, NULL,
+ NULL);
+ XmFileSelectionDoSearch(box,NULL);
+ XmStringFree(s1);
+ free(dir);
+}
+
+static void
+load_done_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
+{
+ XmFileSelectionBoxCallbackStruct *cb = call_data;
+ struct list_handle *h = clientdata;
+ char *filename;
+
+ if (cb->reason == XmCR_OK) {
+ filename = XmStringUnparse(cb->value,NULL,
+ XmMULTIBYTE_TEXT,XmMULTIBYTE_TEXT,
+ NULL,0,0);
+ if (debug)
+ fprintf(stderr,"read list from %s\n",filename);
+ filelist_read(h, filename);
+ }
+ XtUnmanageChild(widget);
+}
+
+static void
+filelist_load_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
+{
+ struct list_handle *h = clientdata;
+ Widget help;
+
+ if (NULL == h->loadbox) {
+ h->loadbox = XmCreateFileSelectionDialog(h->shell,"load",NULL,0);
+ help = XmFileSelectionBoxGetChild(h->loadbox,XmDIALOG_HELP_BUTTON);
+ XtUnmanageChild(help);
+ XtAddCallback(h->loadbox,XmNokCallback,load_done_cb,h);
+ XtAddCallback(h->loadbox,XmNcancelCallback,load_done_cb,h);
+ }
+ init_file_box(h->loadbox,h->filename);
+ XtManageChild(h->loadbox);
+}
+
+static void
+save_done_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
+{
+ XmFileSelectionBoxCallbackStruct *cb = call_data;
+ struct list_handle *h = clientdata;
+ char *filename;
+
+ if (cb->reason == XmCR_OK) {
+ filename = XmStringUnparse(cb->value,NULL,
+ XmMULTIBYTE_TEXT,XmMULTIBYTE_TEXT,
+ NULL,0,0);
+ if (debug)
+ fprintf(stderr,"write list to %s\n",filename);
+ filelist_write(h, filename);
+ }
+ XtUnmanageChild(widget);
+}
+
+static void
+filelist_save_as_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
+{
+ struct list_handle *h = clientdata;
+ Widget help;
+
+ if (NULL == h->savebox) {
+ h->savebox = XmCreateFileSelectionDialog(h->shell,"save",NULL,0);
+ help = XmFileSelectionBoxGetChild(h->savebox,XmDIALOG_HELP_BUTTON);
+ XtUnmanageChild(help);
+
+ XtAddCallback(h->savebox,XmNokCallback,save_done_cb,h);
+ XtAddCallback(h->savebox,XmNcancelCallback,save_done_cb,h);
+ }
+ init_file_box(h->savebox,h->filename);
+ XtManageChild(h->savebox);
+}
+
+static void
+filelist_save_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
+{
+ struct list_handle *h = clientdata;
+
+ if (h->filename) {
+ filelist_write(h, h->filename);
+ } else {
+ filelist_save_as_cb(widget, h, call_data);
+ }
+}
+
+static void
+filelist_destroy(Widget widget, XtPointer clientdata, XtPointer call_data)
+{
+ struct list_handle *h = clientdata;
+
+ if (h->filename)
+ free(h->filename);
+ ptr_unregister(h->shell);
+ free(h);
+}
+
+static void
+filelist_list_load(Widget widget, XtPointer clientdata, XtPointer call_data)
+{
+ struct list_handle *h = clientdata;
+
+ filelist_delall(h);
+ filelist_read(h, XtName(widget));
+}
+
+static void filelist_builddir(Widget menu, char *path, XtPointer clientdata)
+{
+ Widget push,submenu;
+ XmString str;
+ char filename[1024];
+ struct dirent *ent;
+ struct stat st;
+ DIR *dir;
+
+ dir = opendir(path);
+ while (NULL != (ent = readdir(dir))) {
+ if (ent->d_name[0] == '.')
+ continue;
+ snprintf(filename,sizeof(filename),"%s/%s",
+ path,ent->d_name);
+ if (-1 == lstat(filename,&st))
+ continue;
+
+ str = XmStringGenerate(ent->d_name,NULL, XmMULTIBYTE_TEXT,NULL);
+ if (S_ISREG(st.st_mode)) {
+ push = XtVaCreateManagedWidget(filename,
+ xmPushButtonWidgetClass,menu,
+ XmNlabelString,str,
+ NULL);
+ XtAddCallback(push,XmNactivateCallback,filelist_list_load,clientdata);
+ }
+ if (S_ISDIR(st.st_mode)) {
+ submenu = XmCreatePulldownMenu(menu,"subdirM",NULL,0);
+ XtVaCreateManagedWidget("subdir",xmCascadeButtonWidgetClass,menu,
+ XmNlabelString,str,
+ XmNsubMenuId,submenu,
+ NULL);
+ filelist_builddir(submenu,filename,clientdata);
+ }
+ XmStringFree(str);
+ }
+ closedir(dir);
+}
+
+static void
+filelist_lists(Widget widget, XtPointer clientdata, XtPointer call_data)
+{
+ WidgetList children,list;
+ Cardinal nchildren;
+ int i;
+
+ XtVaGetValues(widget,
+ XtNchildren,&children,
+ XtNnumChildren,&nchildren,
+ NULL);
+ list = malloc(sizeof(Widget*)*nchildren);
+ memcpy(list,children,sizeof(Widget*)*nchildren);
+ for (i = 0; i < nchildren; i++)
+ XtDestroyWidget(list[i]);
+ free(list);
+
+ filelist_builddir(widget,ida_lists,clientdata);
+}
+
+static void
+filelist_action_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
+{
+ XmContainerSelectCallbackStruct *cd = call_data;
+ char *file;
+
+ if (XmCR_DEFAULT_ACTION == cd->reason && 1 == cd->selected_item_count) {
+ file = XtName(cd->selected_items[0]);
+ if (debug)
+ fprintf(stderr,"browser: action %s\n", file);
+ new_file(file,1);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+filelist_window(void)
+{
+ Widget form,clip,menubar,menu,push;
+ struct list_handle *h;
+ Arg args[8];
+ int n = 0;
+
+ if (0 == ntargets) {
+ /* first time init */
+ targets[ntargets++] = MIME_TEXT_URI_LIST;
+ targets[ntargets++] = XA_FILE_NAME;
+ targets[ntargets++] = XA_FILE;
+ targets[ntargets++] = _NETSCAPE_URL;
+ }
+
+ h = malloc(sizeof(*h));
+ if (NULL == h) {
+ fprintf(stderr,"out of memory");
+ return;
+ }
+ memset(h,0,sizeof(*h));
+ INIT_LIST_HEAD(&h->files);
+
+ h->shell = XtVaAppCreateShell("filelist","Ida",
+ topLevelShellWidgetClass,
+ dpy,
+ XtNclientLeader,app_shell,
+ XmNdeleteResponse,XmDESTROY,
+ XtNtitle,"new list",
+ NULL);
+ XmdRegisterEditres(h->shell);
+ XtAddCallback(h->shell,XtNdestroyCallback,filelist_destroy,h);
+
+ /* widgets */
+ form = XtVaCreateManagedWidget("form", xmFormWidgetClass, h->shell,
+ NULL);
+ menubar = XmCreateMenuBar(form,"cbar",NULL,0);
+ XtManageChild(menubar);
+ h->status = XtVaCreateManagedWidget("status",xmLabelWidgetClass, form,
+ NULL);
+
+ /* scrolled container */
+ h->details[0] = XmStringGenerate("Image", NULL, XmMULTIBYTE_TEXT,NULL);
+ h->details[DETAIL_SIZE+1] =
+ XmStringGenerate("Size", NULL, XmMULTIBYTE_TEXT,NULL);
+ h->details[DETAIL_COMMENT+1] =
+ XmStringGenerate("Comment", NULL, XmMULTIBYTE_TEXT,NULL);
+ XtSetArg(args[n], XmNdetailColumnHeading, h->details); n++;
+ XtSetArg(args[n], XmNdetailColumnHeadingCount, DETAIL_COUNT+1); n++;
+
+ h->scroll = XmCreateScrolledWindow(form, "scroll", NULL, 0);
+ XtManageChild(h->scroll);
+ h->container = XmCreateContainer(h->scroll,"container",
+ args,n);
+ XtManageChild(h->container);
+ XdndDropSink(h->container);
+
+ XtAddCallback(h->scroll, XmNtraverseObscuredCallback,
+ container_traverse_cb, NULL);
+ XtAddCallback(h->container,XmNdefaultActionCallback,
+ filelist_action_cb,h);
+ XtAddCallback(h->container,XmNconvertCallback,
+ container_convert_cb,h);
+ XtAddCallback(h->container,XmNdestinationCallback,
+ filelist_dest_cb,h);
+
+ XtVaGetValues(h->scroll,XmNclipWindow,&clip,NULL);
+ XtAddEventHandler(clip,StructureNotifyMask,True,container_resize_eh,NULL);
+
+ /* menu - file */
+ menu = XmCreatePulldownMenu(menubar,"fileM",NULL,0);
+ XtVaCreateManagedWidget("file",xmCascadeButtonWidgetClass,menubar,
+ XmNsubMenuId,menu,NULL);
+ push = XtVaCreateManagedWidget("new",xmPushButtonWidgetClass,menu,NULL);
+ XtAddCallback(push,XmNactivateCallback,filelist_new_cb,h);
+ push = XtVaCreateManagedWidget("load",xmPushButtonWidgetClass,menu,NULL);
+ XtAddCallback(push,XmNactivateCallback,filelist_load_cb,h);
+ push = XtVaCreateManagedWidget("save",xmPushButtonWidgetClass,menu,NULL);
+ XtAddCallback(push,XmNactivateCallback,filelist_save_cb,h);
+ push = XtVaCreateManagedWidget("saveas",xmPushButtonWidgetClass,menu,NULL);
+ XtAddCallback(push,XmNactivateCallback,filelist_save_as_cb,h);
+
+ XtVaCreateManagedWidget("sep",xmSeparatorWidgetClass,menu,NULL);
+ push = XtVaCreateManagedWidget("close",xmPushButtonWidgetClass,menu,NULL);
+ XtAddCallback(push,XmNactivateCallback,destroy_cb,h->shell);
+
+ /* menu - edit */
+ menu = XmCreatePulldownMenu(menubar,"editM",NULL,0);
+ XtVaCreateManagedWidget("edit",xmCascadeButtonWidgetClass,menubar,
+ XmNsubMenuId,menu,NULL);
+ container_menu_edit(menu,h->container, 0,1,1,1);
+
+ /* menu - view */
+ menu = XmCreatePulldownMenu(menubar,"viewM",NULL,0);
+ XtVaCreateManagedWidget("view",xmCascadeButtonWidgetClass,menubar,
+ XmNsubMenuId,menu,NULL);
+ container_menu_view(menu,h->container);
+
+ /* menu - lists */
+ menu = XmCreatePulldownMenu(menubar,"listsM",NULL,0);
+ XtVaCreateManagedWidget("lists",xmCascadeButtonWidgetClass,menubar,
+ XmNsubMenuId,menu,NULL);
+ XtAddCallback(menu, XmNmapCallback, filelist_lists, h);
+
+ /* read dir and show window */
+ container_detail_cb(NULL,h->container,NULL);
+ XtPopup(h->shell,XtGrabNone);
+ ptr_register(h->shell);
+}
+
+void
+filelist_ac(Widget widget, XEvent *event,
+ String *params, Cardinal *num_params)
+{
+ filelist_window();
+}