/* * wMousePtr.c * * Finding the posisiton and changing the shape of the mouse pointer * * © 1994-1998 Straylight */ /*----- Licensing note ----------------------------------------------------* * * This file is part of Straylight's Glass. * * Glass is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * Glass is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Glass. If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*----- Header files ------------------------------------------------------*/ /* * ANSI standard headers */ #include #include #include /* * Steel headers */ #define _STDAPP #define _LOWLVL #include "steel/Steel.h" #include "steel/pointer.h" /* * Glass headers */ #include "gStruct.h" #include "gMenus.h" #include "gIcons.h" #include "glass.h" #include "gPrefs.h" #include "window.h" #include "_window.h" /*----- Tables ------------------------------------------------------------*/ /* * This table defines the mapping from drag zones to pointer shapes, to * indicate to the user what operations are possible. There is some * redundancy since there are some 'reserved' zone numbers, and they go up * to &F. Each entry takes up 20 bytes, though, so things aren't exactly * critical as a result of this. */ static struct { char name[12]; int x; int y; } window__ptr[]= { "",0,0, /* 0 */ "ptr_tb",7,5, /* 1 */ "ptr_tb",7,5, /* 2 */ "",0,0, /* 3 */ "ptr_lr",11,4, /* 4 */ "ptr_tlbr",9,5, /* 5 */ "ptr_trbl",9,5, /* 6 */ "ptr_hand",10,9, /* 7 */ "ptr_lr",11,4, /* 8 */ "ptr_trbl",9,5, /* 9 */ "ptr_tlbr",9,5, /* a */ "",0,0, /* b */ "",0,0, /* c */ "ptr_tb",7,5, /* d */ "ptr_lr",11,4, /* e */ "",0,0, /* f */ }; /*----- Main code ---------------------------------------------------------*/ /* * BOOL window__inSizedBox(int px,int py,int x,int y,int d) * * Use * Returns whether the point passed as (px,py) is contained within the * square box with bottom-left corner (x,y) and side length d. * * Parameters * As described above * * Returns * TRUE if the point lies within the box, or FALSE if not */ static BOOL window__inSizedBox(int px,int py,int x,int y,int d) { x&=~(wimpt_dx()-1); y&=~(wimpt_dy()-1); d=(d+wimpt_dy()-1) &~ (wimpt_dy()-1); if (px>=x && py>=y && px<=x+d && py<=y+d) return (TRUE); else return (FALSE); } /* * int window__pointerInfo(glass_windPointer *w,int from,BOOL zones) * * Use * Returns the icon number of the icon which the pointer is over. Guides * are also checked for. * * Parameters * glass_windPointer *w == the window to use info from * int from == number to search down from (or -1 for the top). This is * useful for selection, multiple clicks moving down overlapping icons. * BOOL zones == search for drag zones. If this is set, the routine * searches for selected icons only. If it is clear, zones are not * checked. * * Returns * An icon number, or -1 for the background. */ #define HW window__HANDLEWIDTH int window__pointerInfo(glass_windPointer *w,int from,BOOL zones) { int i; wimp_mousestr m; int ox; int oy; int tries; wimp_box box; BOOL found=FALSE; /* --- Find out where the pointer is in the window --- */ wimpt_noerr(wimp_get_point_info(&m)); if (m.w!=w->h) return (-1); zones=zones&&!w->renumber; ox=w->def->desc.w.box.x0-w->def->desc.w.scx; oy=w->def->desc.w.box.y1-w->def->desc.w.scy; m.x-=ox; m.y-=oy; /* --- Start the search from the right place --- * * * The search can be relative to an icon, for the depth-selection system * to work. If this is the case, we do two passes through the icon array * and start off half-way through. If we're just searching from the top * then we just do one pass. */ if (from==-1) { i=w->def->desc.w.nicons-1; tries=1; } else { i=from-1; tries=2; } /* --- The main search loop --- * * * There's nothing really exciting about this. It's just a brute-force * rectangle comparison. If it finds something, then it returns * immediately. * * We try to be a little cleverer -- we check if the pointer is anywhere * near the icon rectangle and only read the actual bounding area if it * is really worthwhile. */ for (;tries;tries--) { while (i>=0) /* Find higher icons first... */ { if (w->def->i[i].i.flags & wimp_IDELETED) { i--; continue; /* Don't find deleted icons... */ } if (m.x>=w->def->i[i].i.box.x0-20-HW && m.x<=w->def->i[i].i.box.x1+20+HW && m.y>=w->def->i[i].i.box.y0-20-HW && m.y<=w->def->i[i].i.box.y1+32+HW) { /* Roughly in the right place */ /* --- Find the actual bounding box of the icon --- */ window_boundingBox(w,i,&box); /* --- If we're searching for drag zones, do that --- */ if (w->def->i[i].selected && zones) { if (window__inSizedBox(m.x, m.y, box.x1-HW, box.y0-wimpt_dy()-HW, HW*2)) return (i | window__BOTTOMRIGHT); if (window__inSizedBox(m.x, m.y, box.x0-wimpt_dx()-HW, box.y0-wimpt_dy()-HW, HW*2)) return (i | window__BOTTOMLEFT); if (window__inSizedBox(m.x, m.y, box.x0-wimpt_dx()-HW, box.y1-HW, HW*2)) return (i | window__TOPLEFT); if (window__inSizedBox(m.x, m.y, box.x1-HW, box.y1-HW, HW*2)) return (i | window__TOPRIGHT); if (gPrefs_current()->sEdgeHandles) { if (window__inSizedBox(m.x, m.y, box.x0+(box.x1-box.x0-HW*2)/2, box.y0-wimpt_dy()-HW, HW*2)) return (i | window__BOTTOM); if (window__inSizedBox(m.x, m.y, box.x1-HW, box.y0+(box.y1-box.y0-HW*2)/2, HW*2)) return (i | window__RIGHT); if (window__inSizedBox(m.x, m.y, box.x0-wimpt_dx()-HW, box.y0+(box.y1-box.y0-HW*2)/2, HW*2)) return (i | window__LEFT); if (window__inSizedBox(m.x, m.y, box.x0+(box.x1-box.x0-HW*2)/2, box.y1-HW, HW*2)) return (i | window__TOP); } } /* --- If no match in the zones, check the actual icon --- * * * If it's in the icon, then we've found a match. If we're searching * for drag zones, and it's not selected, then just remember we've * found an icon, so don't try to match guidelines. Otherwise, we * just return the match. */ if (m.x>=box.x0 && m.x=box.y0 && m.ydef->i[i].selected) return (i | window__MAIN); else found=TRUE; } else return (i); } } i--; } i=w->def->desc.w.nicons-1; } /* --- We couldn't find anything in the icons, so try guidelines --- */ if (!found) { for (i=0;iguide[i].active) { if (w->guide[i].horiz && abs(m.y-w->guide[i].coord)<8) return (i | window__HORGUIDE); else if (abs(m.x-w->guide[i].coord)<8) return (i | window__VERGUIDE); } } } /* --- Not a sausage, so we failed --- */ return (-1); } #undef HW /* * BOOL window__pointerOverIcon(glass_windPointer *w,int icon) * * Use * Informs the caller if the pointer is over the bounding box of the icon * specified. * * Parameters * glass_windPointer *w == window containing icon * int icon == icon to check for */ BOOL window__pointerOverIcon(glass_windPointer *w,int icon) { wimp_box box; wimp_wstate s; wimp_mousestr m; wimpt_noerr(wimp_get_wind_state(w->h,&s)); wimpt_noerr(wimp_get_point_info(&m)); window_boundingBox(w,icon,&box); m.x-=s.o.box.x0-s.o.x; m.y-=s.o.box.y1-s.o.y; return (m.x>=box.x0 && m.x<=box.x1 && m.y>=box.y0 && m.y<=box.y1); } /* * void window__setPtrShape(int icon) * * Use * Sets the pointer shape accoding to the 'drag zone' part of the given * icon number. * * Parameters * int icon == the icon number */ void window__setPtrShape(int icon) { static int last; static int wouldbe; sprite_id sid; if (icon==-2) icon=wouldbe; wouldbe=icon; if (window__qDragType()!=-1) icon=window__qDragType(); icon=(icon&window__ZONEMASK)>>24; if (icon==last) return; if (window__ptr[icon].name[0]) { sid.s.name=window__ptr[icon].name; sid.tag=0; pointer_set_shape(resspr_area(), &sid, window__ptr[icon].x, window__ptr[icon].y); } else pointer_reset_shape(); last=icon; }