/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* $XConsortium: graphics.c /main/4 1995/11/02 14:05:07 rswiston $ */ /********************************************************************* * (c) Copyright 1993, 1994 Hewlett-Packard Company * (c) Copyright 1993, 1994 International Business Machines Corp. * (c) Copyright 1993, 1994 Sun Microsystems, Inc. * (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of * Novell, Inc. **********************************************************************/ /****************************************************************************** ** Program: dticon ** ** Description: X11-based multi-color icon editor ** ** File: graphics.c, which contains the following subroutines or ** functions: ** Flicker_Arc() ** Circle_Box() ** Set_HotBox_Coords() ** Start_HotBox() ** Do_HotBox() ** Stop_HotBox() ** ****************************************************************************** ** ** Copyright Hewlett-Packard Company, 1990, 1991, 1992. ** All rights are reserved. Copying or reproduction of this program, ** except for archival purposes, is prohibited without prior written ** consent of Hewlett-Packard Company. ** ** Hewlett-Packard makes no representations about the suitibility of this ** software for any purpose. It is provided "as is" without express or ** implied warranty. ** ******************************************************************************/ #include #include #include "externals.h" extern GC scratch_gc; extern Widget editMenu_cut_pb; extern Widget editMenu_copy_pb; extern Widget editMenu_rotate_pb; extern Widget editMenu_flip_pb; extern Widget editMenu_scale_pb; extern void Stop_HotBox(void); /*************************************************************************** * * * Routine: Flicker_Arc * * * * Purpose: Given 2 points (top-left and bottom-right), draw an * * invertable ellipse around the box they form. * * * *X11***********************************************************************/ void Flicker_Arc( Window win, int x1, int y1, int x2, int y2 ) { int x, y, width, height; x = min(x1, x2); y = min(y1, y2); width = abs(x1 - x2); height = abs(y1 - y2); #ifdef DEBUG if (debug) stat_out("Doing Flicker_Arc: x=%d, y=%d, width=%d, height=%d\n", x, y, width, height); #endif if ((width > 0) && (height > 0)) XDrawArc(dpy, win, Flicker_gc, x, y, width, height, 0, 360*64); } /*************************************************************************** * * * Routine: Circle_Box * * * * Purpose: Given 2 points (the center and radius of a circle) * * generate a box which would exactly enclose this circle, * * and then draw a flickering circle that matches the box. * * WARNING: [x1,y1] are always assumed to be the centerpoint * * and this routine will generate bogus results if this is * * not TRUE. * * * *X11***********************************************************************/ void Circle_Box( Window win, int x1, int y1, int x2, int y2, XRectangle *box ) { int radius, top_x, top_y, bottom_x, bottom_y, width, height; double size; #ifdef DEBUG if (debug) stat_out("Entering Circle_Box\n"); #endif width = mag(x1, x2); height = mag(y1, y2); size = (double) ((width * width) + (height * height)); radius = (int) sqrt(size); top_x = x1 - radius; top_y = y1 - radius; bottom_x = x1 + radius; bottom_y = y1 + radius; #ifdef DEBUG if (debug) stat_out(" Circle_Box values: tx=%d, ty=%d, bx=%d, by=%d\n", top_x, top_y, bottom_x, bottom_x); #endif Flicker_Arc(win, top_x, top_y, bottom_x, bottom_y); box->x = top_x; box->y = top_y; box->width = bottom_x - top_x + 1; box->height = bottom_y - top_y + 1; #ifdef DEBUG if (debug) stat_out("Leaving Circle_Box\n"); #endif } /*************************************************************************** * * * Routine: Set_HotBox_Coords * * * * Purpose: A SELECT operation has just occurred. Initiate a timer * * calculate the area to enclose. * * not TRUE. * * * *X11***********************************************************************/ #define FLASH_INTERVAL 300 static Boolean FlashState=False; static int flash_x, flash_y, flash_width, flash_height; static int box_x1, box_y1, box_x2, box_y2; static XtIntervalId selectTimerID; static void Do_HotBox(); void Set_HotBox_Coords( void ) { int min_x, min_y, max_x, max_y, tmp_x, tmp_y; min_x = min(ix, last_ix); min_y = min(iy, last_iy); max_x = max(ix, last_ix); max_y = max(iy, last_iy); /*** make sure all four points are on the tablet ***/ if (min_x < 0) min_x = 0; if (min_y < 0) min_y = 0; if ((max_x) >= icon_width) max_x = icon_width-1; if ((max_y) >= icon_height) max_y = icon_height-1; select_box.x = min_x; select_box.y = min_y; select_box.width = max_x - min_x + 1; select_box.height = max_y - min_y + 1; box_x1 = min_x; box_y1 = min_y; box_x2 = max_x+1; box_y2 = max_y+1; Tablet_Coords(min_x, min_y, &flash_x, &flash_y); Tablet_Coords(max_x+1, max_y+1, &tmp_x, &tmp_y); flash_width = tmp_x - flash_x; flash_height = tmp_y - flash_y; #ifdef DEBUG if (debug) { stat_out(" select_box: x=%d, y=%d, width=%d, height=%d\n", select_box.x, select_box.y, select_box.width, select_box.height); stat_out(" flash box: x=%d, y=%d, width=%d, height=%d\n", flash_x, flash_y, flash_width, flash_height); } #endif } /*************************************************************************** * * * Routine: Start_HotBox * * * * Purpose: A SELECT operation has just occurred. Initiate a timer * * which flashes a 1-pixel wide box around the perimeter of * * the selected rectangle every FLASH_INTERVAL milliseconds. * * Use the global variables ix, iy, last_ix, last_iy to * * calculate the area to enclose. * * * *X11***********************************************************************/ void Start_HotBox( int flag ) { #ifdef DEBUG if (debug) stat_out("Entering Start_HotBox\n"); #endif Selected = True; /* turn on stuff that uses the selected area */ XtSetSensitive( editMenu_cut_pb, True); XtSetSensitive( editMenu_copy_pb, True); XtSetSensitive(editMenu_rotate_pb, True); XtSetSensitive(editMenu_flip_pb, True); XtSetSensitive(editMenu_scale_pb, True); XSync(dpy, 0); if (flag == INITIAL) Set_HotBox_Coords(); selectTimerID = XtAppAddTimeOut(AppContext, FLASH_INTERVAL, (XtTimerCallbackProc) Do_HotBox, NULL); #ifdef DEBUG if (debug) stat_out("Leaving Start_HotBox - TimerID=%d\n", selectTimerID); #endif } /*************************************************************************** * * * Routine: Do_HotBox * * * * Purpose: Flash one alternating pulse around the selected area, and * * then re-set itself to activate again in FLASH_INTERVAL * * milliseconds. * * * * note: Check selectTimerID so that timeouts added for previous selects * * are ignored. ex: if new select is started before previous select * * timeout is serviced, "Selected" will already be set to true again * * (for new select) when timeout from old selection is called... so * * now Stop_HotBox is called immediately (before HotBox Coords are * * set for new select), and last timeout is ignored. * * * *X11***********************************************************************/ static void Do_HotBox( XtPointer *client_data, XtIntervalId *local_id ) { #ifdef DEBUG if (debug) stat_out(". "); #endif if (GraphicsOp != SELECT) Selected = False; if (*local_id == selectTimerID) { if (Selected) { if (FlashState) { FlashState = False; XSetForeground(dpy, scratch_gc, black_pixel); } else { FlashState = True; XSetForeground(dpy, scratch_gc, white_pixel); } XSetLineAttributes(dpy, scratch_gc, 1, LineSolid, CapButt, JoinMiter); XDrawRectangle(dpy, tablet_win, scratch_gc, flash_x, flash_y, flash_width, flash_height); selectTimerID=XtAppAddTimeOut(AppContext, FLASH_INTERVAL, (XtTimerCallbackProc) Do_HotBox, NULL); } else Stop_HotBox(); } } /*************************************************************************** * * * Routine: Stop_HotBox * * * * Purpose: Undo the last Selected border operation. * * * *X11***********************************************************************/ void Stop_HotBox( void ) { int min_x, min_y, max_x, max_y, tmp_x, tmp_y; static int tmp_ix, tmp_iy; static Boolean Rotate_Move=False; #ifdef DEBUG if (debug) stat_out("Entering Stop_HotBox\n"); #endif if (GridEnabled) { XDrawLine(dpy, tablet_win, Grid_gc, flash_x, flash_y, (flash_x+flash_width), flash_y); XDrawLine(dpy, tablet_win, Grid_gc, flash_x, (flash_y+flash_height), (flash_x+flash_width), (flash_y+flash_height)); XDrawLine(dpy, tablet_win, Grid_gc, flash_x, flash_y, flash_x, (flash_y+flash_height)); XDrawLine(dpy, tablet_win, Grid_gc, (flash_x+flash_width), flash_y, (flash_x+flash_width), (flash_y+flash_height)); } else { /* since Rotate left and right moves ix and iy revert to tmp_ix, tmp_iy */ if (Rotate_Move) { Rotate_Move = False; ix = tmp_ix; iy = tmp_iy; } min_x = min(ix, last_ix); min_y = min(iy, last_iy); max_x = max(ix, last_ix); max_y = max(iy, last_iy); if (++max_x >= icon_width) max_x--; if (++max_y >= icon_height) max_y--; Transfer_Back_Image(min_x, min_y, max_x, max_y, HOLLOW); /* if it is a Rotate Op. then keep ix, iy */ if(GraphicsOp == S_ROTATE) { Rotate_Move = True; tmp_ix = ix; tmp_iy = iy; } } #ifdef DEBUG if (debug) stat_out("Leaving Stop_HotBox\n"); #endif }