Logo Search packages:      
Sourcecode: fbi version File versions  Download package

filebutton.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <Xm/Xm.h>
#include <Xm/Label.h>
#include <Xm/RowColumn.h>
#include <Xm/PushB.h>
#include <Xm/Transfer.h>
#include <Xm/TransferP.h>
#include <Xm/Container.h>
#include <Xm/IconG.h>
#include <Xm/ScrolledW.h>
#include <Xm/SelectioB.h>
#include <Xm/Text.h>

#include "RegEdit.h"
#include "list.h"
#include "ida.h"
#include "x11.h"
#include "icons.h"
#include "readers.h"
#include "filter.h"
#include "viewer.h"
#include "selections.h"
#include "filebutton.h"
#include "fileops.h"
#include "idaconfig.h"

/*----------------------------------------------------------------------*/

struct fileinfo {
    struct list_head       list;
    char                   *path;
    struct ida_image_info  img;
    Pixmap                 small;
    Pixmap                 large;
};

static LIST_HEAD(pcache);
static LIST_HEAD(pqueue);
static LIST_HEAD(files);
static XtWorkProcId pproc;

/*----------------------------------------------------------------------*/

static struct fileinfo*
fileinfo_cache_add(char *path, struct ida_image_info *img,
               Pixmap small, Pixmap large)
{
    struct fileinfo *item;

    item = malloc(sizeof(*item));
    memset(item,0,sizeof(*item));
    item->path  = strdup(path);
    item->img   = *img;
    item->small = small;
    item->large = large;
    list_add_tail(&item->list,&pcache);
    return item;
}

static void fileinfo_cache_del(char *path)
{
    struct list_head *item;
    struct fileinfo *b;

    list_for_each(item,&pcache) {
      b = list_entry(item,struct fileinfo,list);
      if (0 == strcmp(path,b->path)) {
          list_del(&b->list);
          free(b);
          return;
      }
    }
}

static struct fileinfo* fileinfo_cache_get(char *path)
{
    struct list_head *item;
    struct fileinfo *b;

    list_for_each(item,&pcache) {
      b = list_entry(item,struct fileinfo,list);
      if (0 == strcmp(path,b->path))
          return b;
    }
    return 0;
}

/*----------------------------------------------------------------------*/

static void
fileinfo_cleanup(struct file_button *file)
{
    switch (file->state) {
    case 1:
      file->loader->done(file->wdata);
      break;
    case 2:
      desc_resize.done(file->wdata);
      break;
    }
    file->state = 0;

    if (file->wimg.data) {
      free(file->wimg.data);
      file->wimg.data = NULL;
    }
    if (file->simg.data) {
      free(file->simg.data);
      file->simg.data = NULL;
    }
    if (!list_empty(&file->queue)) {
      list_del_init(&file->queue);
    }
}

static void fileinfo_details(struct file_button *file)
{
    struct ida_image_info *img;
    struct ida_extra *extra;
    char buf[80];

    img = &file->info->img;
    snprintf(buf, sizeof(buf), "%dx%d",
           img->thumbnail ? img->real_width  : img->width,
           img->thumbnail ? img->real_height : img->height);
    XmStringFree(file->details[DETAIL_SIZE]);
    file->details[DETAIL_SIZE] = XmStringGenerate(buf, NULL, XmMULTIBYTE_TEXT,NULL);

    extra = load_find_extra(img, EXTRA_COMMENT);
    if (extra) {
      XmStringFree(file->details[DETAIL_COMMENT]);
      file->details[DETAIL_COMMENT] =
          XmStringGenerate(extra->data, NULL, XmMULTIBYTE_TEXT,NULL);
    }

    XtVaSetValues(file->widget,
              XmNdetail, file->details,
              XmNdetailCount, DETAIL_COUNT,
              NULL);
}

static Boolean
fileinfo_loader(XtPointer clientdata)
{
    struct op_resize_parm resize;
    struct ida_rect rect;
    struct list_head *item;
    struct file_button *file;
    struct fileinfo *info;
    Pixmap pix;
    char blk[512];
    FILE *fp;
    float xs,ys,scale;
    struct ida_image timg;
    void *data;

    if (list_empty(&pqueue)) {
      /* nothing to do */
      pproc = 0;
      return TRUE;
    }
    file = list_entry(pqueue.next, struct file_button, queue);

    switch (file->state) {
    case 0:
      /* ------------------- new file -------------------- */
      info = fileinfo_cache_get(file->filename);
      if (info) {
          file_set_info(file,info);
          goto next;
      }
      
      /* open file */
      if (NULL == (fp = fopen(file->filename, "r"))) {
          if (debug)
            fprintf(stderr,"open %s: %s\n",file->filename,
                  strerror(errno));
          goto unknown;
      }
      if (debug)
          fprintf(stderr,"OPENED: %s\n",file->filename);
      fstat(fileno(fp),&file->st);
      
      /* pick loader */
      memset(blk,0,sizeof(blk));
      fread(blk,1,sizeof(blk),fp);
      rewind(fp);
      list_for_each(item,&loaders) {
          file->loader = list_entry(item, struct ida_loader, list);
          if (NULL == file->loader->magic)
            continue;
          if (0 == memcmp(blk+file->loader->moff,file->loader->magic,
                      file->loader->mlen))
            break;
          file->loader = NULL;
      }
      if (NULL == file->loader) {
          if (debug)
            fprintf(stderr,"%s: unknown format\n",file->filename);
          fclose(fp);
          goto unknown;
      }

      /* load image */
      file->wdata = file->loader->init(fp, file->filename,
                               0, &file->wimg.i, 1);
      if (NULL == file->wdata) {
          if (debug)
            fprintf(stderr,"loading %s [%s] FAILED\n",
                  file->filename, file->loader->name);
          goto unknown;
      }

      file->wimg.data = malloc(file->wimg.i.width * file->wimg.i.height * 3);
      file->state = 1;
      file->y     = 0;
      return FALSE;

    case 1:
      /* ------------------- loading file -------------------- */
      if (file->y < file->wimg.i.height) {
          file->loader->read(file->wimg.data
                         + 3 * file->y * file->wimg.i.width,
                         file->y, file->wdata);
          file->y++;
          return FALSE;
      }
      file->loader->done(file->wdata);
      if (debug)
          fprintf(stderr,"LOADED: %s [%dx%d]\n",
                file->filename, file->wimg.i.width, file->wimg.i.height);
      
      /* resize image */
      xs = (float)GET_ICON_LARGE() / file->wimg.i.width;
      ys = (float)GET_ICON_LARGE() / file->wimg.i.height;
      scale = (xs < ys) ? xs : ys;
      resize.width  = file->wimg.i.width  * scale;
      resize.height = file->wimg.i.height * scale;
      if (0 == resize.width)
          resize.width = 1;
      if (0 == resize.height)
          resize.height = 1;
      
      rect.x1 = 0;
      rect.x2 = file->wimg.i.width;
      rect.y1 = 0;
      rect.y2 = file->wimg.i.height;
      file->wdata = desc_resize.init(&file->wimg,&rect,&file->simg.i,&resize);
      file->simg.data = malloc(file->simg.i.width * file->simg.i.height * 3);

      file->state = 2;
      file->y     = 0;
      return FALSE;

    case 2:
      /* ------------------- scaling file -------------------- */
      if (file->y < file->simg.i.height) {
          desc_resize.work(&file->wimg,&rect, file->simg.data
                       + 3 * file->simg.i.width * file->y,
                       file->y, file->wdata);
          file->y++;
          return FALSE;
      }
      desc_resize.done(file->wdata);
      if (debug)
          fprintf(stderr,"SCALED: %s [%dx%d]\n",
                file->filename,file->simg.i.width,file->simg.i.height);

      /* scale once more (small icon) */
      xs = (float)GET_ICON_SMALL() / file->simg.i.width;
      ys = (float)GET_ICON_SMALL() / file->simg.i.height;
      scale = (xs < ys) ? xs : ys;
      resize.width  = file->simg.i.width  * scale;
      resize.height = file->simg.i.height * scale;
      if (0 == resize.width)
          resize.width = 1;
      if (0 == resize.height)
          resize.height = 1;
      
      rect.x1 = 0;
      rect.x2 = file->simg.i.width;
      rect.y1 = 0;
      rect.y2 = file->simg.i.height;
      data = desc_resize.init(&file->simg,&rect,&timg.i,&resize);
      timg.data = malloc(timg.i.width * timg.i.height * 3);

      for (file->y = 0; file->y < timg.i.height; file->y++)
          desc_resize.work(&file->simg,&rect,
                       timg.data + 3 * timg.i.width * file->y,
                       file->y, data);
      desc_resize.done(data);

      /* build, cache + install pixmap */
      info = fileinfo_cache_add(file->filename,&file->wimg.i,
                          image_to_pixmap(&timg),
                          image_to_pixmap(&file->simg));
      file_set_info(file,info);
      free(timg.data);
      file->state = 0;
      goto next;

    default:
      /* shouldn't happen */
      fprintf(stderr,"Oops: %s:%d\n",__FILE__,__LINE__);
      exit(1);
    }

 unknown:
    /* generic file icon */
    pix = XmGetPixmap(file->screen,"unknown",0,0);
    file_set_icon(file,pix,pix);
    
 next:
    fileinfo_cleanup(file);
    return FALSE;
}

/*----------------------------------------------------------------------*/

void fileinfo_queue(struct file_button *file)
{
    if (NULL == file->queue.next)
      INIT_LIST_HEAD(&file->queue);

    if (!list_empty(&file->queue)) {
      /* already queued */
      if (0 == file->state)
          return;
      fileinfo_cleanup(file);
    }

    file->state = 0;
    memset(&file->wimg,0,sizeof(file->wimg));
    memset(&file->simg,0,sizeof(file->simg));
    list_add_tail(&file->queue,&pqueue);
    if (0 == pproc)
      pproc = XtAppAddWorkProc(app_context,fileinfo_loader,NULL);
}

void fileinfo_invalidate(char *filename)
{
    struct file_button  *file;
    struct list_head    *item;
    Pixmap              pix;
    
    if (debug)
      fprintf(stderr,"fileinfo invalidate: %s\n",filename);
    fileinfo_cache_del(filename);

    list_for_each(item,&files) {
      file = list_entry(item, struct file_button, global);
      if (0 != strcmp(file->filename,filename))
          continue;
      if (debug)
          fprintf(stderr,"  %p %s\n",file,filename);
      file->info = NULL;
      pix = XmGetPixmap(file->screen,"file",0,0);
      file_set_icon(file,pix,pix);
      fileinfo_queue(file);
    }
}

/*----------------------------------------------------------------------*/

static void
container_ops_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
{
    Widget container = clientdata;
    WidgetList children;
    Cardinal nchildren,i;
    
    XtVaGetValues(container,
              XmNselectedObjects,&children,
              XmNselectedObjectCount,&nchildren,
              NULL);
    for (i = 0; i < nchildren; i++) {
      struct stat st;
      if (-1 == stat(XtName(children[i]),&st))
          continue;
      if (!S_ISREG(st.st_mode))
          continue;
      job_submit(XtName(widget),XtName(children[i]), NULL);
    }
}

static void
comment_box_cb(Widget widget, XtPointer clientdata, XtPointer calldata)
{
    Widget container = clientdata;
    XmSelectionBoxCallbackStruct *cd = calldata;
    WidgetList children;
    Cardinal nchildren,i;
    Widget text;
    char *comment;

    if (XmCR_OK == cd->reason) {
      /* TODO */
      text = XmSelectionBoxGetChild(widget,XmDIALOG_TEXT);
      comment = XmTextGetString(text);
      XtVaGetValues(container,
                  XmNselectedObjects,&children,
                  XmNselectedObjectCount,&nchildren,
                  NULL);
      for (i = 0; i < nchildren; i++) {
          struct stat st;
          if (-1 == stat(XtName(children[i]),&st))
            continue;
          if (!S_ISREG(st.st_mode))
            continue;
          job_submit("comment",XtName(children[i]), comment);
      }
    }
    XtDestroyWidget(XtParent(widget));
}

static void
container_comment_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
{
    Widget container = clientdata;
    Widget box,text;
    WidgetList children;
    Cardinal nchildren;
    static struct fileinfo *info;
    struct ida_extra *extra;
    char *comment = "";

    XtVaGetValues(container,
              XmNselectedObjects,&children,
              XmNselectedObjectCount,&nchildren,
              NULL);
    switch (nchildren) {
    case 0:
      /* nothing to do */
      return;
    case 1:
      /* get old comment */
      info = fileinfo_cache_get(XtName(children[0]));
      if (!info)
          /* not a image */
          return;
      extra = load_find_extra(&info->img, EXTRA_COMMENT);
      if (extra)
          comment = extra->data;
      break;
    default:
      /* start with a empty comment */
      break;
    }
    
    /* dialog box */
    box = XmCreatePromptDialog(container,"comment",NULL,0);
    XtUnmanageChild(XmSelectionBoxGetChild(box,XmDIALOG_HELP_BUTTON));
    XmdRegisterEditres(XtParent(box));
    XtAddCallback(box,XmNokCallback,comment_box_cb,clientdata);
    XtAddCallback(box,XmNcancelCallback,comment_box_cb,clientdata);
    XtAddCallback(XtParent(box),XmNdestroyCallback,destroy_cb,XtParent(box));

    text = XmSelectionBoxGetChild(box,XmDIALOG_TEXT);
    XmTextSetString(text,comment);
    XmTextSetInsertionPosition(text,strlen(comment));
    XtManageChild(box);
}

void container_menu_ops(Widget menu, Widget container)
{
    Widget push;
    
    push = XtVaCreateManagedWidget("rotexif",xmPushButtonWidgetClass,menu,NULL);
    XtAddCallback(push,XmNactivateCallback,container_ops_cb,container);
    push = XtVaCreateManagedWidget("rotcw",xmPushButtonWidgetClass,menu,NULL);
    XtAddCallback(push,XmNactivateCallback,container_ops_cb,container);
    push = XtVaCreateManagedWidget("rotccw",xmPushButtonWidgetClass,menu,NULL);
    XtAddCallback(push,XmNactivateCallback,container_ops_cb,container);
    push = XtVaCreateManagedWidget("comment",xmPushButtonWidgetClass,menu,NULL);
    XtAddCallback(push,XmNactivateCallback,container_comment_cb,container);
}

/*----------------------------------------------------------------------*/

void
container_resize_eh(Widget widget, XtPointer clientdata, XEvent *event, Boolean *d)
{
    Widget clip,scroll,container;
    Dimension width, height, ch;

    clip = widget;
    scroll = XtParent(widget);
    XtVaGetValues(scroll,XmNworkWindow,&container,NULL);

    XtVaGetValues(clip,
              XtNwidth,  &width,
              XtNheight, &height,
              NULL);
    XtVaGetValues(container,
              XtNheight, &ch,
              NULL);
    if (ch < height-5)
      ch = height-5;
    XtVaSetValues(container,
              XtNwidth, width-5,
              XtNheight,ch,
              NULL);
    container_relayout(container);
}

void
container_spatial_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
{
    Widget container = clientdata;
    WidgetList children;
    Cardinal nchildren;

    XtVaSetValues(container,
              XmNlayoutType,    XmSPATIAL,
              XmNspatialStyle,  XmNONE,
              NULL);
    nchildren = XmContainerGetItemChildren(container,NULL,&children);
    if (nchildren) {
      XtFree((XtPointer)children);
      /* FIXME: Hmm, why ??? */
      XtVaSetValues(container,
                  XmNentryViewType, XmLARGE_ICON,
                  NULL);
    }
    container_relayout(container);
}

void container_detail_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
{
    Widget container = clientdata;

    XtVaSetValues(container,
              XmNlayoutType,    XmDETAIL,
              XmNentryViewType, XmSMALL_ICON,
              NULL);
    container_relayout(container);
}

void
container_traverse_cb(Widget scroll, XtPointer clientdata, XtPointer call_data)
{
    XmTraverseObscuredCallbackStruct *cd = call_data;

    if (cd->reason == XmCR_OBSCURED_TRAVERSAL)
      XmScrollVisible(scroll, cd->traversal_destination, 25, 25);
}

void
container_convert_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
{
    XmConvertCallbackStruct *ccs = call_data;
    char *file = NULL;
    Atom *targs;
    int i,n,len;
    WidgetList children;
    Cardinal nchildren;

    if (ccs->location_data) {
      Widget item = ccs->location_data;
      children  = &item;
      nchildren = 1;
    } else {
      XtVaGetValues(widget,
                  XmNselectedObjects,&children,
                  XmNselectedObjectCount,&nchildren,
                  NULL);
    }

    if (debug) {
      char *t = !ccs->target    ? NULL : XGetAtomName(dpy,ccs->target);
      char *s = !ccs->selection ? NULL : XGetAtomName(dpy,ccs->selection);
      fprintf(stderr,"drag: target=%s selection=%s [%d files,%p]\n",
            t, s, nchildren, ccs->location_data);
      if (t) XFree(t);
      if (s) XFree(s);
    }

    if ((ccs->target == XA_TARGETS)                        ||
      (ccs->target == _MOTIF_CLIPBOARD_TARGETS)          ||
      (ccs->target == _MOTIF_EXPORT_TARGETS)) {
      targs = (Atom*)XtMalloc(sizeof(Atom)*8);
      n = 0;
      if (nchildren >= 1) {
          targs[n++] = MIME_TEXT_URI_LIST;
      }
      if (1 == nchildren) {
          targs[n++] = XA_FILE_NAME;
          targs[n++] = XA_FILE;
          targs[n++] = _NETSCAPE_URL;
          targs[n++] = XA_STRING;
      }
      ccs->value  = targs;
      ccs->length = n;
      ccs->type   = XA_ATOM;
      ccs->format = 32;
      ccs->status = XmCONVERT_MERGE;
      return;
    }

    if (ccs->target == _MOTIF_DEFERRED_CLIPBOARD_TARGETS) {
      targs = (Atom*)XtMalloc(sizeof(Atom)*8);
      n = 0;
      ccs->value  = targs;
      ccs->length = n;
      ccs->type   = XA_ATOM;
      ccs->format = 32;
      ccs->status = XmCONVERT_DONE;
    }

    if ((ccs->target == _MOTIF_LOSE_SELECTION) ||
      (ccs->target == XA_DONE)) {
      /* free stuff */
      ccs->value  = NULL;
      ccs->length = 0;
      ccs->type   = XA_INTEGER;
      ccs->format = 32;
      ccs->status = XmCONVERT_DONE;
      return;
    }

    if (ccs->target == XA_FILE_NAME ||
      ccs->target == XA_FILE      ||
      ccs->target == XA_STRING) {
      file = XtMalloc(strlen(XtName(children[0])+1));
      strcpy(file,XtName(children[0]));
      ccs->value  = file;
      ccs->length = strlen(file);
      ccs->type   = XA_STRING;
      ccs->format = 8;
      ccs->status = XmCONVERT_DONE;
      return;
    }

    if (ccs->target == _NETSCAPE_URL ||
      ccs->target == MIME_TEXT_URI_LIST) {
      for (i = 0, len = 0; i < nchildren; i++)
          len += strlen(XtName(children[i]));
      file = XtMalloc(len + 8 * nchildren);
      for (i = 0, len = 0; i < nchildren; i++)
          len += sprintf(file+len,"file:%s\n",XtName(children[i]));
      ccs->value  = file;
      ccs->length = len;
      ccs->type   = XA_STRING;
      ccs->format = 8;
      ccs->status = XmCONVERT_DONE;
      return;
    }

    ccs->status = XmCONVERT_DEFAULT;
}

static void
container_copy_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
{
    Widget container = clientdata;
    XmeClipboardSource(container,XmCOPY,XtLastTimestampProcessed(dpy));
}

static void
container_paste_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
{
    Widget container = clientdata;
    XmeClipboardSink(container,XmCOPY,NULL);
}

static void
container_del_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
{
    Widget container = clientdata;
    WidgetList children,list;
    Cardinal nchildren,i;

    XtVaGetValues(container,
              XmNselectedObjects,&children,
              XmNselectedObjectCount,&nchildren,
              NULL);
    list = malloc(sizeof(Widget*)*nchildren);
    memcpy(list,children,sizeof(Widget*)*nchildren);

    XtVaSetValues(container,
              XmNselectedObjectCount,0,
              NULL);
    XtUnmanageChildren(list,nchildren);
    for (i = 0; i < nchildren; i++)
        XtDestroyWidget(list[i]);
    free(list);
}

void container_menu_edit(Widget menu, Widget container,
                   int cut, int copy, int paste, int del)
{
    Widget push;

#if 0
    if (cut) {
      push = XtVaCreateManagedWidget("cut",xmPushButtonWidgetClass,menu,NULL);
      XtAddCallback(push,XmNactivateCallback,
                  container_cut_cb,container);
    }
#endif
    if (copy) {
      push = XtVaCreateManagedWidget("copy",xmPushButtonWidgetClass,menu,NULL);
      XtAddCallback(push,XmNactivateCallback,
                  container_copy_cb,container);
    }
    if (paste) {
      push = XtVaCreateManagedWidget("paste",xmPushButtonWidgetClass,menu,NULL);
      XtAddCallback(push,XmNactivateCallback,
                  container_paste_cb,container);
    }
    if (del) {
      push = XtVaCreateManagedWidget("del",xmPushButtonWidgetClass,menu,NULL);
      XtAddCallback(push,XmNactivateCallback,
                  container_del_cb,container);
    }
}

void container_menu_view(Widget menu, Widget container)
{
    Widget push;
    
    push = XtVaCreateManagedWidget("details",xmPushButtonWidgetClass,menu,NULL);
    XtAddCallback(push,XmNactivateCallback,
              container_detail_cb,container);
    push = XtVaCreateManagedWidget("spatial",xmPushButtonWidgetClass,menu,NULL);
    XtAddCallback(push,XmNactivateCallback,
              container_spatial_cb,container);
}

void
container_relayout(Widget container)
{
    Widget clip = XtParent(container);
    WidgetList children;
    Cardinal nchildren;
    Dimension wwidth,wheight;
    Dimension iwidth,iheight;
    Position x,y;
    unsigned char layout,style;
    int i,margin = 10;

    XtVaGetValues(container,
              XmNlayoutType,   &layout,
              XmNspatialStyle, &style,
              NULL);
    if (XmSPATIAL != layout || XmNONE != style) {
      XmContainerRelayout(container);
      return;
    }

    nchildren = XmContainerGetItemChildren(container,NULL,&children);
    XtVaGetValues(clip,
              XtNwidth,  &wwidth,
              XtNheight, &wheight,
              NULL);

    wwidth -= 5;
    x = margin; y = margin;
    for (i = 0; i < nchildren; i++) {
      if (!XtIsManaged(children[i]))
          continue;
      XtVaGetValues(children[i],
                  XtNwidth,&iwidth,
                  XtNheight,&iheight,
                  NULL);
      if (x > 0 && x + iwidth + margin > wwidth) {
          /* new row */
          x = margin; y += iheight + margin;
      }
      XtVaSetValues(children[i],
                  XtNx,x, XtNy,y,
                  XmNpositionIndex,i,
                  NULL);
      x += iwidth + margin;
    }

    if (wheight < y + iheight + margin)
      wheight = y + iheight + margin;
    XtVaSetValues(container,
              XtNwidth,  wwidth,
              XtNheight, wheight,
              NULL);
    if (nchildren)
      XtFree((XtPointer)children);
}

void
container_delwidgets(Widget container)
{
    WidgetList children;
    Cardinal nchildren;
    unsigned int i;

    /* delete widgets */
    XtVaSetValues(container,
              XmNselectedObjectCount,0,
              NULL);
    nchildren = XmContainerGetItemChildren(container,NULL,&children);
    XtUnmanageChildren(children,nchildren);
    for (i = 0; i < nchildren; i++)
        XtDestroyWidget(children[i]);
    if (nchildren)
      XtFree((XtPointer)children);
}

/*----------------------------------------------------------------------*/

void file_set_icon(struct file_button *file, Pixmap s, Pixmap l)
{
    Pixmap large, small;
    Pixel background;

    if (file->info)
      return;

    XtVaGetValues(file->widget, XmNbackground,&background, NULL);
    small = x11_icon_fit(DisplayOfScreen(file->screen), s, background,
                   GET_ICON_SMALL(), GET_ICON_SMALL());
    large = x11_icon_fit(DisplayOfScreen(file->screen), l, background,
                   GET_ICON_LARGE(), GET_ICON_LARGE());
    XtVaSetValues(file->widget,
              XmNsmallIconPixmap, small,
              XmNlargeIconPixmap, large,
              NULL);
    if (file->small)
      XFreePixmap(DisplayOfScreen(file->screen),file->small);
    if (file->large)
      XFreePixmap(DisplayOfScreen(file->screen),file->large);
    file->small = small;
    file->large = large;
}

void file_set_info(struct file_button *file, struct fileinfo *info)
{
    file->info = NULL;
    file_set_icon(file,info->small,info->large);
    file->info = info;
    fileinfo_details(file);
}

#if 0
static void
file_copy_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
{
    struct file_button *file = clientdata;

    XmeClipboardSource(file->widget,XmCOPY,XtLastTimestampProcessed(dpy));
}
#endif

/*----------------------------------------------------------------------*/

int file_cmp_alpha(const struct file_button *aa,
               const struct file_button *bb)
{
    if (S_ISDIR(aa->st.st_mode) != S_ISDIR(bb->st.st_mode))
      return S_ISDIR(aa->st.st_mode) ? -1 : 1;
    return strcmp(aa->basename,bb->basename);
}

static void
file_destroy_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
{
    struct file_button *file = clientdata;
    int i;

    if (debug)
      fprintf(stderr,"file: del %p [%s]\n",file,file->filename);

    if (NULL != file->queue.next)
      fileinfo_cleanup(file);
    
    if (file->basename)
      free(file->basename);
    if (file->filename)
      free(file->filename);

    XtVaSetValues(file->widget,
              XmNsmallIconPixmap, XmUNSPECIFIED_PIXMAP,
              XmNlargeIconPixmap, XmUNSPECIFIED_PIXMAP,
              NULL);
    if (file->small)
      XFreePixmap(DisplayOfScreen(file->screen),file->small);
    if (file->large)
      XFreePixmap(DisplayOfScreen(file->screen),file->large);

    if (file->label)
      XmStringFree(file->label);
    for (i = 0; i < DETAIL_COUNT; i++)
      if (file->details[i])
          XmStringFree(file->details[i]);

    list_del(&file->global);
    list_del(&file->window);
    free(file);
}

int file_createwidgets(Widget parent, struct file_button *file)
{
    struct fileinfo *info;
    Pixmap pix;
    Arg args[8];
    int i, n = 0;

    if (debug)
      fprintf(stderr,"file: new %p [%s]\n",file,file->filename);

    file->screen = XtScreen(parent);
    file->label  = XmStringGenerate(file->basename, NULL, XmMULTIBYTE_TEXT,NULL);
    for (i = 0; i < DETAIL_COUNT; i++)
      file->details[i] = XmStringGenerate("-", NULL, XmMULTIBYTE_TEXT,NULL);

    XtSetArg(args[n], XmNlabelString,     file->label);   n++;
    XtSetArg(args[n], XmNdetail,          file->details); n++;
    XtSetArg(args[n], XmNdetailCount,     DETAIL_COUNT);  n++;
    file->widget = XmCreateIconGadget(parent,file->filename,args,n);
    XtAddCallback(file->widget,XtNdestroyCallback,file_destroy_cb,file);
    list_add_tail(&file->global,&files);

    info = fileinfo_cache_get(file->filename);
    if (info) {
      file_set_info(file,info);
    } else {
      pix = XmGetPixmap(file->screen,"question",0,0);
      file_set_icon(file,pix,pix);
    }
    return 0;
}

Generated by  Doxygen 1.6.0   Back to index