📄 srvfunc.c
字号:
GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid);
return;
}
if ((width <= 0) || (height <= 0)) {
GsError(GR_ERROR_BAD_WINDOW_SIZE, wid);
return;
}
if ((wp->width == width) && (wp->height == height))
return;
if (wp->unmapcount || !wp->output) {
wp->width = width;
wp->height = height;
return;
}
/*
* This should be optimized to not require redrawing of the window
* when possible.
*/
GsWpUnmapWindow(wp, GR_TRUE);
wp->width = width;
wp->height = height;
GsWpMapWindow(wp, GR_FALSE);
GsDeliverUpdateEvent(wp, GR_UPDATE_SIZE, wp->x, wp->y, width, height);
}
/* set unmapcount for a window and all its children*/
static void
SetUnmapCountTree(GR_WINDOW *wp, int value, GR_BOOL increment)
{
GR_WINDOW * childwp;
if (increment)
wp->unmapcount += value;
else wp->unmapcount = value;
for (childwp = wp->children; childwp; childwp = childwp->siblings)
SetUnmapCountTree(childwp, value, increment);
}
/*
* Reparent window to new parent, position at passed x, y
*
* NOTE: currently, the new parent must be mapped before
* reparenting, or the children of the newly parented window
* will have bad unmapcount values due to the GrMapWindow
* being called on the parent afterwards, and chaining down
* through the children.
*/
void
GrReparentWindow(GR_WINDOW_ID wid, GR_WINDOW_ID pwid, GR_COORD x, GR_COORD y)
{
GR_WINDOW *wp; /* window structure */
GR_WINDOW *pwp; /* parent window structure */
GR_WINDOW **mysibptr; /* handle to my sibling ptr */
GR_COORD offx, offy;
GR_BOOL wasmapped;
wp = GsFindWindow(wid);
pwp = GsFindWindow(pwid);
if (wp == NULL || pwp == NULL || wp == pwp)
return;
if (wp == rootwp) {
GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid);
return;
}
x += pwp->x;
y += pwp->y;
offx = x - wp->x;
offy = y - wp->y;
/*printf("pid %d wid %d (oldpid %d) %d,%d\n", pwid, wid, wp->parent->id, pwp->unmapcount, wp->unmapcount);*/
/*
* Always unmap window, can't hurt if not mapped.
*/
wasmapped = (wp->unmapcount == 0);
GsWpUnmapWindow(wp, GR_TRUE);
for(mysibptr = &(wp->parent->children); *mysibptr != wp;
mysibptr = &((*mysibptr)->siblings))
continue;
*mysibptr = wp->siblings;
wp->parent = pwp;
wp->siblings = pwp->children;
pwp->children = wp;
OffsetWindow(wp, offx, offy);
#if 1 /* temp fix to bad mapcount reparenting code below*/
GsWpMapWindow(wp, GR_FALSE);
#else
/*
* If parent mapped and window was mapped, set unmapcount
* to 0 and remap window.
*/
if (!pwp->unmapcount && wasmapped) {
SetUnmapCountTree(wp, 0, GR_FALSE);
GsWpMapWindow(wp, GR_FALSE);
} else {
if (wasmapped)
SetUnmapCountTree(wp, pwp->unmapcount, GR_FALSE);
else SetUnmapCountTree(wp, pwp->unmapcount+1, GR_FALSE);
}
#endif
}
static int nextgcid = 1000;
/*
* Allocate a new GC with default parameters.
* The GC is owned by the current client.
*/
GR_GC_ID
GrNewGC(void)
{
GR_GC *gcp;
gcp = (GR_GC *) malloc(sizeof(GR_GC));
if (gcp == NULL) {
GsError(GR_ERROR_MALLOC_FAILED, 0);
return 0;
}
gcp->id = nextgcid++;
gcp->mode = GR_MODE_COPY;
gcp->regionid = 0; /* no region*/
gcp->xoff = 0; /* no offset*/
gcp->yoff = 0;
gcp->fontid = 0; /* 0 is default font*/
gcp->foreground = WHITE;
gcp->background = BLACK;
gcp->usebackground = GR_TRUE;
gcp->changed = GR_TRUE;
gcp->owner = curclient;
gcp->next = listgcp;
listgcp = gcp;
return gcp->id;
}
/*
* Destroy an existing graphics context.
*/
void
GrDestroyGC(GR_GC_ID gc)
{
GR_GC *gcp; /* graphics context */
GR_GC *prevgcp; /* previous graphics context */
gcp = GsFindGC(gc);
if (gcp == NULL)
return;
if (gc == cachegcid) {
cachegcid = 0;
cachegcp = NULL;
}
if (gcp == curgcp)
curgcp = NULL;
if (listgcp == gcp)
listgcp = gcp->next;
else {
prevgcp = listgcp;
while (prevgcp->next != gcp)
prevgcp = prevgcp->next;
prevgcp->next = gcp->next;
}
free(gcp);
}
/*
* Allocate a new GC which is a copy of another one.
* The GC is owned by the current client.
*/
GR_GC_ID
GrCopyGC(GR_GC_ID gc)
{
GR_GC *oldgcp; /* old graphics context */
GR_GC *gcp; /* new graphics context */
oldgcp = GsFindGC(gc);
if (oldgcp == NULL)
return 0;
gcp = (GR_GC *) malloc(sizeof(GR_GC));
if (gcp == NULL) {
GsError(GR_ERROR_MALLOC_FAILED, 0);
return 0;
}
/*
* Copy all the old gcp values into the new one, except allocate
* a new id for it and link it into the list of GCs.
*/
*gcp = *oldgcp;
gcp->id = nextgcid++;
gcp->changed = GR_TRUE;
gcp->owner = curclient;
gcp->next = listgcp;
listgcp = gcp;
return gcp->id;
}
/*
* Return information about the specified graphics context.
*/
void
GrGetGCInfo(GR_GC_ID gcid, GR_GC_INFO *gcip)
{
GR_GC *gcp;
/*
* Find the GC manually so that an error is not generated.
*/
for (gcp = listgcp; gcp && (gcp->id != gcid); gcp = gcp->next)
continue;
if (gcp == NULL) {
memset(gcip, 0, sizeof(GR_GC_INFO));
return;
}
gcip->gcid = gcid;
gcip->mode = gcp->mode;
gcip->region = gcp->regionid;
gcip->xoff = gcp->xoff;
gcip->yoff = gcp->yoff;
gcip->font = gcp->fontid;
gcip->foreground = gcp->foreground;
gcip->background = gcp->background;
gcip->usebackground = gcp->usebackground;
}
static int nextregionid = 1000;
/*
* Allocate a new REGION with default parameters.
* The REGION is owned by the current client.
*/
GR_REGION_ID
GrNewRegion(void)
{
GR_REGION *regionp;
regionp = (GR_REGION *) malloc(sizeof(GR_REGION));
if (regionp == NULL) {
GsError(GR_ERROR_MALLOC_FAILED, 0);
return 0;
}
regionp->rgn = GdAllocRegion();
regionp->id = nextregionid++;
regionp->owner = curclient;
regionp->next = listregionp;
listregionp = regionp;
return regionp->id;
}
/*
* Allocate a new region from a set of points interpreted as a polygon.
* The REGION is owned by the current client.
*/
GR_REGION_ID
GrNewPolygonRegion(int mode, GR_COUNT count, GR_POINT *points)
{
#if POLYREGIONS
GR_REGION *regionp;
regionp = (GR_REGION *) malloc(sizeof(GR_REGION));
if (regionp == NULL) {
GsError(GR_ERROR_MALLOC_FAILED, 0);
return 0;
}
regionp->rgn = GdAllocPolygonRegion(points, count, mode);
regionp->id = nextregionid++;
regionp->owner = curclient;
regionp->next = listregionp;
listregionp = regionp;
return regionp->id;
#else
return 0;
#endif
}
/*
* Destroy an existing region.
*/
void
GrDestroyRegion(GR_REGION_ID region)
{
GR_REGION *regionp; /* region */
GR_REGION *prevregionp; /* previous region */
regionp = GsFindRegion(region);
if (regionp == NULL)
return;
if (listregionp == regionp)
listregionp = regionp->next;
else {
prevregionp = listregionp;
while (prevregionp->next != regionp)
prevregionp = prevregionp->next;
prevregionp->next = regionp->next;
}
GdDestroyRegion(regionp->rgn);
free(regionp);
}
/*
* Updates the region from a union of the specified rectangle
* and the original region.
*/
void
GrUnionRectWithRegion(GR_REGION_ID region, GR_RECT *rect)
{
GR_REGION *regionp;
MWRECT rc;
regionp = GsFindRegion(region);
if (regionp) {
/* convert Nano-X rect to MW rect*/
rc.left = rect->x;
rc.top = rect->y;
rc.right = rect->x + rect->width;
rc.bottom = rect->y + rect->height;
GdUnionRectWithRegion(&rc, regionp->rgn);
}
}
/*
* Updates the region from a union of two regions.
*/
void
GrUnionRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
GR_REGION_ID src_rgn2)
{
GR_REGION *regionp;
GR_REGION *srcregionp1;
GR_REGION *srcregionp2;
regionp = GsFindRegion(dst_rgn);
if (regionp == NULL)
return;
srcregionp1 = GsFindRegion(src_rgn1);
if (srcregionp1 == NULL)
return;
srcregionp2 = GsFindRegion(src_rgn2);
if (srcregionp2 == NULL)
return;
GdUnionRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
}
/*
* Updates the region by subtracting a region from another.
*/
void
GrSubtractRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
GR_REGION_ID src_rgn2)
{
GR_REGION *regionp;
GR_REGION *srcregionp1;
GR_REGION *srcregionp2;
regionp = GsFindRegion(dst_rgn);
if (regionp == NULL)
return;
srcregionp1 = GsFindRegion(src_rgn1);
if (srcregionp1 == NULL)
return;
srcregionp2 = GsFindRegion(src_rgn2);
if (srcregionp2 == NULL)
return;
GdSubtractRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
}
/*
* Updates the region to the difference of two regions.
*/
void
GrXorRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
GR_REGION_ID src_rgn2)
{
GR_REGION *regionp;
GR_REGION *srcregionp1;
GR_REGION *srcregionp2;
regionp = GsFindRegion(dst_rgn);
if (regionp == NULL)
return;
srcregionp1 = GsFindRegion(src_rgn1);
if (srcregionp1 == NULL)
return;
srcregionp2 = GsFindRegion(src_rgn2);
if (srcregionp2 == NULL)
return;
GdXorRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
}
/*
* Updates the region from a intersection of two regions.
*/
void
GrIntersectRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
GR_REGION_ID src_rgn2)
{
GR_REGION *regionp;
GR_REGION *srcregionp1;
GR_REGION *srcregionp2;
regionp = GsFindRegion(dst_rgn);
if (regionp == NULL)
return;
srcregionp1 = GsFindRegion(src_rgn1);
if (srcregionp1 == NULL)
return;
srcregionp2 = GsFindRegion(src_rgn2);
if (srcregionp2 == NULL)
return;
GdIntersectRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
}
/*
* Sets the clip-mask in the GC to the specified region.
*/
void
GrSetGCRegion(GR_GC_ID gc, GR_REGION_ID region)
{
GR_GC *gcp;
gcp = GsFindGC(gc);
if(gcp == NULL)
return;
gcp->regionid = region;
gcp->changed = GR_TRUE;
}
/*
* Set the x,y origin of user clip region in GC.
*/
void
GrSetGCClipOrigin(GR_GC_ID gc, int xoff, int yoff)
{
GR_GC *gcp;
gcp = GsFindGC(gc);
if(gcp == NULL)
return;
gcp->xoff = xoff;
gcp->yoff = yoff;
gcp->changed = GR_TRUE;
}
/*
* Determines whether a specified point resides in a region.
*/
GR_BOOL
GrPointInRegion(GR_REGION_ID region, GR_COORD x, GR_COORD y)
{
GR_REGION *regionp;
regionp = GsFindRegion(region);
if (regionp == NULL)
return GR_FALSE;
return GdPtInRegion(regionp->rgn, x, y);
}
/*
* Determines whether a specified rectangle at least partly resides
* in a region.
*/
int
GrRectInRegion(GR_REGION_ID region, GR_COORD x, GR_COORD y, GR_COORD w,
GR_COORD h)
{
GR_REGION *regionp;
MWRECT rect;
regionp = GsFindRegion(region);
if (regionp == NULL)
return MWRECT_OUT;
rect.left = x;
rect.top = y;
rect.right = x + w;
rect.bottom = y + h;
return GdRectInRegion(regionp->rgn, &rect);
}
/*
* Return GR_TRUE if a region is empty.
*/
GR_BOOL
GrEmptyRegion(GR_REGION_ID region)
{
GR_REGION *regionp;
regionp = GsFindRegion(region);
if (regionp == NULL)
return GR_TRUE;
return GdEmptyRegion(regionp->rgn);
}
/*
* Return GR_TRUE if two regions are identical.
*/
GR_BOOL
GrEqualRegion(GR_REGION_ID rgn1, GR_REGION_ID rgn2)
{
GR_REGION *prgn1;
GR_REGION *prgn2;
prgn1 = GsFindRegion(rgn1);
prgn2 = GsFindRegion(rgn2);
if (!prgn1 && !prgn2)
return GR_TRUE;
if (!prgn1 || !prgn2)
return GR_FALSE;
return GdEqualRegion(prgn1->rgn, prgn2->rgn);
}
/*
* Offset a region by dx, dy.
*/
void
GrOffsetRegion(GR_REGION_ID region, GR_SIZE dx, GR_SIZE dy)
{
GR_REGION *regionp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -