/* +-------------------------------------------------------------------+ */ /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com) | */ /* | Copyright 1995, 1996 Torsten Martinsen (bullestock@dk-online.dk) | */ /* | | */ /* | Permission to use, copy, modify, and to distribute this software | */ /* | and its documentation for any purpose is hereby granted without | */ /* | fee, provided that the above copyright notice appear in all | */ /* | copies and that both that copyright notice and this permission | */ /* | notice appear in supporting documentation. There is no | */ /* | representations about the suitability of this software for | */ /* | any purpose. this software is provided "as is" without express | */ /* | or implied warranty. | */ /* | | */ /* +-------------------------------------------------------------------+ */ /* $Id: graphic.c,v 1.17 2005/03/20 20:15:32 demailly Exp $ */ #include #include #include #include #include #include #include #include #include "xaw_incdir/Form.h" #include "xaw_incdir/Viewport.h" #include "xaw_incdir/Box.h" #include "xaw_incdir/Label.h" #include "xaw_incdir/Toggle.h" #include "xaw_incdir/SmeBSB.h" #include "xaw_incdir/Paned.h" //#include #include #ifdef HAVE_COLTOG #include "ColToggle.h" #endif #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #ifndef NOSTDHDRS #include #include #endif /* * Undefine this if you want the Lookup button to be * inside the palette area (not recommended) */ #define LOOKUP_OUTSIDE #include "Paint.h" #include "PaintP.h" #include "xpaint.h" #include "palette.h" #include "misc.h" #include "menu.h" #include "messages.h" #include "text.h" #include "graphic.h" #include "image.h" #include "region.h" #include "operation.h" #include "rc.h" #include "protocol.h" #include "color.h" #include "ops.h" #include "rw/rwTable.h" #include "bitmaps/xpm/eye.xpm" #include "bitmaps/xpm/fill0.xpm" #include "bitmaps/xpm/fill1.xpm" #include "bitmaps/xpm/fill2.xpm" #define POS_WIDTH 62 extern Boolean * setDrawable(Widget w, Drawable d, XImage * s); extern void fill(int x, int y, int width, int height); enum {W_ICON_PALETTE=0, W_ICON_COLORS, W_ICON_COLPIXMAP, W_ICON_TOOL, W_ICON_BRUSH, W_ICON_FONT, W_INFO_DATA, W_FILE_REVERT, W_EDIT_PASTE, W_EDIT_RECALL, W_EDIT_REMOVE, W_REGION_LAST, W_REGION_UNDO, W_SELECTOR_GRID, W_SELECTOR_SNAP, W_LINE_WIDTHS, W_FONT_DESCR = W_LINE_WIDTHS+7, W_TOPMENU = W_FONT_DESCR + 11 - W_FILE_REVERT, W_NWIDGETS = 2*W_TOPMENU + W_FILE_REVERT + 1 }; static Pixmap ImgProcessPix; static Colormap ImgProcessCmap; static int ImgProcessFlag; static char *fontNames[] = { "-*-times-medium-r-normal-*-*-80-*-*-p-*-*-*", /* Times 8 */ "-*-times-medium-r-normal-*-*-120-*-*-p-*-*-*", /* Times 12 */ "-*-times-medium-r-normal-*-*-180-*-*-p-*-*-*", /* Times 18 */ "-*-times-bold-r-normal-*-*-120-*-*-p-*-*-*", /* Times Bold 12 */ "-*-times-bold-i-normal-*-*-120-*-*-p-*-*-*", /* Times Bold Italic 12 */ "-*-lucida-medium-r-normal-*-*-120-*-*-p-*-*-*", /* Lucida 12 */ "-*-helvetica-medium-r-normal-*-*-120-*-*-p-*-*-*", /* Helvetica 12 */ "-*-helvetica-bold-r-normal-*-*-120-*-*-p-*-*-*", /* Helvetica Bold 12 */ "-*-fixed-medium-r-normal-*-*-120-*-*-m-*-*-*", /* Fixed 12 */ "-*-courier-medium-r-normal-*-*-120-*-*-m-*-*-*" /* Courier 12 */ }; static char dashStyleStr[36] = "="; /* forward references */ static void fontSet(Widget w, void *ptr); /* Global data */ struct imageprocessinfo ImgProcessInfo = { 7, /* oilArea */ 20, /* noiseDelta */ 2, /* spreadDistance */ 4, /* pixelizeXSize */ 4, /* pixelizeYSize */ 3, /* despeckleMask */ 3, /* smoothMaskSize */ 20, /* tilt */ 50, /* solarizeThreshold */ 99, /* contrastW */ 2, /* contrastB */ 0, /* redshift */ 0, /* greenshift */ 0, /* blueshift */ 16, /* quantizeColors */ 0, 0, 0, 0, /* tilt values */ 1.0, 0.0, 0.0, 1.0, /* matrix for linear transform */ NULL /* background color pointer */ }; struct paintWindows { Widget paint; struct paintWindows *next; void *ldata; Boolean done; }; typedef struct { Widget paint, viewport, form, paintbox, position, memory; Pixmap palette_pixmap, mem_pixmap; Palette *map; RCInfo *rcInfo; Pixel *pixels; Pixmap *patterns; int npatterns, npixels; int boolcount, channel, steps, boolpos, mem_index, mem_shift; } LocalInfo; static Boolean selectionOwner = False; static Image *(*lastFilter) (Image *); /* * Begin menus */ static PaintMenuItem fileMenu[] = { #define FILE_SAVE 0 MI_SIMPLE("save"), #define FILE_SAVEAS 1 MI_SIMPLE("saveas"), #define FILE_SAVE_REGION 2 MI_SIMPLE("saveregion"), #define FILE_LOAD_MEMORY 3 MI_SIMPLE("load-mem"), #define FILE_REVERT 4 MI_SIMPLE("revert"), #define FILE_PRINT 5 MI_SIMPLE("print"), #define FILE_EXTERN 6 MI_SIMPLE("extern"), #define FILE_CLOSE 7 MI_SIMPLE("close"), }; static PaintMenuItem editMenu[] = { #define EDIT_UNDO 0 MI_SIMPLE("undo"), #define EDIT_REDO 1 MI_SIMPLE("redo"), #define EDIT_UNDO_SIZE 2 MI_SIMPLE("undosize"), MI_SEPARATOR(), /* 3 */ #define EDIT_REFRESH 4 MI_SIMPLE("refresh"), MI_SEPARATOR(), /* 5 */ #define EDIT_CUT 6 MI_SIMPLE("cut"), #define EDIT_COPY 7 MI_SIMPLE("copy"), #define EDIT_PASTE 8 MI_SIMPLE("paste"), #define EDIT_CLEAR 9 MI_SIMPLE("clear"), MI_SEPARATOR(), /* 10 */ #define EDIT_SELECT_ALL 11 MI_SIMPLE("all"), #define EDIT_UNSELECT 12 MI_SIMPLE("unselect"), MI_SEPARATOR(), /* 13 */ #define EDIT_DUP 14 MI_SIMPLE("dup"), #define EDIT_ERASE_ALL 15 MI_SIMPLE("erase"), MI_SEPARATOR(), /* 16 */ #define EDIT_SNAPSHOT 17 MI_SIMPLE("snapshot"), MI_SEPARATOR(), /* 18 */ #define EDIT_MEMORY 19 MI_SIMPLE("memory"), #define EDIT_RECALL 20 MI_SIMPLE("recall"), #define EDIT_REMOVE 21 MI_SIMPLE("remove"), }; static PaintMenuItem lineMenu[] = { MI_FLAGCB("1", MF_CHECK | MF_GROUP3, lineWidth, NULL), MI_FLAGCB("2", MF_CHECK | MF_GROUP3, lineWidth, NULL), MI_FLAGCB("4", MF_CHECK | MF_GROUP3, lineWidth, NULL), MI_FLAGCB("6", MF_CHECK | MF_GROUP3, lineWidth, NULL), MI_FLAGCB("8", MF_CHECK | MF_GROUP3, lineWidth, NULL), #define LINE_WIDTH_GENERAL 5 MI_FLAGCB("select", MF_CHECK | MF_GROUP3, lineWidth, NULL), MI_SEPARATOR(), MI_SIMPLECB("dashstyle", changeDashStyleAction, NULL), }; static PaintMenuItem fontMenu[] = { MI_FLAGCB("Times 8", MF_CHECK | MF_GROUP1, fontSet, 1), MI_FLAGCB("Times 12", MF_CHECK | MF_GROUP1, fontSet, 2), MI_FLAGCB("Times 18", MF_CHECK | MF_GROUP1, fontSet, 3), MI_FLAGCB("Times Bold 12", MF_CHECK | MF_GROUP1, fontSet, 4), MI_FLAGCB("Times Italic 12", MF_CHECK | MF_GROUP1, fontSet, 5), MI_FLAGCB("Lucida 12", MF_CHECK | MF_GROUP1, fontSet, 6), MI_FLAGCB("Helvetica 12", MF_CHECK | MF_GROUP1, fontSet, 7), MI_FLAGCB("Helvetica Bold 12", MF_CHECK | MF_GROUP1, fontSet, 8), MI_FLAGCB("Fixed 12", MF_CHECK | MF_GROUP1, fontSet, 9), MI_FLAGCB("Courier 12", MF_CHECK | MF_GROUP1, fontSet, 10), MI_SEPARATOR(), MI_FLAGCB("select", MF_CHECK | MF_GROUP1, fontSet, NULL), }; static PaintMenuItem rotateMenu[] = { MI_SEPARATOR(), MI_SIMPLE("rotate1"), MI_SIMPLE("rotate2"), MI_SIMPLE("rotate3"), MI_SIMPLE("rotate4"), MI_SIMPLE("rotate5"), }; static PaintMenuItem regionMenu[] = { #define REGION_FLIPX 0 MI_SIMPLE("flipX"), #define REGION_FLIPY 1 MI_SIMPLE("flipY"), #define REGION_ROTATETO 2 MI_RIGHT("rotateTo", XtNumber(rotateMenu), rotateMenu), #define REGION_ROTATE 3 MI_SIMPLE("rotate"), #define REGION_LINEAR 4 MI_SIMPLE("linear"), #define REGION_RESET 5 MI_SIMPLE("reset"), MI_SEPARATOR(), /* 6 */ #define REGION_CLONE 7 MI_SIMPLE("clone"), #define REGION_CROP 8 MI_SIMPLE("crop"), MI_SEPARATOR(), /* 9 */ #define REGION_AUTOCROP 10 MI_SIMPLE("autocrop"), #define REGION_DELIMIT 11 MI_SIMPLE("delimit"), #define REGION_COMPLEMENT 12 MI_SIMPLE("complement"), }; static PaintMenuItem filterMenu[] = { #define FILTER_INVERT 0 MI_SIMPLE("invert"), #define FILTER_SHARPEN 1 MI_SIMPLE("sharpen"), /* remove noise */ MI_SEPARATOR(), /* 2 */ #define FILTER_SMOOTH 3 MI_SIMPLE("smooth"), #define FILTER_DIRFILT 4 MI_SIMPLE("dirfilt"), #define FILTER_DESPECKLE 5 MI_SIMPLE("despeckle"), MI_SEPARATOR(), /* 6 */ #define FILTER_EDGE 7 MI_SIMPLE("edge"), #define FILTER_EMBOSS 8 MI_SIMPLE("emboss"), #define FILTER_OIL 9 MI_SIMPLE("oil"), #define FILTER_NOISE 10 MI_SIMPLE("noise"), #define FILTER_SPREAD 11 MI_SIMPLE("spread"), #define FILTER_PIXELIZE 12 MI_SIMPLE("pixelize"), /* special fx */ #define FILTER_TILT 13 MI_SIMPLE("tilt"), #define FILTER_BLEND 14 MI_SIMPLE("blend"), #define FILTER_SOLARIZE 15 MI_SIMPLE("solarize"), /* colour manipulation */ MI_SEPARATOR(), /* 16 */ #define FILTER_TOGREY 17 MI_SIMPLE("togrey"), #define FILTER_CONTRAST 18 MI_SIMPLE("contrast"), #define FILTER_MODIFY_RGB 19 MI_SIMPLE("modify_rgb"), #define FILTER_QUANTIZE 20 MI_SIMPLE("quantize"), MI_SEPARATOR(), /* 21 */ #define FILTER_USERDEF 22 MI_SIMPLE("userdef"), MI_SEPARATOR(), /* 23 */ #define FILTER_LAST 24 MI_SIMPLE("last"), #define FILTER_UNDO 25 MI_SIMPLE("undo"), }; static PaintMenuItem selectorMenu[] = { #define SELECTOR_FATBITS 0 MI_SIMPLE("fatbits"), #define SELECTOR_PATTERNS 1 MI_SIMPLE("patterns"), #define SELECTOR_CHROMA 2 MI_SIMPLE("chroma"), #define SELECTOR_BACKGROUND 3 MI_SIMPLE("background"), #define SELECTOR_TOOLS 4 MI_SIMPLE("tools"), #define SELECTOR_BRUSH 5 MI_SIMPLE("brush"), #define SELECTOR_FONT 6 MI_SIMPLE("font"), #define SELECTOR_SCRIPT 7 MI_SIMPLE("c_script"), MI_SEPARATOR(), /* 8 */ #define SELECTOR_CHANGE_SIZE 9 MI_SIMPLE("size"), #define SELECTOR_CHANGE_ZOOM 10 MI_SIMPLE("zoom"), #define SELECTOR_SIZE_ZOOM_DEFS 11 MI_SIMPLE("size_zoom_defs"), #define SELECTOR_CHANGE_SNAP 12 MI_SIMPLE("snapSpacing"), #define SELECTOR_SNAP 13 MI_FLAG("snap", MF_CHECK), #define SELECTOR_GRID 14 MI_FLAG("grid", MF_CHECK), #define SELECTOR_SIMPLE 15 MI_FLAG("simple", MF_CHECK), #define SELECTOR_HIDE_MENUBAR 16 MI_FLAG("hide_menubar", MF_CHECK), MI_SEPARATOR(), /* 17 */ #define SELECTOR_HELP 18 MI_SIMPLECB("help", HelpDialog, "introduction"), }; static PaintMenuBar menuBar[] = { {None, "file", XtNumber(fileMenu), fileMenu}, {None, "edit", XtNumber(editMenu), editMenu}, {None, "line", XtNumber(lineMenu), lineMenu}, {None, "font", XtNumber(fontMenu), fontMenu}, {None, "region", XtNumber(regionMenu), regionMenu}, {None, "filter", XtNumber(filterMenu), filterMenu}, {None, "selector", XtNumber(selectorMenu), selectorMenu}, }; /* ** Standard popup menu */ /* static PaintMenuItem popupCanvasMenu[] = { MI_SEPARATOR(), MI_SIMPLECB("new", GraphicCreate, 0), MI_SIMPLECB("new-size", GraphicCreate, 2), MI_SIMPLECB("open", GraphicCreate, 1), MI_SIMPLECB("snapshot", takeSnapshot, NULL), MI_SEPARATOR(), MI_SIMPLECB("quit", exitPaint, NULL), }; */ static PaintMenuItem popupFileMenu[] = { MI_SEPARATOR(), #define P_FILE_SAVE 1 MI_SIMPLE("save"), #define P_FILE_SAVEAS 2 MI_SIMPLE("saveas"), #define P_FILE_SAVE_REGION 3 MI_SIMPLE("saveregion"), #define P_FILE_LOAD_MEMORY 4 MI_SIMPLE("load-mem"), #define P_FILE_REVERT 5 MI_SIMPLE("revert"), #define P_FILE_PRINT 6 MI_SIMPLE("print"), #define P_FILE_EXTERN 7 MI_SIMPLE("extern"), #define P_FILE_CLOSE 8 MI_SIMPLE("close"), }; static PaintMenuItem popupEditMenu[] = { MI_SEPARATOR(), /* 0 */ #define P_EDIT_UNDO 1 MI_SIMPLE("undo"), #define P_EDIT_REDO 2 MI_SIMPLE("redo"), #define P_EDIT_UNDO_SIZE 3 MI_SIMPLE("undosize"), MI_SEPARATOR(), /* 4 */ #define P_EDIT_REFRESH 5 MI_SIMPLE("refresh"), MI_SEPARATOR(), /* 6 */ #define P_EDIT_CUT 7 MI_SIMPLE("cut"), #define P_EDIT_COPY 8 MI_SIMPLE("copy"), #define P_EDIT_PASTE 9 MI_SIMPLE("paste"), #define P_EDIT_CLEAR 10 MI_SIMPLE("clear"), MI_SEPARATOR(), /* 11 */ #define P_EDIT_SELECT_ALL 12 MI_SIMPLE("all"), #define P_EDIT_UNSELECT 13 MI_SIMPLE("unselect"), MI_SEPARATOR(), /* 14 */ #define P_EDIT_DUP 15 MI_SIMPLE("dup"), #define P_EDIT_ERASE_ALL 16 MI_SIMPLE("erase"), MI_SEPARATOR(), /* 17 */ #define P_EDIT_SNAPSHOT 18 MI_SIMPLE("snapshot"), MI_SEPARATOR(), /* 19 */ #define P_EDIT_MEMORY 20 MI_SIMPLE("memory"), #define P_EDIT_RECALL 21 MI_SIMPLE("recall"), #define P_EDIT_REMOVE 22 MI_SIMPLE("remove") }; static PaintMenuItem popupLineMenu[] = { MI_SEPARATOR(), MI_FLAGCB("1", MF_CHECK | MF_GROUP3, lineWidth, NULL), MI_FLAGCB("2", MF_CHECK | MF_GROUP3, lineWidth, NULL), MI_FLAGCB("4", MF_CHECK | MF_GROUP3, lineWidth, NULL), MI_FLAGCB("6", MF_CHECK | MF_GROUP3, lineWidth, NULL), MI_FLAGCB("8", MF_CHECK | MF_GROUP3, lineWidth, NULL), MI_FLAGCB("select", MF_CHECK | MF_GROUP3, lineWidth, NULL), MI_SEPARATOR(), MI_SIMPLECB("dashstyle", changeDashStyleAction, NULL), }; static PaintMenuItem popupFontMenu[] = { MI_SEPARATOR(), MI_FLAGCB("Times 8", MF_CHECK | MF_GROUP1, fontSet, 1), MI_FLAGCB("Times 12", MF_CHECK | MF_GROUP1, fontSet, 2), MI_FLAGCB("Times 18", MF_CHECK | MF_GROUP1, fontSet, 3), MI_FLAGCB("Times Bold 12", MF_CHECK | MF_GROUP1, fontSet, 4), MI_FLAGCB("Times Italic 12", MF_CHECK | MF_GROUP1, fontSet, 5), MI_FLAGCB("Lucida 12", MF_CHECK | MF_GROUP1, fontSet, 6), MI_FLAGCB("Helvetica 12", MF_CHECK | MF_GROUP1, fontSet, 7), MI_FLAGCB("Helvetica Bold 12", MF_CHECK | MF_GROUP1, fontSet, 8), MI_FLAGCB("Fixed 12", MF_CHECK | MF_GROUP1, fontSet, 9), MI_FLAGCB("Courier 12", MF_CHECK | MF_GROUP1, fontSet, 10), MI_SEPARATOR(), MI_FLAGCB("select", MF_CHECK | MF_GROUP1, fontSet, NULL), }; static PaintMenuItem popupRotateMenu[] = { MI_SEPARATOR(), MI_SIMPLE("rotate1"), MI_SIMPLE("rotate2"), MI_SIMPLE("rotate3"), MI_SIMPLE("rotate4"), MI_SIMPLE("rotate5"), }; static PaintMenuItem popupRegionMenu[] = { MI_SEPARATOR(), /* 0 */ #define P_REGION_FLIPX 1 MI_SIMPLE("flipX"), #define P_REGION_FLIPY 2 MI_SIMPLE("flipY"), #define P_REGION_ROTATETO 3 MI_RIGHT("rotateTo", XtNumber(popupRotateMenu), popupRotateMenu), #define P_REGION_ROTATE 4 MI_SIMPLE("rotate"), #define P_REGION_LINEAR 5 MI_SIMPLE("linear"), #define P_REGION_RESET 6 MI_SIMPLE("reset"), MI_SEPARATOR(), /* 7 */ #define P_REGION_CLONE 8 MI_SIMPLE("clone"), #define P_REGION_CROP 9 MI_SIMPLE("crop"), MI_SEPARATOR(), /* 10 */ #define P_REGION_AUTOCROP 11 MI_SIMPLE("autocrop"), #define P_REGION_DELIMIT 12 MI_SIMPLE("delimit"), #define P_REGION_COMPLEMENT 13 MI_SIMPLE("complement"), }; static PaintMenuItem popupFilterMenu[] = { MI_SEPARATOR(), /* 0 */ #define P_FILTER_INVERT 1 MI_SIMPLE("invert"), #define P_FILTER_SHARPEN 2 MI_SIMPLE("sharpen"), /* remove noise */ MI_SEPARATOR(), /* 3 */ #define P_FILTER_SMOOTH 4 MI_SIMPLE("smooth"), #define P_FILTER_DIRFILT 5 MI_SIMPLE("dirfilt"), #define P_FILTER_DESPECKLE 6 MI_SIMPLE("despeckle"), MI_SEPARATOR(), /* 7 */ #define P_FILTER_EDGE 8 MI_SIMPLE("edge"), #define P_FILTER_EMBOSS 9 MI_SIMPLE("emboss"), #define P_FILTER_OIL 10 MI_SIMPLE("oil"), #define P_FILTER_NOISE 11 MI_SIMPLE("noise"), #define P_FILTER_SPREAD 12 MI_SIMPLE("spread"), #define P_FILTER_PIXELIZE 13 MI_SIMPLE("pixelize"), /* special fx */ #define P_FILTER_TILT 14 MI_SIMPLE("tilt"), #define P_FILTER_BLEND 15 MI_SIMPLE("blend"), #define P_FILTER_SOLARIZE 16 MI_SIMPLE("solarize"), /* colour manipulation */ MI_SEPARATOR(), /* 17 */ #define P_FILTER_TOGREY 18 MI_SIMPLE("togrey"), #define P_FILTER_CONTRAST 19 MI_SIMPLE("contrast"), #define P_FILTER_MODIFY_RGB 20 MI_SIMPLE("modify_rgb"), #define P_FILTER_QUANTIZE 21 MI_SIMPLE("quantize"), MI_SEPARATOR(), /* 22 */ #define P_FILTER_USERDEF 23 MI_SIMPLE("userdef"), MI_SEPARATOR(), /* 24 */ #define P_FILTER_LAST 25 MI_SIMPLE("last"), #define P_FILTER_UNDO 26 MI_SIMPLE("undo"), }; static PaintMenuItem popupSelectorMenu[] = { MI_SEPARATOR(), /* 0 */ #define P_SELECTOR_FATBITS 1 MI_SIMPLE("fatbits"), #define P_SELECTOR_PATTERNS 2 MI_SIMPLE("patterns"), #define P_SELECTOR_CHROMA 3 MI_SIMPLE("chroma"), #define P_SELECTOR_BACKGROUND 4 MI_SIMPLE("background"), #define P_SELECTOR_TOOLS 5 MI_SIMPLE("tools"), #define P_SELECTOR_BRUSH 6 MI_SIMPLE("brush"), #define P_SELECTOR_FONT 7 MI_SIMPLE("font"), #define P_SELECTOR_SCRIPT 8 MI_SIMPLE("c_script"), MI_SEPARATOR(), /* 9 */ #define P_SELECTOR_CHANGE_SIZE 10 MI_SIMPLE("size"), #define P_SELECTOR_CHANGE_ZOOM 11 MI_SIMPLE("zoom"), #define P_SELECTOR_SIZE_ZOOM_DEFS 12 MI_SIMPLE("size_zoom_defs"), #define P_SELECTOR_CHANGE_SNAP 13 MI_SIMPLE("snapSpacing"), #define P_SELECTOR_SNAP 14 MI_FLAG("snap", MF_CHECK), #define P_SELECTOR_GRID 15 MI_FLAG("grid", MF_CHECK), MI_SEPARATOR(), /* 16 */ #define P_SELECTOR_HIDE_MENUBAR 17 MI_SIMPLE("hide_menubar"), #define P_SELECTOR_SHOW_MENUBAR 18 MI_SIMPLE("show_menubar"), MI_SEPARATOR(), /* 19 */ #define P_SELECTOR_HELP 20 MI_SIMPLECB("help", HelpDialog, "introduction"), }; static PaintMenuItem popupMenu[] = { MI_SEPARATOR(), MI_RIGHT("File", XtNumber(popupFileMenu), popupFileMenu), MI_RIGHT("Edit", XtNumber(popupEditMenu), popupEditMenu), MI_RIGHT("Line", XtNumber(popupLineMenu), popupLineMenu), MI_RIGHT("Font", XtNumber(popupFontMenu), popupFontMenu), MI_RIGHT("Region", XtNumber(popupRegionMenu), popupRegionMenu), MI_RIGHT("Filters", XtNumber(popupFilterMenu), popupFilterMenu), MI_RIGHT("Selectors", XtNumber(popupSelectorMenu), popupSelectorMenu), }; /* ** This really should be a "local" or malloced variable */ typedef struct { Pixmap pixmap; int count; int width, height, depth; } selectInfo; /* * End of menus */ static struct paintWindows *head = NULL; void GraphicRemove(Widget paint, XtPointer junk, XtPointer junk2) { struct paintWindows *cur = head, **prev = &head; while (cur != NULL && cur->paint != paint) { prev = &cur->next; cur = cur->next; } if (cur == NULL) return; *prev = cur->next; if (cur->done) CurrentOp->remove(cur->paint, cur->ldata); XtFree((XtPointer) cur); } static void realize(Widget paint, XtPointer ldataArg, XEvent * event, Boolean * junk) { struct paintWindows *cur = (struct paintWindows *) ldataArg; if (event->type == MapNotify) { XtRemoveEventHandler(paint, StructureNotifyMask, False, realize, ldataArg); if (CurrentOp != NULL && CurrentOp->add != NULL) cur->ldata = CurrentOp->add(paint); cur->done = True; } } void GraphicAdd(Widget paint) { struct paintWindows *new = XtNew(struct paintWindows); new->next = head; head = new; new->paint = paint; new->ldata = NULL; new->done = False; if (XtIsRealized(paint)) { if (CurrentOp != NULL && CurrentOp->add != NULL) new->ldata = CurrentOp->add(paint); new->done = True; } else XtAddEventHandler(paint, StructureNotifyMask, False, realize, (XtPointer) new); XtAddCallback(paint, XtNdestroyCallback, GraphicRemove, NULL); } void GraphicAll(GraphicAllProc func, void *data) { struct paintWindows *cur; for (cur = head; cur != NULL; cur = cur->next) { if (!cur->done) continue; func(cur->paint, data); } } void GraphicSetOp(void (*stop) (Widget, void *), void *(*start) (Widget)) { struct paintWindows *cur; for (cur = head; cur != NULL; cur = cur->next) { if (stop != NULL) stop(cur->paint, cur->ldata); if (start != NULL) cur->ldata = start(cur->paint); } } void * GraphicGetData(Widget w) { struct paintWindows *cur; for (cur = head; cur != NULL; cur = cur->next) if (cur->paint == w) return cur->ldata; return NULL; } /* * First level menu callbacks. */ static void closeOkCallback(Widget shell, XtPointer paintArg, XtPointer junk2) { LocalInfo * info = (LocalInfo *) paintArg; Display *dpy = XtDisplay(info->paint); Pixmap pix; WidgetList wlist; int i, rule; if (info->palette_pixmap) XFreePixmap(dpy, info->palette_pixmap); if (info->mem_pixmap) XFreePixmap(dpy, info->mem_pixmap); for (i=0; inpatterns; i++) XFreePixmap(dpy, info->patterns[i]); free(info->pixels); free(info->patterns); XtVaGetValues(info->paint, XtNmenuwidgets, &wlist, NULL); if (wlist) { if (wlist[W_ICON_COLPIXMAP]) { XFreePixmap(dpy, (Pixmap) wlist[W_ICON_COLPIXMAP]); wlist[W_ICON_COLPIXMAP] = 0; } } XtVaGetValues(info->paint, XtNfillRule, &rule, XtNpattern, &pix, NULL); if (rule==FillTiled && pix) XFreePixmap(dpy, pix); XtVaGetValues(info->paint, XtNlineFillRule, &rule, XtNlinePattern, &pix, NULL); if (rule==FillTiled && pix) XFreePixmap(dpy, pix); checkPatternLink(info->paint, 0); checkExternalLink(info->paint); if (Global.canvas == shell) { XtVaSetValues(Global.back, XtNsensitive, False, NULL); Global.canvas = None; } XtDestroyWidget(shell); } static void genericCancelCallback(Widget shell, XtPointer junk, XtPointer junk2) { } static void closeCallback(Widget w, XtPointer wlArg, XtPointer junk2) { LocalInfo *info = (LocalInfo *) wlArg; Widget shell = GetShell(info->paint); Boolean flg; XtVaGetValues(info->paint, XtNdirty, &flg, NULL); if (flg) AlertBox(shell, msgText[UNSAVED_CHANGES_WISH_TO_CLOSE], closeOkCallback, genericCancelCallback, info); else closeOkCallback(shell, info, NULL); } /* * Reload the image from the last saved file. */ /* * We need to use a work procedure, otherwise X gets confused. * Simplify a bit by assuming that there will never be more than * one revert process going on at any one time. */ static XtWorkProcId workProcId; static int workProcDone; static Boolean workProc(XtPointer w) { if (workProcDone) return True; /* this is a kluge, but it is necessary */ workProcDone = 1; XtRemoveWorkProc(workProcId); XtDestroyWidget(GetShell((Widget) w)); return True; } static void doRevert(Widget w) { void *v; char *file; Widget paint, top; int zoom, snap; Boolean snapon; Pixel background; WidgetList wlist; XtVaGetValues(w, XtNzoom, &zoom, XtNsnap, &snap, XtNsnapOn, &snapon, XtNbackground, &background, XtNmenuwidgets, &wlist, XtNfilename, &file, NULL); if ((file == NULL) || (*file == 0)) return; StateSetBusy(True); top = GetToplevel(w); workProcDone = 0; workProcId = XtAppAddWorkProc(Global.appContext, workProc, (XtPointer) w); if ((v = ReadMagic(file)) != NULL) paint = GraphicOpenFileZoom(top, file, v, zoom); else { StateSetBusy(False); Notice(top, msgText[UNABLE_TO_OPEN_INPUT_FILE], file, RWGetMsg()); return; } XtVaSetValues(paint, XtNsnapOn, snapon, XtNsnap, snap, XtNbackground, background, XtNdirty, False, NULL); StateSetBusy(False); XtVaGetValues(paint, XtNmenuwidgets, &wlist, NULL); if (!wlist) return; MenuCheckItem(wlist[W_SELECTOR_SNAP], snapon); MenuCheckItem(wlist[W_TOPMENU+W_SELECTOR_SNAP], snapon); } static void revertOkCallback(Widget shell, XtPointer arg, XtPointer junk2) { doRevert((Widget) arg); } static void revertCallback(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; Boolean flg; XtVaGetValues(paint, XtNdirty, &flg, NULL); if (flg) AlertBox(GetShell(paint), msgText[UNSAVED_CHANGES_WISH_TO_REVERT], revertOkCallback, genericCancelCallback, paint); } static void printCallback(Widget w, XtPointer paintArg, XtPointer junk2) { PrintPopup(GetToplevel(w), paintArg); } static void externCallback(Widget w, XtPointer paintArg, XtPointer junk2) { ExternPopup(GetToplevel(w), paintArg); } /* * Pop up the fatbits window. */ static void fatCallback(Widget w, XtPointer paint, XtPointer junk2) { FatbitsEdit((Widget) paint); } /* * Toggle the 'grid' menu item. */ static void setGridMenu(Widget paint, void *ptr) { WidgetList wlist; Boolean v; v = (ptr)? True : False; XtVaSetValues(paint, XtNgrid, v, NULL); XtVaGetValues(paint, XtNmenuwidgets, &wlist, NULL); if (!wlist) return; MenuCheckItem(wlist[W_SELECTOR_GRID], v); MenuCheckItem(wlist[W_TOPMENU+W_SELECTOR_GRID], v); } static void gridCallback(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; Boolean v; XtVaGetValues(paint, XtNgrid, &v, NULL); v = !v; GraphicAll(setGridMenu, (void *)((int) v)); } /* ** The set line width callback pair */ static char currentLineWidth[10] = "1"; static void setLineWidth(Widget w, void *width) { XtVaSetValues(w, XtNlineWidth, (int) width, NULL); if (Global.patternshell) { setPatternLineWidth(Global.patterninfo, (int) width); checkPatternLink(w, 1); } else setCanvasColorsIcon(w); } static void setLineWidthMenu(Widget w, void *ptr) { WidgetList wlist; XtVaGetValues(w, XtNmenuwidgets, &wlist, NULL); if (!wlist) return; MenuCheckItem(wlist[W_LINE_WIDTHS+(int)ptr], True); MenuCheckItem(wlist[W_TOPMENU+W_LINE_WIDTHS+(int)ptr], True); } void setToolIconPixmap(Widget paint, void *ptr) { WidgetList wlist; XtVaGetValues(paint, XtNmenuwidgets, &wlist, NULL); if (!wlist) return; setToolIconOnWidget(wlist[W_ICON_TOOL]); XtVaSetValues(wlist[W_ICON_TOOL], XtNwidth, ICONWIDTH, XtNheight, ICONHEIGHT, NULL); } void setCanvasColorsIcon(Widget paint) { WidgetList wlist; static int *x0 = NULL, *x1; Pixel bg, fg, lfg; Pixmap pix, lpix, colpixmap; Display *dpy; GC gc; int v_fr, v_lfr, v_lw, x, y, width, height, depth; if (!paint) return; XtVaGetValues(paint, XtNmenuwidgets, &wlist, NULL); if (!wlist || !wlist[W_ICON_COLORS]) return; colpixmap = (Pixmap) wlist[W_ICON_COLPIXMAP]; if (!colpixmap) return; dpy = XtDisplay(paint); gc = XtGetGC(paint, 0, 0); depth = DefaultDepthOfScreen(XtScreen(paint)); XtVaGetValues(paint, XtNbackground, &bg, NULL); XtVaGetValues(paint, XtNfillRule, &v_fr, NULL); XtVaGetValues(paint, XtNforeground, &fg, NULL); XtVaGetValues(paint, XtNpattern, &pix, NULL); XtVaGetValues(paint, XtNlineFillRule, &v_lfr, NULL); XtVaGetValues(paint, XtNlineForeground, &lfg, NULL); XtVaGetValues(paint, XtNlinePattern, &lpix, NULL); XtVaGetValues(paint, XtNlineWidth, &v_lw, NULL); if (v_lw>10) v_lw = 10; if (!x0) { x0 = (int *) xmalloc(ICONHEIGHT*sizeof(int)); x1 = (int *) xmalloc(ICONHEIGHT*sizeof(int)); for (y=0; yICONHEIGHT-5) { x0[y] = ICONWIDTH; } else x0[y] = 11+abs(y-20)/3; x1[y] = ICONWIDTH-3-abs(y-20)/3; } } for (y=0; yICONHEIGHT-5) { for (x=0; x=ICONHEIGHT-v_lw-5) { if (v_fr == FillSolid) { XSetForeground(dpy, gc, fg); for (x=x0[y]; x<=x1[y]; x++) XDrawPoint(dpy, colpixmap, gc, x, y); } else { GetPixmapWHD(dpy, pix, &width, &height, &depth); for (x=x0[y]; x<=x1[y]; x++) XCopyArea(dpy, pix, colpixmap, gc, x%width, y%height, 1, 1, x, y); } continue; } if (v_fr == FillSolid) { XSetForeground(dpy, gc, fg); for (x=x0[y]; x<=x0[y]+v_lw; x++) XDrawPoint(dpy, colpixmap, gc, x, y); for (x=x1[y]-v_lw; x<=x1[y]; x++) XDrawPoint(dpy, colpixmap, gc, x, y); } else { GetPixmapWHD(dpy, pix, &width, &height, &depth); for (x=x0[y]; x<=x0[y]+v_lw; x++) XCopyArea(dpy, pix, colpixmap, gc, x%width, y%height, 1, 1, x, y); for (x=x1[y]-v_lw; x<=x1[y]; x++) XCopyArea(dpy, pix, colpixmap, gc, x%width, y%height, 1, 1, x, y); } if (v_lfr == FillSolid) { XSetForeground(dpy, gc, lfg); for (x=x0[y]+v_lw+1; x<=x1[y]-v_lw-1; x++) XDrawPoint(dpy, colpixmap, gc, x, y); } else { GetPixmapWHD(dpy, lpix, &width, &height, &depth); for (x=x0[y]+v_lw+1; x<=x1[y]-v_lw-1; x++) XCopyArea(dpy, lpix, colpixmap, gc, x%width, y%height, 1, 1, x, y); } } /* Trick to force refresh of background Pixmap, although pointer value colpixmap didn't change ... */ XtVaSetValues(wlist[W_ICON_COLORS], XtNbackgroundPixmap, XtUnspecifiedPixmap, NULL); XtVaSetValues(wlist[W_ICON_COLORS], XtNbackgroundPixmap, colpixmap, NULL); XtReleaseGC(paint, gc); } void setBrushIconPixmap(Widget paint, void *ptr) { WidgetList wlist; XtVaGetValues(paint, XtNmenuwidgets, &wlist, NULL); if (!wlist) return; setBrushIconOnWidget(wlist[W_ICON_BRUSH]); XtVaSetValues(wlist[W_ICON_BRUSH], XtNwidth, ICONWIDTH, XtNheight, ICONHEIGHT, NULL); } extern void LoadRCInfo(RCInfo *rcInfo, Palette *map); static void setPalettePixmap(Widget paint, LocalInfo *info, int mode) { Display *dpy = XtDisplay(paint); Pixel black = BlackPixelOfScreen(XtScreen(paint)), white = WhitePixelOfScreen(XtScreen(paint)); static Pixmap eye_pix; static Pixmap fill_pix[3]; GC gc; int i, j, k, l, x, y; int width, height, depth; XpmAttributes attributes; WidgetList wlist; XtVaGetValues(paint, XtNmenuwidgets, &wlist, NULL); if (!wlist) return; if (!info->rcInfo) { info->rcInfo = ReadDefaultRC(); LoadRCInfo(info->rcInfo, info->map); info->npixels = 0; for (i=0; ircInfo->ncolors; i++) if (info->rcInfo->colorFlags[i]) ++info->npixels; info->pixels = (Pixel *)xmalloc(info->npixels * sizeof(Pixel)); j = 0; for (i=0; ircInfo->ncolors; i++) { if (info->rcInfo->colorFlags[i]) info->pixels[j++] = info->rcInfo->colorPixels[i]; } info->npatterns = info->rcInfo->nimages; info->patterns = (Pixmap *) xmalloc(info->npatterns * sizeof(Pixmap)); for (i=0; inpatterns; i++) { info->patterns[i] = None; info->rcInfo->images[i]->refCount++; ImageToPixmapCmap(info->rcInfo->images[i], info->paint, &info->patterns[i], info->map->cmap); } } if (!info->palette_pixmap) { info->palette_pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), 422, 10*info->steps-1, DefaultDepthOfScreen(XtScreen(paint))); attributes.valuemask = XpmCloseness; attributes.closeness = 40000; XpmCreatePixmapFromData(dpy, DefaultRootWindow(dpy), eye_xpm, &eye_pix, NULL, &attributes); XpmCreatePixmapFromData(dpy, DefaultRootWindow(dpy), fill0_xpm, &fill_pix[0], NULL, &attributes); XpmCreatePixmapFromData(dpy, DefaultRootWindow(dpy), fill1_xpm, &fill_pix[1], NULL, &attributes); XpmCreatePixmapFromData(dpy, DefaultRootWindow(dpy), fill2_xpm, &fill_pix[2], NULL, &attributes); } gc = XCreateGC(dpy, XtWindow(paint), 0, 0); XCopyArea(dpy, fill_pix[info->channel % 3], info->palette_pixmap, gc, 0, 0, 16, 19, 16, 0); if (mode) goto finish; XCopyArea(dpy, eye_pix, info->palette_pixmap, gc, 0, 0, 16, 19, 0, 0); for (k=0; k<=1; k++) for (y = 19; y<10*info->steps-1; y++) XCopyArea(dpy, eye_pix, info->palette_pixmap, gc, 0, 18, 16, 1, 16*k, y); XSetForeground(dpy, gc, white); for (x = 33; x<422; x++) for (y = 0; y<10*info->steps-1; y++) XDrawPoint(dpy, info->palette_pixmap, gc, x, y); i = -info->steps; j = -info->steps; for (x = 32; x<422; x++) { if ((x-32)%10 == 0) { XSetForeground(dpy, gc, black); for (y = 0; y<10*info->steps-1; y++) XDrawPoint(dpy, info->palette_pixmap, gc, x, y); for (k = 1; ksteps; k++) for (l = 0; l<=9; l++) XDrawPoint(dpy, info->palette_pixmap, gc, x+l, 10*k-1); ++x; i += info->steps; if (i >= info->npixels) j += info->steps; } for (k = 0; ksteps; k++) { if (i+knpixels) { XSetForeground(dpy, gc, info->pixels[i+k]); for (y = 0; y<=8; y++) XDrawPoint(dpy, info->palette_pixmap, gc, x, y+10*k); } else { if (j+k>=0 && j+knpatterns) { GetPixmapWHD(dpy, info->patterns[j+k], &width, &height, &depth); for (y = 0; y<=8; y++) { XCopyArea(dpy, info->patterns[j+k], info->palette_pixmap, gc, ((x-32)%10)%width, y%height, 1, 1, x, y+10*k); } } } } } finish: XtVaSetValues(wlist[W_ICON_PALETTE], XtNbackgroundPixmap, XtUnspecifiedPixmap, NULL); XtVaSetValues(wlist[W_ICON_PALETTE], XtNbackgroundPixmap, info->palette_pixmap, NULL); XtReleaseGC(paint, gc); } void AddItemToCanvasPalette(Widget paint, Pixel p, Pixmap pix) { Display *dpy = XtDisplay(paint); LocalInfo *info; WidgetList wlist; int i; XtVaGetValues(paint, XtNmenuwidgets, &wlist, NULL); if (!wlist) return; info = (LocalInfo *)wlist[W_INFO_DATA]; if (!info) return; if (p != None) { i = info->npixels; info->npixels = i+1; info->pixels = realloc(info->pixels, info->npixels * sizeof(Pixel)); info->pixels[i] = p; } if (pix != None) { i = info->npatterns; info->npatterns = i+1; info->patterns = realloc(info->patterns, info->npixels * sizeof(Pixel)); info->patterns[i] = dupPixmap(dpy, pix); } setPalettePixmap(paint, info, 0); } static void paletteHandler(Widget w, LocalInfo * info, XEvent * event, Boolean * flg) { Display *dpy = XtDisplay(w); Pixmap pix; Pixel p; int i, j, rule; if (!event) return; if (event->type == ButtonRelease) { if (event->xbutton.x<16) { if (event->xbutton.y<18) { DoGrabPixel(info->paint, &p, &info->map->cmap); j = 1; for (i=0; inpixels; i++) if (p == info->pixels[i]) { j = 0; break; } if (j) { i = info->npixels; info->npixels = i+1; info->pixels = realloc(info->pixels, info->npixels * sizeof(Pixel)); info->pixels[i] = p; setPalettePixmap(info->paint, info, 0); } if (info->channel & 1) { XtVaGetValues(info->paint, XtNfillRule, &rule, XtNpattern, &pix, NULL); XtVaSetValues(info->paint, XtNfillRule, FillSolid, XtNforeground, p, NULL); if (rule==FillTiled && pix) XFreePixmap(dpy, pix); } if (info->channel & 2) { XtVaGetValues(info->paint, XtNlineFillRule, &rule, XtNlinePattern, &pix, NULL); XtVaSetValues(info->paint, XtNlineFillRule, FillSolid, XtNlineForeground, p, NULL); if (rule==FillTiled && pix) XFreePixmap(dpy, pix); } setCanvasColorsIcon(info->paint); } } else if (event->xbutton.x>=16 && event->xbutton.x<32) { if (event->xbutton.y<18) { info->channel = 1 + info->channel % 3; setPalettePixmap(info->paint, info, 1); } } else { i = info->steps*((event->xbutton.x-32)/10) + event->xbutton.y/10; if (inpixels) { p = info->pixels[i]; if (info->channel & 1) { XtVaGetValues(info->paint, XtNfillRule, &rule, XtNpattern, &pix, NULL); XtVaSetValues(info->paint, XtNfillRule, FillSolid, XtNforeground, p, NULL); if (rule==FillTiled && pix) XFreePixmap(dpy, pix); } if (info->channel & 2) { XtVaGetValues(info->paint, XtNlineFillRule, &rule, XtNlinePattern, &pix, NULL); XtVaSetValues(info->paint, XtNlineFillRule, FillSolid, XtNlineForeground, p, NULL); if (rule==FillTiled && pix) XFreePixmap(dpy, pix); } } else { i = i - ((info->npixels + info->steps-1)/info->steps) * info->steps; if (i>=0 && inpatterns && (info->channel&1)) { XtVaGetValues(info->paint, XtNfillRule, &rule, XtNpattern, &pix, NULL); XtVaSetValues(info->paint, XtNfillRule, FillTiled, XtNpattern, dupPixmap(dpy,info->patterns[i]), NULL); if (rule==FillTiled && pix) XFreePixmap(dpy, pix); } if (i>=0 && inpatterns && (info->channel&2)) { XtVaGetValues(info->paint, XtNlineFillRule, &rule, XtNlinePattern, &pix, NULL); XtVaSetValues(info->paint, XtNlineFillRule, FillTiled, XtNlinePattern, dupPixmap(dpy,info->patterns[i]), NULL); if (rule==FillTiled && pix) XFreePixmap(dpy, pix); } } setCanvasColorsIcon(info->paint); } } } void setMemoryIcon(Widget w, LocalInfo * info) { Display *dpy = XtDisplay(w); WidgetList wlist; Widget paint; Pixel pixel, black, white; GC gc; int i, j, k, l; int memw, memh; char buf[40]; if (!info) { XtVaGetValues(w, XtNmenuwidgets, &wlist, NULL); if (!wlist) return; info = (LocalInfo *)wlist[W_INFO_DATA]; } paint = info->paint; black = BlackPixelOfScreen(XtScreen(paint)); white = WhitePixelOfScreen(XtScreen(paint)); gc = XCreateGC(dpy, XtWindow(paint), 0, 0); memw = 15; memh = 26 + 10*info->steps; XtVaGetValues(info->memory, XtNbackground, &pixel, NULL); if (info->mem_pixmap == None) { info->mem_pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), memw, memh, DefaultDepthOfScreen(XtScreen(paint))); XSetForeground(dpy, gc, pixel); for (j=0; jmem_pixmap, gc, i, j); XSetForeground(dpy, gc, black); for (j=0; j<=memh-1; j+=memh-1) for (i=0; imem_pixmap, gc, i, j); for (i=0; i<=memw-1; i+=memw-1) for (j=0; jmem_pixmap, gc, i, j); } if (7+6*((Global.numregions-1)/2)mem_shift = 0; if (info->mem_index == -1) l = -1; else l = (info->mem_index+info->mem_shift) % Global.numregions; if (l>=0) { if (info->mem_shift) sprintf(buf, "%d / %d (+%d)", info->mem_index+1, Global.numregions, info->mem_shift); else sprintf(buf, "%d / %d", info->mem_index+1, Global.numregions); XtVaSetValues(info->position, XtNlabel, buf, NULL); XtVaSetValues(info->position, XtNwidth, POS_WIDTH, NULL); } for (k=0; k<=Global.numregions; k++) { i = k%2; j = k/2; if (7+6*j >= memh) break; XSetForeground(dpy, gc, white); XFillRectangle(dpy, info->mem_pixmap, gc, 2+6*i, 2+6*j, 4, 4); XSetForeground(dpy, gc, (k==Global.numregions)?pixel:black); if (k == Global.numregions) XFillRectangle(dpy, info->mem_pixmap, gc, 2+6*i, 2+6*j, 5, 5); else if (k == l) XFillRectangle(dpy, info->mem_pixmap, gc, 2+6*i, 2+6*j, 4, 4); else XDrawRectangle(dpy, info->mem_pixmap, gc, 2+6*i, 2+6*j, 4, 4); } XtVaSetValues(info->memory, XtNbackgroundPixmap, XtUnspecifiedPixmap, NULL); XtVaSetValues(info->memory, XtNbackgroundPixmap, info->mem_pixmap, NULL); XFreeGC(dpy, gc); XtVaGetValues(info->paint, XtNmenuwidgets, &wlist, NULL); if (wlist) { l = (Global.numregions>0); if (wlist[W_EDIT_RECALL]) XtVaSetValues(wlist[W_EDIT_RECALL], XtNsensitive, l, NULL); if (wlist[W_TOPMENU+W_EDIT_RECALL]) XtVaSetValues(wlist[W_TOPMENU+W_EDIT_RECALL], XtNsensitive, l, NULL); if (wlist[W_EDIT_REMOVE]) XtVaSetValues(wlist[W_EDIT_REMOVE], XtNsensitive, l, NULL); if (wlist[W_TOPMENU+W_EDIT_REMOVE]) XtVaSetValues(wlist[W_TOPMENU+W_EDIT_REMOVE], XtNsensitive, l, NULL); } } static void removeFromMemory(Display *dpy, int num) { Pixmap pix, mask; int i; if (num<0 || num>=Global.numregions) return; pix = Global.regiondata[num].pix; mask = Global.regiondata[num].mask; if (pix!=None) XFreePixmap(dpy, pix); if (mask!=None) XFreePixmap(dpy, mask); --Global.numregions; for (i=num; ipaint); int width, height, depth; GC gc; XRectangle rect; Pixmap pix, mask; PaintWidget pw = (PaintWidget) info->paint; if (info->mem_index<0) return; if (info->mem_index>=Global.numregions) return; GetPixmapWHD(dpy, Global.regiondata[info->mem_index].pix, &width, &height, &depth); rect.x = Global.regiondata[info->mem_index].x; rect.y = Global.regiondata[info->mem_index].y; rect.width = width; rect.height = height; pix = XCreatePixmap(dpy, DefaultRootWindow(dpy), width, height, depth); gc = XCreateGC(dpy, pix, 0, 0); XCopyArea(dpy, Global.regiondata[info->mem_index].pix, pix, gc, 0, 0, width, height, 0, 0); XFreeGC(dpy, gc); mask = Global.regiondata[info->mem_index].mask; if (mask) { mask = XCreatePixmap(dpy, DefaultRootWindow(dpy), width, height, 1); gc = XCreateGC(dpy, mask, 0, 0); XCopyArea(dpy, Global.regiondata[info->mem_index].mask, mask, gc, 0, 0, width, height, 0, 0); XFreeGC(dpy, gc); } pw->paint.zoomX = 0; pw->paint.zoomY = 0; pw->paint.downX = 0; pw->paint.downY = 0; PwRegionSet(info->paint, &rect, pix, mask); RegionMove(pw, rect.x, rect.y); } static void memoryHandler(Widget w, LocalInfo * info, XEvent * event, Boolean * flg) { Display *dpy = XtDisplay(w); int i, j, x, y, num, no_rotation; num = 0; if (event->type == ButtonRelease && event->xbutton.button == 2) { i = Global.numregions; StdMemoryCallback(w, info, NULL); if (Global.numregions>i) info->mem_index = i; setMemoryIcon(w, info); return; } no_rotation = (7+6*((Global.numregions-1)/2)<26 + 10*info->steps); if ((event->type == ButtonPress || event->type == ButtonRelease) && (event->xbutton.button == 1 || event->xbutton.button == 3)) { num = -1; i = (event->xbutton.x-2)/6; j = (event->xbutton.y-2)/6; x = 2+6*i; y = 2+6*j; if (event->xbutton.x>=x && event->xbutton.x<=x+4 && event->xbutton.y>=y && event->xbutton.y<=y+4) { num = i+2*j; if (num>=0 && nummem_shift) % Global.numregions; if (event->type == ButtonPress) info->mem_index = num; if (event->xbutton.button == 1 && event->type == ButtonRelease) { if (num == info->mem_index || no_rotation) { info->mem_index = num; PwRegionOff(info->paint, True); recallCallback(w, info, NULL); } else { if (info->mem_index>=0) { info->mem_shift += Global.numregions+num-info->mem_index; info->mem_shift = info->mem_shift % Global.numregions; } } } if (event->xbutton.button == 3 && event->type == ButtonRelease) { removeFromMemory(dpy, num); info->mem_index = -1; } setMemoryIcon(w, info); return; } } } } /* This manages Window resize of main canvas */ static void changeSize(Widget w, LocalInfo * l, XEvent * event, Boolean * flg) { Dimension u, v, up, vp, us, vs; Boolean bool; if (event->type == ConfigureNotify) { u = WidthOfScreen(XtScreen(w)); v = HeightOfScreen(XtScreen(w)); XtVaGetValues(w, XtNwidth, &up, XtNheight, &vp, NULL); if (up > u - 20) up = u - 20; if (vp > v - 80) vp = v - 80; if (up >= u-20 || vp >= v-80) XtVaSetValues(w, XtNwidth, up, XtNheight, vp, NULL); XtVaGetValues(l->paint, XtNwidth, &u, XtNheight, &v, NULL); XtVaGetValues(l->viewport, XtNwidth, &up, XtNheight, &vp, NULL); if (up>=u+10) us = up-4; else us = u+10; if (vp>=v+10) vs = vp-4; else vs = v+10; XtVaSetValues(l->paintbox, XtNwidth, us, XtNheight, vs, NULL); XtVaGetValues(l->viewport, XtNallowVert, &bool, NULL); #if defined(XAW3DG) || defined(XAW95) if (up>=u+14 && vp>=v+14) { #else if (up>=u+10 && vp>=v+10) { #endif XtVaSetValues(l->viewport, XtNallowVert, False, XtNallowHoriz, False, NULL); } else { XtVaSetValues(l->viewport, XtNallowVert, True, XtNallowHoriz, True, NULL); bool = !bool; } if (bool) { ++l->boolcount; if (l->boolcount>=2) { XtUnmanageChild(l->paint); XtManageChild(l->paint); } } } } static int xorig = 0; static int yorig = 0; static void buttonHandler(Widget w, LocalInfo * info, XEvent * event, Boolean * flg) { xorig = event->xbutton.x; yorig = event->xbutton.y; } static void motionHandler(Widget w, LocalInfo * info, XEvent * event, Boolean * flg) { char buf[30]; int zoom, h; if (info->boolpos) { XtVaGetValues(w, XtNzoom, &zoom, XtNheight, &h, NULL); if (((XButtonEvent *) event)->state & ControlMask) { sprintf(buf, "%d %d", (event->xbutton.x - xorig)/zoom, (event->xbutton.y - yorig)/zoom); } else sprintf(buf, "%d %d", event->xbutton.x/zoom, event->xbutton.y/zoom); XtVaSetValues(info->position, XtNlabel, buf, NULL); XtVaSetValues(info->position, XtNwidth, POS_WIDTH, NULL); } } void motionExtern(Widget paint, XEvent * event, int x, int y, int flag) { LocalInfo *info; WidgetList wlist; char buf[30]; int h; XtVaGetValues(paint, XtNmenuwidgets, &wlist, XtNdrawHeight, &h, NULL); if (!wlist) return; info = (LocalInfo *)wlist[W_INFO_DATA]; if (flag) { xorig = x; yorig = y; } if (info->boolpos) { if (((XButtonEvent *) event)->state & ControlMask) { sprintf(buf, "%4d %4d", x - xorig, y - yorig); } else sprintf(buf, "%4d %4d", x, y); XtVaSetValues(info->position, XtNlabel, buf, NULL); XtVaSetValues(info->position, XtNwidth, POS_WIDTH, NULL); } } static void positionHandler(Widget w, LocalInfo * info, XEvent * event, Boolean * flg) { info->boolpos = !info->boolpos; XtVaSetValues(info->position, XtNlabel, (info->boolpos)? "??? ???" : msgText[POSITION], NULL); XtVaSetValues(info->position, XtNwidth, POS_WIDTH, NULL); xorig = 0; yorig = 0; } static void formHandler(Widget w, LocalInfo * info, XEvent * event, Boolean * flg) { Display *dpy = XtDisplay(w); Dimension v; WidgetList wlist; int i; XtVaGetValues(info->paint, XtNmenuwidgets, &wlist, NULL); XtVaGetValues(w, XtNheight, &v, NULL); i = (v - 32)/10; if (i<2) i = 2; if (wlist && i != info->steps) { info->steps = i; XFreePixmap(XtDisplay(w), info->palette_pixmap); info->palette_pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), 422, 10*info->steps-1, DefaultDepthOfScreen(XtScreen(info->paint))); if (info->mem_pixmap) { XFreePixmap(XtDisplay(w), info->mem_pixmap); info->mem_pixmap = None; setMemoryIcon(info->paint, info); XtVaSetValues(info->memory, XtNheight, 26 + 10*info->steps, NULL); } XtVaSetValues(wlist[W_ICON_PALETTE], XtNheight, 10*info->steps-1, NULL); setPalettePixmap(info->paint, info, 0); changeSize(GetToplevel(info->paint), info, event, flg); } } static void okLineCallback(Widget w, XtPointer junk, XtPointer infoArg) { Arg arg; TextPromptInfo *info = (TextPromptInfo *) infoArg; int width = atoi(info->prompts[0].rstr); if (width < 1 || width > 1000) { Notice(w, msgText[INVALID_WIDTH_MUST_BE_GREATER_THAN_ZERO]); return; } sprintf(currentLineWidth, "%d", width); if (width == 1) width = 0; GraphicAll(setLineWidth, (void *) width); XtSetArg(arg, XtNlineWidth, width); OperationAddArg(arg); } void lineWidth(Widget w, int width) { String lbl; XtVaGetValues(w, XtNlabel, &lbl, NULL); width = atoi(lbl); if (width <= 0) { static TextPromptInfo info; static struct textPromptInfo value[1]; value[0].prompt = msgText[LINE_WIDTH]; value[0].str = currentLineWidth; value[0].len = 4; info.prompts = value; info.title = msgText[ENTER_DESIRED_LINE_WIDTH]; info.nprompt = 1; GraphicAll(setLineWidthMenu, (void *)LINE_WIDTH_GENERAL); TextPrompt(GetToplevel(w), "linewidth", &info, okLineCallback, NULL, NULL); } else { Arg arg; if (width == 1) width = 0; GraphicAll(setLineWidth, (void *) width); GraphicAll(setLineWidthMenu, (void *) (width/2)); XtSetArg(arg, XtNlineWidth, width); OperationAddArg(arg); } } static void dashOkCallback(Widget w, XtPointer junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; int i, length, valid; length = strlen(info->prompts[0].rstr); if (length > 48) valid = 0; else { valid = 1; for (i = 0; iprompts[0].rstr[i] != '-' && info->prompts[0].rstr[i] != '=') { valid = 0; break; } } if (!valid) { Notice(w, msgText[DASH_IS_GIVEN_BY_ALTERNATING_SUCH_CHARACTERS]); return; } strcpy(dashStyleStr, info->prompts[0].rstr); DashSetStyle(dashStyleStr); } static void dashMenuCallback(Widget w) { static TextPromptInfo info; static struct textPromptInfo value[1]; value[0].prompt = msgText[DASH_STYLE]; value[0].str = dashStyleStr; value[0].len = 48; info.prompts = value; info.title = msgText[ENTER_DESIRED_DASH_STYLE]; info.nprompt = 1; TextPrompt(w, "dashselect", &info, dashOkCallback, NULL, NULL); } void changeDashStyleAction(Widget w, XEvent * event) { dashMenuCallback(GetToplevel(w)); } /* ** Font menu callbacks. */ void setFontIcon(Widget paint) { WidgetList wlist; XFontStruct * info; XtVaGetValues(paint, XtNmenuwidgets, &wlist, XtNfont, &info, NULL); if (wlist && wlist[W_ICON_FONT]) { XtVaSetValues(wlist[W_ICON_FONT], XtNfont, info, NULL); XtVaSetValues(wlist[W_ICON_FONT], XtNwidth, ICONWIDTH, XtNheight, ICONHEIGHT, NULL); /* XFlush(XtDisplay(paint)); */ XtResizeWidget(wlist[W_ICON_FONT], ICONWIDTH, ICONHEIGHT, #ifdef XAWPLAIN 1); #else 0); #endif } } static void fontSetCallback(Widget paint, void *info) { XtVaSetValues(paint, XtNfont, (XFontStruct *) info, NULL); FontChanged(paint); } static void fontMenuCallback(Widget paint, void *ptr) { WidgetList wlist; int i; if (ptr) i = (int)ptr - 1; else i = 10; XtVaGetValues(paint, XtNmenuwidgets, &wlist, NULL); if (!wlist) return; MenuCheckItem(wlist[W_FONT_DESCR+i], True); MenuCheckItem(wlist[W_TOPMENU+W_FONT_DESCR+i], True); } static void fontSet(Widget w, void *ptr) { XFontStruct *info; Arg arg; if (ptr == NULL) { GraphicAll(fontMenuCallback, NULL); FontSelect(w, None); } else { if ((info = XLoadQueryFont(XtDisplay(GetShell(w)), fontNames[(int)ptr-1])) == NULL) { XtVaSetValues(w, XtNsensitive, False, NULL); Notice(w, msgText[UNABLE_TO_LOAD_REQUESTED_FONT]); return; } GraphicAll(fontSetCallback, (void *) info); GraphicAll(fontMenuCallback, ptr); XtSetArg(arg, XtNfont, info); OperationAddArg(arg); } } /* * Toggle the 'snap' menu item. */ static void setSnapMenu(Widget paint, void *ptr) { WidgetList wlist; Boolean v; v = (ptr)? True : False; XtVaSetValues(paint, XtNsnapOn, v, NULL); XtVaGetValues(paint, XtNmenuwidgets, &wlist, NULL); if (!wlist) return; MenuCheckItem(wlist[W_SELECTOR_SNAP], v); MenuCheckItem(wlist[W_TOPMENU+W_SELECTOR_SNAP], v); } static void snapCallback(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; Boolean v; XtVaGetValues(paint, XtNsnapOn, &v, NULL); v = !v; GraphicAll(setSnapMenu, (void *)((int) v)); } /* * Callbacks for setting snap spacing. */ static int snapSpacing = 10; static void changeSnapOkCallback(Widget paint, void *junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; int v = atoi(info->prompts[0].rstr); if (v < 1 || v > 100) { Notice(paint, msgText[BAD_SNAP_SPACING]); return; } snapSpacing = v; XtVaSetValues(paint, XtNsnap, v, NULL); } static void changeSnapCallback(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; static TextPromptInfo info; static struct textPromptInfo value[1]; static char buf[10]; sprintf(buf, "%d", snapSpacing); value[0].prompt = msgText[SPACING]; value[0].str = buf; value[0].len = 4; info.prompts = value; info.title = msgText[ENTER_DESIRED_SNAP_SPACING]; info.nprompt = 1; TextPrompt(paint, "linewidth", &info, changeSnapOkCallback, NULL, NULL); } /* * Callback for changing the image size. */ static void sizeCallback(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; SizeSelect(GetShell(paint), paint, NULL); } static void defaultsizeCallback(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; SizeSelect(GetShell(paint), NULL, NULL); } static void autocropOkCallback(Widget w, XtPointer argArg, XtPointer junk) { AutoCrop((Widget) argArg); } static void undosizeOkCallback(Widget paint, void * junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; int n = atoi(info->prompts[0].rstr); if (n < 0 || n > 20) { Notice(paint, msgText[BAD_NUMBER_OF_UNDO_LEVELS]); return; } XtVaSetValues(paint, XtNundoSize, n, NULL); } static void undosizeCallback(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; static TextPromptInfo info; static struct textPromptInfo value[1]; static char buf[5]; int undosize; XtVaGetValues(paint, XtNundoSize, &undosize, NULL); sprintf(buf, "%d", undosize); value[0].prompt = msgText[LEVELS]; value[0].str = buf; value[0].len = 3; info.prompts = value; info.title = msgText[NUMBER_OF_UNDO_LEVELS]; info.nprompt = 1; TextPrompt(paint, "undolevels", &info, undosizeOkCallback, NULL, NULL); } static void autocropCallback(Widget w, XtPointer paintArg, XtPointer junk2) { AlertBox(GetShell(paintArg), msgText[AUTOCROP_WARNING_CANNOT_BE_UNDONE], autocropOkCallback, genericCancelCallback, paintArg); } /* * Callback functions for changing zoom */ static void zoomAddChild(Widget paint, int zoom) { Cardinal nc; Widget t, box = XtParent(paint); WidgetList children; int dw, dh; /* * 1 child == just paint widget * 2 children paint widget + normal size view */ XtVaGetValues(box, XtNchildren, &children, XtNnumChildren, &nc, NULL); XtVaGetValues(paint, XtNdrawWidth, &dw, XtNdrawHeight, &dh, NULL); if (nc == 1 && zoom > 1 && dw < 256 && dh < 256) { /* * Add child */ t = XtVaCreateManagedWidget("norm", paintWidgetClass, box, XtNpaint, paint, XtNzoom, 1, NULL); GraphicAdd(t); } else if (nc != 1 && zoom <= 1) { /* * Remove child */ t = children[(children[0] == paint) ? 1 : 0]; XtDestroyWidget(t); } } static void zoomOkCallback(Widget w, XtPointer paintArg, XtPointer infoArg) { Widget paint = (Widget) paintArg; TextPromptInfo *info = (TextPromptInfo *) infoArg; int zoom = atoi(info->prompts[0].rstr); int oldzoom, dw, dh; Dimension u, v; if (zoom < 1 || zoom > 32) { Notice(paint, msgText[INVALID_ZOOM]); } else { XtVaGetValues(paint, XtNzoom, &oldzoom, XtNdrawWidth, &dw, XtNdrawHeight, &dh, NULL); if (oldzoom == zoom) return; XtUnmanageChild(paint); XtVaSetValues(paint, XtNwidth, dw*zoom, XtNheight, dh*zoom, XtNzoom, zoom, NULL); zoomAddChild(paint, zoom); if ((CurrentOp->add == BrushAdd) || (CurrentOp->add == EraseAdd) || (CurrentOp->add == SmearAdd)) { if (zoom > 1) { SetCrossHairCursor(paint); FatCursorAddZoom(zoom, paint); } else FatCursorRemoveZoom(paint); } FatbitsUpdate(paint, zoom); w = XtParent(XtParent(paint)); XtVaGetValues(w, XtNwidth, &u, XtNheight, &v, NULL); #if defined(XAW3DG) || defined(XAW95) if (u >= dw*zoom+14 && v >= dh*zoom+14) #else if (u >= dw*zoom+10 && v >= dh*zoom+10) #endif XtVaSetValues(XtParent(XtParent(paint)), XtNallowVert, False, XtNallowHoriz, False, NULL); else XtVaSetValues(XtParent(XtParent(paint)), XtNallowVert, True, XtNallowHoriz, True, NULL); XtManageChild(paint); } } void zoomCallback(Widget w, XtPointer paintArg, XtPointer junk2) { static TextPromptInfo info; static struct textPromptInfo values[2]; char buf[80]; int zoom; Widget paint = (Widget) paintArg; info.nprompt = 1; info.prompts = values; info.title = msgText[CHANGE_ZOOM_FACTOR_FOR_IMAGE]; values[0].prompt = msgText[ZOOM]; values[0].len = 4; values[0].str = buf; XtVaGetValues(paint, XtNzoom, &zoom, NULL); sprintf(buf, "%d", (int) zoom); TextPrompt(GetShell(paint), "zoomselect", &info, zoomOkCallback, NULL, paint); } /* * Callback functions for Region menu */ static void rotateTo(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; float t; pwMatrix m; String lbl; XtVaGetValues(w, XtNlabel, &lbl, NULL); t = atof(lbl); if (t == 0.0) return; t *= M_PI / 180.0; m[0][0] = cos(t); m[0][1] = sin(t); m[1][0] = -sin(t); m[1][1] = cos(t); PwRegionAppendMatrix(paint, m); } static int rotateAngle = 0; static void rotateOkCallback(Widget paint, void *junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; float t = atof(info->prompts[0].rstr) * M_PI / 180.0; pwMatrix m; m[0][0] = cos(t); m[0][1] = -sin(t); m[1][0] = sin(t); m[1][1] = cos(t); PwRegionAppendMatrix(paint, m); rotateAngle = (int) t; } static void rotate(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; static TextPromptInfo info; static struct textPromptInfo value[1]; static char buf[10]; sprintf(buf, "%d", rotateAngle); value[0].prompt = msgText[ANGLE_IN_DEGREES]; value[0].str = buf; value[0].len = 4; info.prompts = value; info.title = msgText[ENTER_DESIRED_ROTATION]; info.nprompt = 1; TextPrompt(paint, "rotation", &info, rotateOkCallback, NULL, NULL); } static void resetMat(Widget w, XtPointer paintArg, XtPointer junk2) { PwRegionReset((Widget) paintArg, True); } static void cropToRegionOkCallback(Widget w, PaintWidget paint, XtPointer infoArg) { RegionCrop(paint); } static void cropToRegion(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; AlertBox(GetShell(paint), msgText[ARE_YOU_SURE_YOU_WANT_TO_CROP_THE_IMAGE_TO_THE_SIZE_OF_THE_REGION], (XtCallbackProc) cropToRegionOkCallback, genericCancelCallback, paint); } static void linearRegionOkCallback(Widget paint, void *junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; pwMatrix m; ImgProcessInfo.linearA = atof(info->prompts[0].rstr); ImgProcessInfo.linearB= atof(info->prompts[1].rstr); ImgProcessInfo.linearC = atof(info->prompts[2].rstr); ImgProcessInfo.linearD = atof(info->prompts[3].rstr); m[0][0] = atof(info->prompts[0].rstr); m[0][1] = -atof(info->prompts[1].rstr); m[1][0] = -atof(info->prompts[2].rstr); m[1][1] = atof(info->prompts[3].rstr); PwRegionAppendMatrix(paint, m); } static void linearRegion(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; static TextPromptInfo info; static struct textPromptInfo value[4]; static char buf1[10], buf2[10], buf3[10], buf4[10]; sprintf(buf1, "%g", ImgProcessInfo.linearA); sprintf(buf2, "%g", ImgProcessInfo.linearB); sprintf(buf3, "%g", ImgProcessInfo.linearC); sprintf(buf4, "%g", ImgProcessInfo.linearD); value[0].prompt = "a11 ="; value[0].str = buf1; value[0].len = 4; value[1].prompt = "a12 ="; value[1].str = buf2; value[1].len = 4; value[2].prompt = "a21 ="; value[2].str = buf3; value[2].len = 4; value[3].prompt = "a22 ="; value[3].str = buf4; value[3].len = 4; info.prompts = value; info.title = msgText[ENTER_TWOBYTWO_MATRIX_ENTRIES]; info.nprompt = 4; TextPrompt(paint, "linear", &info, linearRegionOkCallback, NULL, NULL); } static void tiltRegionOkCallback(Widget paint, void *junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; ImgProcessInfo.tiltX1 = atoi(info->prompts[0].rstr); ImgProcessInfo.tiltY1 = atoi(info->prompts[1].rstr); ImgProcessInfo.tiltX2 = atoi(info->prompts[2].rstr); ImgProcessInfo.tiltY2 = atoi(info->prompts[3].rstr); StdRegionTilt(paint, paint, NULL); } static void tiltRegion(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; static TextPromptInfo info; static struct textPromptInfo value[4]; static char buf1[10], buf2[10], buf3[10], buf4[10]; sprintf(buf1, "%d", ImgProcessInfo.tiltX1); sprintf(buf2, "%d", ImgProcessInfo.tiltY1); sprintf(buf3, "%d", ImgProcessInfo.tiltX2); sprintf(buf4, "%d", ImgProcessInfo.tiltY2); value[0].prompt = "X1:"; value[0].str = buf1; value[0].len = 4; value[1].prompt = "Y1:"; value[1].str = buf2; value[1].len = 4; value[2].prompt = "X2:"; value[2].str = buf3; value[2].len = 4; value[3].prompt = "Y2:"; value[3].str = buf4; value[3].len = 4; info.prompts = value; info.title = msgText[ENTER_POINTS]; info.nprompt = 4; TextPrompt(paint, "tilt", &info, tiltRegionOkCallback, NULL, NULL); } static void unselectRegion(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; PwRegionSet(paint, None, None, None); } /* * Callback functions for Filter menu */ static void oilPaintOkCallback(Widget paint, void *junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; int t; t = atoi(info->prompts[0].rstr); if ((t < 3) || ((t & 1) == 0)) { Notice(paint, msgText[INVALID_MASK_SIZE]); return; } ImgProcessInfo.oilArea = t; StdRegionOilPaint(paint, paint, NULL); } static void oilPaint(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; static TextPromptInfo info; static struct textPromptInfo value[1]; static char buf[10]; sprintf(buf, "%d", ImgProcessInfo.oilArea); info.prompts = value; info.title = msgText[ENTER_MASK_SIZE_FOR_OIL_PAINT_EFFECT]; info.nprompt = 1; value[0].prompt = msgText[MUST_BE_ODD]; value[0].str = buf; value[0].len = 3; TextPrompt(paint, "mask", &info, oilPaintOkCallback, NULL, NULL); } static void SmoothOkCallback(Widget paint, void *junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; int t; t = atoi(info->prompts[0].rstr); if ((t < 3) || ((t & 1) == 0)) { Notice(paint, msgText[INVALID_MASK_SIZE]); return; } ImgProcessInfo.smoothMaskSize = t; StdRegionSmooth(paint, paint, NULL); } static void doSmooth(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; static TextPromptInfo info; static struct textPromptInfo value[1]; static char buf[10]; sprintf(buf, "%d", ImgProcessInfo.smoothMaskSize); info.prompts = value; info.title = msgText[ENTER_MASK_SIZE_FOR_SMOOTHING_EFFECT]; info.nprompt = 1; value[0].prompt = msgText[MUST_BE_ODD]; value[0].str = buf; value[0].len = 3; TextPrompt(paint, "mask", &info, SmoothOkCallback, NULL, NULL); } static void addNoiseOkCallback(Widget paint, void *junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; int t; t = atoi(info->prompts[0].rstr); if (t < 1) { Notice(paint, msgText[INVALID_NOISE_VARIANCE]); return; } ImgProcessInfo.noiseDelta = t; StdRegionAddNoise(paint, paint, NULL); } static void addNoise(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; static TextPromptInfo info; static struct textPromptInfo value[1]; static char buf[10]; sprintf(buf, "%d", ImgProcessInfo.noiseDelta); value[0].prompt = "(0-255):"; value[0].str = buf; value[0].len = 3; info.prompts = value; info.title = msgText[ENTER_DESIRED_NOISE_VARIANCE]; info.nprompt = 1; TextPrompt(paint, "delta", &info, addNoiseOkCallback, NULL, NULL); } static void doSpreadOkCallback(Widget paint, void *junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; int t; t = atoi(info->prompts[0].rstr); if (t < 1) { Notice(paint, msgText[INVALID_SPREAD_DISTANCE]); return; } ImgProcessInfo.spreadDistance = t; StdRegionSpread(paint, paint, NULL); } static void doSpread(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; static TextPromptInfo info; static struct textPromptInfo value[1]; static char buf1[10]; sprintf(buf1, "%d", ImgProcessInfo.spreadDistance); value[0].prompt = msgText[DISTANCE_PIXELS]; value[0].str = buf1; value[0].len = 3; info.prompts = value; info.title = msgText[ENTER_THE_DESIRED_SPREAD_DISTANCE]; info.nprompt = 1; TextPrompt(paint, "distance", &info, doSpreadOkCallback, NULL, NULL); } static void doPixelizeOkCallback(Widget paint, void *junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; char *s = info->prompts[0].rstr; int e = 0, tx, ty; if (strchr(s, 'x')) { if (sscanf(s, "%d x %d", &tx, &ty) != 2) ++e; } else { if (sscanf(s, "%d", &tx) != 1) ++e; ty = tx; } if (e || (tx < 1) || (ty < 1)) { Notice(paint, msgText[INVALID_PIXEL_SIZE]); return; } ImgProcessInfo.pixelizeXSize = tx; ImgProcessInfo.pixelizeYSize = ty; StdRegionPixelize(paint, paint, NULL); } static void doPixelize(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; static TextPromptInfo info; static struct textPromptInfo value[1]; static char buf[10]; if (ImgProcessInfo.pixelizeXSize != ImgProcessInfo.pixelizeYSize) sprintf(buf, "%dx%d", ImgProcessInfo.pixelizeXSize, ImgProcessInfo.pixelizeYSize); else sprintf(buf, "%d", ImgProcessInfo.pixelizeXSize); value[0].prompt = msgText[WIDTH_X_HEIGHT_OR_SINGLE_NUMBER]; value[0].str = buf; value[0].len = 3; info.prompts = value; info.title = msgText[ENTER_DESIRED_MEGAPIXEL_SIZE]; info.nprompt = 1; TextPrompt(paint, "size", &info, doPixelizeOkCallback, NULL, NULL); } static void despeckleOkCallback(Widget paint, void *junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; int t; t = atoi(info->prompts[0].rstr); if ((t < 3) || ((t & 1) == 0)) { Notice(paint, msgText[INVALID_MASK_SIZE]); return; } ImgProcessInfo.despeckleMask = t; StdRegionDespeckle(paint, paint, NULL); } static void doDespeckle(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; static TextPromptInfo info; static struct textPromptInfo value[1]; static char buf[10]; sprintf(buf, "%d", ImgProcessInfo.despeckleMask); info.prompts = value; info.title = msgText[ENTER_MASK_SIZE_FOR_DESPECKLE_FILTER]; info.nprompt = 1; value[0].prompt = msgText[MUST_BE_ODD]; value[0].str = buf; value[0].len = 3; TextPrompt(paint, "despeckle", &info, despeckleOkCallback, NULL, NULL); } static void contrastOkCallback(Widget paint, void *junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; int t1, t2; t1 = atoi(info->prompts[0].rstr); if ((t1 < 0) || (t1 > 100)) { Notice(paint, msgText[INVALID_WHITE_LEVEL]); return; } t2 = atoi(info->prompts[1].rstr); if ((t2 < 0) || (t2 > 100)) { Notice(paint, msgText[INVALID_BLACK_LEVEL]); return; } ImgProcessInfo.contrastB = t1; ImgProcessInfo.contrastW = t2; StdRegionNormContrast(paint, paint, NULL); } static void doContrast(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; static TextPromptInfo info; static struct textPromptInfo value[2]; static char buf1[10], buf2[10]; sprintf(buf1, "%d", ImgProcessInfo.contrastB); sprintf(buf2, "%d", ImgProcessInfo.contrastW); info.prompts = value; info.title = msgText[ENTER_LEVELS_FOR_CONTRAST_ADJUSTMENT]; info.nprompt = 2; value[0].prompt = msgText[BLACK_LEVEL]; value[0].str = buf1; value[0].len = 3; value[1].prompt = msgText[WHITE_LEVEL]; value[1].str = buf2; value[1].len = 3; TextPrompt(paint, "contrast", &info, contrastOkCallback, NULL, NULL); } static void solarizeOkCallback(Widget paint, void *junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; int t; t = atoi(info->prompts[0].rstr); if ((t < 1) || (t > 99)) { Notice(paint, msgText[INVALID_SOLARIZATION_THRESHOLD]); return; } ImgProcessInfo.solarizeThreshold = t; StdRegionSolarize(paint, paint, NULL); } static void doSolarize(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; static TextPromptInfo info; static struct textPromptInfo value[1]; static char buf[10]; sprintf(buf, "%d", ImgProcessInfo.solarizeThreshold); info.prompts = value; info.title = msgText[ENTER_THRESHOLD_FOR_SOLARIZE_FILTER]; info.nprompt = 1; value[0].prompt = "(%):"; value[0].str = buf; value[0].len = 3; TextPrompt(paint, "mask", &info, solarizeOkCallback, NULL, NULL); } static void quantizeOkCallback(Widget paint, void *junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; int t; t = atoi(info->prompts[0].rstr); if ((t < 2) || (t > 256)) { Notice(paint, msgText[INVALID_NUMBER_OF_COLORS]); return; } ImgProcessInfo.quantizeColors = t; StdRegionQuantize(paint, paint, NULL); } static void modifyRGBOkCallback(Widget paint, void *junk, XtPointer infoArg) { TextPromptInfo *info = (TextPromptInfo *) infoArg; int r, g, b; r = atoi(info->prompts[0].rstr); g = atoi(info->prompts[1].rstr); b = atoi(info->prompts[2].rstr); if ((r < -100) || (r > 100) || (g < -100) || (g > 100) || (b < -100) || (b > 100)) { Notice(paint, msgText[INVALID_RGB_PERCENTAGES]); return; } ImgProcessInfo.redshift = r; ImgProcessInfo.greenshift = g; ImgProcessInfo.blueshift = b; StdRegionModifyRGB(paint, paint, NULL); } static void doModifyRGB(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; static TextPromptInfo info; static struct textPromptInfo value[3]; static char buf_r[10], buf_g[10], buf_b[10]; sprintf(buf_r, "%d", ImgProcessInfo.redshift); sprintf(buf_g, "%d", ImgProcessInfo.greenshift); sprintf(buf_b, "%d", ImgProcessInfo.blueshift); info.prompts = value; info.title = msgText[ENTER_DESIRED_SHIFT_FOR_RGB_COMPONENTS]; info.nprompt = 3; value[0].prompt = msgText[RED_SHIFT]; value[0].str = buf_r; value[0].len = 4; value[1].prompt = msgText[GREEN_SHIFT]; value[1].str = buf_g; value[1].len = 4; value[2].prompt = msgText[BLUE_SHIFT]; value[2].str = buf_b; value[2].len = 4; TextPrompt(paint, "mask", &info, modifyRGBOkCallback, NULL, NULL); } static void doQuantize(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; static TextPromptInfo info; static struct textPromptInfo value[1]; static char buf[10]; sprintf(buf, "%d", ImgProcessInfo.quantizeColors); info.prompts = value; info.title = msgText[ENTER_DESIRED_NUMBER_OF_COLORS]; info.nprompt = 1; value[0].prompt = "(2-256):"; value[0].str = buf; value[0].len = 3; TextPrompt(paint, "mask", &info, quantizeOkCallback, NULL, NULL); } static void doLast(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; StdLastImgProcess(paint); } static void prCallback(Widget paint, Widget w, Boolean flag) { XtVaSetValues(w, XtNsensitive, flag, NULL); } void EnableRevert(Widget paint) { WidgetList wlist; XtVaGetValues(paint, XtNmenuwidgets, &wlist, NULL); if (!wlist) return; XtVaSetValues(wlist[W_FILE_REVERT], XtNsensitive, True, NULL); XtVaSetValues(wlist[W_TOPMENU+W_FILE_REVERT], XtNsensitive, True, NULL); } void EnableLast(Widget paint) { WidgetList wlist; XtVaGetValues(paint, XtNmenuwidgets, &wlist, NULL); if (!wlist) return; XtVaSetValues(wlist[W_REGION_LAST], XtNsensitive, True, NULL); XtVaSetValues(wlist[W_REGION_UNDO], XtNsensitive, True, NULL); XtVaSetValues(wlist[W_TOPMENU+W_REGION_LAST], XtNsensitive, True, NULL); XtVaSetValues(wlist[W_TOPMENU+W_REGION_UNDO], XtNsensitive, True, NULL); } /* * Background changer */ static void changeBgOk(Widget w, Palette * map, XColor * col) { StateShellBusy(w, False); if (col != NULL) { Pixel pix = PaletteAlloc(map, col); XtVaSetValues(w, XtNbackground, pix, NULL); if (Global.patternshell) checkPatternLink(w, 1); else setCanvasColorsIcon(w); } } void changeBackground(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; Colormap cmap; Pixel bg; Palette *map; /* StateShellBusy(paint, True); */ XtVaGetValues(GetShell(paint), XtNcolormap, &cmap, NULL); XtVaGetValues(paint, XtNbackground, &bg, NULL); map = PaletteFind(paint, cmap); ColorEditor(paint, bg, map, False, (XtCallbackProc) changeBgOk, (XtPointer) map); } static void selectColorRange(Widget w, XtPointer paintArg, XtPointer junk) { Widget paint = (Widget) paintArg; Colormap cmap; Palette *map; /* StateShellBusy(paint, True); */ XtVaGetValues(GetShell(paint), XtNcolormap, &cmap, NULL); map = PaletteFind(paint, cmap); ChromaDialog(paint, map); } /* * Start of graphic window creation routines */ Widget makeGraphicShell(Widget wid) { Arg args[8]; int nargs = 0; Widget shell; XtSetArg(args[nargs], XtNtitle, DEFAULT_TITLE); nargs++; XtSetArg(args[nargs], XtNiconName, DEFAULT_TITLE); nargs++; XtSetArg(args[nargs], XtNdepth, Global.vis.depth); nargs++; XtSetArg(args[nargs], XtNvisual, Global.vis.visual); nargs++; shell = XtAppCreateShell("Canvas", "Canvas", topLevelShellWidgetClass, XtDisplay(GetToplevel(wid)), args, nargs); return shell; } #define ADDCALLBACK(menu, item, pw, func) \ XtAddCallback(menu[item].widget, XtNcallback, (XtCallbackProc) func, \ (XtPointer) pw); static void simpleMenuPopup(Widget w, XtPointer infoArg, XtPointer junk) { SetFullMenuPopup(!IsFullPopup()); MenuCheckItem(w, !IsFullPopup()); } static void hideMenuBar(Widget w, XtPointer infoArg, XtPointer junk) { LocalInfo * info = (LocalInfo *) infoArg; SetMenuBarHidden(True); XtUnmanageChild(info->form); } static void showMenuBar(Widget w, XtPointer infoArg, XtPointer junk) { LocalInfo * info = (LocalInfo *) infoArg; XEvent event; SetMenuBarHidden(False); XtUnmanageChild(info->viewport); XtManageChild(info->form); XtManageChild(info->viewport); event.type = ConfigureNotify; changeSize(GetShell(info->paint), info, &event, NULL); } void setPasteItemMenu(Widget paint, void *ptr ) { WidgetList wlist; XtVaGetValues(paint, XtNmenuwidgets, &wlist, NULL); if (!wlist) return; if (Global.region.pix || Global.region.image) { XtVaSetValues(wlist[W_EDIT_PASTE], XtNsensitive, True, NULL); XtVaSetValues(wlist[W_TOPMENU+W_EDIT_PASTE], XtNsensitive, True, NULL); } } /* ** */ static void loadClipboardCallback(Widget w, char *file, void *image) { ClipboardSetImage(w, image); GraphicAll(setPasteItemMenu, NULL); } void loadClipboard(Widget w, XtPointer junk, XtPointer junk2) { GetFileName(GetShell(w), 0, NULL, (XtCallbackProc) loadClipboardCallback, NULL); } int ImageToMemory(Image * image) { Pixmap pix, mask, source; Colormap cmap; Widget w = Global.toplevel; int i; if (!image) return 0; XtVaGetValues(w, XtNcolormap, &cmap, NULL); source = (Pixmap)image; mask = ImageMaskToPixmap(w, image); if (!ImageToPixmap(image, w, &pix, &cmap)) { XFreePixmap(XtDisplay(w), mask); return -1; } i = Global.numregions; ++Global.numregions; Global.regiondata = (RegionData *) realloc(Global.regiondata, Global.numregions*sizeof(RegionData)); Global.regiondata[i].x = 0; Global.regiondata[i].y = 0; Global.regiondata[i].sourcepix = source; Global.regiondata[i].pix = pix; Global.regiondata[i].mask = mask; GraphicAll((GraphicAllProc) setMemoryIcon, NULL); return i; } static void loadMemoryImage(Widget w, char *file, Image *image) { Pixmap pix, mask, source; Colormap cmap; int i; if (!image) return; XtVaGetValues(w, XtNcolormap, &cmap, NULL); source = (Pixmap)image; mask = ImageMaskToPixmap(w, image); if (!ImageToPixmap(image, w, &pix, &cmap)) { XFreePixmap(XtDisplay(w), mask); return; } i = Global.numregions; ++Global.numregions; Global.regiondata = (RegionData *) realloc(Global.regiondata, Global.numregions*sizeof(RegionData)); Global.regiondata[i].x = 0; Global.regiondata[i].y = 0; Global.regiondata[i].sourcepix = source; Global.regiondata[i].pix = pix; Global.regiondata[i].mask = mask; } static void loadMemoryCallback(LocalInfo *info, char *file, Image *image) { loadMemoryImage(info->paint, file, image); setMemoryIcon(info->paint, info); } static void loadMemory(Widget w, XtPointer paintArg, XtPointer junk2) { GetFileName(paintArg, 0, NULL, (XtCallbackProc) loadMemoryCallback, NULL); } void BrushSelectCallback(Widget w, XtPointer junk, XtPointer junk2) { BrushSelect(Global.toplevel); } void ToolSelectCallback(Widget w, XtPointer shell, XtPointer junk2) { Global.canvas = (Widget) shell; XtVaSetValues(Global.back, XtNsensitive, True, NULL); XMapRaised(XtDisplay(Global.toplevel), XtWindow(Global.toplevel)); } static void PatternSelectCallback(Widget w, XtPointer wlArg, XtPointer junk) { LocalInfo *info = (LocalInfo *) wlArg; PatternEdit(info->paint, info->pixels, info->patterns, (void *)info->rcInfo->brushes, info->npixels, info->npatterns, info->rcInfo->nbrushes); } void checkPaintDimension(Widget shell) { Dimension dw, dh; int u, v, up, vp, uset=0, vset=0; GetPaintWH(&u, &v); XtVaGetValues(shell, XtNwidth, &dw, XtNheight, &dh, NULL); if (u>50) { up = WidthOfScreen(XtScreen(shell)); if (u > up-12) u = up-12; #if defined(XAW3DG) || defined(XAW95) u -= 4; #endif XtVaSetValues(shell, XtNwidth, u, NULL); uset = 1; } if (v>30) { vp = HeightOfScreen(XtScreen(shell)); if (v > vp-40) v = vp-40; #if defined(XAW3DG) || defined(XAW95) v -= 4; #endif XtVaSetValues(shell, XtNheight, v, NULL); vset = 1; } if (!uset) u = dw; if (!vset) v = dh; if (uset || vset) XResizeWindow(XtDisplay(shell), XtWindow(shell), u, v); } /* * Key actions on selected regions */ void selectKeyPress(Widget w, void * l, XKeyEvent * event, void * info) { KeySym keysym; int len, i, dx, dy; char buf[21]; len = XLookupString(event, buf, sizeof(buf) - 1, &keysym, NULL); dx = dy = 0; switch (keysym) { case XK_Up: dy = -1; break; case XK_Down: dy = 1; break; case XK_Left: dx = -1; break; case XK_Right: dx = 1; break; case XK_Escape: PwRegionFinish(w, True); Global.escape = True; break; case XK_space: Global.transparent = !Global.transparent; PwRegionTear(w); RegionTransparency((PaintWidget) w); break; default: break; } if (event->state & ControlMask) { dx *= 5; dy *= 5; } if (dx || dy) { RegionMove((PaintWidget) w, dx, dy); RegionTransparency((PaintWidget) w); return; } /* ** Look for either backspace or delete and remove region */ for (i = 0; i < len; i++) { if (buf[i] == 0x08 || buf[i] == 0x7f) { PwRegionClear(w); return; } } } void selectKeyRelease(Widget w, void * l, XKeyEvent * event, void * info) { KeySym keysym; int len; char buf[21]; len = XLookupString(event, buf, sizeof(buf) - 1, &keysym, NULL); /* Noop at this time */ } /* * This assumes that you either * - specify a pixmap, in which case width and height are taken from that, or * - specify width and height, in which case the pixmap is not needed. * Returns the created PaintWidget. */ Widget graphicCreate(Widget shell, int width, int height, int zoom, Pixmap pix, Colormap cmap) { Display *dpy = XtDisplay(shell); Widget form, viewport; Widget paint; Widget pane, paintbox; Widget bar, position, palette; Widget colors, tool, brush, font; WidgetList wlist; Palette *map; Dimension u, v; int i, j, k, l, m; int depth; LocalInfo *info = XtNew(LocalInfo); if (cmap == None) { map = PaletteCreate(shell); cmap = map->cmap; } else { map = PaletteFind(shell, cmap); } depth = map->depth; XtVaSetValues(shell, XtNcolormap, cmap, NULL); Global.canvas = shell; XtVaSetValues(Global.back, XtNsensitive, True, NULL); PaletteAddUser(map, shell); info->map = map; info->channel = 3; info->steps = 2; info->palette_pixmap = None; info->mem_pixmap = None; info->rcInfo = NULL; info->mem_index = -1; info->mem_shift = 0; pane = XtVaCreateManagedWidget("pane", panedWidgetClass, shell, NULL); /* * Menu area */ form = XtVaCreateManagedWidget("form", formWidgetClass, pane, NULL); info -> form = form; /* * Menu Bar */ bar = MenuBarCreate(form, XtNumber(menuBar), menuBar); XtVaSetValues(bar, XtNhorizDistance, -1, XtNvertDistance, 0, NULL); XtVaSetValues(form, XtNshowGrip, True, NULL); position = XtVaCreateManagedWidget(msgText[POSITION], labelWidgetClass, form, XtNbackground, WhitePixelOfScreen(XtScreen(shell)), XtNborderWidth, 1, XtNwidth, POS_WIDTH, XtNfromHoriz, bar, #ifdef XAW3D XtNvertDistance, 5, #else XtNvertDistance, 4, #endif XtNhorizDistance, 0, NULL); info->position = position; info->boolpos = True; palette = XtVaCreateManagedWidget("palette", coreWidgetClass, form, XtNwidth, 422, XtNheight, 10*info->steps-1, XtNfromVert, bar, XtNvertDistance, 0, XtNhorizDistance, 3, NULL); info->memory = XtVaCreateManagedWidget("memory", coreWidgetClass, form, XtNwidth, 15, XtNheight, 46, XtNborderWidth, 0, XtNfromHoriz, palette, #ifdef XAW3D XtNvertDistance, 5, #else XtNvertDistance, 4, #endif XtNhorizDistance, 3, NULL); colors = XtVaCreateManagedWidget("", commandWidgetClass, form, XtNwidth, ICONWIDTH, XtNheight, ICONHEIGHT, XtNfromHoriz, info->memory, XtNhorizDistance, 3, NULL); XtAddCallback(colors, XtNcallback, (XtCallbackProc) PatternSelectCallback, (XtPointer) info); tool = XtVaCreateManagedWidget("tool", commandWidgetClass, form, XtNwidth, ICONWIDTH, XtNheight, ICONHEIGHT, XtNfromHoriz, colors, XtNhorizDistance, 2, NULL); XtAddCallback(tool, XtNcallback, (XtCallbackProc) ToolSelectCallback, (XtPointer) shell); brush = XtVaCreateManagedWidget("brush", commandWidgetClass, form, XtNwidth, ICONWIDTH, XtNheight, ICONHEIGHT, XtNfromHoriz, tool, XtNhorizDistance, 2, NULL); XtAddCallback(brush, XtNcallback, (XtCallbackProc) BrushSelectCallback, (XtPointer) NULL); font = XtVaCreateManagedWidget("Abc", commandWidgetClass, form, XtNwidth, ICONWIDTH, XtNheight, ICONHEIGHT, XtNfromHoriz, brush, XtNhorizDistance, 2, NULL); XtAddCallback(font, XtNcallback, (XtCallbackProc) FontSelect, (XtPointer) NULL); /* * Drawing Area */ viewport = XtVaCreateWidget("viewport", viewportWidgetClass, pane, XtNfromVert, form, XtNuseBottom, True, XtNuseRight, True, XtNtop, XtChainTop, NULL); info->viewport = viewport; /* * Custom Drawing Widget here */ paintbox = XtVaCreateWidget("paintBox", boxWidgetClass, viewport, XtNbackgroundPixmap,GetBackgroundPixmap(viewport), NULL); info->paintbox = paintbox; info->boolcount = 0; /* * Try and do something nice for the user */ if (pix != None) GetPixmapWHD(dpy, pix, &width, &height, NULL); if (zoom == -1 && width <= 64 && height <= 64) zoom = 6; paint = XtVaCreateManagedWidget("paint", paintWidgetClass, paintbox, XtNdrawWidth, width, XtNdrawHeight, height, XtNzoom, zoom, XtNcolormap, cmap, XtNallowResize, True, XtNundoSize, 6, NULL); /* Hack to get a correct display of the menu bar */ /* This seems to be buggy - drop it ! */ /* XtVaSetValues(viewport, XtNwidth, 650, XtNheight, 490, NULL); */ XtVaSetValues(viewport, XtNwidth, 650, NULL); XtSetKeyboardFocus(pane, paint); zoomAddChild(paint, zoom); info->paint = paint; OperationSetPaint(paint); ccpAddStdPopup(paint, (void *)info); prCallback(paint, popupFileMenu[P_FILE_PRINT].widget, True); prCallback(paint, popupFileMenu[P_FILE_EXTERN].widget, True); prCallback(paint, popupEditMenu[P_EDIT_PASTE].widget, False); prCallback(paint, popupSelectorMenu[P_SELECTOR_FATBITS].widget, True); XtInsertRawEventHandler(paint, ButtonPressMask, False, (XtEventHandler) buttonHandler, info, XtListHead); XtInsertRawEventHandler(paint, PointerMotionMask, False, (XtEventHandler) motionHandler, info, XtListHead); XtAddEventHandler(shell, StructureNotifyMask, False, (XtEventHandler) changeSize, info); XtAddEventHandler(form, StructureNotifyMask, False, (XtEventHandler) formHandler, info); XtAddEventHandler(position, ButtonPressMask, False, (XtEventHandler) positionHandler, info); XtAddEventHandler(info->memory, ButtonPressMask | ButtonReleaseMask, False, (XtEventHandler) memoryHandler, info); XtAddEventHandler(palette, ButtonPressMask | ButtonReleaseMask, False, (XtEventHandler) paletteHandler, info); XtAddEventHandler(paint, ButtonPressMask, False, (XtEventHandler) mousewheelScroll, (XtPointer) 2); XtAddEventHandler(paintbox, ButtonPressMask, False, (XtEventHandler) mousewheelScroll, (XtPointer) 1); XtAddEventHandler(paint, KeyPressMask, False, (XtEventHandler) selectKeyPress, NULL); XtAddEventHandler(paint, KeyReleaseMask, False, (XtEventHandler) selectKeyRelease, NULL); XtManageChild(paintbox); XtManageChild(viewport); ADDCALLBACK(fileMenu, FILE_SAVEAS, paint, StdSaveAsFile); ADDCALLBACK(fileMenu, FILE_SAVE, paint, StdSaveFile); ccpAddSaveRegion(fileMenu[FILE_SAVE_REGION].widget, paint); ADDCALLBACK(fileMenu, FILE_LOAD_MEMORY, info, loadMemory); ADDCALLBACK(fileMenu, FILE_REVERT, paint, revertCallback); prCallback(paint, fileMenu[FILE_REVERT].widget, False); ADDCALLBACK(fileMenu, FILE_PRINT, paint, printCallback); ADDCALLBACK(fileMenu, FILE_EXTERN, paint, externCallback); XtAddCallback(fileMenu[FILE_CLOSE].widget, XtNcallback, (XtCallbackProc) closeCallback, (XtPointer) info); ccpAddUndo(editMenu[EDIT_UNDO].widget, paint); ccpAddRedo(editMenu[EDIT_REDO].widget, paint); ADDCALLBACK(editMenu, EDIT_UNDO_SIZE, paint, undosizeCallback); ccpAddRefresh(editMenu[EDIT_REFRESH].widget, paint); ccpAddCut(editMenu[EDIT_CUT].widget, paint); ccpAddCopy(editMenu[EDIT_COPY].widget, paint); ccpAddPaste(editMenu[EDIT_PASTE].widget, paint); ccpAddClear(editMenu[EDIT_CLEAR].widget, paint); ADDCALLBACK(editMenu, EDIT_SELECT_ALL, paint, StdSelectAllCallback); ADDCALLBACK(editMenu, EDIT_UNSELECT, paint, unselectRegion); ccpAddDuplicate(editMenu[EDIT_DUP].widget, paint); ADDCALLBACK(editMenu, EDIT_ERASE_ALL, paint, StdEraseAllCallback); ADDCALLBACK(editMenu, EDIT_SNAPSHOT, paint, StdSnapshotCallback); ADDCALLBACK(editMenu, EDIT_MEMORY, info, StdMemoryCallback); ADDCALLBACK(editMenu, EDIT_RECALL, info, StdRecallCallback); ADDCALLBACK(editMenu, EDIT_REMOVE, info, StdRemoveCallback); prCallback(paint, editMenu[EDIT_RECALL].widget, False); prCallback(paint, editMenu[EDIT_REMOVE].widget, False); ADDCALLBACK(regionMenu, REGION_FLIPX, paint, StdRegionFlipX); ADDCALLBACK(regionMenu, REGION_FLIPY, paint, StdRegionFlipY); for (i = 0; i < XtNumber(rotateMenu); i++) { if (rotateMenu[i].name[0] == '\0') continue; ADDCALLBACK(rotateMenu, i, paint, rotateTo); XtAddCallback(paint, XtNregionCallback, (XtCallbackProc) prCallback, (XtPointer) rotateMenu[i].widget); prCallback(paint, rotateMenu[i].widget, False); } ADDCALLBACK(regionMenu, REGION_ROTATE, paint, rotate); XtAddCallback(paint, XtNregionCallback, (XtCallbackProc) prCallback, (XtPointer) regionMenu[REGION_ROTATE].widget); prCallback(paint, regionMenu[REGION_ROTATE].widget, False); ADDCALLBACK(regionMenu, REGION_LINEAR, paint, linearRegion); ADDCALLBACK(regionMenu, REGION_RESET, paint, resetMat); XtAddCallback(paint, XtNregionCallback, (XtCallbackProc) prCallback, (XtPointer) regionMenu[REGION_RESET].widget); prCallback(paint, regionMenu[REGION_RESET].widget, False); ADDCALLBACK(regionMenu, REGION_CROP, paint, cropToRegion); ADDCALLBACK(regionMenu, REGION_DELIMIT, paint, StdRegionDelimit); ADDCALLBACK(regionMenu, REGION_COMPLEMENT, paint, StdRegionComplement); ccpAddCloneRegion(regionMenu[REGION_CLONE].widget, paint); XtAddCallback(paint, XtNregionCallback, (XtCallbackProc) prCallback, (XtPointer) regionMenu[REGION_CROP].widget); prCallback(paint, regionMenu[REGION_CROP].widget, False); ADDCALLBACK(regionMenu, REGION_AUTOCROP, paint, autocropCallback); ADDCALLBACK(filterMenu, FILTER_INVERT, paint, StdRegionInvert); ADDCALLBACK(filterMenu, FILTER_SHARPEN, paint, StdRegionSharpen); ADDCALLBACK(filterMenu, FILTER_SMOOTH, paint, doSmooth); ADDCALLBACK(filterMenu, FILTER_DIRFILT, paint, StdRegionDirFilt); ADDCALLBACK(filterMenu, FILTER_EDGE, paint, StdRegionEdge); ADDCALLBACK(filterMenu, FILTER_EMBOSS, paint, StdRegionEmboss); ADDCALLBACK(filterMenu, FILTER_OIL, paint, oilPaint); ADDCALLBACK(filterMenu, FILTER_NOISE, paint, addNoise); ADDCALLBACK(filterMenu, FILTER_SPREAD, paint, doSpread); ADDCALLBACK(filterMenu, FILTER_PIXELIZE, paint, doPixelize); ADDCALLBACK(filterMenu, FILTER_DESPECKLE, paint, doDespeckle); ADDCALLBACK(filterMenu, FILTER_TILT, paint, tiltRegion); ADDCALLBACK(filterMenu, FILTER_BLEND, paint, StdRegionBlend); ADDCALLBACK(filterMenu, FILTER_SOLARIZE, paint, doSolarize); ADDCALLBACK(filterMenu, FILTER_TOGREY, paint, StdRegionGrey); ADDCALLBACK(filterMenu, FILTER_CONTRAST, paint, doContrast); ADDCALLBACK(filterMenu, FILTER_MODIFY_RGB, paint, doModifyRGB); ADDCALLBACK(filterMenu, FILTER_QUANTIZE, paint, doQuantize); ADDCALLBACK(filterMenu, FILTER_USERDEF, paint, StdRegionUserDefined); ADDCALLBACK(filterMenu, FILTER_LAST, paint, doLast); prCallback(paint, filterMenu[FILTER_LAST].widget, False); ADDCALLBACK(filterMenu, FILTER_UNDO, paint, StdRegionUndo); prCallback(paint, filterMenu[FILTER_UNDO].widget, False); ADDCALLBACK(selectorMenu, SELECTOR_PATTERNS, info, PatternSelectCallback); ADDCALLBACK(selectorMenu, SELECTOR_CHROMA, paint, selectColorRange); ADDCALLBACK(selectorMenu, SELECTOR_BACKGROUND, paint, changeBackground); ADDCALLBACK(selectorMenu, SELECTOR_FATBITS, paint, fatCallback); ADDCALLBACK(selectorMenu, SELECTOR_TOOLS, GetShell(paint), ToolSelectCallback); ADDCALLBACK(selectorMenu, SELECTOR_BRUSH, NULL, BrushSelectCallback); ADDCALLBACK(selectorMenu, SELECTOR_FONT, NULL, FontSelect); ADDCALLBACK(selectorMenu, SELECTOR_SCRIPT, NULL, ScriptEditor); ADDCALLBACK(selectorMenu, SELECTOR_CHANGE_SIZE, paint, sizeCallback); ADDCALLBACK(selectorMenu, SELECTOR_SIZE_ZOOM_DEFS, paint, defaultsizeCallback); ADDCALLBACK(selectorMenu, SELECTOR_CHANGE_ZOOM, paint, zoomCallback); ADDCALLBACK(selectorMenu, SELECTOR_SNAP, paint, snapCallback); ADDCALLBACK(selectorMenu, SELECTOR_CHANGE_SNAP, paint, changeSnapCallback); ADDCALLBACK(selectorMenu, SELECTOR_GRID, paint, gridCallback); ADDCALLBACK(selectorMenu, SELECTOR_SIMPLE, paint, simpleMenuPopup); MenuCheckItem(selectorMenu[SELECTOR_SIMPLE].widget, !IsFullPopup()); ADDCALLBACK(selectorMenu, SELECTOR_HIDE_MENUBAR, info, hideMenuBar); /* Store menu widgets for later reference */ wlist = (WidgetList) XtMalloc(W_NWIDGETS * sizeof(Widget)); for (i=0; imemory); XtUnmanageChild(colors); XtUnmanageChild(tool); XtUnmanageChild(brush); XtUnmanageChild(font); XFlush(dpy); usleep(50000); XMapWindow(dpy, XtWindow(bar)); XMapWindow(dpy, XtWindow(position)); XMapWindow(dpy, XtWindow(palette)); XMapWindow(dpy, XtWindow(info->memory)); XMapWindow(dpy, XtWindow(colors)); XMapWindow(dpy, XtWindow(tool)); XMapWindow(dpy, XtWindow(brush)); XMapWindow(dpy, XtWindow(font)); XMapWindow(dpy, XtWindow(shell)); XFlush(dpy); usleep(10000); XtVaSetValues(colors, XtNbackgroundPixmap, (Pixmap) wlist[W_ICON_COLPIXMAP], XtNwidth, ICONWIDTH, XtNheight, ICONHEIGHT, NULL); XtVaGetValues(shell, XtNwidth, &u, XtNheight, &v, NULL); if (u < width+10) { u = width+10; } if (u > WidthOfScreen(XtScreen(shell)) - 20) u = WidthOfScreen(XtScreen(shell)) - 20; if (v > HeightOfScreen(XtScreen(shell)) - 80) v = HeightOfScreen(XtScreen(shell)) - 80; #if defined(XAW95) || defined(XAW3DG) XtVaSetValues(shell, XtNwidth, u+4, XtNheight, v+4, NULL); #else XtVaSetValues(shell, XtNwidth, u, XtNheight, v, NULL); #endif SetIconImage(shell); setPalettePixmap(paint, info, 0); setToolIconPixmap(paint, NULL); setCanvasColorsIcon(paint); setBrushIconPixmap(paint, NULL); setFontIcon(paint); setMemoryIcon(paint, info); if (pix) { XRectangle rect; rect.width = width; rect.height = height; PwRegionSet(paint, &rect, pix, None); PwRegionSet(paint, None, None, None); } if (head) { struct paintWindows *cur; wlist = NULL; cur = head; while (!wlist && cur) { XtVaGetValues(cur->paint, XtNmenuwidgets, &wlist, NULL); cur = cur->next; } } if (head && wlist) { i = 0; XtVaGetValues(head->paint, XtNlineWidth, &i, NULL); for (j=0; j<=5; j++) if (IsItemChecked(wlist[W_LINE_WIDTHS+j])) break; for (k=0; k<=10; k++) if (IsItemChecked(wlist[W_FONT_DESCR+k])) break; l = IsItemChecked(wlist[W_SELECTOR_GRID]); m = IsItemChecked(wlist[W_SELECTOR_SNAP]); } else { i = 0; j = 0; k = 1; l = 0; m = 0; } GraphicAdd(paint); GraphicAll(setLineWidth, (void *)i); GraphicAll(setLineWidthMenu, (void *)j); GraphicAll(fontMenuCallback, (void *)(k+1)); if (k==10) { XFontStruct * info; XtVaGetValues(head->paint, XtNfont, &info, NULL); XtVaSetValues(paint, XtNfont, info, NULL); } GraphicAll(setGridMenu, (void *)l); GraphicAll(setSnapMenu, (void *)m); GraphicAll(setPasteItemMenu, NULL); /* Avoid unnecessary scrollbars */ { Dimension w, h, wp, hp; XtVaGetValues(paint, XtNwidth, &w, XtNheight, &h, NULL); XtVaGetValues(viewport, XtNwidth, &wp, XtNheight, &hp, NULL); #if defined(XAW3DG) || defined(XAW95) if (wp >= w+14 && hp >= h+14 && w <= (Dimension)(WidthOfScreen(XtScreen(paint))-20) && h <= (Dimension)(HeightOfScreen(XtScreen(paint))-80) ) #else if (wp >= w+10 && hp >= h+10 && w <= (Dimension)(WidthOfScreen(XtScreen(paint))-20) && h <= (Dimension)(HeightOfScreen(XtScreen(paint))-80) ) #endif XtVaSetValues(viewport, XtNallowHoriz, False, XtNallowVert, False, NULL); else { XtVaSetValues(viewport, XtNallowHoriz, True, XtNallowVert, True, NULL); #if defined(XAW3DG) || defined(XAWPLAIN) XtUnmanageChild(paint); XtManageChild(paint); #endif } } //checkPaintDimension(shell); return paint; } typedef struct cwi_s { Widget paint; void *id; struct cwi_s *next; } CanvasWriteInfo; static CanvasWriteInfo *cwiHead = NULL; static void removeCWI(Widget w, CanvasWriteInfo * ci, XtPointer junk) { CanvasWriteInfo *cur = cwiHead, **pp = &cwiHead; while (cur != NULL && cur != ci) { pp = &cur->next; cur = cur->next; } if (cur == NULL) return; *pp = cur->next; XtFree((XtPointer) ci); } void * GraphicGetReaderId(Widget paint) { CanvasWriteInfo *cur; paint = GetShell(paint); for (cur = cwiHead; cur != NULL && cur->paint != paint; cur = cur->next); if (cur == NULL) return NULL; return cur->id; } Widget GraphicOpenFileZoom(Widget w, char *file, XtPointer imageArg, int zoom) { Image *image = (Image *) imageArg; Colormap cmap; Pixmap pix = None; Widget shell = makeGraphicShell(w); CanvasWriteInfo *ci = XtNew(CanvasWriteInfo); PaintWidget paint; ci->next = cwiHead; cwiHead = ci; ci->paint = shell; ci->id = GetFileNameGetLastId(); XtAddCallback(shell, XtNdestroyCallback, (XtCallbackProc) removeCWI, (XtPointer) ci); if (ImageToPixmap(image, shell, &pix, &cmap)) { /* * If mask != None, set the mask region color to the BG color of the Canvas */ if ((paint = (PaintWidget) graphicCreate(shell, 0, 0, zoom, pix, cmap)) != None) { char *cp = strrchr(file, '/'); if (cp == NULL) cp = file; else cp++; XtVaSetValues(shell, XtNiconName, cp, XtNtitle, file, NULL); cp = xmalloc(strlen(file) + 1); strcpy(cp, file); paint->paint.filename = cp; EnableRevert((Widget) paint); return (Widget) paint; } else { XtDestroyWidget(shell); } } else { Notice(w, msgText[UNABLE_TO_CREATE_PAINT_WINDOW_WITH_IMAGE]); XtDestroyWidget(shell); } return NULL; } void GraphicOpenFile(Widget w, XtPointer fileArg, XtPointer imageArg) { int zoom; GetInitZoom(&zoom); GraphicOpenFileZoom(w, (char *) fileArg, imageArg, zoom); } static void doCreate(Widget wid, int width, int height, int zoom) { graphicCreate(makeGraphicShell(wid), width, height, zoom, None, None); } /* * 0: Create new (blank) canvas * 1: Open a file * 2: Create new (blank) canvas, querying for size */ void GraphicCreate(Widget wid, int value) { int width, height, zoom; switch (value) { case 0: GetDefaultWH(&width, &height); GetInitZoom(&zoom); graphicCreate(makeGraphicShell(wid), width, height, zoom, None, None); break; case 1: GetFileName(GetToplevel(wid), 0, NULL, GraphicOpenFile, NULL); break; case 2: SizeSelect(wid, None, doCreate); break; } } /* This starts what used to be cutCopyPaste.c */ static void setToSelectOp(void) { static String names[2] = {"selectBox", "selectArea"}; OperationSet(names, 2); } static void selectionLost(Widget w, Atom * selection) { selectionOwner = False; } static void selectionDone(Widget w, Atom * selection, Atom * target) { /* empty */ } static Boolean selectionConvert(Widget w, Atom * selection, Atom * target, Atom * type, XtPointer * value, unsigned long *len, int *format) { Pixmap src = Global.region.pix; Pixmap *pix, np; GC gc; int wth, hth, dth; static Atom A_TARGETS = 0; if (src == None) return False; if (A_TARGETS == 0) A_TARGETS = XInternAtom (XtDisplay(w), "TARGETS", False); if (*target == A_TARGETS) { Atom *targets; int num_targets = 3; targets = (Atom *) XtMalloc (sizeof (Atom) * num_targets); targets[0] = XA_PIXMAP; targets[1] = XA_BITMAP; targets[2] = A_TARGETS; *type = XA_ATOM; *value = (XtPointer) targets; *len = num_targets; *format = 32; return True; } if (*target != XA_PIXMAP && *target != XA_BITMAP) return False; pix = XtNew(Pixmap); GetPixmapWHD(XtDisplay(w), src, &wth, &hth, &dth); np = XCreatePixmap(XtDisplay(w), XtWindow(w), wth, hth, dth); gc = XCreateGC(XtDisplay(w), np, 0, 0); XCopyArea(XtDisplay(w), src, np, gc, 0, 0, wth, hth, 0, 0); XFreeGC(XtDisplay(w), gc); *pix = np; *type = XA_PIXMAP; *len = 1; *format = 32; *value = (XtPointer) pix; return True; } static void setMemoryRegion(Widget w, int x, int y, Pixmap source, Pixmap pix, Pixmap mask) { Display *dpy = XtDisplay(w); GC gc; int i, width, height, depth; GetPixmapWHD(dpy, pix, &width, &height, &depth); i = Global.numregions; ++Global.numregions; Global.regiondata = (RegionData *) realloc(Global.regiondata, Global.numregions*sizeof(RegionData)); Global.regiondata[i].x = x; Global.regiondata[i].y = y; Global.regiondata[i].sourcepix = source; Global.regiondata[i].pix = XCreatePixmap(dpy, DefaultRootWindow(dpy), width, height, depth); gc = XCreateGC(dpy, pix, 0, 0); XCopyArea(dpy, pix, Global.regiondata[i].pix, gc, 0, 0, width, height, 0, 0); XFreeGC(dpy, gc); Global.regiondata[i].mask = None; if (mask) { Global.regiondata[i].mask = XCreatePixmap(dpy, DefaultRootWindow(dpy), width, height, 1); gc = XCreateGC(dpy, Global.regiondata[i].mask, 0, 0); XCopyArea(dpy, mask, Global.regiondata[i].mask, gc, 0, 0, width, height, 0, 0); XFreeGC(dpy, gc); } } void StdMemoryCallback(Widget w, XtPointer paintArg, XtPointer junk2) { LocalInfo * info = (LocalInfo *) paintArg; Widget paint = info->paint; Pixmap pix, mask; XRectangle rect; int i, width, height, all = 0; PaintWidget pw = (PaintWidget) paint; if (!PwRegionGet(paint, &pix, None)) { XtVaGetValues(paint, XtNdrawWidth, &width, XtNdrawHeight, &height, NULL); rect.x = 0; rect.y = 0; rect.width = width; rect.height = height; PwRegionSet(paint, &rect, None, None); all = 1; } if (!PwRegionGet(paint, &pix, &mask)) return; /* bail out if region already in memory */ for (i=0; ipaint.region.source) return; setMemoryRegion(paint, pw->paint.region.rect.x, pw->paint.region.rect.y, pw->paint.region.source, pix, mask); setMemoryIcon(paint, info); if (all) PwRegionSet(paint, None, None, None); } static void recallOkCallback(Widget paint, XtPointer paintArg, XtPointer infoArg) { LocalInfo *localinfo = (LocalInfo *) paintArg; TextPromptInfo *info = (TextPromptInfo *) infoArg; int n = atoi(info->prompts[0].rstr) - 1; if (n < 0 || n >= Global.numregions) { Notice(localinfo->paint, msgText[IMAGE_NUMBER_OUT_OF_RANGE]); return; } localinfo->mem_index = n; recallCallback(localinfo->paint, localinfo, NULL); setMemoryIcon(localinfo->paint, localinfo); } void StdRecallCallback(Widget w, XtPointer paintArg, XtPointer junk2) { LocalInfo *localinfo = (LocalInfo *) paintArg; static TextPromptInfo info; static struct textPromptInfo value[1]; static char buf[5]; static char title[80]; if (Global.numregions == 0) return; if (Global.numregions == 1) { localinfo->mem_index = 0; recallCallback(localinfo->paint, localinfo, NULL); setMemoryIcon(localinfo->paint, localinfo); return; } if (localinfo->mem_index>=0) sprintf(buf, "%d", localinfo->mem_index+1); else *buf = '\0'; value[0].prompt = msgText[IMAGE_NUMBER]; value[0].str = buf; value[0].len = 3; info.prompts = value; sprintf(title, "%s (n = 1...%d)", msgText[RECALL_AN_IMAGE], Global.numregions); info.title = title; info.nprompt = 1; TextPrompt(localinfo->paint, "mem_recall", &info, recallOkCallback, NULL, localinfo); } void removeOkCallback(Widget w, XtPointer paintArg, XtPointer infoArg) { LocalInfo *localinfo = (LocalInfo *) paintArg; TextPromptInfo *info = (TextPromptInfo *) infoArg; int n = atoi(info->prompts[0].rstr) - 1; if (n < 0 || n >= Global.numregions) { Notice(localinfo->paint, msgText[IMAGE_NUMBER_OUT_OF_RANGE]); return; } removeFromMemory(XtDisplay(localinfo->paint), n); localinfo->mem_index = -1; setMemoryIcon(localinfo->paint, localinfo); } void StdRemoveCallback(Widget w, XtPointer paintArg, XtPointer junk2) { LocalInfo *localinfo = (LocalInfo *) paintArg; static TextPromptInfo info; static struct textPromptInfo value[1]; static char buf[5]; static char title[80]; if (!Global.numregions) return; if (localinfo->mem_index>=0) sprintf(buf, "%d", localinfo->mem_index+1); else *buf = '\0'; value[0].prompt = msgText[IMAGE_NUMBER]; value[0].str = buf; value[0].len = 3; info.prompts = value; sprintf(title, "%s (n = 1...%d)", msgText[REMOVE_AN_IMAGE], Global.numregions); info.title = title; info.nprompt = 1; TextPrompt(localinfo->paint, "mem_remove", &info, removeOkCallback, NULL, localinfo); } void StdCopyCallback(Widget w, XtPointer paintArg, String * nm, XEvent * event) { Widget paint = (Widget) paintArg; Pixmap pix, mask; int width, height; if (!PwRegionGet(paint, &pix, &mask)) return; GetPixmapWHD(XtDisplay(paint), pix, &width, &height, NULL); if (Global.region.pix != None) XFreePixmap(XtDisplay(paint), Global.region.pix); if (Global.region.mask != None) XFreePixmap(XtDisplay(paint), Global.region.mask); Global.region.pix = pix; Global.region.mask = mask; Global.region.width = width; Global.region.height = height; XtVaGetValues(paint, XtNcolormap, &Global.region.cmap, NULL); selectionOwner = XtOwnSelection(paint, XA_PRIMARY, Global.currentTime, selectionConvert, selectionLost, selectionDone); GraphicAll(setPasteItemMenu, NULL); } static void stdPasteCB(Widget paint, XtPointer infoArg, Atom * selection, Atom * type, XtPointer value, unsigned long *len, int *format) { selectInfo *info = (selectInfo *) infoArg; Display *dpy = XtDisplay(paint); XRectangle rect; Pixmap pix; Colormap cmap; Pixmap newMask = None; GC gc; if (type != NULL) { info->count--; if (*type == XA_BITMAP) { int wth, hth, dth = 0; Pixmap pix = *(Pixmap *) value; if (pix) GetPixmapWHD(dpy, pix, &wth, &hth, &dth); if (info->pixmap == None || info->depth < dth) { info->pixmap = pix; info->width = wth; info->height = hth; info->depth = dth; } } else if (*type == XA_PIXMAP) { int wth, hth, dth = 0; Pixmap pix = *(Pixmap *) value; if (pix) GetPixmapWHD(dpy, pix, &wth, &hth, &dth); if (info->pixmap == None || info->depth < dth) { info->pixmap = pix; info->width = wth; info->height = hth; info->depth = dth; } } /* ** Are there more possible selections coming? */ if (info->count != 0) return; /* ** Now that we have gotten all of the selections ** use the best one. */ if (info->pixmap != None) { Pixmap np; GC gc; if (Global.region.pix != None) XFreePixmap(dpy, Global.region.pix); if (Global.region.mask != None) XFreePixmap(dpy, Global.region.mask); if (Global.region.image != NULL) ImageDelete((Image *) Global.region.image); Global.region.pix = None; Global.region.mask = None; Global.region.image = NULL; np = XCreatePixmap(dpy, XtWindow(paint), info->width, info->height, info->depth); gc = XCreateGC(dpy, np, 0, 0); XCopyArea(dpy, info->pixmap, np, gc, 0, 0, info->width, info->height, 0, 0); XFreeGC(dpy, gc); Global.region.width = info->width; Global.region.height = info->height; Global.region.pix = np; if (info->depth == 1) Global.region.cmap = -1; else Global.region.cmap = DefaultColormapOfScreen(XtScreen(paint)); } XtFree((XtPointer) info); } /* ** No valid selections anywhere or we own the selection. */ if (Global.region.pix == None && Global.region.image == NULL) return; rect.x = 0; rect.y = 0; rect.width = Global.region.width; rect.height = Global.region.height; if (Global.region.mask != None) { newMask = XCreatePixmap(dpy, XtWindow(paint), rect.width, rect.height, 1); gc = XCreateGC(dpy, newMask, 0, 0); XCopyArea(dpy, Global.region.mask, newMask, gc, 0, 0, rect.width, rect.height, 0, 0); XFreeGC(dpy, gc); } else if (Global.region.image != NULL && ((Image *) Global.region.image)->maskData != NULL) { newMask = ImageMaskToPixmap(paint, (Image *) Global.region.image); } XtVaGetValues(paint, XtNcolormap, &cmap, NULL); if (cmap != Global.region.cmap) { Image *image; Pixmap npix = None; if (rect.width * rect.height > 1024) StateSetBusy(True); if (Global.region.pix == None) { image = (Image *) Global.region.image; image->refCount++; } else { image = PixmapToImage(paint, Global.region.pix, Global.region.cmap); } ImageToPixmapCmap(image, paint, &npix, cmap); PwRegionSet(paint, &rect, npix, newMask); if (rect.width * rect.height > 1024) StateSetBusy(False); } else { int depth; XtVaGetValues(paint, XtNdepth, &depth, NULL); pix = XCreatePixmap(dpy, XtWindow(paint), rect.width, rect.height, depth); gc = XtGetGC(paint, 0, 0); XCopyArea(dpy, Global.region.pix, pix, gc, 0, 0, rect.width, rect.height, 0, 0); XtReleaseGC(paint, gc); PwRegionSet(paint, &rect, pix, newMask); } // setToSelectOp(); } void StdPasteCallback(Widget w, XtPointer paintArg, XtPointer junk) { Widget paint = (Widget) paintArg; if (!selectionOwner) { static Atom targets[2] = {XA_PIXMAP, XA_BITMAP}; XtPointer data[2]; selectInfo *info = XtNew(selectInfo); info->count = XtNumber(targets); info->pixmap = None; data[0] = (XtPointer) info; data[1] = (XtPointer) info; XtGetSelectionValues(paint, XA_PRIMARY, targets, 2, stdPasteCB, data, Global.currentTime); } else { stdPasteCB(paint, NULL, NULL, NULL, 0, NULL, NULL); } } void StdSnapshotCallback(Widget w, XtPointer paintArg, XtPointer junk) { Widget paint; PaintWidget pw; Boolean selection; XRectangle rect; Position x1, y1, x2, y2; Dimension width, height; WidgetList wlist; paint = (Widget) paintArg; pw = (PaintWidget) paint; /* First unselect selected region, if any */ PwRegionSet(paint, None, None, None); /* Calculate menu position */ XtVaGetValues(paint, XtNmenuwidgets, &wlist, NULL); if (wlist) { XtVaGetValues(wlist[W_TOPMENU+W_EDIT_REMOVE], XtNwidth, &width, XtNheight, &height, NULL); XtTranslateCoords(paint, 0, 0, &x1, &y1); XtTranslateCoords(wlist[W_TOPMENU+W_EDIT_REMOVE], 0, 0, &x2, &y2); y2 += height; /* Popdown menu */ XtPopdown(XtParent(wlist[W_TOPMENU+W_EDIT_REMOVE])); /* Redraw area erased by menu popup */ rect.x = x2-x1 - 3; rect.y = 0; rect.width = 5 + width; if (rect.width>pw->paint.drawWidth) rect.width = pw->paint.drawWidth; rect.height = y2-y1 + 1; if (rect.height>pw->paint.drawHeight) rect.height = pw->paint.drawHeight; zoomUpdate(pw, True, &rect); XFlush(XtDisplay(paint)); } /* Clear slection issues */ selection = selectionOwner; selectionOwner = True; /* Now, really start snapshot ! */ SnapshotImage(GetToplevel(paint), paint, 1); /* Another ugly way of forcing window refresh */ if (wlist) { XtPopup(XtParent(wlist[W_TOPMENU+W_EDIT_REMOVE]), XtGrabExclusive); XtPopdown(XtParent(wlist[W_TOPMENU+W_EDIT_REMOVE])); } selectionOwner = selection; } void StdClearCallback(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; PwRegionClear(paint); } void StdCutCallback(Widget w, XtPointer paintArg, String * nm, XEvent * event) { StdCopyCallback(w, paintArg, nm, event); StdClearCallback(w, paintArg, NULL); } void StdDuplicateCallback(Widget w, XtPointer paintArg, XtPointer junk2) { XRectangle rect; Widget paint = (Widget) paintArg; Pixmap pix, mask; int width, height; if (!PwRegionGet(paint, &pix, &mask)) return; GetPixmapWHD(XtDisplay(paint), pix, &width, &height, NULL); rect.x = 0; rect.y = 0; rect.width = width; rect.height = height; PwRegionSet(paint, &rect, pix, mask); } void StdSelectAllCallback(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; XRectangle rect; int dw, dh; XtVaGetValues(paint, XtNdrawWidth, &dw, XtNdrawHeight, &dh, NULL); rect.x = 0; rect.y = 0; rect.width = dw; rect.height = dh; PwRegionSet(paint, &rect, None, None); // setToSelectOp(); } void StdEraseAllCallback(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; XRectangle rect; int dw, dh; XtVaGetValues(paint, XtNdrawWidth, &dw, XtNdrawHeight, &dh, NULL); rect.x = 0; rect.y = 0; rect.width = dw; rect.height = dh; PwRegionSet(paint, &rect, None, None); PwRegionClear(paint); } void StdUndoCallback(Widget w, XtPointer paintArg, XtPointer junk2) { PaintWidget pw = (PaintWidget) paintArg; int haveRegion = 0; XRectangle *o, *r; /* Only fiddle with the region if it has not been moved or resized */ o = &pw->paint.region.orig; r = &pw->paint.region.rect; if ((o->x == r->x) && (o->y == r->y) && (o->width == r->width) && (o->height == r->height)) haveRegion = PwRegionOff((Widget) pw, True); Undo((Widget) pw); if (haveRegion) PwRegionSet((Widget) pw, &pw->paint.region.rect, None, None); XtUnmapWidget((Widget) pw); XtMapWidget((Widget) pw); } void StdRedoCallback(Widget w, XtPointer paintArg, XtPointer junk2) { PaintWidget pw = (PaintWidget) paintArg; int haveRegion = 0; XRectangle *o, *r; /* Only fiddle with the region if it has not been moved or resized */ o = &pw->paint.region.orig; r = &pw->paint.region.rect; if ((o->x == r->x) && (o->y == r->y) && (o->width == r->width) && (o->height == r->height)) haveRegion = PwRegionOff((Widget) pw, True); Redo((Widget) pw); if (haveRegion) PwRegionSet((Widget) pw, &pw->paint.region.rect, None, None); XtUnmapWidget((Widget) pw); XtMapWidget((Widget) pw); } void StdRefreshCallback(Widget w, XtPointer paintArg, XtPointer junk2) { PaintWidget pw = (PaintWidget) paintArg; XtUnmapWidget((Widget) pw); XtMapWidget((Widget) pw); } void ClipboardSetImage(Widget w, Image * image) { if (image==NULL) return; if (Global.region.pix != None) XFreePixmap(XtDisplay(Global.toplevel), Global.region.pix); if (Global.region.mask != None) XFreePixmap(XtDisplay(Global.toplevel), Global.region.mask); if (Global.region.image != NULL) ImageDelete(Global.region.image); Global.region.pix = None; Global.region.mask = None; Global.region.cmap = None; Global.region.image = (void *) image; Global.region.width = image->width; Global.region.height = image->height; } void MemorySetImage(Widget w, Image * image) { if (image==NULL) return; } /* ** End of "edit" menu function, start region menu functions. ** */ void StdRegionFlipX(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; float v = -1.0; PwRegionAddScale(paint, &v, NULL); } void StdRegionFlipY(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; float v = -1.0; PwRegionAddScale(paint, NULL, &v); } void StdRegionClone(Widget w, XtPointer paintArg, XtPointer junk2) { PaintWidget pw = (PaintWidget) paintArg; Widget paint = (Widget) paintArg; Display *dpy; Pixel p, bg; Pixmap pix, mask, newpix; XImage *maskImg = NULL; int x, y, width, height, depth, zoom; Colormap cmap; GC gc; dpy = XtDisplay(paint); if (PwRegionGet(paint, &pix, &mask)) { XtVaGetValues(paint, XtNcolormap, &cmap, XtNzoom, &zoom, NULL); if (pw->paint.region.source) { pix = pw->paint.region.source; mask = pw->paint.region.mask; width = pw->paint.region.rect.width/zoom; height = pw->paint.region.rect.height/zoom; } else { width = pw->paint.region.orig.width/zoom; height = pw->paint.region.orig.height/zoom; } gc = XtGetGC(paint, 0, 0); depth = DefaultDepthOfScreen(XtScreen(paint)); /* Create newpix, since original pixmap may be destroyed ... */ newpix = XCreatePixmap(dpy, XtWindow(Global.toplevel), width, height, depth); XCopyArea(dpy, pix, newpix, gc, 0, 0, width, height, 0, 0); if (mask) { maskImg = NewXImage(dpy, NULL, pw->core.depth, width, height); XGetSubImage(dpy, mask, 0, 0, width, height, AllPlanes, ZPixmap, maskImg, 0, 0); XtVaGetValues(paint, XtNbackground, &bg, NULL); XSetForeground(dpy, gc, bg); for (y=0; yrect.width) rect.width = x; if (y>rect.height) rect.height = y; } } if (rect.widthcore.depth; pix = XCreatePixmap(dpy, XtWindow(paint), rect.width, rect.height, depth); mask = XCreatePixmap(dpy, XtWindow(paint), rect.width, rect.height, 1); gc = XtGetGC(paint, 0, 0); XSetForeground(dpy, gc, bg); gcw = XCreateGC(dpy, mask, 0, NULL); XSetForeground(dpy, gcw, white); gcb = XCreateGC(dpy, mask, 0, NULL); XSetForeground(dpy, gcb, black); XCopyArea(dpy, pw->paint.current, pix, gc, rect.x, rect.y, rect.width, rect.height, 0, 0); for (y = 0; y < rect.height; y++) for (x = 0; x < rect.width; x++) { u = (y + rect.y) * dw + x + rect.x; if (maskdata[u] == target) { XDrawPoint(dpy, mask, gcw, x, y); XDrawPoint(dpy, pw->paint.current, gc, x+rect.x, y+rect.y); } else { XDrawPoint(dpy, mask, gcb, x, y); } } PwRegionSet(paint, &rect, pix, mask); XtMoveWidget(pw->paint.region.child, rect.x*zoom, rect.y*zoom); pw->paint.region.rect.x = rect.x; pw->paint.region.rect.y = rect.y; XFreeGC(dpy, gc); XFreeGC(dpy, gcb); XFreeGC(dpy, gcw); } void StdRegionDelimit(Widget w, XtPointer paintArg, XtPointer junk2) { PaintWidget pw = (PaintWidget) paintArg; Widget paint = (Widget) paintArg; Display *dpy = XtDisplay(paint); XImage * source; Boolean *maskdata; Pixel corner[4]; Pixmap pix, mask; int u, x0, y0, x, y, dw, dh, depth; if (PwRegionGet(paint, &pix, &mask)) return; StateSetBusy(True); XtVaGetValues(paint, XtNdrawWidth, &dw, XtNdrawHeight, &dh, NULL); depth = pw->core.depth; source = NewXImage(dpy, NULL, depth, dw, dh); XGetSubImage(dpy, pw->paint.current, 0, 0, dw, dh, AllPlanes, ZPixmap, source, 0, 0); for (y = 0, u = 0; y < dh; y += dh - 1) for (x = 0; x < dw; x += dw - 1) corner[u++] = XGetPixel(source, x, y); if ((corner[0] == corner[1]) || (corner[0] == corner[2]) || (corner[0] == corner[3])) { x0 = 0; y0 = 0; } else if ((corner[1] == corner[2]) || (corner[1] == corner[3])) { x0 = dw-1; y0 = 0; } else if (corner[2] == corner[3]) { x0 = 0; y0 = dh-1; } else { XDestroyImage(source); StateSetBusy(False); return; /* No two corners have the same colour */ } maskdata = setDrawable(paint, pw->paint.current, source); if (!maskdata) { XDestroyImage(source); return; } fill(x0, y0, dw, dh); XDestroyImage(source); createRegionFromMaskData(paint, maskdata, False); XtFree((char *)maskdata); StateSetBusy(False); } void StdRegionComplement(Widget w, XtPointer paintArg, XtPointer junk2) { PaintWidget pw = (PaintWidget) paintArg; Widget paint = (Widget) paintArg; Display *dpy = XtDisplay(paint); XImage * source; Boolean *maskdata; Pixmap pix, mask; Pixel bg; XRectangle rect; int x, y, dw, dh, depth; if (!PwRegionGet(paint, &pix, &mask)) return; StateSetBusy(True); XtVaGetValues(paint, XtNdrawWidth, &dw, XtNdrawHeight, &dh, XtNbackground, &bg, NULL); depth = pw->core.depth; rect = pw->paint.region.rect; maskdata = (Boolean *)xmalloc(dw * dh * sizeof(Boolean)); memset(maskdata, False, dw * dh * sizeof(Boolean)); if (mask) { source = NewXImage(dpy, NULL, 1, rect.width, rect.height); XGetSubImage(dpy, mask, 0, 0, rect.width, rect.height, AllPlanes, ZPixmap, source, 0, 0); for (y=0; ypaint.region.unfilterPixmap != None) XFreePixmap(dpy, pw->paint.region.unfilterPixmap); /* create new unfilterPixmap and copy selected area to it */ pw->paint.region.unfilterPixmap = XCreatePixmap(dpy, XtWindow(paint), dw, dh, depth); gc = XCreateGC(dpy, ImgProcessPix, 0, 0); XCopyArea(dpy, ImgProcessPix, pw->paint.region.unfilterPixmap, gc, 0, 0, dw, dh, 0, 0); XFreeGC(dpy, gc); PwRegionTear(paint); XtVaGetValues(paint, XtNcolormap, &ImgProcessCmap, NULL); XtVaGetValues(paint, XtNbackground, &bg, NULL); pal = PaletteFind(paint, ImgProcessCmap); ImgProcessInfo.background = PaletteLookup(pal, bg); in = PixmapToImage(paint, ImgProcessPix, ImgProcessCmap); StateSetBusy(False); return in; } Image * ImgProcessFinish(Widget paint, Image * in, Image * (*func) (Image *)) { Image *out; StateSetBusy(True); Global.curpaint = paint; out = func(in); if (out != in) /* delete input unless done in place */ ImageDelete(in); ImageToPixmapCmap(out, paint, &ImgProcessPix, ImgProcessCmap); if (!ImgProcessFlag) PwRegionSetRawPixmap(paint, ImgProcessPix); else { PwUpdate(paint, NULL, True); XtVaSetValues(paint, XtNdirty, True, NULL); } StateSetBusy(False); return out; } static void stdImgProcess(Widget paint, Image * (*func) (Image *)) { Image *in, *out; lastFilter = func; EnableLast(paint); if ((in = ImgProcessSetup(paint)) == NULL) return; out = ImgProcessFinish(paint, in, func); XtUnmapWidget(paint); XtMapWidget(paint); } void StdLastImgProcess(Widget paint) { if (lastFilter != NULL) stdImgProcess(paint, lastFilter); } void StdRegionInvert(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; stdImgProcess(paint, ImageInvert); } void StdRegionSharpen(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; stdImgProcess(paint, ImageSharpen); } void StdRegionSmooth(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; stdImgProcess(paint, ImageSmooth); } void StdRegionEdge(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; stdImgProcess(paint, ImageEdge); } void StdRegionEmboss(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; stdImgProcess(paint, ImageEmboss); } void StdRegionOilPaint(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; stdImgProcess(paint, ImageOilPaint); } void StdRegionAddNoise(Widget w, XtPointer paintArg, XtPointer junk2) { stdImgProcess((Widget) paintArg, ImageAddNoise); } void StdRegionSpread(Widget w, XtPointer paintArg, XtPointer junk2) { stdImgProcess((Widget) paintArg, ImageSpread); } void StdRegionBlend(Widget w, XtPointer paintArg, XtPointer junk2) { stdImgProcess((Widget) paintArg, ImageBlend); } void StdRegionPixelize(Widget w, XtPointer paintArg, XtPointer junk2) { stdImgProcess((Widget) paintArg, ImagePixelize); } void StdRegionDespeckle(Widget w, XtPointer paintArg, XtPointer junk2) { stdImgProcess((Widget) paintArg, ImageDespeckle); } void StdRegionNormContrast(Widget w, XtPointer paintArg, XtPointer junk2) { stdImgProcess((Widget) paintArg, ImageNormContrast); } void StdRegionSolarize(Widget w, XtPointer paintArg, XtPointer junk2) { stdImgProcess((Widget) paintArg, ImageSolarize); } void StdRegionModifyRGB(Widget w, XtPointer paintArg, XtPointer junk2) { stdImgProcess((Widget) paintArg, ImageModifyRGB); } void StdRegionGrey(Widget w, XtPointer paintArg, XtPointer junk2) { stdImgProcess((Widget) paintArg, ImageGrey); } void StdRegionQuantize(Widget w, XtPointer paintArg, XtPointer junk2) { stdImgProcess((Widget) paintArg, ImageQuantize); } void StdRegionUserDefined(Widget w, XtPointer paintArg, XtPointer junk2) { if (!isFilterDefined()) { Notice(w, msgText[YOU_MUST_FIRST_COMPILE_A_C_SCRIPT]); return; } stdImgProcess((Widget) paintArg, ImageUserDefined); } void StdRegionDirFilt(Widget w, XtPointer paintArg, XtPointer junk2) { stdImgProcess((Widget) paintArg, ImageDirectionalFilter); } void StdRegionUndo(Widget w, XtPointer paintArg, XtPointer junk2) { Widget paint = (Widget) paintArg; PaintWidget pw = (PaintWidget) paintArg; Display * dpy = XtDisplay(paint); Pixmap np; GC gc; int width, height, depth; if (!pw->paint.region.unfilterPixmap) return; if (!PwRegionGet(paint, &ImgProcessPix, None)) return; GetPixmapWHD(dpy, pw->paint.region.unfilterPixmap, &width, &height, &depth); np = XCreatePixmap(dpy, XtWindow(paint), width, height, depth); gc = XCreateGC(dpy, np, 0, 0); XCopyArea(dpy, pw->paint.region.unfilterPixmap, np, gc, 0, 0, width, height, 0, 0); XFreeGC(dpy, gc); XFreePixmap(dpy, ImgProcessPix); XFreePixmap(dpy, pw->paint.region.unfilterPixmap); pw->paint.region.unfilterPixmap = None; PwRegionSetRawPixmap(paint, np); } void StdRegionTilt(Widget w, XtPointer paintArg, XtPointer junk2) { stdImgProcess((Widget) paintArg, ImageTilt); } /* ** Start callback functions */ static void addFunction(Widget item, Widget paint, XtCallbackProc func) { XtAddCallback(item, XtNcallback, func, (XtPointer) paint); XtAddCallback(paint, XtNregionCallback, (XtCallbackProc) prCallback, (XtPointer) item); XtVaSetValues(item, XtNsensitive, (XtPointer) False, NULL); } void ccpAddUndo(Widget w, Widget paint) { XtAddCallback(w, XtNcallback, StdUndoCallback, (XtPointer) paint); } void ccpAddRedo(Widget w, Widget paint) { XtAddCallback(w, XtNcallback, StdRedoCallback, (XtPointer) paint); } void ccpAddRefresh(Widget w, Widget paint) { XtAddCallback(w, XtNcallback, StdRefreshCallback, (XtPointer) paint); } void ccpAddCut(Widget w, Widget paint) { addFunction(w, paint, (XtCallbackProc) StdCutCallback); } void ccpAddCopy(Widget w, Widget paint) { addFunction(w, paint, (XtCallbackProc) StdCopyCallback); } void ccpAddPaste(Widget w, Widget paint) { XtVaSetValues(w, XtNsensitive, (Global.region.pix || Global.region.image)?True:False, NULL); XtAddCallback(w, XtNcallback, (XtCallbackProc) StdPasteCallback, (XtPointer) paint); } void ccpAddClear(Widget w, Widget paint) { addFunction(w, paint, (XtCallbackProc) StdClearCallback); } void ccpAddDuplicate(Widget w, Widget paint) { addFunction(w, paint, (XtCallbackProc) StdDuplicateCallback); } void ccpAddSelectAll(Widget w, Widget paint) { XtAddCallback(w, XtNcallback, (XtCallbackProc) StdSelectAllCallback, (XtPointer) paint); } void ccpAddEraseAll(Widget w, Widget paint) { XtAddCallback(w, XtNcallback, (XtCallbackProc) StdEraseAllCallback, (XtPointer) paint); } /* ** Region functions */ void ccpAddSaveRegion(Widget w, Widget paint) { addFunction(w, paint, (XtCallbackProc) StdSaveRegionFile); } void ccpAddCloneRegion(Widget w, Widget paint) { addFunction(w, paint, (XtCallbackProc) StdRegionClone); } #define ADDCALLBACK(menu, item, pw, func) \ XtAddCallback(menu[item].widget, XtNcallback, (XtCallbackProc) func, \ (XtPointer) pw); void ccpAddStdPopup(Widget paint, void *info) { int i; MenuPopupCreate(paint, "popup-menu", XtNumber(popupMenu), popupMenu); ADDCALLBACK(popupFileMenu, P_FILE_SAVE, paint, StdSaveFile); ADDCALLBACK(popupFileMenu, P_FILE_SAVEAS, paint, StdSaveAsFile); ccpAddSaveRegion(popupFileMenu[P_FILE_SAVE_REGION].widget, paint); ADDCALLBACK(popupFileMenu, P_FILE_LOAD_MEMORY, info, loadMemory); ADDCALLBACK(popupFileMenu, P_FILE_REVERT, paint, revertCallback); prCallback(paint, popupFileMenu[P_FILE_REVERT].widget, False); ADDCALLBACK(popupFileMenu, P_FILE_PRINT, paint, printCallback); ADDCALLBACK(popupFileMenu, P_FILE_EXTERN, paint, externCallback); if (info) XtAddCallback(popupFileMenu[P_FILE_CLOSE].widget, XtNcallback, (XtCallbackProc) closeCallback, (XtPointer) info); else prCallback(paint, popupFileMenu[P_FILE_CLOSE].widget, False); ccpAddUndo(popupEditMenu[P_EDIT_UNDO].widget, paint); ccpAddRedo(popupEditMenu[P_EDIT_REDO].widget, paint); ADDCALLBACK(popupEditMenu, P_EDIT_UNDO_SIZE, paint, undosizeCallback); ccpAddRefresh(popupEditMenu[P_EDIT_REFRESH].widget, paint); ccpAddCut(popupEditMenu[P_EDIT_CUT].widget, paint); ccpAddCopy(popupEditMenu[P_EDIT_COPY].widget, paint); ccpAddPaste(popupEditMenu[P_EDIT_PASTE].widget, paint); ccpAddClear(popupEditMenu[P_EDIT_CLEAR].widget, paint); ccpAddSelectAll(popupEditMenu[P_EDIT_SELECT_ALL].widget, paint); prCallback(paint, popupEditMenu[P_EDIT_SELECT_ALL].widget, True); ADDCALLBACK(popupEditMenu, P_EDIT_UNSELECT, paint, unselectRegion); ccpAddDuplicate(popupEditMenu[P_EDIT_DUP].widget, paint); ccpAddEraseAll(popupEditMenu[P_EDIT_ERASE_ALL].widget, paint); prCallback(paint, popupEditMenu[P_EDIT_ERASE_ALL].widget, True); ADDCALLBACK(popupEditMenu, P_EDIT_SNAPSHOT, paint, StdSnapshotCallback); if (info) { ADDCALLBACK(popupEditMenu, P_EDIT_MEMORY, info, StdMemoryCallback); ADDCALLBACK(popupEditMenu, P_EDIT_RECALL, info, StdRecallCallback); ADDCALLBACK(popupEditMenu, P_EDIT_REMOVE, info, StdRemoveCallback); } else { prCallback(paint, popupEditMenu[P_EDIT_MEMORY].widget, False); } prCallback(paint, popupEditMenu[P_EDIT_RECALL].widget, False); prCallback(paint, popupEditMenu[P_EDIT_REMOVE].widget, False); ADDCALLBACK(popupRegionMenu, P_REGION_FLIPX, paint, StdRegionFlipX); ADDCALLBACK(popupRegionMenu, P_REGION_FLIPY, paint, StdRegionFlipY); ADDCALLBACK(popupRegionMenu, P_REGION_ROTATE, paint, rotate); for (i = 0; i < XtNumber(popupRotateMenu); i++) { if (popupRotateMenu[i].name[0] == '\0') continue; ADDCALLBACK(popupRotateMenu, i, paint, rotateTo); XtAddCallback(paint, XtNregionCallback, (XtCallbackProc) prCallback, (XtPointer) popupRotateMenu[i].widget); prCallback(paint, popupRotateMenu[i].widget, False); } XtAddCallback(paint, XtNregionCallback, (XtCallbackProc) prCallback, (XtPointer) popupRegionMenu[P_REGION_ROTATE].widget); prCallback(paint, popupRegionMenu[P_REGION_ROTATE].widget, False); ADDCALLBACK(popupRegionMenu, P_REGION_LINEAR, paint, linearRegion); ADDCALLBACK(popupRegionMenu, P_REGION_RESET, paint, resetMat); XtAddCallback(paint, XtNregionCallback, (XtCallbackProc) prCallback, (XtPointer) popupRegionMenu[P_REGION_RESET].widget); prCallback(paint, popupRegionMenu[P_REGION_RESET].widget, False); ADDCALLBACK(popupRegionMenu, P_REGION_CROP, paint, cropToRegion); XtAddCallback(paint, XtNregionCallback, (XtCallbackProc) prCallback, (XtPointer) popupRegionMenu[P_REGION_CROP].widget); prCallback(paint, popupRegionMenu[P_REGION_CROP].widget, False); ADDCALLBACK(popupRegionMenu, P_REGION_DELIMIT, paint, StdRegionDelimit); ADDCALLBACK(popupRegionMenu, P_REGION_COMPLEMENT, paint, StdRegionComplement); ccpAddCloneRegion(popupRegionMenu[P_REGION_CLONE].widget, paint); ADDCALLBACK(popupRegionMenu, P_REGION_AUTOCROP, paint, autocropCallback); ADDCALLBACK(popupFilterMenu, P_FILTER_INVERT, paint, StdRegionInvert); ADDCALLBACK(popupFilterMenu, P_FILTER_SHARPEN, paint, StdRegionSharpen); ADDCALLBACK(popupFilterMenu, P_FILTER_SMOOTH, paint, doSmooth); ADDCALLBACK(popupFilterMenu, P_FILTER_DIRFILT, paint, StdRegionDirFilt); ADDCALLBACK(popupFilterMenu, P_FILTER_DESPECKLE, paint, doDespeckle); ADDCALLBACK(popupFilterMenu, P_FILTER_EDGE, paint, StdRegionEdge); ADDCALLBACK(popupFilterMenu, P_FILTER_EMBOSS, paint, StdRegionEmboss); ADDCALLBACK(popupFilterMenu, P_FILTER_OIL, paint, oilPaint); ADDCALLBACK(popupFilterMenu, P_FILTER_NOISE, paint, addNoise); ADDCALLBACK(popupFilterMenu, P_FILTER_SPREAD, paint, doSpread); ADDCALLBACK(popupFilterMenu, P_FILTER_PIXELIZE, paint, doPixelize); ADDCALLBACK(popupFilterMenu, P_FILTER_TILT, paint, StdRegionTilt); ADDCALLBACK(popupFilterMenu, P_FILTER_BLEND, paint, StdRegionBlend); ADDCALLBACK(popupFilterMenu, P_FILTER_SOLARIZE, paint, doSolarize); ADDCALLBACK(popupFilterMenu, P_FILTER_TOGREY, paint, StdRegionGrey); ADDCALLBACK(popupFilterMenu, P_FILTER_CONTRAST, paint, doContrast); ADDCALLBACK(popupFilterMenu, P_FILTER_MODIFY_RGB, paint, doModifyRGB); ADDCALLBACK(popupFilterMenu, P_FILTER_QUANTIZE, paint, doQuantize); ADDCALLBACK(popupFilterMenu, P_FILTER_USERDEF, paint, StdRegionUserDefined); ADDCALLBACK(popupFilterMenu, P_FILTER_LAST, paint, doLast); prCallback(paint, popupFilterMenu[P_FILTER_LAST].widget, False); ADDCALLBACK(popupFilterMenu, P_FILTER_UNDO, paint, StdRegionUndo); prCallback(paint, popupFilterMenu[P_FILTER_UNDO].widget, False); if (info) { ADDCALLBACK(popupSelectorMenu, P_SELECTOR_PATTERNS, info, PatternSelectCallback); } else { prCallback(paint, popupSelectorMenu[P_SELECTOR_PATTERNS].widget, False); } ADDCALLBACK(popupSelectorMenu, P_SELECTOR_CHROMA, paint, selectColorRange); ADDCALLBACK(popupSelectorMenu, P_SELECTOR_BACKGROUND, paint, changeBackground); ADDCALLBACK(popupSelectorMenu, P_SELECTOR_FATBITS, paint, fatCallback); ADDCALLBACK(popupSelectorMenu, P_SELECTOR_TOOLS, GetShell(paint), ToolSelectCallback); ADDCALLBACK(popupSelectorMenu, P_SELECTOR_BRUSH, NULL, BrushSelectCallback); ADDCALLBACK(popupSelectorMenu, P_SELECTOR_FONT, NULL, FontSelect); ADDCALLBACK(popupSelectorMenu, P_SELECTOR_SCRIPT, NULL, ScriptEditor); ADDCALLBACK(popupSelectorMenu, P_SELECTOR_CHANGE_SIZE, paint, sizeCallback); ADDCALLBACK(popupSelectorMenu, P_SELECTOR_SIZE_ZOOM_DEFS, paint, defaultsizeCallback); ADDCALLBACK(popupSelectorMenu, P_SELECTOR_CHANGE_ZOOM, paint, zoomCallback); ADDCALLBACK(popupSelectorMenu, P_SELECTOR_SNAP, paint, snapCallback); ADDCALLBACK(popupSelectorMenu, P_SELECTOR_CHANGE_SNAP, paint, changeSnapCallback); ADDCALLBACK(popupSelectorMenu, P_SELECTOR_GRID, paint, gridCallback); if (info) { ADDCALLBACK(popupSelectorMenu, P_SELECTOR_HIDE_MENUBAR, info, hideMenuBar); ADDCALLBACK(popupSelectorMenu, P_SELECTOR_SHOW_MENUBAR, info, showMenuBar); } else { prCallback(paint, popupSelectorMenu[P_SELECTOR_HIDE_MENUBAR].widget, False); prCallback(paint, popupSelectorMenu[P_SELECTOR_SHOW_MENUBAR].widget, False); } prCallback(paint, popupFileMenu[P_FILE_PRINT].widget, False); prCallback(paint, popupFileMenu[P_FILE_EXTERN].widget, False); prCallback(paint, popupEditMenu[P_EDIT_PASTE].widget, True); prCallback(paint, popupSelectorMenu[P_SELECTOR_FATBITS].widget, False); }