📄 gobject.c
字号:
/*..........................................................................*//* *//* L a s t W a v e K e r n e l 3 . 0 *//* *//* Copyright (C) 1998-2003 Emmanuel Bacry. *//* email : lastwave@cmap.polytechnique.fr *//* *//*..........................................................................*//* *//* This program is a 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 of the *//* License, or (at your option) any later version *//* *//* This program 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 this program (in a file named COPYRIGHT); *//* if not, write to the Free Software Foundation, Inc., *//* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* *//*..........................................................................*/#include "lastwave.h"#include <stdarg.h>#define MaxSizeGObjectList 8000/************************************************ * * Miscellenaous functions * ************************************************/extern void ApplyProc2Listv(LWPROC proc, LISTV lv);extern void ApplyProc2List(LWPROC proc, char **argv);static char DrawMessage(GOBJECT o, WINDOW win, GCLASS c, int x, int y, int w, int h){ char flag; LISTV lv1; if (c->draw == NULL && c->drawSCommand == NULL) return(NO); flag = toplevelCur->flagInDrawMessage; toplevelCur->flagInDrawMessage = YES; /* C function drawing ? */ if (c->draw) (*(c->draw))(win,o,x,y,w,h); /* Script drawing ? */ else { lv1 = TNewListv(); SetLengthListv(lv1,5); lv1->values[0] = (VALUE) NewStrValue(); SetStrValue((STRVALUE) lv1->values[0],GetNameGObject(o)); lv1->f[1] = x; lv1->f[2] = y; lv1->f[3] = w; lv1->f[4] = h; ApplyProc2Listv(c->drawSCommand,lv1); } toplevelCur->flagInDrawMessage = flag; return(YES);}/* Executing the script command 'scommand' with arguments being the 'object' name, the 'message' and 'listv' */static void DoScriptListv(GOBJECT o,LWPROC scommand, char *message, LISTV lv, char flagStoreResult){ LISTV lv1; int i; char oldFlagStoreResult = NO; int n; if (message) n = 2; else n = 1; lv1 = TNewListv(); if (lv != NULL) { SetLengthListv(lv1,lv->length+n); for (i=0;i<lv->length;i++) { if (lv->values[i] != NULL) { lv1->values[i+n] = lv->values[i]; AddRefValue(lv->values[i]); } else lv1->f[i+n] = lv->f[i]; } } else SetLengthListv(lv1,n); lv1->values[0] = (VALUE) NewStrValue(); SetStrValue((STRVALUE) lv1->values[0],GetNameGObject(o)); if (n == 2) { lv1->values[1] = (VALUE) NewStrValue(); SetStrValue((STRVALUE) lv1->values[1],message); } switch (flagStoreResult) { case 0 : oldFlagStoreResult = toplevelCur->flagStoreResult; toplevelCur->flagStoreResult = 0; break; case 1 : oldFlagStoreResult = toplevelCur->flagStoreResult; toplevelCur->flagStoreResult = 1; break; } ApplyProc2Listv(scommand,lv1); switch (flagStoreResult) { case 0 : case 1: toplevelCur->flagStoreResult = oldFlagStoreResult; break; } }/* Executing the script command 'scommand' with arguments being the 'object' name, the 'message' and 'argv' */static void DoScriptArgv(GOBJECT o, LWPROC scommand, char **argv){ char str[200]; char str1[200]; char *list[100]; int n; n= 0; str[0] = '"'; strcpy(str+1,GetNameGObject(o)); strcat(str,"\""); list[n++] = str; str1[0] = '"'; strcpy(str1+1,argv[0]); strcat(str1,"\""); list[n++] = str1; argv++; while (1) { if (*argv == NULL) break; list[n++] = *argv; argv++; } list[n] = NULL; ApplyProc2List(scommand,list);}/********************************************************************************** * * Basic procedures to deal with local and global coordinates of points * **********************************************************************************//* * Conversion of a point from local (x,y) to global (*mx,*my) coordinates */void Local2Global(GOBJECT o,LWFLOAT x, LWFLOAT y, int *mx, int *my){ VIEW view; /* Case the object is the root window */ if (o == NULL) { *mx = (int) x; *my = (int) y; return; } /* Get the first object in the hierarchy which has local coordinates */ while (o != NULL && !(o->gclass->flags & GClassLocalCoor)) o = (GOBJECT) o->father; if (o == NULL) Errorf("Local2Global() : Weird error"); /* Case of a window */ if (IsWin(o)) { *mx = (int) x; *my = (int) y; return; } /* Case of a non view object */ if (!IsView(o)) { if (o->rw == o->w) *mx = (int) (x+o->x); else *mx = (int) (x*o->w/o->rw+o->x); if (o->rh == o->h) *my = (int) (y+o->y); else *my = (int) (y*o->h/o->rh+o->y); return; } /* Case of a view */ view = (VIEW) o; if (view->flagReverse & YFlagReverse) *my = (int) ((view->yMax-y)*(o->h-1)/(view->yMax-view->yMin)+o->y + .5); else *my = (int) ((y-view->yMin)*(o->h-1)/(view->yMax-view->yMin)+o->y + .5); if (view->flagReverse & XFlagReverse) *mx = (int) ((view->xMax-x)*(o->w-1)/(view->xMax-view->xMin)+o->x + .5); else *mx = (int) ((x-view->xMin)*(o->w-1)/(view->xMax-view->xMin)+o->x + .5);}/* * Conversion of a point from global (mx,my) to local (*x,*y) coordinates */void Global2Local(GOBJECT o,int mx, int my, LWFLOAT *x, LWFLOAT *y){ VIEW view; /* Case the object is the root window */ if (o == NULL) { *x = mx; *y = my; return; } /* Get the first object in the hierarchy which has a bounding box */ while (o != NULL && !(o->gclass->flags & GClassLocalCoor)) o = (GOBJECT) o->father; if (o == NULL) Errorf("Global2Local() : Weird error"); /* Case of a window */ if (IsWin(o)) { *x = mx; *y = my; return; } /* Case of a non view object */ if (!IsView(o)) { if (o->rw == o->w) *x = mx - o->x; else *x = (mx-o->x)*o->rw/o->w; if (o->rh == o->h) *y = my - o->y; else *y = (my-o->y)*o->rh/o->h; return; } /* Case of a view object */ view = (VIEW) o; if (view->flagReverse & YFlagReverse) *y = -(my-o->y)*(view->yMax-view->yMin)/(o->h-1)+view->yMax; else *y = (my-o->y)*(view->yMax-view->yMin)/(o->h-1)+view->yMin; if (view->flagReverse & XFlagReverse) *x = -(mx-o->x)*(view->xMax-view->xMin)/(o->w-1)+view->xMax; else *x = (mx-o->x)*(view->xMax-view->xMin)/(o->w-1)+view->xMin;}/********************************************************************************** * * Basic procedures to deal with rectangles. * * Notice that a 'regular' rectangle in Lastwave is defined by * four integers : the position (x,y) of the top left corner and the * (w,h) width and the height (>0). * Such a rectangle is drawn using the basic XXDrawRectangle or is stored * in the (x,y,w,h) field of a gobject. * However LastWave allows the user to deal with more general definitions of rectangles * referred to as 'grect' (for general rectangles) * for which (w,h) are no longer necessary positive integers and for which boundaries can be * extended in any directions. * This is crucial for drawing using float coordinates (i.e, relative position in a view). * The type of a rectangle is coded in structure of type RectType with four fields left,top,right,bottom * codind coding * (using a short) how many points it is extended by respectively : left,top,right,bottom. * There are 3 predefined rectangleTypes : * - LargeRect (=0,0,1,1) : both the points (x,y) and (x+w,y+h) belong to the rectangle * - SmallRect (= -1,-1,0,0) : none of the points (x,y) and (x+w,y+h) belong to the rectangle * - NormalRect (=0,0,0,0) : the point (x,y) belong to the rectangle whereas the * point (x+w,y+h) do not belong to the rectangle * * Warning : Let us note that, in a View, if the y-axis (resp. the x-axis) is reversed \ * then the top-bottom (resp. left-right) are reversed. * **********************************************************************************//* * Initializes the different rectType constants */const RectType LargeRect = {0,0,1,1};const RectType NormalRect = {0,0,0,0};const RectType SmallRect = {-1,-1,0,0};/* * Compute the intersection of two 'regular' rectangles * The result is in *x1,*y1,*w1,*h1 * It return YES if intersection is not empty and NO otherwise * (in that case *x1,*y1,*w1,*h1 values are not supposed to be used) */ static char IntersectRect(int x,int y,int w,int h,int *x1,int *y1,int *w1,int *h1){ int xx,yy,ww,hh; xx = MAX(x,*x1); yy = MAX(y,*y1); ww = MIN(x+w,*x1+*w1)-xx; hh = MIN(y+h,*y1+*h1)-yy; if (hh <=0 || ww <= 0) { *w1 = *h1 = -1; return(NO); } *x1 = xx; *y1 = yy; *w1 = ww; *h1 = hh; return(YES); }/* * Compute the union of two 'regular' rectangles * The result is in *x1,*y1,*w1,*h1 * It return YES if union is not empty and NO otherwise * (in that case *x1,*y1,*w1,*h1 values are not supposed to be used) */ char UnionRect1(int x,int y,int w,int h,int *x1,int *y1,int *w1,int *h1){ int xx,yy,ww,hh; xx = MIN(x,*x1); yy = MIN(y,*y1); ww = MAX(x+w,*x1+*w1)-xx; hh = MAX(y+h,*y1+*h1)-yy; if (hh <=0 || ww <= 0) { *w1 = *h1 = -1; return(NO); } *x1 = xx; *y1 = yy; *w1 = ww; *h1 = hh; return(YES); }/* * Get the intersection of a regular rectangle with the clip rect of a gobject */static char IntersectClipRect(GOBJECT o,int *x, int *y, int *w, int *h){ int x1,y1,w1,h1; if (o->flagClip==0 || (o->flagClip == 2 && PSMode)) return(YES); if (IsWin(o)) { x1 = 0; y1 = 0; w1 = o->w; h1 = o->h; } else { x1 = o->x; y1 = o->y; w1 = o->w; h1 = o->h; } return(IntersectRect(x1,y1,w1,h1,x,y,w,h));}/* * Get the visible rect of an object (intersected with the original rect value *x,*y,*w,*h) * The result is in *x1,*y1,*w1,*h1 * It return YES if intersection is not empty and NO otherwise * (in that case *x,*y,*w,*h values are not supposed to be used) */ char GetVisibleRect(GOBJECT o,int *x, int *y, int *w, int *h){ while (o != NULL) { if (o->flagHide) return(NO); if (IntersectClipRect(o,x,y,w,h) == NO) return(NO); o = (GOBJECT) o->father; } return(YES);}/* * The following routine transform a general rectangle into a regular one using * its type. */void GRect2Rect(int *x, int *y, int *w, int *h, RectType rectType){ short temp; if (*w < 0) { temp = rectType.left; rectType.left = rectType.right; rectType.right = temp; } if (*h < 0) { temp = rectType.top; rectType.top = rectType.bottom; rectType.bottom = temp; } if (*w<0) { *x += *w+1; *w = -*w; } if (*h<0) { *y += *h+1; *h = -*h; } *x -= rectType.left; *w += rectType.left+rectType.right; *y -= rectType.top; *h += rectType.bottom+rectType.top; }/* * The following routine transform a regular rectangle into a general rectangle one using * its type. However there are several possibilities (since w and h can be negative). * Thus signW and signH are the respective signs of h and w. */void Rect2GRect(int *x, int *y, int *w, int *h,RectType rectType, int signW, int signH) { *x += rectType.left; *y += rectType.top; *w -= rectType.left+rectType.right; *h -= rectType.top+rectType.bottom; if (signH < 0) { *y += *h-1; *h = -(*h); } if (signW < 0) { *x += *w-1; *w = -(*w); }}/* * Conversion of a 'generalized' rectangle of local coordinates (x,y,w,h) to global (*mx,*my,*mw,*mh) coordinates */void Local2GlobalRect(GOBJECT o,LWFLOAT x, LWFLOAT y, LWFLOAT w, LWFLOAT h, RectType rectType,int *mx, int *my, int*mw, int*mh){ /* We convert each extremity of the rectangle */ Local2Global(o,x,y,mx,my); Local2Global(o,x+w,y+h,mw,mh); *mw -= *mx; *mh -= *my; /* Then convert the rectangle from generalized to regular */ GRect2Rect(mx,my,mw,mh,rectType);}/* * Conversion of a 'regular' rectangle from global (mx,my,mw,mh) to 'generalized' local (*x,*y,*w,*h) */void Global2LocalRect(GOBJECT o,int mx, int my, int mw, int mh, LWFLOAT *x, LWFLOAT *y, LWFLOAT *w, LWFLOAT *h,RectType rectType){ int signW,signH; GOBJECT o1; /* Getting the signW and signH */ signW = signH = 1; for (o1 = o; o1 != NULL; o1 = (GOBJECT) o1->father) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -