/*********************************************************************** * * TITLE: * image.c * * AUTHOR: * Cassie Mulnix * * DESCRIPTION: * This module is part of the OPPS editor, xopps. It contains * routines for image objects. * * CHANGE HISTORY * * $Log: image.c,v $ * Revision 1.57 1994/12/31 04:05:51 kevin * fixed memory allocation problem after DialogTextGet * * Revision 1.56 1994/08/10 22:02:18 cassie * fixed DialogFlagSet calls * * Revision 1.55 1994/07/20 19:06:35 clm * updated TRUE, ERROR etc in cancel & ok_button functions * to DIALOG_ constants * * Revision 1.54 1994/06/16 21:55:48 clm * updated to new dialog routines - extra parameter to DialogTextCreate * * Revision 1.53 1994/06/16 16:56:35 clm * updated to new gr_ routines using GR_ for font names * * Revision 1.52 1994/06/14 22:01:40 clm * fixed image display for 1:4 * * Revision 1.51 1994/06/08 18:47:59 clm * removed Xm library includes since they are in dialog * * Revision 1.50 1994/06/07 16:39:09 clm * increased size of text widget for filename * * Revision 1.49 1994/06/01 22:27:07 clm * rewrote init functions to use dialog oellib functions * also don't initialize popups until object called * * Revision 1.48 1994/05/20 23:31:43 clm * updated with HP, SGI changes * * Revision 1.47 1994/05/04 23:34:36 clm * ported to ANSI C * * Revision 1.46 1993/05/18 22:39:41 clm * added meaningful error messages for check_num and check_day * * Revision 1.45 1993/05/18 20:58:30 clm * added new message.c function * * Revision 1.44 1993/02/08 16:07:59 clm * fixed illegal character in help popup. * * Revision 1.43 1992/12/22 16:00:38 clm * fixed lim and load so objects cannot be loaded or moved outside chart lines * * Revision 1.42 1992/12/10 21:45:40 clm * fixed new_index so chart is always object 0 * * Revision 1.41 1992/10/02 20:16:06 clm * housekeeping * * Revision 1.40 1992/09/16 14:55:27 clm * fixed load function so doesn't add object if error in load * * Revision 1.39 1992/09/14 19:05:17 clm * fixed load_image * * Revision 1.38 1992/09/14 18:33:59 clm * added layer to object * * Revision 1.37 1992/09/11 15:51:16 clm * fixed file value so IMAGE_DIRECTORY can be used * * Revision 1.36 1992/08/26 19:48:03 clm * changed message call to warning * * Revision 1.35 1992/08/13 18:09:21 clm * fixed error checking for load module * * Revision 1.33 1992/08/10 17:41:16 clm * fixed locate function * * Revision 1.32 1992/08/04 17:01:10 clm * changed malloc and free to XtMalloc and XtFree * * Revision 1.31 1992/07/22 22:07:28 clm * changed mov function to reflect change in mover.c * * Revision 1.30 1992/07/08 18:05:50 clm * fix comment format * * Revision 1.29 1992/06/03 16:40:35 clm * updated dialog shell * * Revision 1.28 1992/05/26 15:35:23 clm * incorporated rectangle routines * * Revision 1.24 1992/05/21 15:08:31 clm * removed help_button function * * Revision 1.22 1992/05/20 19:50:57 clm * cleaned up file and help format * * Revision 1.21 1992/05/11 22:39:04 kevin * renamed project include file to xopps.h * * Revision 1.1 90/11/02 08:41:04 ana * Initial revision * *********************************************************************** * * WARNINGS: * * EXTERNAL CALLABLE COMPONENTS (PUBLIC): * * GLOBALS: * * WAIVERS: * * NOTES: * * MANPAGE: * ***********************************************************************/ #ifndef lint static char rcsid[] = "$Id: image.c,v 1.57 1994/12/31 04:05:51 kevin OEL $"; #endif /************************************************************************* global functions: add_image(x, y, file) - add object to data base *************************************************************************/ /* local functions: dsp_image(i) - display image object edt_image(i, new) - null function rem_image(i) - remove image object lim_image(i) - limit range of motion of image object loc_image(i) - locate position of image on screen mov_image(i) - move image object cpy_image(i) - copy image object msg_image(i) - display message on screen sav_image(i, fp) - save image to file */ #include "xopps.h" #define MISSING_SIZE 48 static int xlate[] = { 1, 2, 3, 4 }; /* local functions */ static void create_dialog(void); static int load_image(char *); /* load a box object */ static void img_ok_button(void); /* Callback for ok button */ static void cancel_button(void); /* Callback for cancel button */ static void change_color(Widget, XtPointer, XtPointer); static void change_scale(Widget, XtPointer, XtPointer); static void change_drawlyr(Widget, XtPointer, XtPointer); static void dsp_image(int); static void edt_image(int, int); static void rem_image(int, int); static void lim_image(int, int *, int *, int *, int *, int); static void loc_image(int, int); static void mov_image(int, int, int, int); static void cpy_image(struct obj *, struct obj *); static void msg_image(int, int); static void sav_image(int, FILE *, int); static void verify_fun(Widget w, XtPointer x, XtPointer y); static struct ops img_ops = { dsp_image, edt_image, rem_image, lim_image, loc_image, mov_image, cpy_image, msg_image, sav_image }; static DialogText *file; static DialogText *xoff, *yoff; static DialogOption *scale, *color; static DialogOption *drawlyr; static Widget image_dialog; /* dialog shell for popup */ static Widget parent_shell; static int new_drawlyr; /* new draw layer id */ static int new_color; /* new color id */ static int new_scale; /* new scale id */ /*********************************************************************** * * FUNCTION: * init_image_object() * * INPUTS: * parent (Widget) * * OUTPUTS: * none * * RETURNS: * none * * EXTERNALLY READ: * none * * EXTERNALLY MODIFIED: * none * * DESCRIPTION: * registers the image object and sets the parent */ void init_image_object(Widget parent) { register_io_obj('I', load_image); parent_shell = parent; } /*********************************************************************** * * FUNCTION: * create_dialog() * * INPUTS: * none * * OUTPUTS: * none * * RETURNS: * none * * EXTERNALLY READ: * none * * EXTERNALLY MODIFIED: * none * * DESCRIPTION: * sets up widgets for image object */ static void create_dialog(void) { static char *scales[] = { "1 : 1", "1 : 2", "1 : 3", "1 : 4" }; static char *drawlyrs[] = { "0", "1", "2", "3" }; image_dialog = DialogInit(parent_shell, "Image Object", "image", verify_fun, (XtPointer)DIALOG_CANCEL); file = DialogTextCreate("File ", 50, 100); DialogAddRow(2); xoff = DialogTextCreate("X-Offset ", 3, 3); scale = DialogOptionCreate("Scale ", 4, 1, change_scale, DIALOG_OPT_STR_ARY, scales, xlate); DialogAddRow(2); yoff = DialogTextCreate("Y-Offset ", 3, 3); color = DialogOptionCreate("Color ", ncolor, 0, change_color, DIALOG_OPT_STR_ARY, color_name, color_index); drawlyr = DialogOptionCreate("Draw Layer ", 4, 0, change_drawlyr, DIALOG_OPT_STR_ARY, drawlyrs, NULL); DialogStdButtons(verify_fun, (XtPointer)DIALOG_UPDATE, verify_fun, (XtPointer)DIALOG_CANCEL, (XtCallbackProc)ShowHelp, "image"); } /*********************************************************************** * * FUNCTION: * change_color() * * INPUTS: * button (Widget) * option, any_data (XtPointer) * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * sets new color option */ static void change_color(Widget button, XtPointer option, XtPointer any_data) { new_color = (int)option; } /*********************************************************************** * * FUNCTION: * change_scale() * * INPUTS: * button (Widget) * option, any_data (XtPointer) * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * sets new scale option */ static void change_scale(Widget button, XtPointer option, XtPointer any_data) { new_scale = (int)option; } /*********************************************************************** * * FUNCTION: * change_drawlyr() * * INPUTS: * button (Widget) * option, any_data (XtPointer) * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * sets new drawlyr for symbol object */ static void change_drawlyr(Widget button, XtPointer option, XtPointer any_data) { new_drawlyr = (int)option; } /*********************************************************************** * * FUNCTION: * load_image() * * INPUTS: * buf (char *) * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * loads image object record */ static int load_image(char *buf) { int x, y, scale, color, layer; /* image values */ char file[80]; /* temp text buffer */ int i; /* temp index */ if (record_scan(buf + 1, "dddddq", &x, &y, &scale, &color, &layer, file) == 6) { if ((x < xlnary[0].z.lnptr->cord) || (x > xlnary[nxln-1].z.lnptr->cord)) { Warning("Illegal Image x %d", x); } else if ((y < ylnary[0].z.lnptr->cord) || (y > ylnary[nyln-1].z.lnptr->cord)) { Warning("Illegal Image y %d", y); } else if ((scale < 1) || (scale > 4)) { Warning("Illegal Image scale %d", scale); } else if ((color < 0) || (color > ncolor)) { Warning("Illegal Image color %d", color); } else if ((layer < 0) || (layer > 3)) { Warning ("Illegal Image draw layer %d", layer); } else { i = add_image(x, y, scale, color, layer, file); (*(objary[i].opsptr->loc))(i, OBJECT); return 0; } return -1; } else { return -1; } } /*********************************************************************** * * FUNCTION: * add_image() * * INPUTS: * x, y, scale, color (int) * file (char *) * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * creates image from file */ int add_image(int x, int y, int scale, int color, int layer, char *file) { int i; /* index */ i = new_index(FALSE); objary[i].z.imgptr = (struct img *)XtMalloc(sizeof(struct img)); objary[i].z.imgptr->x = x; objary[i].z.imgptr->y = y; objary[i].z.imgptr->scale = scale; objary[i].z.imgptr->color = color; objary[i].z.imgptr->file = XtNewString(file); objary[i].z.imgptr->pr = open_bitmap(file); objary[i].z.imgptr->apr = scale_bitmap(objary[i].z.imgptr->pr, scale); objary[i].type = OBJ_IMG; objary[i].opsptr = &img_ops; objary[i].layer = layer; return i; } /*********************************************************************** * * FUNCTION: * cpy_image() * * INPUTS: * to, from (obj *) * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * copies image from "from" to "to" */ static void cpy_image(struct obj *to, struct obj *from) { to->z.imgptr = (struct img *)XtMalloc(sizeof(struct img)); to->z.imgptr->x = from->z.imgptr->x; to->z.imgptr->y = from->z.imgptr->y; to->z.imgptr->scale = from->z.imgptr->scale; to->z.imgptr->color = from->z.imgptr->color; to->z.imgptr->file = XtNewString(from->z.imgptr->file); to->z.imgptr->pr = copy_bitmap(from->z.imgptr->pr); to->z.imgptr->apr = copy_bitmap(from->z.imgptr->apr); to->type = OBJ_IMG; to->opsptr = &img_ops; to->layer = from->layer; to->rlist = copyRectList(from->rlist); } /*********************************************************************** * * FUNCTION: * rem_image() * * INPUTS: * i (int) * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * removes image object i from data base */ static void rem_image(int i, int dir) { struct obj *objptr; switch (i) { default: objptr = &(objary[i]); break; case BACK: objptr = &objbck; break; case TEMP: objptr = &objtmp; break; } freeRectList(objptr->rlist); XtFree(objptr->z.imgptr->file); if (objptr->z.imgptr->pr != NULL) { XtFree(objptr->z.imgptr->pr->bits); XtFree((char *)objptr->z.imgptr->pr); } if (objptr->z.imgptr->apr != NULL) { XtFree(objptr->z.imgptr->apr->bits); XtFree((char *)objptr->z.imgptr->apr); } rem_object(objptr); } /*********************************************************************** * * FUNCTION: * lim_image() * * INPUTS: * i (int) * x1, y1, x2, y2 (char *) * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * limits range of motion of image object */ static void lim_image(int i, int *x1, int *y1, int *x2, int *y2, int dir) { XRectangle *(*r)[]; /*rectangle */ r = getMoveRect(objary[i].rlist); *x1 = xlnary[0].z.lnptr->cord; *y1 = ylnary[0].z.lnptr->cord; *x2 = xlnary[nxln-1].z.lnptr->cord - (1 + (*r)[0]->width); *y2 = ylnary[nyln-1].z.lnptr->cord - (1 + (*r)[0]->height); } /*********************************************************************** * * FUNCTION: * loc_image() * * INPUTS: * i (int) * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * locates position of image i on screen */ static void loc_image(int i, int dir) { struct img *imgptr; /* local pointer */ XRectangle r; /* rectangle */ imgptr = objary[i].z.imgptr; r.x = imgptr->x; r.y = imgptr->y; if (imgptr->apr != NULL) { r.width = (imgptr->apr)->width; r.height = (imgptr->apr)->height; } else { r.width = MISSING_SIZE; r.height = MISSING_SIZE; } setRectList(objary[i].rlist, 1, &r, RL_PRIMARY); } /*********************************************************************** * * FUNCTION: * mov_image() * * INPUTS: * i, x, y (int) * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * moves image object i to x,y */ static void mov_image(int i, int x, int y, int dir) { objary[i].z.imgptr->x += x; objary[i].z.imgptr->y += y; } /*********************************************************************** * * FUNCTION: * dsp_image() * * INPUTS: * i (int) * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * displays image object i */ static void dsp_image(int i) { struct img *imgptr; /* local pointer */ XRectangle *(*r)[]; r = getMoveRect(objary[i].rlist); imgptr = objary[i].z.imgptr; gr_set_color(color_name[imgptr->color], color_gscale[imgptr->color]); if ((*(imgptr->file) == '\0') || (imgptr->pr == NULL)) { gr_text(imgptr->x + MISSING_SIZE / 2, imgptr->y + MISSING_SIZE / 3, "MISSING", GR_CENTER, GR_TIMES | 10, 0); gr_text(imgptr->x + MISSING_SIZE / 2, imgptr->y + (2 * MISSING_SIZE) / 3, "IMAGE", GR_CENTER, GR_TIMES | 10, 0); gr_rectangle((*r)[0]->x, (*r)[0]->y, MISSING_SIZE-1, MISSING_SIZE-1); } else { gr_image((*r)[0]->x, (*r)[0]->y, imgptr->pr, imgptr->apr, imgptr->scale); } } /*********************************************************************** * * FUNCTION: * sav_image() * * INPUTS: * i (int) * fp (FILE *) * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * saves image record i to fp */ static void sav_image(int i, FILE *fp, int dir) { struct img *imgptr; /* image pointer */ char buf[128]; /* temp text buffer */ imgptr = objary[i].z.imgptr; buf[0] = 'I'; buf[1] = ' '; record_print(buf + 2, "dddddq", imgptr->x, imgptr->y, imgptr->scale, imgptr->color, objary[i].layer, imgptr->file); fputs(buf, fp); } /*********************************************************************** * * FUNCTION: * msg_image() * * INPUTS: * i (int) * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * displays image i message on screen */ static void msg_image(int i, int dir) { char text[128]; /* temp text buffer */ strcpy(text, "Image file: "); strcat(text, objary[i].z.imgptr->file); Message(text); } /*********************************************************************** * * FUNCTION: * edt_image() * * INPUTS: * i, new (int) * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * edits image object i */ static void edt_image(int i, int new) { char buf[4]; if (image_dialog == NULL) { create_dialog(); } (*(objary[i].opsptr->cpy))(&objtmp, &objary[i]); new_color = objtmp.z.imgptr->color; new_scale = objtmp.z.imgptr->scale; new_drawlyr = objtmp.layer; if (new) { (*(objary[i].opsptr->rem))(i, OBJECT); i = -1; } sprintf(buf, "%d", objtmp.z.imgptr->x); DialogTextSet(xoff, buf); sprintf(buf, "%d", objtmp.z.imgptr->y); DialogTextSet(yoff, buf); DialogTextSet(file, objtmp.z.imgptr->file); DialogOptionSet(color, (int)new_color); DialogOptionSet(scale, (int)new_scale); DialogOptionSet(drawlyr, (int)new_drawlyr); EditObject(i, image_dialog); } /*********************************************************************** * * FUNCTION: * img_ok_button() * * INPUTS: * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * checks input after ok button is pressed */ static void img_ok_button(void) { int change = DIALOG_NO_CHANGE; char *buf; int val; val = DialogTextGetInt(xoff); if ((val < 0) || (val >= PAGE_WIDTH)) { Warning("Improper X Coordinate"); change |= DIALOG_ERROR; } else if (val != objtmp.z.imgptr->x) { change |= DIALOG_UPDATE; objtmp.z.imgptr->x = val; } val = DialogTextGetInt(yoff); if ((val < 0) || (val >= PAGE_WIDTH)) { Warning("Improper Y Coordinate"); change |= DIALOG_ERROR; } else if (val != objtmp.z.imgptr->y) { change |= DIALOG_UPDATE; objtmp.z.imgptr->y = val; } if (new_color != objtmp.z.imgptr->color) { change |= DIALOG_UPDATE; } objtmp.z.imgptr->color = DialogOptionGet(color); buf = DialogTextGet(file); if (strcmp(buf, objtmp.z.imgptr->file)) { change |= DIALOG_UPDATE; XtFree(objtmp.z.imgptr->file); objtmp.z.imgptr->file = buf; } else { XtFree(buf); } if (new_scale != objtmp.z.imgptr->scale) { change |= DIALOG_UPDATE; } objtmp.z.imgptr->scale = DialogOptionGet(scale); if (new_drawlyr != objtmp.layer) { change |= DIALOG_UPDATE; } objtmp.layer = DialogOptionGet(drawlyr); if ((change == DIALOG_UPDATE) || (objtmp.z.imgptr->pr == NULL)) { if (objtmp.z.imgptr->pr != NULL) { XtFree(objtmp.z.imgptr->pr->bits); XtFree((char *)objtmp.z.imgptr->pr); } if (objtmp.z.imgptr->apr != NULL) { XtFree(objtmp.z.imgptr->apr->bits); XtFree((char *)objtmp.z.imgptr->apr); } objtmp.z.imgptr->pr = open_bitmap(objtmp.z.imgptr->file); objtmp.z.imgptr->apr = scale_bitmap(objtmp.z.imgptr->pr, objtmp.z.imgptr->scale); if (objtmp.z.imgptr->pr == NULL) { Warning("ERROR - Improper File"); change |= DIALOG_ERROR; } } object_change = change; DialogFlagSet(change); } /*********************************************************************** * * FUNCTION: * cancel_button() * * INPUTS: * * OUTPUTS: * * RETURNS: * * EXTERNALLY READ: * * EXTERNALLY MODIFIED: * * DESCRIPTION: * discard any edits and close edit window */ static void cancel_button(void) { object_change = DIALOG_CANCEL; DialogFlagSet(DIALOG_CANCEL); } /*********************************************************************** * * FUNCTION: * verify_fun() * * INPUTS: * w (Widget) * x, y (XtPointer) * * OUTPUTS: * none * * RETURNS: * none * * EXTERNALLY READ: * none * * EXTERNALLY MODIFIED: * none * * DESCRIPTION: * validates that the popup dialog can be closed */ static void verify_fun(Widget w, XtPointer x, XtPointer y) { if ((int)x == DIALOG_CANCEL) { if (!ShellValidateClose(w)) return; cancel_button(); } else if ((int)x == DIALOG_UPDATE) { img_ok_button(); } }