#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "RegEdit.h" #include "ida.h" #include "x11.h" #include "man.h" #include "readers.h" #include "writers.h" #include "viewer.h" #include "op.h" #include "lut.h" #include "filter.h" #include "color.h" #include "icons.h" #include "browser.h" #include "filelist.h" #include "xdnd.h" #include "selections.h" #include "sane.h" #include "curl.h" #include "idaconfig.h" /* ---------------------------------------------------------------------- */ static void popup_ac(Widget, XEvent*, String*, Cardinal*); static void exit_ac(Widget, XEvent*, String*, Cardinal*); static void next_ac(Widget, XEvent*, String*, Cardinal*); static void prev_ac(Widget, XEvent*, String*, Cardinal*); static void next_page_ac(Widget, XEvent*, String*, Cardinal*); static void prev_page_ac(Widget, XEvent*, String*, Cardinal*); static void zoom_ac(Widget, XEvent*, String*, Cardinal*); static void scroll_ac(Widget, XEvent*, String*, Cardinal*); static void debug_ac(Widget, XEvent*, String*, Cardinal*); static void load_ac(Widget, XEvent*, String*, Cardinal*); static void save_ac(Widget, XEvent*, String*, Cardinal*); static void scan_ac(Widget, XEvent*, String*, Cardinal*); static void print_ac(Widget, XEvent*, String*, Cardinal*); static void undo_ac(Widget, XEvent*, String*, Cardinal*); static void filter_ac(Widget, XEvent*, String*, Cardinal*); static void gamma_ac(Widget, XEvent*, String*, Cardinal*); static void bright_ac(Widget, XEvent*, String*, Cardinal*); static void contrast_ac(Widget, XEvent*, String*, Cardinal*); static void color_ac(Widget, XEvent*, String*, Cardinal*); static void f3x3_ac(Widget, XEvent*, String*, Cardinal*); static void resize_ac(Widget, XEvent*, String*, Cardinal*); static void rotate_ac(Widget, XEvent*, String*, Cardinal*); static void sharpe_ac(Widget, XEvent*, String*, Cardinal*); static XtActionsRec actionTable[] = { { "Exit", exit_ac }, { "Next", next_ac }, { "Prev", prev_ac }, { "NextPage", next_page_ac }, { "PrevPage", prev_page_ac }, { "Zoom", zoom_ac }, { "Scroll", scroll_ac }, { "Debug", debug_ac }, { "Popup", popup_ac }, { "Man", man_action }, { "Load", load_ac }, { "Save", save_ac }, { "Scan", scan_ac }, { "Print", print_ac }, { "Browser", browser_ac }, { "Filelist", filelist_ac }, { "Undo", undo_ac }, { "Filter", filter_ac }, { "Gamma", gamma_ac }, { "Bright", bright_ac }, { "Contrast", contrast_ac }, { "Color", color_ac }, { "F3x3", f3x3_ac }, { "Resize", resize_ac }, { "Rotate", rotate_ac }, { "Sharpe", sharpe_ac }, { "Ipc", ipc_ac }, { "Xdnd", XdndAction }, }; /* ---------------------------------------------------------------------- */ XtAppContext app_context; Display *dpy; Widget app_shell; int gray=0; char *binary; struct ida_viewer *ida; /* ---------------------------------------------------------------------- */ struct ARGS args; unsigned int pcd_res; unsigned int sane_res; XtResource args_desc[] = { { "debug", XtCBoolean, XtRBoolean, sizeof(Boolean), XtOffset(struct ARGS*,debug), XtRString, "false" },{ "help", XtCBoolean, XtRBoolean, sizeof(Boolean), XtOffset(struct ARGS*,help), XtRString, "false" },{ "testload", XtCBoolean, XtRBoolean, sizeof(Boolean), XtOffset(struct ARGS*,testload), XtRString, "false" } }; const int args_count = XtNumber(args_desc); XrmOptionDescRec opt_desc[] = { { "-d", "debug", XrmoptionNoArg, "true" }, { "-debug", "debug", XrmoptionNoArg, "true" }, { "-testload", "testload", XrmoptionNoArg, "true" }, { "-h", "help", XrmoptionNoArg, "true" }, { "-help", "help", XrmoptionNoArg, "true" }, { "--help", "help", XrmoptionNoArg, "true" }, }; const int opt_count = (sizeof(opt_desc)/sizeof(XrmOptionDescRec)); static String fallback_ressources[] = { #include "Ida.ad.h" NULL }; /* ---------------------------------------------------------------------- */ static struct ida_writer *cwriter; static char *save_filename; static char *print_command; static Widget control_shell,status; static Atom wm_delete_window; static Widget view,loadbox,savebox,printbox; /* file list */ static Widget wlist; static char **files = NULL; static int cfile = -1; static int nfiles = 0; static int cpage = 0; static int npages = 1; /* filter controls */ static int gamma_val = 100; static int bright_val = 0; static int contrast_val = 0; static int rotate_val = 0; static int sharpe_val = 10; static struct MY_TOPLEVELS { char *name; Widget *shell; int mapped; } my_toplevels [] = { { "control", &control_shell }, }; #define TOPLEVELS (sizeof(my_toplevels)/sizeof(struct MY_TOPLEVELS)) /* ---------------------------------------------------------------------- */ static void popup_ac(Widget widget, XEvent *event, String *params, Cardinal *num_params) { unsigned int i; /* which window we are talking about ? */ if (*num_params > 0) { for (i = 0; i < TOPLEVELS; i++) { if (0 == strcasecmp(my_toplevels[i].name,params[0])) break; } if (i == TOPLEVELS) { fprintf(stderr,"PopupAction: oops: shell not found (name=%s)\n", params[0]); return; } } else { for (i = 0; i < TOPLEVELS; i++) { if (*(my_toplevels[i].shell) == widget) break; } if (i == TOPLEVELS) { fprintf(stderr,"PopupAction: oops: shell not found (%p:%s)\n", widget,XtName(widget)); return; } } /* popup/down window */ if (!my_toplevels[i].mapped) { XtPopup(*(my_toplevels[i].shell), XtGrabNone); my_toplevels[i].mapped = 1; } else { XtPopdown(*(my_toplevels[i].shell)); my_toplevels[i].mapped = 0; } } static void popupdown_cb(Widget widget, XtPointer clientdata, XtPointer call_data) { int i = 0; popup_ac(clientdata, NULL, NULL, &i); } /* ---------------------------------------------------------------------- */ void destroy_cb(Widget widget, XtPointer clientdata, XtPointer call_data) { XtDestroyWidget(clientdata); } void action_cb(Widget widget, XtPointer clientdata, XtPointer call_data) { char *calls, *action, *argv[16]; /* max: F3x3(9 args) */ int argc; calls = strdup(clientdata); action = strtok(calls,"(),"); for (argc = 0; NULL != (argv[argc] = strtok(NULL,"(),")); argc++) /* nothing */; XtCallActionProc(widget,action,NULL,argv,argc); free(calls); } static void about_cb(Widget widget, XtPointer clientdata, XtPointer call_data) { Widget msgbox; msgbox = XmCreateInformationDialog(app_shell,"aboutbox",NULL,0); XtUnmanageChild(XmMessageBoxGetChild(msgbox,XmDIALOG_HELP_BUTTON)); XtUnmanageChild(XmMessageBoxGetChild(msgbox,XmDIALOG_CANCEL_BUTTON)); XtAddCallback(msgbox,XmNokCallback,destroy_cb,msgbox); XtManageChild(msgbox); } #if 0 static void sorry_cb(Widget widget, XtPointer clientdata, XtPointer call_data) { Widget msgbox; msgbox = XmCreateErrorDialog(app_shell,"sorrybox",NULL,0); XtUnmanageChild(XmMessageBoxGetChild(msgbox,XmDIALOG_HELP_BUTTON)); XtUnmanageChild(XmMessageBoxGetChild(msgbox,XmDIALOG_CANCEL_BUTTON)); XtAddCallback(msgbox,XmNokCallback,destroy_cb,msgbox); XtManageChild(msgbox); } #endif void debug_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { unsigned int i; fprintf(stderr,"Debug:"); for (i = 0; i < *num; i++) fprintf(stderr," %s",params[i]); fprintf(stderr,"\n"); } static void display_cb(Widget widget, XtPointer clientdata, XtPointer call_data) { XmDisplayCallbackStruct *arg = call_data; switch (arg->reason) { case XmCR_NO_RENDITION: fprintf(stderr,"display_cb: no rendition: \"%s\"\n",arg->tag); break; case XmCR_NO_FONT: fprintf(stderr,"display_cb: no font: \"%s\"\n",arg->font_name); break; default: /* should not happen */ fprintf(stderr,"display_cb: unknown reason [%d]\n",arg->reason); break; } } /* ---------------------------------------------------------------------- */ struct ptr_list { struct ptr_list *next; Widget widget; }; struct ptr_list *ptr_head; void ptr_register(Widget widget) { struct ptr_list *item; if (XtWindow(widget)) XDefineCursor(XtDisplay(widget), XtWindow(widget), ptrs[POINTER_NORMAL]); item = malloc(sizeof(*item)); memset(item,0,sizeof(*item)); item->widget = widget; item->next = ptr_head; ptr_head = item; } void ptr_unregister(Widget widget) { struct ptr_list *item,*fitem; if (ptr_head->widget == widget) { fitem = ptr_head; ptr_head = ptr_head->next; free(fitem); return; } for (item = ptr_head; NULL != item->next; item = item->next) { if (item->next->widget == widget) { fitem = item->next; item->next = fitem->next; free(fitem); return; } } /* shouldn't happen */ fprintf(stderr,"Oops: widget not found in list\n"); } void ptr_busy(void) { struct ptr_list *item; for (item = ptr_head; NULL != item; item = item->next) { if (!XtWindow(item->widget)) continue; XDefineCursor(XtDisplay(item->widget), XtWindow(item->widget), ptrs[POINTER_BUSY]); } XSync(dpy,False); } void ptr_idle(void) { struct ptr_list *item; for (item = ptr_head; NULL != item; item = item->next) { if (!XtWindow(item->widget)) continue; XDefineCursor(XtDisplay(item->widget), XtWindow(item->widget), ptrs[POINTER_NORMAL]); } } /* ---------------------------------------------------------------------- */ static Boolean exit_wp(XtPointer client_data) { exit(0); } static void exit_cb(Widget widget, XtPointer client_data, XtPointer calldata) { XtAppAddWorkProc(app_context,exit_wp, NULL); XtDestroyWidget(app_shell); } void exit_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { exit_cb(widget,NULL,NULL); } /* ---------------------------------------------------------------------- */ static void list_update(void) { XmStringTable tab; int i; tab = malloc(nfiles * sizeof(XmString)); for (i = 0; i < nfiles; i++) tab[i] = XmStringGenerate(files[i], NULL, XmMULTIBYTE_TEXT, NULL); XtVaSetValues(wlist, XmNitems, tab, XmNitemCount, nfiles, NULL); for (i = 0; i < nfiles; i++) XmStringFree(tab[i]); free(tab); } static int list_append(char *filename) { int i; for (i = 0; i < nfiles; i++) if (0 == strcmp(files[i],filename)) return i; files = realloc(files,sizeof(char*)*(nfiles+1)); files[nfiles] = strdup(filename); nfiles++; return nfiles-1; } static void list_cb(Widget widget, XtPointer client_data, XtPointer calldata) { XmListCallbackStruct *list = calldata; if (0 == list->selected_item_count) return; cfile = list->selected_item_positions[0]-1; cpage = 0; npages = viewer_loadimage(ida,files[cfile],cpage); if (-1 == npages) return; resize_shell(); } static void pcd_set(Widget widget) { WidgetList items; Cardinal nitems; unsigned int i; int value; value = GET_PHOTOCD_RES(); XtVaGetValues(widget,XtNchildren,&items, XtNnumChildren,&nitems,NULL); for (i = 0; i < nitems; i++) XmToggleButtonSetState(items[i],value == i+1,False); pcd_res = value; } static void pcd_cb(Widget widget, XtPointer client_data, XtPointer calldata) { cfg_set_int(O_PHOTOCD_RES,(intptr_t)client_data); pcd_set(XtParent(widget)); } static void cfg_bool_cb(Widget widget, XtPointer client_data, XtPointer calldata) { char *option = XtName(widget); Boolean value = XmToggleButtonGetState(widget); cfg_set_bool(O_OPTIONS, option, value); } static void cfg_save_cb(Widget widget, XtPointer client_data, XtPointer calldata) { ida_write_config(); } static void create_control(void) { Widget form,menubar,tool,menu,smenu,push; control_shell = XtVaAppCreateShell("ctrl","Iv", topLevelShellWidgetClass, dpy, XtNclientLeader,app_shell, XmNdeleteResponse,XmDO_NOTHING, NULL); XmdRegisterEditres(control_shell); XmAddWMProtocolCallback(control_shell,wm_delete_window, popupdown_cb,control_shell); /* widgets */ form = XtVaCreateManagedWidget("form", xmFormWidgetClass, control_shell, NULL); menubar = XmCreateMenuBar(form,"bar",NULL,0); XtManageChild(menubar); tool = XtVaCreateManagedWidget("tool",xmRowColumnWidgetClass, form, NULL); status = XtVaCreateManagedWidget("status", xmLabelWidgetClass, form, NULL); wlist = XmCreateScrolledList(form,"list",NULL,0); XtManageChild(wlist); XtAddCallback(wlist,XmNdefaultActionCallback,list_cb,NULL); XtAddCallback(wlist,XmNdestinationCallback,selection_dest,NULL); dnd_add(wlist); /* menu - file */ menu = XmCreatePulldownMenu(menubar,"fileM",NULL,0); XtVaCreateManagedWidget("file",xmCascadeButtonWidgetClass,menubar, XmNsubMenuId,menu,NULL); push = XtVaCreateManagedWidget("load",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Load()"); push = XtVaCreateManagedWidget("save",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Save()"); push = XtVaCreateManagedWidget("browse",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Browser()"); push = XtVaCreateManagedWidget("filelist",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Filelist()"); XtVaCreateManagedWidget("sep",xmSeparatorWidgetClass,menu,NULL); #ifdef HAVE_LIBSANE sane_menu(menu); #endif push = XtVaCreateManagedWidget("print",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Print()"); XtVaCreateManagedWidget("sep",xmSeparatorWidgetClass,menu,NULL); push = XtVaCreateManagedWidget("quit",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,exit_cb,NULL); /* menu - edit */ menu = XmCreatePulldownMenu(menubar,"editM",NULL,0); XtVaCreateManagedWidget("edit",xmCascadeButtonWidgetClass,menubar, XmNsubMenuId,menu,NULL); push = XtVaCreateManagedWidget("undo",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Undo()"); XtVaCreateManagedWidget("sep",xmSeparatorWidgetClass,menu,NULL); push = XtVaCreateManagedWidget("copy",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Ipc(copy)"); push = XtVaCreateManagedWidget("paste",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Ipc(paste)"); XtVaCreateManagedWidget("sep",xmSeparatorWidgetClass,menu,NULL); push = XtVaCreateManagedWidget("flipv",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Filter(flip-vert)"); push = XtVaCreateManagedWidget("fliph",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Filter(flip-horz)"); push = XtVaCreateManagedWidget("rotcw",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Filter(rotate-cw)"); push = XtVaCreateManagedWidget("rotccw",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Filter(rotate-ccw)"); push = XtVaCreateManagedWidget("invert",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Filter(invert)"); XtVaCreateManagedWidget("sep",xmSeparatorWidgetClass,menu,NULL); push = XtVaCreateManagedWidget("crop",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Filter(crop)"); push = XtVaCreateManagedWidget("acrop",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Filter(autocrop)"); push = XtVaCreateManagedWidget("scale",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Resize()"); push = XtVaCreateManagedWidget("rotany",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Rotate()"); /* menu - filters / operations */ menu = XmCreatePulldownMenu(menubar,"opM",NULL,0); XtVaCreateManagedWidget("op",xmCascadeButtonWidgetClass,menubar, XmNsubMenuId,menu,NULL); push = XtVaCreateManagedWidget("gamma",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Gamma()"); push = XtVaCreateManagedWidget("bright",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Bright()"); push = XtVaCreateManagedWidget("contr",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Contrast()"); push = XtVaCreateManagedWidget("color",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Color()"); push = XtVaCreateManagedWidget("gray",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Filter(grayscale)"); XtVaCreateManagedWidget("sep",xmSeparatorWidgetClass,menu,NULL); push = XtVaCreateManagedWidget("blur",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb, "F3x3(1,1,1, 1,1,1, 1,1,1, 1,9,0)"); push = XtVaCreateManagedWidget("sharpe",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Sharpe()"); push = XtVaCreateManagedWidget("edge",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb, "F3x3(-1,-1,-1, -1,8,-1, -1,-1,-1)"); push = XtVaCreateManagedWidget("emboss",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb, "F3x3(1,0,0, 0,0,0, 0,0,-1, 0,0,128)"); /* menu - view */ menu = XmCreatePulldownMenu(menubar,"viewM",NULL,0); XtVaCreateManagedWidget("view",xmCascadeButtonWidgetClass,menubar, XmNsubMenuId,menu,NULL); push = XtVaCreateManagedWidget("prev",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Prev()"); push = XtVaCreateManagedWidget("next",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Next()"); XtVaCreateManagedWidget("sep",xmSeparatorWidgetClass,menu,NULL); push = XtVaCreateManagedWidget("prevpage",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"PrevPage()"); push = XtVaCreateManagedWidget("nextpage",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"NextPage()"); XtVaCreateManagedWidget("sep",xmSeparatorWidgetClass,menu,NULL); push = XtVaCreateManagedWidget("zoomin",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Zoom(inc)"); push = XtVaCreateManagedWidget("zoomout",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Zoom(dec)"); /* menu - options */ menu = XmCreatePulldownMenu(menubar,"optM",NULL,0); push = XtVaCreateManagedWidget("opt",xmCascadeButtonWidgetClass,menubar, XmNsubMenuId,menu,NULL); smenu = XmCreatePulldownMenu(menu,"pcdM",NULL,0); XtVaCreateManagedWidget("pcd",xmCascadeButtonWidgetClass,menu, XmNsubMenuId,smenu,NULL); push = XtVaCreateManagedWidget("1",xmToggleButtonWidgetClass,smenu,NULL); XtAddCallback(push,XmNvalueChangedCallback,pcd_cb,(XtPointer)1); push = XtVaCreateManagedWidget("2",xmToggleButtonWidgetClass,smenu,NULL); XtAddCallback(push,XmNvalueChangedCallback,pcd_cb,(XtPointer)2); push = XtVaCreateManagedWidget("3",xmToggleButtonWidgetClass,smenu,NULL); XtAddCallback(push,XmNvalueChangedCallback,pcd_cb,(XtPointer)3); push = XtVaCreateManagedWidget("4",xmToggleButtonWidgetClass,smenu,NULL); XtAddCallback(push,XmNvalueChangedCallback,pcd_cb,(XtPointer)4); push = XtVaCreateManagedWidget("5",xmToggleButtonWidgetClass,smenu,NULL); XtAddCallback(push,XmNvalueChangedCallback,pcd_cb,(XtPointer)5); pcd_set(smenu); push = XtVaCreateManagedWidget("autozoom",xmToggleButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNvalueChangedCallback,cfg_bool_cb,NULL); XmToggleButtonSetState(push,GET_AUTOZOOM(),False); XtVaCreateManagedWidget("sep",xmSeparatorWidgetClass,menu,NULL); push = XtVaCreateManagedWidget("cfgsave",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,cfg_save_cb,NULL); /* menu - help */ menu = XmCreatePulldownMenu(menubar,"helpM",NULL,0); push = XtVaCreateManagedWidget("help",xmCascadeButtonWidgetClass,menubar, XmNsubMenuId,menu,NULL); XtVaSetValues(menubar,XmNmenuHelpWidget,push,NULL); push = XtVaCreateManagedWidget("man",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Man(ida)"); XtVaCreateManagedWidget("sep",xmSeparatorWidgetClass,menu,NULL); push = XtVaCreateManagedWidget("about",xmPushButtonWidgetClass,menu,NULL); XtAddCallback(push,XmNactivateCallback,about_cb,NULL); /* toolbar */ push = XtVaCreateManagedWidget("prev",xmPushButtonWidgetClass,tool,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Prev()"); push = XtVaCreateManagedWidget("next",xmPushButtonWidgetClass,tool,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Next()"); push = XtVaCreateManagedWidget("zoomin",xmPushButtonWidgetClass,tool,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Zoom(inc)"); push = XtVaCreateManagedWidget("zoomout",xmPushButtonWidgetClass,tool,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Zoom(dec)"); XtVaCreateManagedWidget("sep",xmSeparatorWidgetClass,tool,NULL); push = XtVaCreateManagedWidget("flipv",xmPushButtonWidgetClass,tool,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Filter(flip-vert)"); push = XtVaCreateManagedWidget("fliph",xmPushButtonWidgetClass,tool,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Filter(flip-horz)"); push = XtVaCreateManagedWidget("rotccw",xmPushButtonWidgetClass,tool,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Filter(rotate-ccw)"); push = XtVaCreateManagedWidget("rotcw",xmPushButtonWidgetClass,tool,NULL); XtAddCallback(push,XmNactivateCallback,action_cb,"Filter(rotate-cw)"); XtVaCreateManagedWidget("sep",xmSeparatorWidgetClass,tool,NULL); push = XtVaCreateManagedWidget("exit",xmPushButtonWidgetClass,tool,NULL); XtAddCallback(push,XmNactivateCallback,exit_cb,NULL); } /* ---------------------------------------------------------------------- */ void resize_shell(void) { char *title,*base; Dimension x,y,w,h,sw,sh; XmString str; int len; XtVaGetValues(app_shell, XtNx,&x, XtNy,&y, NULL); /* resize shell + move shell size: image size + 2*shadowThickness */ w = ida->scrwidth+2; h = ida->scrheight+2; sw = XtScreen(ida->widget)->width; sh = XtScreen(ida->widget)->height; if (w > sw) w = sw; if (h > sh) h = sh; if (x+w > sw) x = sw-w; if (y+h > sh) y = sh-h; base = strrchr(ida->file,'/'); if (base) base++; else base = ida->file; title = malloc(strlen(base)+128); len = sprintf(title,"%s (%dx%d", base, ida->img.i.width, ida->img.i.height); if (ida->img.i.dpi) len += sprintf(title+len," | %d dpi", ida->img.i.dpi); if (ida->img.i.npages > 1) len += sprintf(title+len," | page %d/%d", cpage+1, ida->img.i.npages); len += sprintf(title+len," | %d%%)", viewer_i2s(ida->zoom,100)); XtVaSetValues(app_shell, XtNtitle,title, /* XtNx,x, XtNy,y, */ XtNwidth,w, XtNheight,h, NULL); str = XmStringGenerate(title,NULL,XmMULTIBYTE_TEXT,NULL); XtVaSetValues(status,XmNlabelString,str,NULL); XmStringFree(str); free(title); } static int load_file(int nr, int np) { if(nr < 0 || nr >= nfiles) return -1; npages = viewer_loadimage(ida,files[nr],np); if (-1 == npages) return -1; resize_shell(); #if 0 XmListSelectPos(wlist,nr+1,False); cfile = nr; #endif return npages; } char* load_tmpfile(char *base) { char *tmpdir; char *filename; tmpdir = getenv("TMPDIR"); if (NULL == tmpdir) tmpdir="/tmp"; filename = malloc(strlen(tmpdir)+strlen(base)+16); sprintf(filename,"%s/%s-XXXXXX",tmpdir,base); return filename; } static void load_logo(void) { static unsigned char logo[] = { #include "logo.h" }; char *filename = load_tmpfile("ida-logo"); int fd; fd = mkstemp(filename); write(fd,logo,sizeof(logo)); close(fd); cpage = 0; npages = 1; if (0 < viewer_loadimage(ida,filename,cpage)) { ida->file = "ida " VERSION; resize_shell(); } unlink(filename); free(filename); } static void load_stdin(void) { char *filename = load_tmpfile("ida-stdin"); char buf[4096]; int rc,fd; fd = mkstemp(filename); for (;;) { rc = read(0,buf,sizeof(buf)); if (rc <= 0) break; write(fd,buf,rc); } close(fd); cpage = 0; npages = 1; if (0 < viewer_loadimage(ida,filename,cpage)) { ida->file = "stdin"; resize_shell(); } unlink(filename); free(filename); } void next_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { for (;;) { if (cfile >= nfiles-1) return; cfile++; cpage = 0; if (0 <= load_file(cfile,cpage)) break; } } void prev_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { for (;;) { if (cfile < 1) return; cfile--; cpage = 0; if (0 <= load_file(cfile,cpage)) break; } } void next_page_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { for (;;) { if (cpage >= npages-1) return; cpage++; if (0 <= load_file(cfile,cpage)) break; } } void prev_page_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { for (;;) { if (cpage <= 0) return; cpage--; if (0 <= load_file(cfile,cpage)) break; } } void zoom_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { int zoom; if (0 == *num) return; if (0 == strcasecmp(params[0],"auto")) { viewer_autozoom(ida); return; } if (0 == strcasecmp(params[0],"inc")) { zoom = ida->zoom+1; } else if (0 == strcasecmp(params[0],"dec")) { zoom = ida->zoom-1; } else { zoom = atoi(params[0]); } viewer_setzoom(ida,zoom); resize_shell(); } void scroll_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { fprintf(stderr,"Scroll(): %s\n",XtName(widget)); } /* ---------------------------------------------------------------------- */ void new_file(char *name, int complain) { struct stat st; int n; if (curl_is_url(name)) goto load; if (0 == strncasecmp(name,"file:",5)) name += 5; if (-1 == stat(name,&st)) { if (complain) fprintf(stderr,"stat %s: %s\n",name,strerror(errno)); return; } switch (st.st_mode & S_IFMT) { case S_IFDIR: browser_window(name); break; case S_IFREG: goto load; break; } return; load: n = list_append(name); list_update(); cpage = 0; load_file(n,cpage); } static void load_done_cb(Widget widget, XtPointer clientdata, XtPointer call_data) { XmFileSelectionBoxCallbackStruct *cb = call_data; char *line; if (cb->reason == XmCR_OK) { line = XmStringUnparse(cb->value,NULL, XmMULTIBYTE_TEXT,XmMULTIBYTE_TEXT, NULL,0,0); new_file(line,1); } XtUnmanageChild(widget); } void load_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { Widget help; if (NULL == loadbox) { loadbox = XmCreateFileSelectionDialog(app_shell,"load",NULL,0); help = XmFileSelectionBoxGetChild(loadbox,XmDIALOG_HELP_BUTTON); XtUnmanageChild(help); XtAddCallback(loadbox,XmNokCallback,load_done_cb,NULL); XtAddCallback(loadbox,XmNcancelCallback,load_done_cb,NULL); } else { XmFileSelectionDoSearch(loadbox,NULL); } XtManageChild(loadbox); } void scan_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { #ifdef HAVE_LIBSANE cpage = 0; if (*num) npages = viewer_loader_start(ida, &sane_loader, NULL, params[0], 0); else npages = viewer_loader_start(ida, &sane_loader, NULL, "", 0); if (-1 == npages) return; ida->file = "scanned image"; resize_shell(); #endif } /* ---------------------------------------------------------------------- */ void do_save_print(void) { FILE *fp; if (save_filename) { XtUnmanageChild(savebox); ptr_busy(); if (NULL == (fp = fopen(save_filename,"wb"))) { fprintf(stderr,"save: can't open %s: %s\n", save_filename,strerror(errno)); } else if (-1 == cwriter->write(fp,&ida->img)) { fclose(fp); fprintf(stderr,"saving %s FAILED",save_filename); } else { fclose(fp); list_append(save_filename); list_update(); } ptr_idle(); } if (print_command) { XtUnmanageChild(printbox); ptr_busy(); if (NULL == (fp = popen(print_command,"w"))) { fprintf(stderr,"print: can't exec %s: %s\n", print_command,strerror(errno)); } else { if (-1 == cwriter->write(fp,&ida->img)) fprintf(stderr,"printing FAILED"); fclose(fp); } ptr_idle(); } } static void save_done_cb(Widget widget, XtPointer clientdata, XtPointer call_data) { XmFileSelectionBoxCallbackStruct *cb = call_data; if (cb->reason == XmCR_OK) { print_command = NULL; save_filename = XmStringUnparse(cb->value,NULL, XmMULTIBYTE_TEXT,XmMULTIBYTE_TEXT, NULL,0,0); if (cwriter->conf) { cwriter->conf(widget,&ida->img); } else { do_save_print(); } } else { XtUnmanageChild(widget); } } static void save_fmt_cb(Widget widget, XtPointer clientdata, XtPointer call_data) { cwriter = clientdata; } static void save_ext_cb(Widget widget, XtPointer clientdata, XtPointer call_data) { Widget option = clientdata; Widget menu; WidgetList children; Cardinal nchildren; struct ida_writer *wr = NULL; struct list_head *item; char *name,*ext; int i,j,pick; name = XmTextGetString(widget); ext = strrchr(name,'.'); if (NULL == ext) return; if (strchr(ext,'/')) return; ext++; i = 0; pick = -1; list_for_each(item,&writers) { wr = list_entry(item, struct ida_writer, list); for (j = 0; NULL != wr->ext[j]; j++) if (0 == strcasecmp(ext,wr->ext[j])) pick = i; if (-1 != pick) break; i++; } if (-1 == pick) return; XtVaGetValues(option,XmNsubMenuId,&menu,NULL); XtVaGetValues(menu,XtNchildren,&children, XtNnumChildren,&nchildren,NULL); XtVaSetValues(option,XmNmenuHistory,children[pick],NULL); cwriter = wr; } static void save_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { Widget help,menu,option,push,text; Arg args[2]; struct ida_writer *wr = NULL; struct list_head *item; if (NULL == savebox) { savebox = XmCreateFileSelectionDialog(app_shell,"save",NULL,0); help = XmFileSelectionBoxGetChild(savebox,XmDIALOG_HELP_BUTTON); text = XmFileSelectionBoxGetChild(savebox,XmDIALOG_TEXT); XtUnmanageChild(help); menu = XmCreatePulldownMenu(savebox,"formatM",NULL,0); XtSetArg(args[0],XmNsubMenuId,menu); option = XmCreateOptionMenu(savebox,"format",args,1); XtManageChild(option); list_for_each(item,&writers) { wr = list_entry(item, struct ida_writer, list); push = XtVaCreateManagedWidget(wr->label, xmPushButtonWidgetClass,menu, NULL); XtAddCallback(push,XmNactivateCallback,save_fmt_cb,wr); } cwriter = list_entry(writers.next, struct ida_writer, list); XtAddCallback(text,XmNvalueChangedCallback,save_ext_cb,option); XtAddCallback(savebox,XmNokCallback,save_done_cb,NULL); XtAddCallback(savebox,XmNcancelCallback,save_done_cb,NULL); } else { XmFileSelectionDoSearch(savebox,NULL); } XtManageChild(savebox); } /* ---------------------------------------------------------------------- */ static void print_done_cb(Widget widget, XtPointer clientdata, XtPointer call_data) { XmSelectionBoxCallbackStruct *cb = call_data; if (cb->reason == XmCR_OK) { save_filename = NULL; print_command = XmStringUnparse(cb->value,NULL, XmMULTIBYTE_TEXT,XmMULTIBYTE_TEXT, NULL,0,0); cwriter = &ps_writer; cwriter->conf(widget,&ida->img); } else { XtUnmanageChild(widget); } } static void print_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { if (NULL == printbox) { printbox = XmCreatePromptDialog(app_shell,"print",NULL,0); XtUnmanageChild(XmSelectionBoxGetChild(printbox,XmDIALOG_HELP_BUTTON)); XtAddCallback(printbox,XmNokCallback,print_done_cb,NULL); XtAddCallback(printbox,XmNcancelCallback,print_done_cb,NULL); } XtManageChild(printbox); } /* ---------------------------------------------------------------------- */ static struct ida_op *ops[] = { &desc_flip_vert, &desc_flip_horz, &desc_rotate_cw, &desc_rotate_ccw, &desc_invert, &desc_crop, &desc_autocrop, &desc_grayscale, NULL }; void filter_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { struct ida_op *op = NULL; int i; if (*num < 1) return; for (i = 0; NULL != ops[i]; i++) { op = ops[i]; if (0 == strcasecmp(op->name,params[0])) break; } if (NULL == ops[i]) { fprintf(stderr,"Oops: unknown filter: %s\n",params[0]); return; } viewer_start_op(ida,op,NULL); if (ida->op_src.i.width != ida->img.i.width || ida->op_src.i.height != ida->img.i.height) resize_shell(); } void f3x3_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { struct op_3x3_parm p; if (*num < 9) { fprintf(stderr,"F3x3: wrong number of args (%d, need 9)\n",*num); return; } memset(&p,0,sizeof(p)); p.f1[0] = atoi(params[0]); p.f1[1] = atoi(params[1]); p.f1[2] = atoi(params[2]); p.f2[0] = atoi(params[3]); p.f2[1] = atoi(params[4]); p.f2[2] = atoi(params[5]); p.f3[0] = atoi(params[6]); p.f3[1] = atoi(params[7]); p.f3[2] = atoi(params[8]); if (*num > 9) p.mul = atoi(params[ 9]); if (*num > 10) p.div = atoi(params[10]); if (*num > 11) p.add = atoi(params[11]); if (debug) { fprintf(stderr,"f3x3: -----------\n"); fprintf(stderr,"f3x3: %3d %3d %3d\n",p.f1[0],p.f1[1],p.f1[2]); fprintf(stderr,"f3x3: %3d %3d %3d\n",p.f2[0],p.f2[1],p.f2[2]); fprintf(stderr,"f3x3: %3d %3d %3d\n",p.f3[0],p.f3[1],p.f3[2]); fprintf(stderr,"f3x3: *%d/%d+%d\n",p.mul,p.div,p.add); } viewer_start_op(ida,&desc_3x3,&p); } void undo_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { Widget msgbox; int resize; resize = (ida->undo.i.width != ida->img.i.width || ida->undo.i.height != ida->img.i.height); if (-1 == viewer_undo(ida)) { msgbox = XmCreateInformationDialog(app_shell,"noundobox",NULL,0); XtUnmanageChild(XmMessageBoxGetChild(msgbox,XmDIALOG_HELP_BUTTON)); XtUnmanageChild(XmMessageBoxGetChild(msgbox,XmDIALOG_CANCEL_BUTTON)); XtAddCallback(msgbox,XmNokCallback,destroy_cb,msgbox); XtManageChild(msgbox); } else { if (resize) resize_shell(); } } /* ---------------------------------------------------------------------- */ struct ida_prompt { Widget shell; Widget box; Widget scale; Widget text; int apply; int value; int decimal; int factor; /* 10^decimal */ void (*notify)(int value, int preview); }; static void prompt_setvalue(struct ida_prompt *me, int value, int scale, int text) { char str[32]; int min,max; if (me->value == value) return; XtVaGetValues(me->scale,XmNminimum,&min,XmNmaximum,&max,NULL); if (value < min || value > max) return; me->value = value; if (scale) XmScaleSetValue(me->scale,value); if (text) { if (me->decimal) { sprintf(str,"%*.*f",me->decimal+2,me->decimal, (float)value/me->factor); } else { sprintf(str,"%d",value); } XmTextSetString(me->text,str); } if (me->notify) me->notify(value,1); } static void prompt_scale_cb(Widget widget, XtPointer client_data, XtPointer calldata) { struct ida_prompt *me = client_data; XmScaleCallbackStruct *cd = calldata; prompt_setvalue(me,cd->value,0,1); } static void prompt_text_cb(Widget widget, XtPointer client_data, XtPointer calldata) { struct ida_prompt *me = client_data; float fvalue; int value; if (me->decimal) { fvalue = atof(XmTextGetString(me->text)); fvalue += 0.5/me->factor; value = (int)(fvalue * me->factor); } else { value = atoi(XmTextGetString(me->text)); } prompt_setvalue(me,value,1,0); } static void prompt_box_cb(Widget widget, XtPointer client_data, XtPointer calldata) { struct ida_prompt *me = client_data; XmSelectionBoxCallbackStruct *cd = calldata; if (XmCR_OK == cd->reason) me->apply = 1; XtDestroyWidget(me->shell); } static void prompt_shell_cb(Widget widget, XtPointer client_data, XtPointer calldata) { struct ida_prompt *me = client_data; if (me->apply) me->notify(me->value,0); else viewer_cancel_preview(ida); free(me); } static void prompt_init(char *name, int decimal, int value, void (*notify)(int value, int preview)) { struct ida_prompt *me; me = malloc(sizeof(*me)); memset(me,0,sizeof(*me)); if (decimal) { int i; me->decimal = decimal; me->factor = 1; for (i = 0; i < decimal; i++) me->factor *= 10; } me->notify = notify; me->box = XmCreatePromptDialog(app_shell,name,NULL,0); me->shell = XtParent(me->box); me->text = XmSelectionBoxGetChild(me->box,XmDIALOG_TEXT); XmdRegisterEditres(XtParent(me->box)); XtUnmanageChild(XmSelectionBoxGetChild(me->box,XmDIALOG_HELP_BUTTON)); me->scale = XtVaCreateManagedWidget("scale",xmScaleWidgetClass, me->box,NULL); XtAddCallback(me->scale,XmNdragCallback,prompt_scale_cb,me); XtAddCallback(me->scale,XmNvalueChangedCallback,prompt_scale_cb,me); XtAddCallback(me->text,XmNvalueChangedCallback,prompt_text_cb,me); XtAddCallback(me->box,XmNokCallback,prompt_box_cb,me); XtAddCallback(me->box,XmNcancelCallback,prompt_box_cb,me); XtAddCallback(me->shell,XmNdestroyCallback,prompt_shell_cb,me); XtManageChild(me->box); prompt_setvalue(me,value,1,1); } /* ---------------------------------------------------------------------- */ static void gamma_notify(int value, int preview) { struct op_map_parm param; float gamma = (float)value/100; param.red = op_map_nothing; param.red.gamma = gamma; param.green = param.red; param.blue = param.red; if (preview) { viewer_start_preview(ida,&desc_map,¶m); } else { gamma_val = value; viewer_start_op(ida,&desc_map,¶m); } } void gamma_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { prompt_init("gamma",2,gamma_val,gamma_notify); } static void bright_notify(int value, int preview) { struct op_map_parm param; param.red = op_map_nothing; param.red.bottom += value; param.red.top += value; param.green = param.red; param.blue = param.red; if (preview) { viewer_start_preview(ida,&desc_map,¶m); } else { bright_val = value; viewer_start_op(ida,&desc_map,¶m); } } void bright_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { prompt_init("bright",0,bright_val,bright_notify); } static void contrast_notify(int value, int preview) { struct op_map_parm param; param.red = op_map_nothing; param.red.bottom -= value; param.red.top += value; param.green = param.red; param.blue = param.red; if (preview) { viewer_start_preview(ida,&desc_map,¶m); } else { contrast_val = value; viewer_start_op(ida,&desc_map,¶m); } } void contrast_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { prompt_init("contrast",0,contrast_val,contrast_notify); } static void rotate_notify(int value, int preview) { struct op_rotate_parm parm; parm.angle = value; if (preview) { viewer_start_preview(ida,&desc_rotate,&parm); } else { rotate_val = value; viewer_start_op(ida,&desc_rotate,&parm); } } void rotate_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { prompt_init("rotate",0,rotate_val,rotate_notify); } static void sharpe_notify(int value, int preview) { struct op_sharpe_parm parm; parm.factor = value; if (preview) { viewer_start_preview(ida,&desc_sharpe,&parm); } else { sharpe_val = value; viewer_start_op(ida,&desc_sharpe,&parm); } } void sharpe_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { prompt_init("sharpe",0,sharpe_val,sharpe_notify); } void color_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { color_init(&ida->img); } /* ---------------------------------------------------------------------- */ struct ida_resize { Widget dlg,tx,ty,tr,lock,size,res,label; int yupdate,xupdate,rupdate; int apply; }; static void resize_phys_size(struct ida_resize *h) { char buf[128]; XmString str; int dpi; float x,y; dpi = atoi(XmTextGetString(h->tr)); if (dpi) { x = (float)atoi(XmTextGetString(h->tx)) / dpi; y = (float)atoi(XmTextGetString(h->ty)) / dpi; sprintf(buf,"%.2f x %.2f inch\n%.2f x %.2f cm", x,y, x*2.54, y*2.54); } else { strcpy(buf,"unknown"); } str = XmStringGenerate(buf, NULL, XmMULTIBYTE_TEXT,NULL); XtVaSetValues(h->label,XmNlabelString,str,NULL); } static void resize_sync_cb(Widget widget, XtPointer client_data, XtPointer calldata) { struct ida_resize *h = client_data; char buf[32]; int i,lock,res; lock = XmToggleButtonGetState(h->lock); res = XmToggleButtonGetState(h->res); /* update text fields */ if (h->tx == widget) { if (h->xupdate) { h->xupdate--; return; } i = atoi(XmTextGetString(h->tx)); if (lock) { sprintf(buf,"%d",i * ida->img.i.height / ida->img.i.width); h->yupdate++; XmTextSetString(h->ty,buf); if (res) { sprintf(buf,"%d", ida->img.i.dpi * i / ida->img.i.width); h->rupdate++; XmTextSetString(h->tr,buf); } } else { if (res) { h->rupdate++; XmTextSetString(h->tr,"0"); } } resize_phys_size(h); } if (h->ty == widget) { if (h->yupdate) { h->yupdate--; return; } i = atoi(XmTextGetString(h->ty)); if (lock) { sprintf(buf,"%d",i * ida->img.i.width / ida->img.i.height); h->xupdate++; XmTextSetString(h->tx,buf); if (res) { sprintf(buf,"%d", ida->img.i.dpi * i / ida->img.i.height); h->rupdate++; XmTextSetString(h->tr,buf); } } else { if (res) { h->rupdate++; XmTextSetString(h->tr,"0"); } } resize_phys_size(h); } if (h->tr == widget) { if (h->rupdate) { h->rupdate--; return; } i = atoi(XmTextGetString(h->tr)); sprintf(buf,"%d", ida->img.i.width * i / ida->img.i.dpi); h->xupdate++; XmTextSetString(h->tx,buf); sprintf(buf,"%d", ida->img.i.height * i / ida->img.i.dpi); h->yupdate++; XmTextSetString(h->ty,buf); resize_phys_size(h); } /* radio buttons pressed */ if (h->size == widget && XmToggleButtonGetState(h->size)) { XmToggleButtonSetState(h->res,0,False); sprintf(buf,"%d", ida->img.i.dpi); h->rupdate++; XmTextSetString(h->tr,buf); XtVaSetValues(h->tr,XmNsensitive,False,NULL); resize_phys_size(h); } if (h->res == widget && XmToggleButtonGetState(h->res)) { XmToggleButtonSetState(h->size,0,False); XtVaSetValues(h->tr,XmNsensitive,True,NULL); } } static void resize_button_cb(Widget widget, XtPointer client_data, XtPointer calldata) { struct ida_resize *h = client_data; XmSelectionBoxCallbackStruct *cb = calldata; if (cb->reason == XmCR_OK) h->apply = 1; XtDestroyWidget(XtParent(h->dlg)); } static void resize_destroy(Widget widget, XtPointer client_data, XtPointer calldata) { struct ida_resize *h = client_data; struct op_resize_parm param; if (!h->apply) return; param.width = atoi(XmTextGetString(h->tx)); param.height = atoi(XmTextGetString(h->ty)); param.dpi = atoi(XmTextGetString(h->tr)); if (0 == param.width || 0 == param.height) { fprintf(stderr,"resize: invalid argument\n"); return; } viewer_start_op(ida,&desc_resize,¶m); resize_shell(); free(h); } static void resize_ac(Widget widget, XEvent *event, String *params, Cardinal *num) { Widget rc,rc2; char buf[32]; struct ida_resize *h; h = malloc(sizeof(*h)); memset(h,0,sizeof(*h)); h->dlg = XmCreatePromptDialog(app_shell,"resize",NULL,0); XmdRegisterEditres(XtParent(h->dlg)); XtUnmanageChild(XmSelectionBoxGetChild(h->dlg,XmDIALOG_SELECTION_LABEL)); XtUnmanageChild(XmSelectionBoxGetChild(h->dlg,XmDIALOG_HELP_BUTTON)); XtUnmanageChild(XmSelectionBoxGetChild(h->dlg,XmDIALOG_TEXT)); rc = XtVaCreateManagedWidget("rc", xmRowColumnWidgetClass,h->dlg, NULL); XtVaCreateManagedWidget("lx", xmLabelWidgetClass,rc, NULL); h->tx = XtVaCreateManagedWidget("tx", xmTextWidgetClass,rc, NULL); XtVaCreateManagedWidget("ly", xmLabelWidgetClass,rc, NULL); h->ty = XtVaCreateManagedWidget("ty", xmTextWidgetClass,rc, NULL); XtVaCreateManagedWidget("lr", xmLabelWidgetClass,rc, NULL); h->tr = XtVaCreateManagedWidget("tr", xmTextWidgetClass,rc, NULL); h->lock = XtVaCreateManagedWidget("lock", xmToggleButtonWidgetClass, rc, NULL); rc2 = XtVaCreateManagedWidget("rc", xmRowColumnWidgetClass,rc, NULL); h->size = XtVaCreateManagedWidget("size", xmToggleButtonWidgetClass, rc2, NULL); h->res = XtVaCreateManagedWidget("res", xmToggleButtonWidgetClass, rc2, NULL); XtVaCreateManagedWidget("phys", xmLabelWidgetClass,rc,NULL); h->label = XtVaCreateManagedWidget("label", xmLabelWidgetClass, rc, NULL); sprintf(buf,"%d",ida->img.i.width); XmTextSetString(h->tx,buf); sprintf(buf,"%d",ida->img.i.height); XmTextSetString(h->ty,buf); sprintf(buf,"%d",ida->img.i.dpi); XmTextSetString(h->tr,buf); XtVaSetValues(h->tr,XmNsensitive,False,NULL); XmToggleButtonSetState(h->lock,1,False); XmToggleButtonSetState(h->size,1,False); XmToggleButtonSetState(h->res,0,False); if (!ida->img.i.dpi) { XtVaSetValues(h->size,XmNsensitive,False,NULL); XtVaSetValues(h->res, XmNsensitive,False,NULL); } resize_phys_size(h); XtAddCallback(XtParent(h->dlg),XmNdestroyCallback,resize_destroy,h); XtAddCallback(h->dlg, XmNokCallback, resize_button_cb, h); XtAddCallback(h->dlg, XmNcancelCallback, resize_button_cb, h); XtAddCallback(h->tx, XmNvalueChangedCallback, resize_sync_cb, h); XtAddCallback(h->ty, XmNvalueChangedCallback, resize_sync_cb, h); XtAddCallback(h->tr, XmNvalueChangedCallback, resize_sync_cb, h); XtAddCallback(h->size,XmNvalueChangedCallback, resize_sync_cb, h); XtAddCallback(h->res, XmNvalueChangedCallback, resize_sync_cb, h); XtManageChild(h->dlg); } /* ---------------------------------------------------------------------- */ struct stderr_handler { Widget box; XmString str; int pipe,err; XtInputId id; }; static void stderr_input(XtPointer clientdata, int *src, XtInputId *id) { struct stderr_handler *h = clientdata; XmString item; Widget label; char buf[1024]; int rc; rc = read(h->pipe,buf,sizeof(buf)-1); if (rc <= 0) { /* Oops */ XtRemoveInput(h->id); close(h->pipe); XtDestroyWidget(h->box); free(h); } buf[rc] = 0; write(h->err,buf,rc); item = XmStringGenerate(buf, NULL, XmMULTIBYTE_TEXT,NULL); h->str = XmStringConcatAndFree(h->str,item); label = XmMessageBoxGetChild(h->box,XmDIALOG_MESSAGE_LABEL); XtVaSetValues(label,XmNlabelString,h->str,NULL); XtManageChild(h->box); } static void stderr_ok_cb(Widget widget, XtPointer clientdata, XtPointer call_data) { struct stderr_handler *h = clientdata; XmStringFree(h->str); h->str = XmStringGenerate("", NULL, XmMULTIBYTE_TEXT,NULL); XtUnmanageChild(h->box); } static void stderr_close_cb(Widget widget, XtPointer clientdata, XtPointer call_data) { struct stderr_handler *h = clientdata; XmStringFree(h->str); h->str = XmStringGenerate("", NULL, XmMULTIBYTE_TEXT,NULL); } static void stderr_init(void) { struct stderr_handler *h; int p[2]; h = malloc(sizeof(*h)); memset(h,0,sizeof(*h)); h->str = XmStringGenerate("", NULL, XmMULTIBYTE_TEXT,NULL); h->box = XmCreateErrorDialog(app_shell,"errbox",NULL,0); XtUnmanageChild(XmMessageBoxGetChild(h->box,XmDIALOG_HELP_BUTTON)); XtUnmanageChild(XmMessageBoxGetChild(h->box,XmDIALOG_CANCEL_BUTTON)); XtAddCallback(h->box,XmNokCallback,stderr_ok_cb,h); XtAddCallback(XtParent(h->box),XmNpopdownCallback,stderr_close_cb,h); XSync(XtDisplay(app_shell),False); if (!debug) { pipe(p); h->err = dup(2); dup2(p[1],2); close(p[1]); h->pipe = p[0]; h->id = XtAppAddInput(app_context,h->pipe,(XtPointer)XtInputReadMask, stderr_input,h); } } /* ---------------------------------------------------------------------- */ static void create_mainwindow(void) { Widget img; XmdRegisterEditres(app_shell); view = XmCreateScrolledWindow(app_shell,"view",NULL,0); XtManageChild(view); img = XtVaCreateManagedWidget("image", xmDrawingAreaWidgetClass,view,NULL); XtAddCallback(img,XmNdestinationCallback,selection_dest,NULL); XtAddCallback(img,XmNconvertCallback,selection_convert,NULL); dnd_add(img); ida = viewer_init(img); XtInstallAllAccelerators(img,app_shell); } static void usage(void) { fprintf(stderr, "ida " VERSION " - image viewer & editor\n" "usage: ida [ options ] [ files ]\n" "options:\n" " -h, -help this text\n" " -pcd n pick PhotoCD size (n = 1 .. 5, default 3)\n" " -d, -debug enable debug messages\n"); exit(0); } int main(int argc, char *argv[]) { int i, files, zero = 0; struct stat st; Pixel background; setlocale(LC_ALL,""); if (0 == strcasecmp("utf-8", nl_langinfo(CODESET))) { /* ### FIXME ### * for not-yet known reasons ida crashes somewhere deep in * the Motif libraries when running in utf-8 locale ... */ setenv("LC_ALL", "POSIX", 1); setlocale(LC_ALL,""); } binary = argv[0]; ida_init_config(); ida_read_config(); XtSetLanguageProc(NULL,NULL,NULL); app_shell = XtAppInitialize(&app_context, "Ida", opt_desc, opt_count, &argc, argv, fallback_ressources, NULL, 0); dpy = XtDisplay(app_shell); XtGetApplicationResources(app_shell,&args, args_desc,args_count, NULL,0); pcd_res = GET_PHOTOCD_RES(); sane_res = GET_SANE_RES(); if (args.help) usage(); if (args.debug) { debug=1; xdnd_debug = 1; XSynchronize(dpy,1); } XtAppAddActions(app_context, actionTable, sizeof(actionTable) / sizeof(XtActionsRec)); if (0) { XtAddCallback(XmGetXmDisplay(dpy),XmNnoFontCallback, display_cb,NULL); XtAddCallback(XmGetXmDisplay(dpy),XmNnoRenditionCallback, display_cb,NULL); } XtVaGetValues(app_shell, XtNbackground,&background, NULL); x11_color_init(app_shell,&gray); x11_icons_init(dpy, background /* x11_gray */); stderr_init(); ipc_init(); wm_delete_window = XInternAtom(dpy,"WM_DELETE_WINDOW",False); create_mainwindow(); create_control(); XtRealizeWidget(app_shell); ptr_register(ida->widget); ptr_register(control_shell); /* handle cmd line args */ if (2 == argc && 0 == strcmp(argv[1],"-")) { load_stdin(); } else if (argc > 1) { for (files = 0, i = 1; i < argc; i++) { if (curl_is_url(argv[i])) { list_append(argv[i]); files++; continue; } if (-1 == stat(argv[i],&st)) { if (debug) fprintf(stderr,"stat %s: %s\n",argv[i],strerror(errno)); continue; } switch (st.st_mode & S_IFMT) { case S_IFDIR: browser_window(argv[i]); break; case S_IFREG: list_append(argv[i]); files++; break; } } if (files) { list_update(); next_ac(ida->widget,NULL,NULL,&zero); } } if (NULL == ida->file) load_logo(); XtAppMainLoop(app_context); return 0; /* keep compiler happy */ }