/*
|
/*
|
* Copyright (c) 1999, 2000, 2001 Greg Haerr <greg@censoft.com>
|
* Copyright (c) 1999, 2000, 2001 Greg Haerr <greg@censoft.com>
|
* Copyright (c) 2000 Alex Holden <alex@linuxhacker.org>
|
* Copyright (c) 2000 Alex Holden <alex@linuxhacker.org>
|
* Copyright (c) 1991 David I. Bell
|
* Copyright (c) 1991 David I. Bell
|
* Permission is granted to use, distribute, or modify this source,
|
* Permission is granted to use, distribute, or modify this source,
|
* provided that this copyright notice remains intact.
|
* provided that this copyright notice remains intact.
|
*/
|
*/
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <string.h>
|
#define MWINCLUDECOLORS
|
#define MWINCLUDECOLORS
|
#include "serv.h"
|
#include "serv.h"
|
|
|
static int nextid = GR_ROOT_WINDOW_ID + 1;
|
static int nextid = GR_ROOT_WINDOW_ID + 1;
|
|
|
static void CheckNextEvent(GR_EVENT *ep, GR_BOOL doSelect);
|
static void CheckNextEvent(GR_EVENT *ep, GR_BOOL doSelect);
|
|
|
/*
|
/*
|
* Return information about the screen for clients to use.
|
* Return information about the screen for clients to use.
|
*/
|
*/
|
void
|
void
|
GrGetScreenInfo(GR_SCREEN_INFO *sip)
|
GrGetScreenInfo(GR_SCREEN_INFO *sip)
|
{
|
{
|
GdGetScreenInfo(rootwp->psd, sip);
|
GdGetScreenInfo(rootwp->psd, sip);
|
|
|
/* virtual/workspace screen sizing*/
|
/* virtual/workspace screen sizing*/
|
#if 0
|
#if 0
|
/* force small screen for emulation purposes*/
|
/* force small screen for emulation purposes*/
|
sip->vs_width = 240; /* PDA*/
|
sip->vs_width = 240; /* PDA*/
|
sip->vs_height = 320;
|
sip->vs_height = 320;
|
sip->ws_width = 240;
|
sip->ws_width = 240;
|
sip->ws_height = 298;
|
sip->ws_height = 298;
|
#else
|
#else
|
/* set workspace equal to screen area minus 22 pixel taskbar*/
|
/* set workspace equal to screen area minus 22 pixel taskbar*/
|
sip->vs_width = sip->cols;
|
sip->vs_width = sip->cols;
|
sip->vs_height = sip->rows;
|
sip->vs_height = sip->rows;
|
sip->ws_width = sip->cols;
|
sip->ws_width = sip->cols;
|
sip->ws_height = sip->rows - 22;
|
sip->ws_height = sip->rows - 22;
|
#endif
|
#endif
|
}
|
}
|
|
|
/*
|
/*
|
* Return the size of a text string for the font in a graphics context.
|
* Return the size of a text string for the font in a graphics context.
|
* This is the width of the string, the height of the string,
|
* This is the width of the string, the height of the string,
|
* and the height above the bottom of the font of the baseline for the font.
|
* and the height above the bottom of the font of the baseline for the font.
|
*/
|
*/
|
void
|
void
|
GrGetGCTextSize(GR_GC_ID gc, void *str, int count, int flags,
|
GrGetGCTextSize(GR_GC_ID gc, void *str, int count, int flags,
|
GR_SIZE *retwidth, GR_SIZE *retheight, GR_SIZE *retbase)
|
GR_SIZE *retwidth, GR_SIZE *retheight, GR_SIZE *retbase)
|
{
|
{
|
GR_GC *gcp;
|
GR_GC *gcp;
|
GR_FONT *fontp;
|
GR_FONT *fontp;
|
PMWFONT pf;
|
PMWFONT pf;
|
|
|
gcp = GsFindGC(gc);
|
gcp = GsFindGC(gc);
|
if (gcp == NULL)
|
if (gcp == NULL)
|
fontp = NULL;
|
fontp = NULL;
|
else
|
else
|
fontp = GsFindFont(gcp->fontid);
|
fontp = GsFindFont(gcp->fontid);
|
pf = fontp? fontp->pfont: stdfont;
|
pf = fontp? fontp->pfont: stdfont;
|
GdGetTextSize(pf, str, count, retwidth, retheight, retbase, flags);
|
GdGetTextSize(pf, str, count, retwidth, retheight, retbase, flags);
|
}
|
}
|
|
|
#if NONETWORK
|
#if NONETWORK
|
/*
|
/*
|
* Return the next waiting event for a client, or wait for one if there
|
* Return the next waiting event for a client, or wait for one if there
|
* is none yet. The event is copied into the specified structure, and
|
* is none yet. The event is copied into the specified structure, and
|
* then is moved from the event queue to the free event queue. If there
|
* then is moved from the event queue to the free event queue. If there
|
* is an error event waiting, it is delivered before any other events.
|
* is an error event waiting, it is delivered before any other events.
|
*/
|
*/
|
void
|
void
|
GrGetNextEvent(GR_EVENT *ep)
|
GrGetNextEvent(GR_EVENT *ep)
|
{
|
{
|
GrGetNextEventTimeout(ep, 0L);
|
GrGetNextEventTimeout(ep, 0L);
|
}
|
}
|
|
|
/*
|
/*
|
* Return the next event from the event queue, or
|
* Return the next event from the event queue, or
|
* wait for a new one if one is not ready. If timeout
|
* wait for a new one if one is not ready. If timeout
|
* is nonzero, return timeout event if time elapsed.
|
* is nonzero, return timeout event if time elapsed.
|
*/
|
*/
|
void
|
void
|
GrGetNextEventTimeout(GR_EVENT *ep, GR_TIMEOUT timeout)
|
GrGetNextEventTimeout(GR_EVENT *ep, GR_TIMEOUT timeout)
|
{
|
{
|
/* If no event ready, wait for one*/
|
/* If no event ready, wait for one*/
|
/* Note: won't work for multiple clients*/
|
/* Note: won't work for multiple clients*/
|
/* This is OK, since only static linked apps call this function*/
|
/* This is OK, since only static linked apps call this function*/
|
while(curclient->eventhead == NULL)
|
while(curclient->eventhead == NULL)
|
GsSelect(timeout);
|
GsSelect(timeout);
|
CheckNextEvent(ep, GR_FALSE);
|
CheckNextEvent(ep, GR_FALSE);
|
}
|
}
|
|
|
/*
|
/*
|
* Wait until an event is available for a client, and then peek at it.
|
* Wait until an event is available for a client, and then peek at it.
|
*/
|
*/
|
void
|
void
|
GrPeekWaitEvent(GR_EVENT *ep)
|
GrPeekWaitEvent(GR_EVENT *ep)
|
{
|
{
|
while(curclient->eventhead == NULL)
|
while(curclient->eventhead == NULL)
|
GsSelect(0L);
|
GsSelect(0L);
|
GrPeekEvent(ep);
|
GrPeekEvent(ep);
|
}
|
}
|
#endif
|
#endif
|
|
|
/*
|
/*
|
* Return the next event from the event queue if one is ready.
|
* Return the next event from the event queue if one is ready.
|
* If one is not ready, then the type GR_EVENT_TYPE_NONE is returned.
|
* If one is not ready, then the type GR_EVENT_TYPE_NONE is returned.
|
* If it is an error event, then a user-specified routine is called
|
* If it is an error event, then a user-specified routine is called
|
* if it was defined, otherwise we clean up and exit.
|
* if it was defined, otherwise we clean up and exit.
|
*/
|
*/
|
void
|
void
|
GrCheckNextEvent(GR_EVENT *ep)
|
GrCheckNextEvent(GR_EVENT *ep)
|
{
|
{
|
CheckNextEvent(ep, GR_TRUE);
|
CheckNextEvent(ep, GR_TRUE);
|
}
|
}
|
|
|
static void
|
static void
|
CheckNextEvent(GR_EVENT *ep, GR_BOOL doSelect)
|
CheckNextEvent(GR_EVENT *ep, GR_BOOL doSelect)
|
{
|
{
|
GR_EVENT_LIST * elp;
|
GR_EVENT_LIST * elp;
|
|
|
#if NONETWORK
|
#if NONETWORK
|
/* Since we're bound to server, select() is only called
|
/* Since we're bound to server, select() is only called
|
* thru here
|
* thru here
|
*/
|
*/
|
if(doSelect)
|
if(doSelect)
|
GsSelect(0L);
|
GsSelect(0L);
|
#endif
|
#endif
|
/* Copy first event if any*/
|
/* Copy first event if any*/
|
if(!GrPeekEvent(ep))
|
if(!GrPeekEvent(ep))
|
return;
|
return;
|
|
|
/* Get first event again*/
|
/* Get first event again*/
|
elp = curclient->eventhead;
|
elp = curclient->eventhead;
|
|
|
/* Remove first event from queue*/
|
/* Remove first event from queue*/
|
curclient->eventhead = elp->next;
|
curclient->eventhead = elp->next;
|
if (curclient->eventtail == elp)
|
if (curclient->eventtail == elp)
|
curclient->eventtail = NULL;
|
curclient->eventtail = NULL;
|
|
|
elp->next = eventfree;
|
elp->next = eventfree;
|
eventfree = elp;
|
eventfree = elp;
|
}
|
}
|
|
|
/*
|
/*
|
* Peek at the event queue for the current client to see if there are any
|
* Peek at the event queue for the current client to see if there are any
|
* outstanding events. Returns the event at the head of the queue, or
|
* outstanding events. Returns the event at the head of the queue, or
|
* else a null event type. The event is still left in the queue, however.
|
* else a null event type. The event is still left in the queue, however.
|
*/
|
*/
|
int
|
int
|
GrPeekEvent(GR_EVENT *ep)
|
GrPeekEvent(GR_EVENT *ep)
|
{
|
{
|
GR_EVENT_LIST * elp;
|
GR_EVENT_LIST * elp;
|
|
|
elp = curclient->eventhead;
|
elp = curclient->eventhead;
|
if(elp == NULL) {
|
if(elp == NULL) {
|
ep->type = GR_EVENT_TYPE_NONE;
|
ep->type = GR_EVENT_TYPE_NONE;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* copy event out*/
|
/* copy event out*/
|
*ep = elp->event;
|
*ep = elp->event;
|
return 1;
|
return 1;
|
}
|
}
|
|
|
/*
|
/*
|
* Return information about a window id.
|
* Return information about a window id.
|
*/
|
*/
|
void
|
void
|
GrGetWindowInfo(GR_WINDOW_ID wid, GR_WINDOW_INFO *infoptr)
|
GrGetWindowInfo(GR_WINDOW_ID wid, GR_WINDOW_INFO *infoptr)
|
{
|
{
|
GR_WINDOW *wp; /* window structure */
|
GR_WINDOW *wp; /* window structure */
|
GR_PIXMAP *pp;
|
GR_PIXMAP *pp;
|
GR_EVENT_CLIENT *evp; /* event-client structure */
|
GR_EVENT_CLIENT *evp; /* event-client structure */
|
|
|
/* first check window list*/
|
/* first check window list*/
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if (wp) {
|
if (wp) {
|
infoptr->wid = wid;
|
infoptr->wid = wid;
|
/* report parent-relative x,y coordinates*/
|
/* report parent-relative x,y coordinates*/
|
infoptr->x = wp->x - (wp->parent ? wp->parent->x : 0);
|
infoptr->x = wp->x - (wp->parent ? wp->parent->x : 0);
|
infoptr->y = wp->y - (wp->parent ? wp->parent->y : 0);
|
infoptr->y = wp->y - (wp->parent ? wp->parent->y : 0);
|
infoptr->width = wp->width;
|
infoptr->width = wp->width;
|
infoptr->height = wp->height;
|
infoptr->height = wp->height;
|
infoptr->parent = wp->parent? wp->parent->id: 0;
|
infoptr->parent = wp->parent? wp->parent->id: 0;
|
infoptr->child = wp->children? wp->children->id: 0;
|
infoptr->child = wp->children? wp->children->id: 0;
|
infoptr->sibling = wp->siblings? wp->siblings->id: 0;
|
infoptr->sibling = wp->siblings? wp->siblings->id: 0;
|
infoptr->mapped = wp->mapped;
|
infoptr->mapped = wp->mapped;
|
infoptr->unmapcount = wp->unmapcount;
|
infoptr->unmapcount = wp->unmapcount;
|
infoptr->inputonly = !wp->output;
|
infoptr->inputonly = !wp->output;
|
infoptr->bordersize = wp->bordersize;
|
infoptr->bordersize = wp->bordersize;
|
infoptr->bordercolor = wp->bordercolor;
|
infoptr->bordercolor = wp->bordercolor;
|
infoptr->background = wp->background;
|
infoptr->background = wp->background;
|
infoptr->props = wp->props;
|
infoptr->props = wp->props;
|
infoptr->cursor = wp->cursorid;
|
infoptr->cursor = wp->cursorid;
|
infoptr->processid = wp->owner? wp->owner->processid: 0;
|
infoptr->processid = wp->owner? wp->owner->processid: 0;
|
infoptr->eventmask = 0;
|
infoptr->eventmask = 0;
|
|
|
for (evp = wp->eventclients; evp; evp = evp->next) {
|
for (evp = wp->eventclients; evp; evp = evp->next) {
|
if (evp->client == curclient)
|
if (evp->client == curclient)
|
infoptr->eventmask = evp->eventmask;
|
infoptr->eventmask = evp->eventmask;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
|
|
/* then pixmap list*/
|
/* then pixmap list*/
|
pp = GsFindPixmap(wid);
|
pp = GsFindPixmap(wid);
|
if (pp) {
|
if (pp) {
|
infoptr->wid = wid;
|
infoptr->wid = wid;
|
infoptr->x = pp->x;
|
infoptr->x = pp->x;
|
infoptr->y = pp->y;
|
infoptr->y = pp->y;
|
infoptr->width = pp->width;
|
infoptr->width = pp->width;
|
infoptr->height = pp->height;
|
infoptr->height = pp->height;
|
infoptr->parent = 0;
|
infoptr->parent = 0;
|
infoptr->child = 0;
|
infoptr->child = 0;
|
infoptr->sibling = 0;
|
infoptr->sibling = 0;
|
infoptr->mapped = GR_FALSE;
|
infoptr->mapped = GR_FALSE;
|
infoptr->unmapcount = 0;
|
infoptr->unmapcount = 0;
|
infoptr->inputonly = GR_FALSE;
|
infoptr->inputonly = GR_FALSE;
|
infoptr->bordersize = 0;
|
infoptr->bordersize = 0;
|
infoptr->bordercolor = 0;
|
infoptr->bordercolor = 0;
|
infoptr->background = 0;
|
infoptr->background = 0;
|
infoptr->eventmask = 0;
|
infoptr->eventmask = 0;
|
infoptr->cursor = 0;
|
infoptr->cursor = 0;
|
infoptr->processid = pp->owner? pp->owner->processid: 0;
|
infoptr->processid = pp->owner? pp->owner->processid: 0;
|
return;
|
return;
|
}
|
}
|
|
|
/* No error if window id is invalid.*/
|
/* No error if window id is invalid.*/
|
memset(infoptr, 0, sizeof(GR_WINDOW_INFO));
|
memset(infoptr, 0, sizeof(GR_WINDOW_INFO));
|
}
|
}
|
|
|
/*
|
/*
|
* Destroy an existing window and all of its children.
|
* Destroy an existing window and all of its children.
|
* Also used to destroy a pixmap.
|
* Also used to destroy a pixmap.
|
*/
|
*/
|
void
|
void
|
GrDestroyWindow(GR_WINDOW_ID wid)
|
GrDestroyWindow(GR_WINDOW_ID wid)
|
{
|
{
|
GR_WINDOW *wp; /* window structure */
|
GR_WINDOW *wp; /* window structure */
|
GR_PIXMAP *pp;
|
GR_PIXMAP *pp;
|
GR_PIXMAP *prevpp;
|
GR_PIXMAP *prevpp;
|
PSD psd;
|
PSD psd;
|
|
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if (wp) {
|
if (wp) {
|
GsWpDestroyWindow(wp);
|
GsWpDestroyWindow(wp);
|
} else {
|
} else {
|
pp = GsFindPixmap(wid);
|
pp = GsFindPixmap(wid);
|
if (pp) {
|
if (pp) {
|
psd = pp->psd;
|
psd = pp->psd;
|
/* deallocate pixmap memory*/
|
/* deallocate pixmap memory*/
|
if (psd->flags & PSF_ADDRMALLOC)
|
if (psd->flags & PSF_ADDRMALLOC)
|
free(psd->addr);
|
free(psd->addr);
|
|
|
/* deallocate mem gc*/
|
/* deallocate mem gc*/
|
psd->FreeMemGC(psd);
|
psd->FreeMemGC(psd);
|
|
|
/*
|
/*
|
* Remove this pixmap from the complete list of pixmaps.
|
* Remove this pixmap from the complete list of pixmaps.
|
*/
|
*/
|
prevpp = listpp;
|
prevpp = listpp;
|
if (prevpp == pp)
|
if (prevpp == pp)
|
listpp = pp->next;
|
listpp = pp->next;
|
else {
|
else {
|
while (prevpp->next != pp)
|
while (prevpp->next != pp)
|
prevpp = prevpp->next;
|
prevpp = prevpp->next;
|
prevpp->next = pp->next;
|
prevpp->next = pp->next;
|
}
|
}
|
|
|
/*
|
/*
|
* Forget various information if they related to this
|
* Forget various information if they related to this
|
* pixmap. Then finally free the structure.
|
* pixmap. Then finally free the structure.
|
*/
|
*/
|
if (pp == cachepp) {
|
if (pp == cachepp) {
|
cachepixmapid = 0;
|
cachepixmapid = 0;
|
cachepp = NULL;
|
cachepp = NULL;
|
}
|
}
|
free(pp);
|
free(pp);
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
|
|
/*
|
/*
|
* Raise a window to the highest level among its siblings.
|
* Raise a window to the highest level among its siblings.
|
*/
|
*/
|
void
|
void
|
GrRaiseWindow(GR_WINDOW_ID wid)
|
GrRaiseWindow(GR_WINDOW_ID wid)
|
{
|
{
|
GR_WINDOW *wp; /* window structure */
|
GR_WINDOW *wp; /* window structure */
|
GR_WINDOW *prevwp; /* previous window pointer */
|
GR_WINDOW *prevwp; /* previous window pointer */
|
GR_BOOL overlap; /* TRUE if there was overlap */
|
GR_BOOL overlap; /* TRUE if there was overlap */
|
|
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if ((wp == NULL) || (wp == rootwp))
|
if ((wp == NULL) || (wp == rootwp))
|
return;
|
return;
|
|
|
/*
|
/*
|
* If this is already the highest window then we are done.
|
* If this is already the highest window then we are done.
|
*/
|
*/
|
prevwp = wp->parent->children;
|
prevwp = wp->parent->children;
|
if (prevwp == wp)
|
if (prevwp == wp)
|
return;
|
return;
|
|
|
/*
|
/*
|
* Find the sibling just before this window so we can unlink it.
|
* Find the sibling just before this window so we can unlink it.
|
* Also, determine if any sibling ahead of us overlaps the window.
|
* Also, determine if any sibling ahead of us overlaps the window.
|
* Remember that for exposure events.
|
* Remember that for exposure events.
|
*/
|
*/
|
overlap = GR_FALSE;
|
overlap = GR_FALSE;
|
while (prevwp->siblings != wp) {
|
while (prevwp->siblings != wp) {
|
overlap |= GsCheckOverlap(prevwp, wp);
|
overlap |= GsCheckOverlap(prevwp, wp);
|
prevwp = prevwp->siblings;
|
prevwp = prevwp->siblings;
|
}
|
}
|
overlap |= GsCheckOverlap(prevwp, wp);
|
overlap |= GsCheckOverlap(prevwp, wp);
|
|
|
/*
|
/*
|
* Now unlink the window and relink it in at the front of the
|
* Now unlink the window and relink it in at the front of the
|
* sibling chain.
|
* sibling chain.
|
*/
|
*/
|
prevwp->siblings = wp->siblings;
|
prevwp->siblings = wp->siblings;
|
wp->siblings = wp->parent->children;
|
wp->siblings = wp->parent->children;
|
wp->parent->children = wp;
|
wp->parent->children = wp;
|
|
|
/*
|
/*
|
* Finally redraw the window if necessary.
|
* Finally redraw the window if necessary.
|
*/
|
*/
|
if (overlap) {
|
if (overlap) {
|
GsDrawBorder(wp);
|
GsDrawBorder(wp);
|
GsExposeArea(wp, wp->x, wp->y, wp->width, wp->height, NULL);
|
GsExposeArea(wp, wp->x, wp->y, wp->width, wp->height, NULL);
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Lower a window to the lowest level among its siblings.
|
* Lower a window to the lowest level among its siblings.
|
*/
|
*/
|
void GrLowerWindow(GR_WINDOW_ID wid)
|
void GrLowerWindow(GR_WINDOW_ID wid)
|
{
|
{
|
GR_WINDOW *wp; /* window structure */
|
GR_WINDOW *wp; /* window structure */
|
GR_WINDOW *prevwp; /* previous window pointer */
|
GR_WINDOW *prevwp; /* previous window pointer */
|
GR_WINDOW *sibwp; /* sibling window */
|
GR_WINDOW *sibwp; /* sibling window */
|
GR_WINDOW *expwp; /* siblings being exposed */
|
GR_WINDOW *expwp; /* siblings being exposed */
|
|
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if ((wp == NULL) || (wp == rootwp))
|
if ((wp == NULL) || (wp == rootwp))
|
return;
|
return;
|
if (wp->siblings == NULL)
|
if (wp->siblings == NULL)
|
return;
|
return;
|
|
|
/*
|
/*
|
* Find the sibling just before this window so we can unlink us.
|
* Find the sibling just before this window so we can unlink us.
|
*/
|
*/
|
prevwp = wp->parent->children;
|
prevwp = wp->parent->children;
|
if (prevwp != wp) {
|
if (prevwp != wp) {
|
while (prevwp->siblings != wp)
|
while (prevwp->siblings != wp)
|
prevwp = prevwp->siblings;
|
prevwp = prevwp->siblings;
|
}
|
}
|
|
|
/*
|
/*
|
* Remember the first sibling that is after us, so we can
|
* Remember the first sibling that is after us, so we can
|
* generate exposure events for the remaining siblings. Then
|
* generate exposure events for the remaining siblings. Then
|
* walk down the sibling chain looking for the last sibling.
|
* walk down the sibling chain looking for the last sibling.
|
*/
|
*/
|
expwp = wp->siblings;
|
expwp = wp->siblings;
|
sibwp = wp;
|
sibwp = wp;
|
while (sibwp->siblings)
|
while (sibwp->siblings)
|
sibwp = sibwp->siblings;
|
sibwp = sibwp->siblings;
|
|
|
/*
|
/*
|
* Now unlink the window and relink it in at the end of the
|
* Now unlink the window and relink it in at the end of the
|
* sibling chain.
|
* sibling chain.
|
*/
|
*/
|
if (prevwp == wp)
|
if (prevwp == wp)
|
wp->parent->children = wp->siblings;
|
wp->parent->children = wp->siblings;
|
else
|
else
|
prevwp->siblings = wp->siblings;
|
prevwp->siblings = wp->siblings;
|
sibwp->siblings = wp;
|
sibwp->siblings = wp;
|
|
|
wp->siblings = NULL;
|
wp->siblings = NULL;
|
|
|
/*
|
/*
|
* Finally redraw the sibling windows which this window covered
|
* Finally redraw the sibling windows which this window covered
|
* if they overlapped our window.
|
* if they overlapped our window.
|
*/
|
*/
|
while (expwp && (expwp != wp)) {
|
while (expwp && (expwp != wp)) {
|
if (GsCheckOverlap(wp, expwp)) {
|
if (GsCheckOverlap(wp, expwp)) {
|
GsExposeArea(expwp, wp->x - wp->bordersize,
|
GsExposeArea(expwp, wp->x - wp->bordersize,
|
wp->y - wp->bordersize,
|
wp->y - wp->bordersize,
|
wp->width + wp->bordersize * 2,
|
wp->width + wp->bordersize * 2,
|
wp->height + wp->bordersize * 2, NULL);
|
wp->height + wp->bordersize * 2, NULL);
|
}
|
}
|
expwp = expwp->siblings;
|
expwp = expwp->siblings;
|
}
|
}
|
}
|
}
|
|
|
/* Offset a window position and all children by offx,offy*/
|
/* Offset a window position and all children by offx,offy*/
|
static void
|
static void
|
OffsetWindow(GR_WINDOW *wp, GR_COORD offx, GR_COORD offy)
|
OffsetWindow(GR_WINDOW *wp, GR_COORD offx, GR_COORD offy)
|
{
|
{
|
GR_WINDOW *cp;
|
GR_WINDOW *cp;
|
|
|
wp->x += offx;
|
wp->x += offx;
|
wp->y += offy;
|
wp->y += offy;
|
for(cp=wp->children; cp; cp=cp->siblings)
|
for(cp=wp->children; cp; cp=cp->siblings)
|
OffsetWindow(cp, offx, offy);
|
OffsetWindow(cp, offx, offy);
|
}
|
}
|
|
|
/* deliver an update move event to window and all children*/
|
/* deliver an update move event to window and all children*/
|
static void
|
static void
|
DeliverUpdateMoveEventAndChildren(GR_WINDOW *wp)
|
DeliverUpdateMoveEventAndChildren(GR_WINDOW *wp)
|
{
|
{
|
GR_WINDOW * childwp;
|
GR_WINDOW * childwp;
|
|
|
GsDeliverUpdateEvent(wp, GR_UPDATE_MOVE, wp->x, wp->y,
|
GsDeliverUpdateEvent(wp, GR_UPDATE_MOVE, wp->x, wp->y,
|
wp->width, wp->height);
|
wp->width, wp->height);
|
|
|
for (childwp = wp->children; childwp; childwp = childwp->siblings)
|
for (childwp = wp->children; childwp; childwp = childwp->siblings)
|
DeliverUpdateMoveEventAndChildren(childwp);
|
DeliverUpdateMoveEventAndChildren(childwp);
|
}
|
}
|
|
|
/*
|
/*
|
* Move the window to the specified position relative to its parent.
|
* Move the window to the specified position relative to its parent.
|
*/
|
*/
|
void
|
void
|
GrMoveWindow(GR_WINDOW_ID wid, GR_COORD x, GR_COORD y)
|
GrMoveWindow(GR_WINDOW_ID wid, GR_COORD x, GR_COORD y)
|
{
|
{
|
GR_WINDOW *wp; /* window structure */
|
GR_WINDOW *wp; /* window structure */
|
GR_COORD offx, offy;
|
GR_COORD offx, offy;
|
|
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if (wp == NULL)
|
if (wp == NULL)
|
return;
|
return;
|
if (wp == rootwp) {
|
if (wp == rootwp) {
|
GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid);
|
GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid);
|
return;
|
return;
|
}
|
}
|
|
|
x += wp->parent->x;
|
x += wp->parent->x;
|
y += wp->parent->y;
|
y += wp->parent->y;
|
offx = x - wp->x;
|
offx = x - wp->x;
|
offy = y - wp->y;
|
offy = y - wp->y;
|
|
|
if (wp->x == x && wp->y == y)
|
if (wp->x == x && wp->y == y)
|
return;
|
return;
|
|
|
/*** move algorithms not requiring unmap/map ***/
|
/*** move algorithms not requiring unmap/map ***/
|
#if 1
|
#if 1
|
/* perform screen blit if topmost and mapped - no flicker!*/
|
/* perform screen blit if topmost and mapped - no flicker!*/
|
if (wp->mapped && wp == wp->parent->children
|
if (wp->mapped && wp == wp->parent->children
|
&& wp->parent->id == GR_ROOT_WINDOW_ID
|
&& wp->parent->id == GR_ROOT_WINDOW_ID
|
|
|
/* temp don't blit in portrait mode, still buggy*/
|
/* temp don't blit in portrait mode, still buggy*/
|
&& !(wp->psd->portrait & (MWPORTRAIT_LEFT|MWPORTRAIT_RIGHT))
|
&& !(wp->psd->portrait & (MWPORTRAIT_LEFT|MWPORTRAIT_RIGHT))
|
) {
|
) {
|
int oldx = wp->x;
|
int oldx = wp->x;
|
int oldy = wp->y;
|
int oldy = wp->y;
|
GR_WINDOW_ID pixid = GrNewPixmap(wp->width, wp->height,NULL);
|
GR_WINDOW_ID pixid = GrNewPixmap(wp->width, wp->height,NULL);
|
GR_GC_ID gc = GrNewGC();
|
GR_GC_ID gc = GrNewGC();
|
GR_WINDOW * stopwp = wp;
|
GR_WINDOW * stopwp = wp;
|
int X, Y, W, H;
|
int X, Y, W, H;
|
|
|
/* must hide cursor first or GdFixCursor() will show it*/
|
/* must hide cursor first or GdFixCursor() will show it*/
|
GdHideCursor(rootwp->psd);
|
GdHideCursor(rootwp->psd);
|
|
|
/* turn off clipping of root's children*/
|
/* turn off clipping of root's children*/
|
GrSetGCMode(gc, GR_MODE_COPY|GR_MODE_EXCLUDECHILDREN);
|
GrSetGCMode(gc, GR_MODE_COPY|GR_MODE_EXCLUDECHILDREN);
|
|
|
/* copy topmost window contents offscreen*/
|
/* copy topmost window contents offscreen*/
|
GrCopyArea(pixid, gc, 0, 0, wp->width, wp->height,
|
GrCopyArea(pixid, gc, 0, 0, wp->width, wp->height,
|
GR_ROOT_WINDOW_ID, oldx, oldy, MWROP_COPY);
|
GR_ROOT_WINDOW_ID, oldx, oldy, MWROP_COPY);
|
|
|
/* calc new window offsets*/
|
/* calc new window offsets*/
|
OffsetWindow(wp, offx, offy);
|
OffsetWindow(wp, offx, offy);
|
|
|
/* force recalc of clip region*/
|
/* force recalc of clip region*/
|
clipwp = NULL;
|
clipwp = NULL;
|
|
|
/* copy window bits to new location*/
|
/* copy window bits to new location*/
|
GrCopyArea(GR_ROOT_WINDOW_ID, gc, wp->x, wp->y, wp->width,
|
GrCopyArea(GR_ROOT_WINDOW_ID, gc, wp->x, wp->y, wp->width,
|
wp->height, pixid, 0, 0, MWROP_COPY);
|
wp->height, pixid, 0, 0, MWROP_COPY);
|
|
|
/*
|
/*
|
* If any portion of the window was offscreen
|
* If any portion of the window was offscreen
|
* and is coming onscreen, must send expose events
|
* and is coming onscreen, must send expose events
|
* to this window as well.
|
* to this window as well.
|
*/
|
*/
|
if ((oldx < 0 && wp->x > oldx) ||
|
if ((oldx < 0 && wp->x > oldx) ||
|
(oldy < 0 && wp->y > oldy) ||
|
(oldy < 0 && wp->y > oldy) ||
|
(oldx+wp->width > rootwp->width && wp->x < oldx) ||
|
(oldx+wp->width > rootwp->width && wp->x < oldx) ||
|
(oldy+wp->height > rootwp->height && wp->y < oldy))
|
(oldy+wp->height > rootwp->height && wp->y < oldy))
|
stopwp = NULL;
|
stopwp = NULL;
|
|
|
/*
|
/*
|
* Calculate bounded exposed area and
|
* Calculate bounded exposed area and
|
* redraw anything lower than stopwp window.
|
* redraw anything lower than stopwp window.
|
*/
|
*/
|
X = MWMIN(oldx, wp->x);
|
X = MWMIN(oldx, wp->x);
|
Y = MWMIN(oldy, wp->y);
|
Y = MWMIN(oldy, wp->y);
|
W = MWMAX(oldx, wp->x) + wp->width - X;
|
W = MWMAX(oldx, wp->x) + wp->width - X;
|
H = MWMAX(oldy, wp->y) + wp->height - Y;
|
H = MWMAX(oldy, wp->y) + wp->height - Y;
|
GsExposeArea(rootwp, X, Y, W, H, stopwp);
|
GsExposeArea(rootwp, X, Y, W, H, stopwp);
|
|
|
GdShowCursor(rootwp->psd);
|
GdShowCursor(rootwp->psd);
|
GrDestroyGC(gc);
|
GrDestroyGC(gc);
|
GrDestroyWindow(pixid);
|
GrDestroyWindow(pixid);
|
DeliverUpdateMoveEventAndChildren(wp);
|
DeliverUpdateMoveEventAndChildren(wp);
|
return;
|
return;
|
}
|
}
|
#endif
|
#endif
|
#if 0
|
#if 0
|
/* perform quick move and expose if topmost and mapped - no blit*/
|
/* perform quick move and expose if topmost and mapped - no blit*/
|
if (wp->mapped && wp == wp->parent->children) {
|
if (wp->mapped && wp == wp->parent->children) {
|
int oldx = wp->x;
|
int oldx = wp->x;
|
int oldy = wp->y;
|
int oldy = wp->y;
|
int X, Y, W, H;
|
int X, Y, W, H;
|
|
|
OffsetWindow(wp, offx, offy);
|
OffsetWindow(wp, offx, offy);
|
|
|
/* force recalc of clip region*/
|
/* force recalc of clip region*/
|
clipwp = NULL;
|
clipwp = NULL;
|
|
|
X = MWMIN(oldx, wp->x);
|
X = MWMIN(oldx, wp->x);
|
Y = MWMIN(oldy, wp->y);
|
Y = MWMIN(oldy, wp->y);
|
W = MWMAX(oldx, wp->x) + wp->width - X;
|
W = MWMAX(oldx, wp->x) + wp->width - X;
|
H = MWMAX(oldy, wp->y) + wp->height - Y;
|
H = MWMAX(oldy, wp->y) + wp->height - Y;
|
GsExposeArea(rootwp, X, Y, W, H, NULL);
|
GsExposeArea(rootwp, X, Y, W, H, NULL);
|
DeliverUpdateMoveEventAndChildren(wp);
|
DeliverUpdateMoveEventAndChildren(wp);
|
return;
|
return;
|
}
|
}
|
#endif
|
#endif
|
/*
|
/*
|
* This method will redraw the window entirely,
|
* This method will redraw the window entirely,
|
* resulting in considerable flicker.
|
* resulting in considerable flicker.
|
*/
|
*/
|
GsWpUnmapWindow(wp, GR_TRUE);
|
GsWpUnmapWindow(wp, GR_TRUE);
|
OffsetWindow(wp, offx, offy);
|
OffsetWindow(wp, offx, offy);
|
GsWpMapWindow(wp, GR_FALSE);
|
GsWpMapWindow(wp, GR_FALSE);
|
DeliverUpdateMoveEventAndChildren(wp);
|
DeliverUpdateMoveEventAndChildren(wp);
|
}
|
}
|
|
|
/*
|
/*
|
* Resize the window to be the specified size.
|
* Resize the window to be the specified size.
|
*/
|
*/
|
void
|
void
|
GrResizeWindow(GR_WINDOW_ID wid, GR_SIZE width, GR_SIZE height)
|
GrResizeWindow(GR_WINDOW_ID wid, GR_SIZE width, GR_SIZE height)
|
{
|
{
|
GR_WINDOW *wp; /* window structure */
|
GR_WINDOW *wp; /* window structure */
|
|
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if (wp == NULL)
|
if (wp == NULL)
|
return;
|
return;
|
if (wp == rootwp) {
|
if (wp == rootwp) {
|
GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid);
|
GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid);
|
return;
|
return;
|
}
|
}
|
if ((width <= 0) || (height <= 0)) {
|
if ((width <= 0) || (height <= 0)) {
|
GsError(GR_ERROR_BAD_WINDOW_SIZE, wid);
|
GsError(GR_ERROR_BAD_WINDOW_SIZE, wid);
|
return;
|
return;
|
}
|
}
|
|
|
if ((wp->width == width) && (wp->height == height))
|
if ((wp->width == width) && (wp->height == height))
|
return;
|
return;
|
|
|
if (wp->unmapcount || !wp->output) {
|
if (wp->unmapcount || !wp->output) {
|
wp->width = width;
|
wp->width = width;
|
wp->height = height;
|
wp->height = height;
|
return;
|
return;
|
}
|
}
|
|
|
/*
|
/*
|
* This should be optimized to not require redrawing of the window
|
* This should be optimized to not require redrawing of the window
|
* when possible.
|
* when possible.
|
*/
|
*/
|
GsWpUnmapWindow(wp, GR_TRUE);
|
GsWpUnmapWindow(wp, GR_TRUE);
|
wp->width = width;
|
wp->width = width;
|
wp->height = height;
|
wp->height = height;
|
GsWpMapWindow(wp, GR_FALSE);
|
GsWpMapWindow(wp, GR_FALSE);
|
GsDeliverUpdateEvent(wp, GR_UPDATE_SIZE, wp->x, wp->y, width, height);
|
GsDeliverUpdateEvent(wp, GR_UPDATE_SIZE, wp->x, wp->y, width, height);
|
}
|
}
|
|
|
/* set unmapcount for a window and all its children*/
|
/* set unmapcount for a window and all its children*/
|
static void
|
static void
|
SetUnmapCountTree(GR_WINDOW *wp, int value, GR_BOOL increment)
|
SetUnmapCountTree(GR_WINDOW *wp, int value, GR_BOOL increment)
|
{
|
{
|
GR_WINDOW * childwp;
|
GR_WINDOW * childwp;
|
|
|
if (increment)
|
if (increment)
|
wp->unmapcount += value;
|
wp->unmapcount += value;
|
else wp->unmapcount = value;
|
else wp->unmapcount = value;
|
|
|
for (childwp = wp->children; childwp; childwp = childwp->siblings)
|
for (childwp = wp->children; childwp; childwp = childwp->siblings)
|
SetUnmapCountTree(childwp, value, increment);
|
SetUnmapCountTree(childwp, value, increment);
|
}
|
}
|
|
|
/*
|
/*
|
* Reparent window to new parent, position at passed x, y
|
* Reparent window to new parent, position at passed x, y
|
*
|
*
|
* NOTE: currently, the new parent must be mapped before
|
* NOTE: currently, the new parent must be mapped before
|
* reparenting, or the children of the newly parented window
|
* reparenting, or the children of the newly parented window
|
* will have bad unmapcount values due to the GrMapWindow
|
* will have bad unmapcount values due to the GrMapWindow
|
* being called on the parent afterwards, and chaining down
|
* being called on the parent afterwards, and chaining down
|
* through the children.
|
* through the children.
|
*/
|
*/
|
void
|
void
|
GrReparentWindow(GR_WINDOW_ID wid, GR_WINDOW_ID pwid, GR_COORD x, GR_COORD y)
|
GrReparentWindow(GR_WINDOW_ID wid, GR_WINDOW_ID pwid, GR_COORD x, GR_COORD y)
|
{
|
{
|
GR_WINDOW *wp; /* window structure */
|
GR_WINDOW *wp; /* window structure */
|
GR_WINDOW *pwp; /* parent window structure */
|
GR_WINDOW *pwp; /* parent window structure */
|
GR_WINDOW **mysibptr; /* handle to my sibling ptr */
|
GR_WINDOW **mysibptr; /* handle to my sibling ptr */
|
GR_COORD offx, offy;
|
GR_COORD offx, offy;
|
GR_BOOL wasmapped;
|
GR_BOOL wasmapped;
|
|
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
pwp = GsFindWindow(pwid);
|
pwp = GsFindWindow(pwid);
|
if (wp == NULL || pwp == NULL || wp == pwp)
|
if (wp == NULL || pwp == NULL || wp == pwp)
|
return;
|
return;
|
if (wp == rootwp) {
|
if (wp == rootwp) {
|
GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid);
|
GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid);
|
return;
|
return;
|
}
|
}
|
|
|
x += pwp->x;
|
x += pwp->x;
|
y += pwp->y;
|
y += pwp->y;
|
offx = x - wp->x;
|
offx = x - wp->x;
|
offy = y - wp->y;
|
offy = y - wp->y;
|
|
|
/*printf("pid %d wid %d (oldpid %d) %d,%d\n", pwid, wid, wp->parent->id, pwp->unmapcount, wp->unmapcount);*/
|
/*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.
|
* Always unmap window, can't hurt if not mapped.
|
*/
|
*/
|
wasmapped = (wp->unmapcount == 0);
|
wasmapped = (wp->unmapcount == 0);
|
GsWpUnmapWindow(wp, GR_TRUE);
|
GsWpUnmapWindow(wp, GR_TRUE);
|
|
|
for(mysibptr = &(wp->parent->children); *mysibptr != wp;
|
for(mysibptr = &(wp->parent->children); *mysibptr != wp;
|
mysibptr = &((*mysibptr)->siblings))
|
mysibptr = &((*mysibptr)->siblings))
|
continue;
|
continue;
|
*mysibptr = wp->siblings;
|
*mysibptr = wp->siblings;
|
wp->parent = pwp;
|
wp->parent = pwp;
|
wp->siblings = pwp->children;
|
wp->siblings = pwp->children;
|
pwp->children = wp;
|
pwp->children = wp;
|
OffsetWindow(wp, offx, offy);
|
OffsetWindow(wp, offx, offy);
|
#if 1 /* temp fix to bad mapcount reparenting code below*/
|
#if 1 /* temp fix to bad mapcount reparenting code below*/
|
GsWpMapWindow(wp, GR_FALSE);
|
GsWpMapWindow(wp, GR_FALSE);
|
#else
|
#else
|
/*
|
/*
|
* If parent mapped and window was mapped, set unmapcount
|
* If parent mapped and window was mapped, set unmapcount
|
* to 0 and remap window.
|
* to 0 and remap window.
|
*/
|
*/
|
if (!pwp->unmapcount && wasmapped) {
|
if (!pwp->unmapcount && wasmapped) {
|
SetUnmapCountTree(wp, 0, GR_FALSE);
|
SetUnmapCountTree(wp, 0, GR_FALSE);
|
GsWpMapWindow(wp, GR_FALSE);
|
GsWpMapWindow(wp, GR_FALSE);
|
} else {
|
} else {
|
if (wasmapped)
|
if (wasmapped)
|
SetUnmapCountTree(wp, pwp->unmapcount, GR_FALSE);
|
SetUnmapCountTree(wp, pwp->unmapcount, GR_FALSE);
|
else SetUnmapCountTree(wp, pwp->unmapcount+1, GR_FALSE);
|
else SetUnmapCountTree(wp, pwp->unmapcount+1, GR_FALSE);
|
}
|
}
|
#endif
|
#endif
|
}
|
}
|
|
|
static int nextgcid = 1000;
|
static int nextgcid = 1000;
|
/*
|
/*
|
* Allocate a new GC with default parameters.
|
* Allocate a new GC with default parameters.
|
* The GC is owned by the current client.
|
* The GC is owned by the current client.
|
*/
|
*/
|
GR_GC_ID
|
GR_GC_ID
|
GrNewGC(void)
|
GrNewGC(void)
|
{
|
{
|
GR_GC *gcp;
|
GR_GC *gcp;
|
|
|
gcp = (GR_GC *) malloc(sizeof(GR_GC));
|
gcp = (GR_GC *) malloc(sizeof(GR_GC));
|
if (gcp == NULL) {
|
if (gcp == NULL) {
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
gcp->id = nextgcid++;
|
gcp->id = nextgcid++;
|
gcp->mode = GR_MODE_COPY;
|
gcp->mode = GR_MODE_COPY;
|
gcp->regionid = 0; /* no region*/
|
gcp->regionid = 0; /* no region*/
|
gcp->xoff = 0; /* no offset*/
|
gcp->xoff = 0; /* no offset*/
|
gcp->yoff = 0;
|
gcp->yoff = 0;
|
gcp->fontid = 0; /* 0 is default font*/
|
gcp->fontid = 0; /* 0 is default font*/
|
gcp->foreground = WHITE;
|
gcp->foreground = WHITE;
|
gcp->background = BLACK;
|
gcp->background = BLACK;
|
gcp->usebackground = GR_TRUE;
|
gcp->usebackground = GR_TRUE;
|
gcp->changed = GR_TRUE;
|
gcp->changed = GR_TRUE;
|
gcp->owner = curclient;
|
gcp->owner = curclient;
|
gcp->next = listgcp;
|
gcp->next = listgcp;
|
|
|
listgcp = gcp;
|
listgcp = gcp;
|
|
|
return gcp->id;
|
return gcp->id;
|
}
|
}
|
|
|
/*
|
/*
|
* Destroy an existing graphics context.
|
* Destroy an existing graphics context.
|
*/
|
*/
|
void
|
void
|
GrDestroyGC(GR_GC_ID gc)
|
GrDestroyGC(GR_GC_ID gc)
|
{
|
{
|
GR_GC *gcp; /* graphics context */
|
GR_GC *gcp; /* graphics context */
|
GR_GC *prevgcp; /* previous graphics context */
|
GR_GC *prevgcp; /* previous graphics context */
|
|
|
gcp = GsFindGC(gc);
|
gcp = GsFindGC(gc);
|
if (gcp == NULL)
|
if (gcp == NULL)
|
return;
|
return;
|
|
|
if (gc == cachegcid) {
|
if (gc == cachegcid) {
|
cachegcid = 0;
|
cachegcid = 0;
|
cachegcp = NULL;
|
cachegcp = NULL;
|
}
|
}
|
if (gcp == curgcp)
|
if (gcp == curgcp)
|
curgcp = NULL;
|
curgcp = NULL;
|
|
|
if (listgcp == gcp)
|
if (listgcp == gcp)
|
listgcp = gcp->next;
|
listgcp = gcp->next;
|
else {
|
else {
|
prevgcp = listgcp;
|
prevgcp = listgcp;
|
while (prevgcp->next != gcp)
|
while (prevgcp->next != gcp)
|
prevgcp = prevgcp->next;
|
prevgcp = prevgcp->next;
|
|
|
prevgcp->next = gcp->next;
|
prevgcp->next = gcp->next;
|
}
|
}
|
free(gcp);
|
free(gcp);
|
}
|
}
|
|
|
/*
|
/*
|
* Allocate a new GC which is a copy of another one.
|
* Allocate a new GC which is a copy of another one.
|
* The GC is owned by the current client.
|
* The GC is owned by the current client.
|
*/
|
*/
|
GR_GC_ID
|
GR_GC_ID
|
GrCopyGC(GR_GC_ID gc)
|
GrCopyGC(GR_GC_ID gc)
|
{
|
{
|
GR_GC *oldgcp; /* old graphics context */
|
GR_GC *oldgcp; /* old graphics context */
|
GR_GC *gcp; /* new graphics context */
|
GR_GC *gcp; /* new graphics context */
|
|
|
oldgcp = GsFindGC(gc);
|
oldgcp = GsFindGC(gc);
|
if (oldgcp == NULL)
|
if (oldgcp == NULL)
|
return 0;
|
return 0;
|
|
|
gcp = (GR_GC *) malloc(sizeof(GR_GC));
|
gcp = (GR_GC *) malloc(sizeof(GR_GC));
|
if (gcp == NULL) {
|
if (gcp == NULL) {
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/*
|
/*
|
* Copy all the old gcp values into the new one, except allocate
|
* 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.
|
* a new id for it and link it into the list of GCs.
|
*/
|
*/
|
*gcp = *oldgcp;
|
*gcp = *oldgcp;
|
gcp->id = nextgcid++;
|
gcp->id = nextgcid++;
|
gcp->changed = GR_TRUE;
|
gcp->changed = GR_TRUE;
|
gcp->owner = curclient;
|
gcp->owner = curclient;
|
gcp->next = listgcp;
|
gcp->next = listgcp;
|
listgcp = gcp;
|
listgcp = gcp;
|
|
|
return gcp->id;
|
return gcp->id;
|
}
|
}
|
|
|
/*
|
/*
|
* Return information about the specified graphics context.
|
* Return information about the specified graphics context.
|
*/
|
*/
|
void
|
void
|
GrGetGCInfo(GR_GC_ID gcid, GR_GC_INFO *gcip)
|
GrGetGCInfo(GR_GC_ID gcid, GR_GC_INFO *gcip)
|
{
|
{
|
GR_GC *gcp;
|
GR_GC *gcp;
|
|
|
/*
|
/*
|
* Find the GC manually so that an error is not generated.
|
* Find the GC manually so that an error is not generated.
|
*/
|
*/
|
for (gcp = listgcp; gcp && (gcp->id != gcid); gcp = gcp->next)
|
for (gcp = listgcp; gcp && (gcp->id != gcid); gcp = gcp->next)
|
continue;
|
continue;
|
|
|
if (gcp == NULL) {
|
if (gcp == NULL) {
|
memset(gcip, 0, sizeof(GR_GC_INFO));
|
memset(gcip, 0, sizeof(GR_GC_INFO));
|
return;
|
return;
|
}
|
}
|
|
|
gcip->gcid = gcid;
|
gcip->gcid = gcid;
|
gcip->mode = gcp->mode;
|
gcip->mode = gcp->mode;
|
gcip->region = gcp->regionid;
|
gcip->region = gcp->regionid;
|
gcip->xoff = gcp->xoff;
|
gcip->xoff = gcp->xoff;
|
gcip->yoff = gcp->yoff;
|
gcip->yoff = gcp->yoff;
|
gcip->font = gcp->fontid;
|
gcip->font = gcp->fontid;
|
gcip->foreground = gcp->foreground;
|
gcip->foreground = gcp->foreground;
|
gcip->background = gcp->background;
|
gcip->background = gcp->background;
|
gcip->usebackground = gcp->usebackground;
|
gcip->usebackground = gcp->usebackground;
|
}
|
}
|
|
|
static int nextregionid = 1000;
|
static int nextregionid = 1000;
|
/*
|
/*
|
* Allocate a new REGION with default parameters.
|
* Allocate a new REGION with default parameters.
|
* The REGION is owned by the current client.
|
* The REGION is owned by the current client.
|
*/
|
*/
|
GR_REGION_ID
|
GR_REGION_ID
|
GrNewRegion(void)
|
GrNewRegion(void)
|
{
|
{
|
GR_REGION *regionp;
|
GR_REGION *regionp;
|
|
|
regionp = (GR_REGION *) malloc(sizeof(GR_REGION));
|
regionp = (GR_REGION *) malloc(sizeof(GR_REGION));
|
if (regionp == NULL) {
|
if (regionp == NULL) {
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
regionp->rgn = GdAllocRegion();
|
regionp->rgn = GdAllocRegion();
|
regionp->id = nextregionid++;
|
regionp->id = nextregionid++;
|
regionp->owner = curclient;
|
regionp->owner = curclient;
|
regionp->next = listregionp;
|
regionp->next = listregionp;
|
|
|
listregionp = regionp;
|
listregionp = regionp;
|
return regionp->id;
|
return regionp->id;
|
}
|
}
|
|
|
/*
|
/*
|
* Allocate a new region from a set of points interpreted as a polygon.
|
* Allocate a new region from a set of points interpreted as a polygon.
|
* The REGION is owned by the current client.
|
* The REGION is owned by the current client.
|
*/
|
*/
|
GR_REGION_ID
|
GR_REGION_ID
|
GrNewPolygonRegion(int mode, GR_COUNT count, GR_POINT *points)
|
GrNewPolygonRegion(int mode, GR_COUNT count, GR_POINT *points)
|
{
|
{
|
#if POLYREGIONS
|
#if POLYREGIONS
|
GR_REGION *regionp;
|
GR_REGION *regionp;
|
|
|
regionp = (GR_REGION *) malloc(sizeof(GR_REGION));
|
regionp = (GR_REGION *) malloc(sizeof(GR_REGION));
|
if (regionp == NULL) {
|
if (regionp == NULL) {
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
regionp->rgn = GdAllocPolygonRegion(points, count, mode);
|
regionp->rgn = GdAllocPolygonRegion(points, count, mode);
|
regionp->id = nextregionid++;
|
regionp->id = nextregionid++;
|
regionp->owner = curclient;
|
regionp->owner = curclient;
|
regionp->next = listregionp;
|
regionp->next = listregionp;
|
|
|
listregionp = regionp;
|
listregionp = regionp;
|
return regionp->id;
|
return regionp->id;
|
#else
|
#else
|
return 0;
|
return 0;
|
#endif
|
#endif
|
}
|
}
|
|
|
/*
|
/*
|
* Destroy an existing region.
|
* Destroy an existing region.
|
*/
|
*/
|
void
|
void
|
GrDestroyRegion(GR_REGION_ID region)
|
GrDestroyRegion(GR_REGION_ID region)
|
{
|
{
|
GR_REGION *regionp; /* region */
|
GR_REGION *regionp; /* region */
|
GR_REGION *prevregionp; /* previous region */
|
GR_REGION *prevregionp; /* previous region */
|
|
|
regionp = GsFindRegion(region);
|
regionp = GsFindRegion(region);
|
if (regionp == NULL)
|
if (regionp == NULL)
|
return;
|
return;
|
|
|
if (listregionp == regionp)
|
if (listregionp == regionp)
|
listregionp = regionp->next;
|
listregionp = regionp->next;
|
else {
|
else {
|
prevregionp = listregionp;
|
prevregionp = listregionp;
|
while (prevregionp->next != regionp)
|
while (prevregionp->next != regionp)
|
prevregionp = prevregionp->next;
|
prevregionp = prevregionp->next;
|
|
|
prevregionp->next = regionp->next;
|
prevregionp->next = regionp->next;
|
}
|
}
|
GdDestroyRegion(regionp->rgn);
|
GdDestroyRegion(regionp->rgn);
|
free(regionp);
|
free(regionp);
|
}
|
}
|
|
|
/*
|
/*
|
* Updates the region from a union of the specified rectangle
|
* Updates the region from a union of the specified rectangle
|
* and the original region.
|
* and the original region.
|
*/
|
*/
|
void
|
void
|
GrUnionRectWithRegion(GR_REGION_ID region, GR_RECT *rect)
|
GrUnionRectWithRegion(GR_REGION_ID region, GR_RECT *rect)
|
{
|
{
|
GR_REGION *regionp;
|
GR_REGION *regionp;
|
MWRECT rc;
|
MWRECT rc;
|
|
|
regionp = GsFindRegion(region);
|
regionp = GsFindRegion(region);
|
if (regionp) {
|
if (regionp) {
|
/* convert Nano-X rect to MW rect*/
|
/* convert Nano-X rect to MW rect*/
|
rc.left = rect->x;
|
rc.left = rect->x;
|
rc.top = rect->y;
|
rc.top = rect->y;
|
rc.right = rect->x + rect->width;
|
rc.right = rect->x + rect->width;
|
rc.bottom = rect->y + rect->height;
|
rc.bottom = rect->y + rect->height;
|
GdUnionRectWithRegion(&rc, regionp->rgn);
|
GdUnionRectWithRegion(&rc, regionp->rgn);
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Updates the region from a union of two regions.
|
* Updates the region from a union of two regions.
|
*/
|
*/
|
void
|
void
|
GrUnionRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
|
GrUnionRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
|
GR_REGION_ID src_rgn2)
|
GR_REGION_ID src_rgn2)
|
{
|
{
|
GR_REGION *regionp;
|
GR_REGION *regionp;
|
GR_REGION *srcregionp1;
|
GR_REGION *srcregionp1;
|
GR_REGION *srcregionp2;
|
GR_REGION *srcregionp2;
|
|
|
regionp = GsFindRegion(dst_rgn);
|
regionp = GsFindRegion(dst_rgn);
|
if (regionp == NULL)
|
if (regionp == NULL)
|
return;
|
return;
|
|
|
srcregionp1 = GsFindRegion(src_rgn1);
|
srcregionp1 = GsFindRegion(src_rgn1);
|
if (srcregionp1 == NULL)
|
if (srcregionp1 == NULL)
|
return;
|
return;
|
|
|
srcregionp2 = GsFindRegion(src_rgn2);
|
srcregionp2 = GsFindRegion(src_rgn2);
|
if (srcregionp2 == NULL)
|
if (srcregionp2 == NULL)
|
return;
|
return;
|
|
|
GdUnionRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
|
GdUnionRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
|
}
|
}
|
|
|
/*
|
/*
|
* Updates the region by subtracting a region from another.
|
* Updates the region by subtracting a region from another.
|
*/
|
*/
|
void
|
void
|
GrSubtractRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
|
GrSubtractRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
|
GR_REGION_ID src_rgn2)
|
GR_REGION_ID src_rgn2)
|
{
|
{
|
GR_REGION *regionp;
|
GR_REGION *regionp;
|
GR_REGION *srcregionp1;
|
GR_REGION *srcregionp1;
|
GR_REGION *srcregionp2;
|
GR_REGION *srcregionp2;
|
|
|
regionp = GsFindRegion(dst_rgn);
|
regionp = GsFindRegion(dst_rgn);
|
if (regionp == NULL)
|
if (regionp == NULL)
|
return;
|
return;
|
|
|
srcregionp1 = GsFindRegion(src_rgn1);
|
srcregionp1 = GsFindRegion(src_rgn1);
|
if (srcregionp1 == NULL)
|
if (srcregionp1 == NULL)
|
return;
|
return;
|
|
|
srcregionp2 = GsFindRegion(src_rgn2);
|
srcregionp2 = GsFindRegion(src_rgn2);
|
if (srcregionp2 == NULL)
|
if (srcregionp2 == NULL)
|
return;
|
return;
|
|
|
GdSubtractRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
|
GdSubtractRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
|
}
|
}
|
|
|
/*
|
/*
|
* Updates the region to the difference of two regions.
|
* Updates the region to the difference of two regions.
|
*/
|
*/
|
void
|
void
|
GrXorRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
|
GrXorRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
|
GR_REGION_ID src_rgn2)
|
GR_REGION_ID src_rgn2)
|
{
|
{
|
GR_REGION *regionp;
|
GR_REGION *regionp;
|
GR_REGION *srcregionp1;
|
GR_REGION *srcregionp1;
|
GR_REGION *srcregionp2;
|
GR_REGION *srcregionp2;
|
|
|
regionp = GsFindRegion(dst_rgn);
|
regionp = GsFindRegion(dst_rgn);
|
if (regionp == NULL)
|
if (regionp == NULL)
|
return;
|
return;
|
|
|
srcregionp1 = GsFindRegion(src_rgn1);
|
srcregionp1 = GsFindRegion(src_rgn1);
|
if (srcregionp1 == NULL)
|
if (srcregionp1 == NULL)
|
return;
|
return;
|
|
|
srcregionp2 = GsFindRegion(src_rgn2);
|
srcregionp2 = GsFindRegion(src_rgn2);
|
if (srcregionp2 == NULL)
|
if (srcregionp2 == NULL)
|
return;
|
return;
|
|
|
GdXorRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
|
GdXorRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
|
}
|
}
|
|
|
/*
|
/*
|
* Updates the region from a intersection of two regions.
|
* Updates the region from a intersection of two regions.
|
*/
|
*/
|
void
|
void
|
GrIntersectRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
|
GrIntersectRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
|
GR_REGION_ID src_rgn2)
|
GR_REGION_ID src_rgn2)
|
{
|
{
|
GR_REGION *regionp;
|
GR_REGION *regionp;
|
GR_REGION *srcregionp1;
|
GR_REGION *srcregionp1;
|
GR_REGION *srcregionp2;
|
GR_REGION *srcregionp2;
|
|
|
regionp = GsFindRegion(dst_rgn);
|
regionp = GsFindRegion(dst_rgn);
|
if (regionp == NULL)
|
if (regionp == NULL)
|
return;
|
return;
|
|
|
srcregionp1 = GsFindRegion(src_rgn1);
|
srcregionp1 = GsFindRegion(src_rgn1);
|
if (srcregionp1 == NULL)
|
if (srcregionp1 == NULL)
|
return;
|
return;
|
|
|
srcregionp2 = GsFindRegion(src_rgn2);
|
srcregionp2 = GsFindRegion(src_rgn2);
|
if (srcregionp2 == NULL)
|
if (srcregionp2 == NULL)
|
return;
|
return;
|
|
|
GdIntersectRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
|
GdIntersectRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
|
}
|
}
|
|
|
/*
|
/*
|
* Sets the clip-mask in the GC to the specified region.
|
* Sets the clip-mask in the GC to the specified region.
|
*/
|
*/
|
void
|
void
|
GrSetGCRegion(GR_GC_ID gc, GR_REGION_ID region)
|
GrSetGCRegion(GR_GC_ID gc, GR_REGION_ID region)
|
{
|
{
|
GR_GC *gcp;
|
GR_GC *gcp;
|
|
|
gcp = GsFindGC(gc);
|
gcp = GsFindGC(gc);
|
if(gcp == NULL)
|
if(gcp == NULL)
|
return;
|
return;
|
|
|
gcp->regionid = region;
|
gcp->regionid = region;
|
gcp->changed = GR_TRUE;
|
gcp->changed = GR_TRUE;
|
}
|
}
|
|
|
/*
|
/*
|
* Set the x,y origin of user clip region in GC.
|
* Set the x,y origin of user clip region in GC.
|
*/
|
*/
|
void
|
void
|
GrSetGCClipOrigin(GR_GC_ID gc, int xoff, int yoff)
|
GrSetGCClipOrigin(GR_GC_ID gc, int xoff, int yoff)
|
{
|
{
|
GR_GC *gcp;
|
GR_GC *gcp;
|
|
|
gcp = GsFindGC(gc);
|
gcp = GsFindGC(gc);
|
if(gcp == NULL)
|
if(gcp == NULL)
|
return;
|
return;
|
|
|
gcp->xoff = xoff;
|
gcp->xoff = xoff;
|
gcp->yoff = yoff;
|
gcp->yoff = yoff;
|
gcp->changed = GR_TRUE;
|
gcp->changed = GR_TRUE;
|
}
|
}
|
|
|
/*
|
/*
|
* Determines whether a specified point resides in a region.
|
* Determines whether a specified point resides in a region.
|
*/
|
*/
|
GR_BOOL
|
GR_BOOL
|
GrPointInRegion(GR_REGION_ID region, GR_COORD x, GR_COORD y)
|
GrPointInRegion(GR_REGION_ID region, GR_COORD x, GR_COORD y)
|
{
|
{
|
GR_REGION *regionp;
|
GR_REGION *regionp;
|
|
|
regionp = GsFindRegion(region);
|
regionp = GsFindRegion(region);
|
if (regionp == NULL)
|
if (regionp == NULL)
|
return GR_FALSE;
|
return GR_FALSE;
|
|
|
return GdPtInRegion(regionp->rgn, x, y);
|
return GdPtInRegion(regionp->rgn, x, y);
|
}
|
}
|
|
|
/*
|
/*
|
* Determines whether a specified rectangle at least partly resides
|
* Determines whether a specified rectangle at least partly resides
|
* in a region.
|
* in a region.
|
*/
|
*/
|
int
|
int
|
GrRectInRegion(GR_REGION_ID region, GR_COORD x, GR_COORD y, GR_COORD w,
|
GrRectInRegion(GR_REGION_ID region, GR_COORD x, GR_COORD y, GR_COORD w,
|
GR_COORD h)
|
GR_COORD h)
|
{
|
{
|
GR_REGION *regionp;
|
GR_REGION *regionp;
|
MWRECT rect;
|
MWRECT rect;
|
|
|
regionp = GsFindRegion(region);
|
regionp = GsFindRegion(region);
|
if (regionp == NULL)
|
if (regionp == NULL)
|
return MWRECT_OUT;
|
return MWRECT_OUT;
|
|
|
rect.left = x;
|
rect.left = x;
|
rect.top = y;
|
rect.top = y;
|
rect.right = x + w;
|
rect.right = x + w;
|
rect.bottom = y + h;
|
rect.bottom = y + h;
|
return GdRectInRegion(regionp->rgn, &rect);
|
return GdRectInRegion(regionp->rgn, &rect);
|
}
|
}
|
|
|
/*
|
/*
|
* Return GR_TRUE if a region is empty.
|
* Return GR_TRUE if a region is empty.
|
*/
|
*/
|
GR_BOOL
|
GR_BOOL
|
GrEmptyRegion(GR_REGION_ID region)
|
GrEmptyRegion(GR_REGION_ID region)
|
{
|
{
|
GR_REGION *regionp;
|
GR_REGION *regionp;
|
|
|
regionp = GsFindRegion(region);
|
regionp = GsFindRegion(region);
|
if (regionp == NULL)
|
if (regionp == NULL)
|
return GR_TRUE;
|
return GR_TRUE;
|
|
|
return GdEmptyRegion(regionp->rgn);
|
return GdEmptyRegion(regionp->rgn);
|
}
|
}
|
|
|
/*
|
/*
|
* Return GR_TRUE if two regions are identical.
|
* Return GR_TRUE if two regions are identical.
|
*/
|
*/
|
GR_BOOL
|
GR_BOOL
|
GrEqualRegion(GR_REGION_ID rgn1, GR_REGION_ID rgn2)
|
GrEqualRegion(GR_REGION_ID rgn1, GR_REGION_ID rgn2)
|
{
|
{
|
GR_REGION *prgn1;
|
GR_REGION *prgn1;
|
GR_REGION *prgn2;
|
GR_REGION *prgn2;
|
|
|
prgn1 = GsFindRegion(rgn1);
|
prgn1 = GsFindRegion(rgn1);
|
prgn2 = GsFindRegion(rgn2);
|
prgn2 = GsFindRegion(rgn2);
|
|
|
if (!prgn1 && !prgn2)
|
if (!prgn1 && !prgn2)
|
return GR_TRUE;
|
return GR_TRUE;
|
if (!prgn1 || !prgn2)
|
if (!prgn1 || !prgn2)
|
return GR_FALSE;
|
return GR_FALSE;
|
|
|
return GdEqualRegion(prgn1->rgn, prgn2->rgn);
|
return GdEqualRegion(prgn1->rgn, prgn2->rgn);
|
}
|
}
|
|
|
/*
|
/*
|
* Offset a region by dx, dy.
|
* Offset a region by dx, dy.
|
*/
|
*/
|
void
|
void
|
GrOffsetRegion(GR_REGION_ID region, GR_SIZE dx, GR_SIZE dy)
|
GrOffsetRegion(GR_REGION_ID region, GR_SIZE dx, GR_SIZE dy)
|
{
|
{
|
GR_REGION *regionp;
|
GR_REGION *regionp;
|
|
|
regionp = GsFindRegion(region);
|
regionp = GsFindRegion(region);
|
if (regionp)
|
if (regionp)
|
GdOffsetRegion(regionp->rgn, dx, dy);
|
GdOffsetRegion(regionp->rgn, dx, dy);
|
}
|
}
|
|
|
/*
|
/*
|
* Return the bounding box for the specified region.
|
* Return the bounding box for the specified region.
|
*/
|
*/
|
int
|
int
|
GrGetRegionBox(GR_REGION_ID region, GR_RECT *rect)
|
GrGetRegionBox(GR_REGION_ID region, GR_RECT *rect)
|
{
|
{
|
GR_REGION *regionp;
|
GR_REGION *regionp;
|
MWRECT rc;
|
MWRECT rc;
|
int ret_val;
|
int ret_val;
|
|
|
regionp = GsFindRegion(region);
|
regionp = GsFindRegion(region);
|
if (regionp == NULL) {
|
if (regionp == NULL) {
|
memset(rect, 0, sizeof(GR_RECT));
|
memset(rect, 0, sizeof(GR_RECT));
|
return MWREGION_ERROR;
|
return MWREGION_ERROR;
|
}
|
}
|
|
|
ret_val = GdGetRegionBox(regionp->rgn, &rc);
|
ret_val = GdGetRegionBox(regionp->rgn, &rc);
|
/* convert MW rect to Nano-X rect*/
|
/* convert MW rect to Nano-X rect*/
|
rect->x = rc.left;
|
rect->x = rc.left;
|
rect->y = rc.top;
|
rect->y = rc.top;
|
rect->width = rc.right - rc.left;
|
rect->width = rc.right - rc.left;
|
rect->height = rc.bottom - rc.top;
|
rect->height = rc.bottom - rc.top;
|
return ret_val;
|
return ret_val;
|
}
|
}
|
|
|
static int nextfontid = 1000;
|
static int nextfontid = 1000;
|
/*
|
/*
|
* Allocate a new GC with default parameters.
|
* Allocate a new GC with default parameters.
|
* The GC is owned by the current client.
|
* The GC is owned by the current client.
|
*/
|
*/
|
GR_FONT_ID
|
GR_FONT_ID
|
GrCreateFont(GR_CHAR *name, GR_COORD height, GR_LOGFONT *plogfont)
|
GrCreateFont(GR_CHAR *name, GR_COORD height, GR_LOGFONT *plogfont)
|
{
|
{
|
GR_FONT *fontp;
|
GR_FONT *fontp;
|
|
|
fontp = (GR_FONT *) malloc(sizeof(GR_FONT));
|
fontp = (GR_FONT *) malloc(sizeof(GR_FONT));
|
if (fontp == NULL) {
|
if (fontp == NULL) {
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
if (plogfont)
|
if (plogfont)
|
fontp->pfont = GdCreateFont(&scrdev, NULL, 0, plogfont);
|
fontp->pfont = GdCreateFont(&scrdev, NULL, 0, plogfont);
|
else
|
else
|
fontp->pfont = GdCreateFont(&scrdev, name, height, NULL);
|
fontp->pfont = GdCreateFont(&scrdev, name, height, NULL);
|
fontp->id = nextfontid++;
|
fontp->id = nextfontid++;
|
fontp->owner = curclient;
|
fontp->owner = curclient;
|
fontp->next = listfontp;
|
fontp->next = listfontp;
|
|
|
listfontp = fontp;
|
listfontp = fontp;
|
|
|
return fontp->id;
|
return fontp->id;
|
}
|
}
|
|
|
/* Set the font size for the passed font*/
|
/* Set the font size for the passed font*/
|
void
|
void
|
GrSetFontSize(GR_FONT_ID fontid, GR_COORD size)
|
GrSetFontSize(GR_FONT_ID fontid, GR_COORD size)
|
{
|
{
|
GR_FONT *fontp;
|
GR_FONT *fontp;
|
|
|
fontp = GsFindFont(fontid);
|
fontp = GsFindFont(fontid);
|
if (fontp)
|
if (fontp)
|
GdSetFontSize(fontp->pfont, size);
|
GdSetFontSize(fontp->pfont, size);
|
}
|
}
|
|
|
/* Set the font rotation in tenths of degrees for the passed font*/
|
/* Set the font rotation in tenths of degrees for the passed font*/
|
void
|
void
|
GrSetFontRotation(GR_FONT_ID fontid, int tenthdegrees)
|
GrSetFontRotation(GR_FONT_ID fontid, int tenthdegrees)
|
{
|
{
|
GR_FONT *fontp;
|
GR_FONT *fontp;
|
|
|
fontp = GsFindFont(fontid);
|
fontp = GsFindFont(fontid);
|
if (fontp)
|
if (fontp)
|
GdSetFontRotation(fontp->pfont, tenthdegrees);
|
GdSetFontRotation(fontp->pfont, tenthdegrees);
|
}
|
}
|
|
|
/* Set the font size for the passed font*/
|
/* Set the font size for the passed font*/
|
void
|
void
|
GrSetFontAttr(GR_FONT_ID fontid, int setflags, int clrflags)
|
GrSetFontAttr(GR_FONT_ID fontid, int setflags, int clrflags)
|
{
|
{
|
GR_FONT *fontp;
|
GR_FONT *fontp;
|
|
|
fontp = GsFindFont(fontid);
|
fontp = GsFindFont(fontid);
|
if (fontp)
|
if (fontp)
|
GdSetFontAttr(fontp->pfont, setflags, clrflags);
|
GdSetFontAttr(fontp->pfont, setflags, clrflags);
|
}
|
}
|
|
|
/*
|
/*
|
* Unload and deallocate an existing font.
|
* Unload and deallocate an existing font.
|
*/
|
*/
|
void
|
void
|
GrDestroyFont(GR_FONT_ID fontid)
|
GrDestroyFont(GR_FONT_ID fontid)
|
{
|
{
|
GR_FONT *fontp;
|
GR_FONT *fontp;
|
GR_FONT *prevfontp;
|
GR_FONT *prevfontp;
|
|
|
fontp = GsFindFont(fontid);
|
fontp = GsFindFont(fontid);
|
if (fontp == NULL)
|
if (fontp == NULL)
|
return;
|
return;
|
|
|
if (listfontp == fontp)
|
if (listfontp == fontp)
|
listfontp = fontp->next;
|
listfontp = fontp->next;
|
else {
|
else {
|
prevfontp = listfontp;
|
prevfontp = listfontp;
|
while (prevfontp->next != fontp)
|
while (prevfontp->next != fontp)
|
prevfontp = prevfontp->next;
|
prevfontp = prevfontp->next;
|
|
|
prevfontp->next = fontp->next;
|
prevfontp->next = fontp->next;
|
}
|
}
|
GdDestroyFont(fontp->pfont);
|
GdDestroyFont(fontp->pfont);
|
free(fontp);
|
free(fontp);
|
}
|
}
|
|
|
/*
|
/*
|
* Return useful information about the specified font.
|
* Return useful information about the specified font.
|
* Font #0 returns info about the standard font.
|
* Font #0 returns info about the standard font.
|
*/
|
*/
|
void
|
void
|
GrGetFontInfo(GR_FONT_ID font, GR_FONT_INFO *fip)
|
GrGetFontInfo(GR_FONT_ID font, GR_FONT_INFO *fip)
|
{
|
{
|
GR_FONT *fontp;
|
GR_FONT *fontp;
|
PMWFONT pf;
|
PMWFONT pf;
|
|
|
if (font == 0)
|
if (font == 0)
|
pf = stdfont;
|
pf = stdfont;
|
else {
|
else {
|
fontp = GsFindFont(font);
|
fontp = GsFindFont(font);
|
if (!fontp) {
|
if (!fontp) {
|
memset(fip, 0, sizeof(GR_FONT_INFO));
|
memset(fip, 0, sizeof(GR_FONT_INFO));
|
return;
|
return;
|
}
|
}
|
pf = fontp->pfont;
|
pf = fontp->pfont;
|
}
|
}
|
GdGetFontInfo(pf, fip);
|
GdGetFontInfo(pf, fip);
|
}
|
}
|
|
|
/*
|
/*
|
* Select events for a window for this client.
|
* Select events for a window for this client.
|
* The events are a bitmask for the events desired.
|
* The events are a bitmask for the events desired.
|
*/
|
*/
|
void
|
void
|
GrSelectEvents(GR_WINDOW_ID wid, GR_EVENT_MASK eventmask)
|
GrSelectEvents(GR_WINDOW_ID wid, GR_EVENT_MASK eventmask)
|
{
|
{
|
GR_WINDOW *wp; /* window structure */
|
GR_WINDOW *wp; /* window structure */
|
GR_EVENT_CLIENT *evp; /* event-client structure */
|
GR_EVENT_CLIENT *evp; /* event-client structure */
|
|
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if (wp == NULL)
|
if (wp == NULL)
|
return;
|
return;
|
|
|
/*
|
/*
|
* See if this client is already in the event client list.
|
* See if this client is already in the event client list.
|
* If so, then just replace the events he is selecting for.
|
* If so, then just replace the events he is selecting for.
|
*/
|
*/
|
for (evp = wp->eventclients; evp; evp = evp->next) {
|
for (evp = wp->eventclients; evp; evp = evp->next) {
|
if (evp->client == curclient) {
|
if (evp->client == curclient) {
|
evp->eventmask = eventmask;
|
evp->eventmask = eventmask;
|
return;
|
return;
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* A new client for this window, so allocate a new event client
|
* A new client for this window, so allocate a new event client
|
* structure and insert it into the front of the list in the window.
|
* structure and insert it into the front of the list in the window.
|
*/
|
*/
|
evp = (GR_EVENT_CLIENT *) malloc(sizeof(GR_EVENT_CLIENT));
|
evp = (GR_EVENT_CLIENT *) malloc(sizeof(GR_EVENT_CLIENT));
|
if (evp == NULL) {
|
if (evp == NULL) {
|
GsError(GR_ERROR_MALLOC_FAILED, wid);
|
GsError(GR_ERROR_MALLOC_FAILED, wid);
|
return;
|
return;
|
}
|
}
|
|
|
evp->client = curclient;
|
evp->client = curclient;
|
evp->eventmask = eventmask;
|
evp->eventmask = eventmask;
|
evp->next = wp->eventclients;
|
evp->next = wp->eventclients;
|
wp->eventclients = evp;
|
wp->eventclients = evp;
|
|
|
/*
|
/*
|
* If it's a request for child updates to the root window,
|
* If it's a request for child updates to the root window,
|
* then search entire list and send map events for
|
* then search entire list and send map events for
|
* mapped windows now. This allows a window manager
|
* mapped windows now. This allows a window manager
|
* to get the mapped window list without another API call.
|
* to get the mapped window list without another API call.
|
*/
|
*/
|
if (wid==GR_ROOT_WINDOW_ID && (eventmask & GR_EVENT_MASK_CHLD_UPDATE)) {
|
if (wid==GR_ROOT_WINDOW_ID && (eventmask & GR_EVENT_MASK_CHLD_UPDATE)) {
|
for (wp = listwp; wp; wp = wp->next) {
|
for (wp = listwp; wp; wp = wp->next) {
|
if (wp->unmapcount == 0)
|
if (wp->unmapcount == 0)
|
GsDeliverUpdateEvent(wp, GR_UPDATE_MAP,
|
GsDeliverUpdateEvent(wp, GR_UPDATE_MAP,
|
wp->x, wp->y, wp->width, wp->height);
|
wp->x, wp->y, wp->width, wp->height);
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
static GR_WINDOW *
|
static GR_WINDOW *
|
NewWindow(GR_WINDOW *pwp, GR_COORD x, GR_COORD y, GR_SIZE width,
|
NewWindow(GR_WINDOW *pwp, GR_COORD x, GR_COORD y, GR_SIZE width,
|
GR_SIZE height, GR_SIZE bordersize, GR_COLOR background,
|
GR_SIZE height, GR_SIZE bordersize, GR_COLOR background,
|
GR_COLOR bordercolor)
|
GR_COLOR bordercolor)
|
{
|
{
|
GR_WINDOW *wp; /* new window*/
|
GR_WINDOW *wp; /* new window*/
|
|
|
if (width <= 0 || height <= 0 || bordersize < 0) {
|
if (width <= 0 || height <= 0 || bordersize < 0) {
|
GsError(GR_ERROR_BAD_WINDOW_SIZE, 0);
|
GsError(GR_ERROR_BAD_WINDOW_SIZE, 0);
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
wp = (GR_WINDOW *) malloc(sizeof(GR_WINDOW));
|
wp = (GR_WINDOW *) malloc(sizeof(GR_WINDOW));
|
if (wp == NULL) {
|
if (wp == NULL) {
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
wp->id = nextid++;
|
wp->id = nextid++;
|
wp->psd = rootwp->psd;
|
wp->psd = rootwp->psd;
|
wp->parent = pwp;
|
wp->parent = pwp;
|
wp->children = NULL;
|
wp->children = NULL;
|
wp->siblings = pwp->children;
|
wp->siblings = pwp->children;
|
wp->next = listwp;
|
wp->next = listwp;
|
wp->x = pwp->x + x;
|
wp->x = pwp->x + x;
|
wp->y = pwp->y + y;
|
wp->y = pwp->y + y;
|
wp->width = width;
|
wp->width = width;
|
wp->height = height;
|
wp->height = height;
|
wp->bordersize = bordersize;
|
wp->bordersize = bordersize;
|
wp->background = background;
|
wp->background = background;
|
wp->bgpixmap = NULL;
|
wp->bgpixmap = NULL;
|
wp->bgpixmapflags = GR_BACKGROUND_TILE;
|
wp->bgpixmapflags = GR_BACKGROUND_TILE;
|
wp->bordercolor = bordercolor;
|
wp->bordercolor = bordercolor;
|
wp->nopropmask = 0;
|
wp->nopropmask = 0;
|
wp->eventclients = NULL;
|
wp->eventclients = NULL;
|
wp->owner = curclient;
|
wp->owner = curclient;
|
wp->cursorid = pwp->cursorid;
|
wp->cursorid = pwp->cursorid;
|
wp->mapped = GR_FALSE;
|
wp->mapped = GR_FALSE;
|
wp->unmapcount = pwp->unmapcount + 1;
|
wp->unmapcount = pwp->unmapcount + 1;
|
wp->output = GR_TRUE;
|
wp->output = GR_TRUE;
|
wp->props = 0;
|
wp->props = 0;
|
wp->title = NULL;
|
wp->title = NULL;
|
|
|
pwp->children = wp;
|
pwp->children = wp;
|
listwp = wp;
|
listwp = wp;
|
|
|
return wp;
|
return wp;
|
}
|
}
|
|
|
/*
|
/*
|
* Allocate a new window which is a child of the specified window.
|
* Allocate a new window which is a child of the specified window.
|
* The window inherits the cursor of the parent window.
|
* The window inherits the cursor of the parent window.
|
* The window is owned by the current client.
|
* The window is owned by the current client.
|
*/
|
*/
|
GR_WINDOW_ID
|
GR_WINDOW_ID
|
GrNewWindow(GR_WINDOW_ID parent, GR_COORD x, GR_COORD y, GR_SIZE width,
|
GrNewWindow(GR_WINDOW_ID parent, GR_COORD x, GR_COORD y, GR_SIZE width,
|
GR_SIZE height, GR_SIZE bordersize, GR_COLOR background,
|
GR_SIZE height, GR_SIZE bordersize, GR_COLOR background,
|
GR_COLOR bordercolor)
|
GR_COLOR bordercolor)
|
{
|
{
|
GR_WINDOW *pwp; /* parent window */
|
GR_WINDOW *pwp; /* parent window */
|
GR_WINDOW *wp; /* new window */
|
GR_WINDOW *wp; /* new window */
|
|
|
pwp = GsFindWindow(parent);
|
pwp = GsFindWindow(parent);
|
if (pwp == NULL)
|
if (pwp == NULL)
|
return 0;
|
return 0;
|
|
|
if (!pwp->output) {
|
if (!pwp->output) {
|
GsError(GR_ERROR_INPUT_ONLY_WINDOW, pwp->id);
|
GsError(GR_ERROR_INPUT_ONLY_WINDOW, pwp->id);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
wp = NewWindow(pwp, x, y, width, height, bordersize, background,
|
wp = NewWindow(pwp, x, y, width, height, bordersize, background,
|
bordercolor);
|
bordercolor);
|
return wp? wp->id: 0;
|
return wp? wp->id: 0;
|
}
|
}
|
|
|
/*
|
/*
|
* Allocate a new input-only window which is a child of the specified window.
|
* Allocate a new input-only window which is a child of the specified window.
|
* Such a window is invisible, cannot be drawn into, and is only used to
|
* Such a window is invisible, cannot be drawn into, and is only used to
|
* return events. The window inherits the cursor of the parent window.
|
* return events. The window inherits the cursor of the parent window.
|
* The window is owned by the current client.
|
* The window is owned by the current client.
|
*/
|
*/
|
GR_WINDOW_ID
|
GR_WINDOW_ID
|
GrNewInputWindow(GR_WINDOW_ID parent, GR_COORD x, GR_COORD y,
|
GrNewInputWindow(GR_WINDOW_ID parent, GR_COORD x, GR_COORD y,
|
GR_SIZE width, GR_SIZE height)
|
GR_SIZE width, GR_SIZE height)
|
{
|
{
|
GR_WINDOW *pwp; /* parent window */
|
GR_WINDOW *pwp; /* parent window */
|
GR_WINDOW *wp; /* new window */
|
GR_WINDOW *wp; /* new window */
|
|
|
pwp = GsFindWindow(parent);
|
pwp = GsFindWindow(parent);
|
if (pwp == NULL)
|
if (pwp == NULL)
|
return 0;
|
return 0;
|
|
|
wp = NewWindow(pwp, x, y, width, height, 0, BLACK, BLACK);
|
wp = NewWindow(pwp, x, y, width, height, 0, BLACK, BLACK);
|
if (wp) {
|
if (wp) {
|
/* convert to input-only window*/
|
/* convert to input-only window*/
|
wp->output = GR_FALSE;
|
wp->output = GR_FALSE;
|
return wp->id;
|
return wp->id;
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/*
|
/*
|
* Allocate a pixmap, can be used with any drawing functions
|
* Allocate a pixmap, can be used with any drawing functions
|
* for offscreen drawing
|
* for offscreen drawing
|
*/
|
*/
|
GR_WINDOW_ID
|
GR_WINDOW_ID
|
GrNewPixmap(GR_SIZE width, GR_SIZE height, void * pixels)
|
GrNewPixmap(GR_SIZE width, GR_SIZE height, void * pixels)
|
{
|
{
|
GR_PIXMAP *pp;
|
GR_PIXMAP *pp;
|
PSD psd;
|
PSD psd;
|
int size, linelen, bpp, planes;
|
int size, linelen, bpp, planes;
|
|
|
if (width <= 0 || height <= 0) {
|
if (width <= 0 || height <= 0) {
|
/* no error for now, server will desynchronize w/app*/
|
/* no error for now, server will desynchronize w/app*/
|
/*GsError(GR_ERROR_BAD_WINDOW_SIZE, 0);*/
|
/*GsError(GR_ERROR_BAD_WINDOW_SIZE, 0);*/
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/*
|
/*
|
* allocate offscreen psd. If screen driver doesn't
|
* allocate offscreen psd. If screen driver doesn't
|
* support blitting, this will fail. Use root window screen
|
* support blitting, this will fail. Use root window screen
|
* device for compatibility for now.
|
* device for compatibility for now.
|
*/
|
*/
|
planes = rootwp->psd->planes;
|
planes = rootwp->psd->planes;
|
bpp = rootwp->psd->bpp;
|
bpp = rootwp->psd->bpp;
|
psd = rootwp->psd->AllocateMemGC(rootwp->psd);
|
psd = rootwp->psd->AllocateMemGC(rootwp->psd);
|
if (!psd)
|
if (!psd)
|
return 0;
|
return 0;
|
|
|
pp = (GR_PIXMAP *) malloc(sizeof(GR_PIXMAP));
|
pp = (GR_PIXMAP *) malloc(sizeof(GR_PIXMAP));
|
if (pp == NULL) {
|
if (pp == NULL) {
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
psd->FreeMemGC(psd);
|
psd->FreeMemGC(psd);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
GdCalcMemGCAlloc(psd, width, height, 0, 0, &size, &linelen);
|
GdCalcMemGCAlloc(psd, width, height, 0, 0, &size, &linelen);
|
|
|
/* Allocate space for pixel values */
|
/* Allocate space for pixel values */
|
if (!pixels) {
|
if (!pixels) {
|
pixels = calloc(size, 1);
|
pixels = calloc(size, 1);
|
psd->flags |= PSF_ADDRMALLOC;
|
psd->flags |= PSF_ADDRMALLOC;
|
}
|
}
|
if (!pixels) {
|
if (!pixels) {
|
free(pp);
|
free(pp);
|
psd->FreeMemGC(psd);
|
psd->FreeMemGC(psd);
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
pp->id = nextid++;
|
pp->id = nextid++;
|
pp->next = listpp;
|
pp->next = listpp;
|
pp->psd = psd;
|
pp->psd = psd;
|
pp->x = 0;
|
pp->x = 0;
|
pp->y = 0;
|
pp->y = 0;
|
pp->width = width;
|
pp->width = width;
|
pp->height = height;
|
pp->height = height;
|
pp->owner = curclient;
|
pp->owner = curclient;
|
|
|
psd->MapMemGC(psd, width, height, planes, bpp, linelen, size,
|
psd->MapMemGC(psd, width, height, planes, bpp, linelen, size,
|
pixels);
|
pixels);
|
|
|
listpp = pp;
|
listpp = pp;
|
return pp->id;
|
return pp->id;
|
}
|
}
|
|
|
/*
|
/*
|
* Map the window to make it (and possibly its children) visible on the screen.
|
* Map the window to make it (and possibly its children) visible on the screen.
|
*/
|
*/
|
void
|
void
|
GrMapWindow(GR_WINDOW_ID wid)
|
GrMapWindow(GR_WINDOW_ID wid)
|
{
|
{
|
GR_WINDOW *wp; /* window structure */
|
GR_WINDOW *wp; /* window structure */
|
|
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if (!wp || wp->mapped)
|
if (!wp || wp->mapped)
|
return;
|
return;
|
|
|
wp->mapped = GR_TRUE;
|
wp->mapped = GR_TRUE;
|
|
|
GsWpMapWindow(wp, GR_FALSE);
|
GsWpMapWindow(wp, GR_FALSE);
|
}
|
}
|
|
|
/*
|
/*
|
* Unmap the window to make it and its children invisible on the screen.
|
* Unmap the window to make it and its children invisible on the screen.
|
*/
|
*/
|
void
|
void
|
GrUnmapWindow(GR_WINDOW_ID wid)
|
GrUnmapWindow(GR_WINDOW_ID wid)
|
{
|
{
|
GR_WINDOW *wp; /* window structure */
|
GR_WINDOW *wp; /* window structure */
|
|
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if (!wp || !wp->mapped)
|
if (!wp || !wp->mapped)
|
return;
|
return;
|
|
|
GsWpUnmapWindow(wp, GR_FALSE);
|
GsWpUnmapWindow(wp, GR_FALSE);
|
|
|
wp->mapped = GR_FALSE;
|
wp->mapped = GR_FALSE;
|
}
|
}
|
|
|
/*
|
/*
|
* Clear the associated area of a window to its background color
|
* Clear the associated area of a window to its background color
|
* or pixmap. Generate expose event for window if exposeflag set.
|
* or pixmap. Generate expose event for window if exposeflag set.
|
*/
|
*/
|
void
|
void
|
GrClearArea(GR_WINDOW_ID wid, GR_COORD x, GR_COORD y, GR_SIZE width,
|
GrClearArea(GR_WINDOW_ID wid, GR_COORD x, GR_COORD y, GR_SIZE width,
|
GR_SIZE height, GR_BOOL exposeflag)
|
GR_SIZE height, GR_BOOL exposeflag)
|
{
|
{
|
GR_WINDOW *wp; /* window structure */
|
GR_WINDOW *wp; /* window structure */
|
|
|
wp = GsPrepareWindow(wid);
|
wp = GsPrepareWindow(wid);
|
if (wp) {
|
if (wp) {
|
if (width == 0)
|
if (width == 0)
|
width = wp->width;
|
width = wp->width;
|
if (height == 0)
|
if (height == 0)
|
height = wp->height;
|
height = wp->height;
|
GsWpClearWindow(wp, x, y, width, height, exposeflag);
|
GsWpClearWindow(wp, x, y, width, height, exposeflag);
|
}
|
}
|
}
|
}
|
|
|
/* Return window with keyboard focus.*/
|
/* Return window with keyboard focus.*/
|
GR_WINDOW_ID
|
GR_WINDOW_ID
|
GrGetFocus(void)
|
GrGetFocus(void)
|
{
|
{
|
return focuswp->id;
|
return focuswp->id;
|
}
|
}
|
|
|
/*
|
/*
|
* Set the focus to a particular window.
|
* Set the focus to a particular window.
|
* This makes keyboard events only visible to that window or children of it,
|
* This makes keyboard events only visible to that window or children of it,
|
* depending on the pointer location.
|
* depending on the pointer location.
|
*/
|
*/
|
void
|
void
|
GrSetFocus(GR_WINDOW_ID wid)
|
GrSetFocus(GR_WINDOW_ID wid)
|
{
|
{
|
GR_WINDOW *wp; /* window structure */
|
GR_WINDOW *wp; /* window structure */
|
|
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if (wp == NULL)
|
if (wp == NULL)
|
return;
|
return;
|
|
|
if (wp->unmapcount) {
|
if (wp->unmapcount) {
|
GsError(GR_ERROR_UNMAPPED_FOCUS_WINDOW, wid);
|
GsError(GR_ERROR_UNMAPPED_FOCUS_WINDOW, wid);
|
return;
|
return;
|
}
|
}
|
|
|
/* Check if window wants focus, if not, ignore call*/
|
/* Check if window wants focus, if not, ignore call*/
|
if (wp->props & GR_WM_PROPS_NOFOCUS)
|
if (wp->props & GR_WM_PROPS_NOFOCUS)
|
return;
|
return;
|
|
|
focusfixed = (wp != rootwp);
|
focusfixed = (wp != rootwp);
|
GsWpSetFocus(wp);
|
GsWpSetFocus(wp);
|
}
|
}
|
|
|
/*
|
/*
|
* Create a new server-based cursor resource.
|
* Create a new server-based cursor resource.
|
*/
|
*/
|
static int nextcursorid = 1000;
|
static int nextcursorid = 1000;
|
GR_CURSOR_ID
|
GR_CURSOR_ID
|
GrNewCursor(GR_SIZE width, GR_SIZE height, GR_COORD hotx, GR_COORD hoty,
|
GrNewCursor(GR_SIZE width, GR_SIZE height, GR_COORD hotx, GR_COORD hoty,
|
GR_COLOR foreground, GR_COLOR background, GR_BITMAP *fgbitmap,
|
GR_COLOR foreground, GR_COLOR background, GR_BITMAP *fgbitmap,
|
GR_BITMAP *bgbitmap)
|
GR_BITMAP *bgbitmap)
|
{
|
{
|
GR_CURSOR *cp;
|
GR_CURSOR *cp;
|
int bytes;
|
int bytes;
|
|
|
/*
|
/*
|
* Make sure the size of the bitmap is reasonable.
|
* Make sure the size of the bitmap is reasonable.
|
*/
|
*/
|
if (width <= 0 || width > MWMAX_CURSOR_SIZE ||
|
if (width <= 0 || width > MWMAX_CURSOR_SIZE ||
|
height <= 0 || height > MWMAX_CURSOR_SIZE) {
|
height <= 0 || height > MWMAX_CURSOR_SIZE) {
|
GsError(GR_ERROR_BAD_CURSOR_SIZE, 0);
|
GsError(GR_ERROR_BAD_CURSOR_SIZE, 0);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
cp = (GR_CURSOR *)malloc(sizeof(GR_CURSOR));
|
cp = (GR_CURSOR *)malloc(sizeof(GR_CURSOR));
|
if (cp == NULL) {
|
if (cp == NULL) {
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* fill in cursor structure*/
|
/* fill in cursor structure*/
|
cp->cursor.width = width;
|
cp->cursor.width = width;
|
cp->cursor.height = height;
|
cp->cursor.height = height;
|
cp->cursor.hotx = hotx;
|
cp->cursor.hotx = hotx;
|
cp->cursor.hoty = hoty;
|
cp->cursor.hoty = hoty;
|
cp->cursor.fgcolor = foreground;
|
cp->cursor.fgcolor = foreground;
|
cp->cursor.bgcolor = background;
|
cp->cursor.bgcolor = background;
|
bytes = GR_BITMAP_SIZE(width, height) * sizeof(GR_BITMAP);
|
bytes = GR_BITMAP_SIZE(width, height) * sizeof(GR_BITMAP);
|
memcpy(&cp->cursor.image, fgbitmap, bytes);
|
memcpy(&cp->cursor.image, fgbitmap, bytes);
|
memcpy(&cp->cursor.mask, bgbitmap, bytes);
|
memcpy(&cp->cursor.mask, bgbitmap, bytes);
|
|
|
cp->id = nextcursorid++;
|
cp->id = nextcursorid++;
|
cp->owner = curclient;
|
cp->owner = curclient;
|
cp->next = listcursorp;
|
cp->next = listcursorp;
|
listcursorp = cp;
|
listcursorp = cp;
|
|
|
return cp->id;
|
return cp->id;
|
}
|
}
|
|
|
/*
|
/*
|
* Destroy a server-based cursor.
|
* Destroy a server-based cursor.
|
*/
|
*/
|
void
|
void
|
GrDestroyCursor(GR_CURSOR_ID cid)
|
GrDestroyCursor(GR_CURSOR_ID cid)
|
{
|
{
|
GR_CURSOR *cursorp;
|
GR_CURSOR *cursorp;
|
GR_CURSOR *prevcursorp;
|
GR_CURSOR *prevcursorp;
|
|
|
cursorp = GsFindCursor(cid);
|
cursorp = GsFindCursor(cid);
|
if (cursorp == NULL)
|
if (cursorp == NULL)
|
return;
|
return;
|
|
|
if (listcursorp == cursorp)
|
if (listcursorp == cursorp)
|
listcursorp = cursorp->next;
|
listcursorp = cursorp->next;
|
else {
|
else {
|
prevcursorp = listcursorp;
|
prevcursorp = listcursorp;
|
while (prevcursorp->next != cursorp)
|
while (prevcursorp->next != cursorp)
|
prevcursorp = prevcursorp->next;
|
prevcursorp = prevcursorp->next;
|
|
|
prevcursorp->next = cursorp->next;
|
prevcursorp->next = cursorp->next;
|
}
|
}
|
|
|
if (curcursor == cursorp)
|
if (curcursor == cursorp)
|
curcursor = NULL;
|
curcursor = NULL;
|
|
|
free(cursorp);
|
free(cursorp);
|
GsCheckCursor();
|
GsCheckCursor();
|
}
|
}
|
|
|
/*
|
/*
|
* Specify a cursor for a window.
|
* Specify a cursor for a window.
|
* This cursor will only be used within that window, and by default
|
* This cursor will only be used within that window, and by default
|
* for its new children. If the cursor is currently within this
|
* for its new children. If the cursor is currently within this
|
* window, it will be changed to the new one immediately.
|
* window, it will be changed to the new one immediately.
|
* If the new cursor id is 0, revert to the root window cursor.
|
* If the new cursor id is 0, revert to the root window cursor.
|
*/
|
*/
|
void
|
void
|
GrSetWindowCursor(GR_WINDOW_ID wid, GR_CURSOR_ID cid)
|
GrSetWindowCursor(GR_WINDOW_ID wid, GR_CURSOR_ID cid)
|
{
|
{
|
GR_WINDOW *wp;
|
GR_WINDOW *wp;
|
GR_CURSOR *cp; /* cursor structure */
|
GR_CURSOR *cp; /* cursor structure */
|
|
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if (wp == NULL)
|
if (wp == NULL)
|
return;
|
return;
|
|
|
if (cid == 0)
|
if (cid == 0)
|
cp = stdcursor;
|
cp = stdcursor;
|
else {
|
else {
|
cp = GsFindCursor(cid);
|
cp = GsFindCursor(cid);
|
if (!cp)
|
if (!cp)
|
return; /* FIXME add server errmsg*/
|
return; /* FIXME add server errmsg*/
|
}
|
}
|
wp->cursorid = cid;
|
wp->cursorid = cid;
|
|
|
/*
|
/*
|
* If this was the current cursor, then draw the new one.
|
* If this was the current cursor, then draw the new one.
|
*/
|
*/
|
if (cp == curcursor || curcursor == NULL) {
|
if (cp == curcursor || curcursor == NULL) {
|
GdMoveCursor(cursorx - cp->cursor.hotx,
|
GdMoveCursor(cursorx - cp->cursor.hotx,
|
cursory - cp->cursor.hoty);
|
cursory - cp->cursor.hoty);
|
GdSetCursor(&cp->cursor);
|
GdSetCursor(&cp->cursor);
|
}
|
}
|
|
|
GsCheckCursor();
|
GsCheckCursor();
|
}
|
}
|
|
|
/*
|
/*
|
* Move the cursor to the specified absolute screen coordinates.
|
* Move the cursor to the specified absolute screen coordinates.
|
* The coordinates are that of the defined hot spot of the cursor.
|
* The coordinates are that of the defined hot spot of the cursor.
|
* The cursor's appearance is changed to that defined for the window
|
* The cursor's appearance is changed to that defined for the window
|
* in which the cursor is moved to. In addition, mouse enter, mouse
|
* in which the cursor is moved to. In addition, mouse enter, mouse
|
* exit, focus in, and focus out events are generated if necessary.
|
* exit, focus in, and focus out events are generated if necessary.
|
* The current mouse location is also changed.
|
* The current mouse location is also changed.
|
*/
|
*/
|
void
|
void
|
GrMoveCursor(GR_COORD x, GR_COORD y)
|
GrMoveCursor(GR_COORD x, GR_COORD y)
|
{
|
{
|
/*
|
/*
|
* Move the cursor only if necessary, offsetting it to
|
* Move the cursor only if necessary, offsetting it to
|
* place the hot spot at the specified coordinates.
|
* place the hot spot at the specified coordinates.
|
*/
|
*/
|
if ((x != cursorx) || (y != cursory)) {
|
if ((x != cursorx) || (y != cursory)) {
|
if(curcursor) {
|
if(curcursor) {
|
GdMoveCursor(x - curcursor->cursor.hotx,
|
GdMoveCursor(x - curcursor->cursor.hotx,
|
y - curcursor->cursor.hoty);
|
y - curcursor->cursor.hoty);
|
GdMoveMouse(x, y);
|
GdMoveMouse(x, y);
|
}
|
}
|
cursorx = x;
|
cursorx = x;
|
cursory = y;
|
cursory = y;
|
}
|
}
|
|
|
/*
|
/*
|
* Now check to see which window the mouse is in, whether or
|
* Now check to see which window the mouse is in, whether or
|
* not the cursor shape should be changed, and whether or not
|
* not the cursor shape should be changed, and whether or not
|
* the input focus window should be changed.
|
* the input focus window should be changed.
|
*/
|
*/
|
GsCheckMouseWindow();
|
GsCheckMouseWindow();
|
GsCheckFocusWindow();
|
GsCheckFocusWindow();
|
GsCheckCursor();
|
GsCheckCursor();
|
}
|
}
|
|
|
/*
|
/*
|
* Set the foreground color in a graphics context.
|
* Set the foreground color in a graphics context.
|
*/
|
*/
|
void
|
void
|
GrSetGCForeground(GR_GC_ID gc, GR_COLOR foreground)
|
GrSetGCForeground(GR_GC_ID gc, GR_COLOR foreground)
|
{
|
{
|
GR_GC *gcp; /* graphics context */
|
GR_GC *gcp; /* graphics context */
|
|
|
gcp = GsFindGC(gc);
|
gcp = GsFindGC(gc);
|
if (!gcp || gcp->foreground == foreground)
|
if (!gcp || gcp->foreground == foreground)
|
return;
|
return;
|
|
|
gcp->foreground = foreground;
|
gcp->foreground = foreground;
|
gcp->changed = GR_TRUE;
|
gcp->changed = GR_TRUE;
|
}
|
}
|
|
|
/*
|
/*
|
* Set the background color in a graphics context.
|
* Set the background color in a graphics context.
|
*/
|
*/
|
void
|
void
|
GrSetGCBackground(GR_GC_ID gc, GR_COLOR background)
|
GrSetGCBackground(GR_GC_ID gc, GR_COLOR background)
|
{
|
{
|
GR_GC *gcp; /* graphics context */
|
GR_GC *gcp; /* graphics context */
|
|
|
gcp = GsFindGC(gc);
|
gcp = GsFindGC(gc);
|
if (!gcp || gcp->background == background)
|
if (!gcp || gcp->background == background)
|
return;
|
return;
|
|
|
gcp->background = background;
|
gcp->background = background;
|
gcp->changed = GR_TRUE;
|
gcp->changed = GR_TRUE;
|
}
|
}
|
|
|
/*
|
/*
|
* Set whether or not the background color is drawn in bitmaps and text.
|
* Set whether or not the background color is drawn in bitmaps and text.
|
*/
|
*/
|
void
|
void
|
GrSetGCUseBackground(GR_GC_ID gc, GR_BOOL flag)
|
GrSetGCUseBackground(GR_GC_ID gc, GR_BOOL flag)
|
{
|
{
|
GR_GC *gcp; /* graphics context */
|
GR_GC *gcp; /* graphics context */
|
|
|
flag = (flag != 0);
|
flag = (flag != 0);
|
gcp = GsFindGC(gc);
|
gcp = GsFindGC(gc);
|
if (!gcp || gcp->usebackground == flag)
|
if (!gcp || gcp->usebackground == flag)
|
return;
|
return;
|
|
|
gcp->usebackground = flag;
|
gcp->usebackground = flag;
|
gcp->changed = GR_TRUE;
|
gcp->changed = GR_TRUE;
|
}
|
}
|
|
|
/*
|
/*
|
* Set the drawing mode in a graphics context.
|
* Set the drawing mode in a graphics context.
|
*/
|
*/
|
void
|
void
|
GrSetGCMode(GR_GC_ID gc, int mode)
|
GrSetGCMode(GR_GC_ID gc, int mode)
|
{
|
{
|
GR_GC *gcp; /* graphics context */
|
GR_GC *gcp; /* graphics context */
|
|
|
gcp = GsFindGC(gc);
|
gcp = GsFindGC(gc);
|
if (!gcp || gcp->mode == mode)
|
if (!gcp || gcp->mode == mode)
|
return;
|
return;
|
if ((mode & GR_MODE_DRAWMASK) > GR_MAX_MODE) {
|
if ((mode & GR_MODE_DRAWMASK) > GR_MAX_MODE) {
|
GsError(GR_ERROR_BAD_DRAWING_MODE, gc);
|
GsError(GR_ERROR_BAD_DRAWING_MODE, gc);
|
return;
|
return;
|
}
|
}
|
|
|
gcp->mode = mode;
|
gcp->mode = mode;
|
gcp->changed = GR_TRUE;
|
gcp->changed = GR_TRUE;
|
}
|
}
|
|
|
/*
|
/*
|
* Set the text font in a graphics context.
|
* Set the text font in a graphics context.
|
*/
|
*/
|
void
|
void
|
GrSetGCFont(GR_GC_ID gc, GR_FONT_ID font)
|
GrSetGCFont(GR_GC_ID gc, GR_FONT_ID font)
|
{
|
{
|
GR_GC *gcp; /* graphics context */
|
GR_GC *gcp; /* graphics context */
|
GR_FONT *fontp;
|
GR_FONT *fontp;
|
|
|
gcp = GsFindGC(gc);
|
gcp = GsFindGC(gc);
|
if (!gcp || gcp->fontid == font)
|
if (!gcp || gcp->fontid == font)
|
return;
|
return;
|
|
|
fontp = GsFindFont(font);
|
fontp = GsFindFont(font);
|
gcp->fontid = font;
|
gcp->fontid = font;
|
gcp->changed = GR_TRUE;
|
gcp->changed = GR_TRUE;
|
}
|
}
|
|
|
/*
|
/*
|
* Draw a line in the specified drawable using the specified graphics context.
|
* Draw a line in the specified drawable using the specified graphics context.
|
*/
|
*/
|
|
|
void
|
void
|
GrLine(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x1, GR_COORD y1, GR_COORD x2,
|
GrLine(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x1, GR_COORD y1, GR_COORD x2,
|
GR_COORD y2)
|
GR_COORD y2)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
GdLine(dp->psd, dp->x + x1, dp->y + y1,
|
GdLine(dp->psd, dp->x + x1, dp->y + y1,
|
dp->x + x2, dp->y + y2, TRUE);
|
dp->x + x2, dp->y + y2, TRUE);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Draw the boundary of a rectangle in the specified drawable using the
|
* Draw the boundary of a rectangle in the specified drawable using the
|
* specified graphics context.
|
* specified graphics context.
|
* NOTE: this function draws a rectangle 1 pixel wider and higher
|
* NOTE: this function draws a rectangle 1 pixel wider and higher
|
* than Xlib's XDrawRectangle().
|
* than Xlib's XDrawRectangle().
|
*/
|
*/
|
void
|
void
|
GrRect(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE width,
|
GrRect(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE width,
|
GR_SIZE height)
|
GR_SIZE height)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
GdRect(dp->psd, dp->x + x, dp->y + y, width, height);
|
GdRect(dp->psd, dp->x + x, dp->y + y, width, height);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Fill a rectangle in the specified drawable using the specified
|
* Fill a rectangle in the specified drawable using the specified
|
* graphics context.
|
* graphics context.
|
*/
|
*/
|
void
|
void
|
GrFillRect(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GrFillRect(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GR_SIZE width, GR_SIZE height)
|
GR_SIZE width, GR_SIZE height)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
GdFillRect(dp->psd, dp->x + x, dp->y + y, width,height);
|
GdFillRect(dp->psd, dp->x + x, dp->y + y, width,height);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Draw the boundary of an ellipse in the specified drawable with
|
* Draw the boundary of an ellipse in the specified drawable with
|
* the specified graphics context. Integer only.
|
* the specified graphics context. Integer only.
|
*/
|
*/
|
void
|
void
|
GrEllipse(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE rx,
|
GrEllipse(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE rx,
|
GR_SIZE ry)
|
GR_SIZE ry)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
GdEllipse(dp->psd, dp->x + x, dp->y + y, rx, ry, FALSE);
|
GdEllipse(dp->psd, dp->x + x, dp->y + y, rx, ry, FALSE);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Fill an ellipse in the specified drawable using the specified
|
* Fill an ellipse in the specified drawable using the specified
|
* graphics context. Integer only.
|
* graphics context. Integer only.
|
*/
|
*/
|
void
|
void
|
GrFillEllipse(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE rx,
|
GrFillEllipse(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE rx,
|
GR_SIZE ry)
|
GR_SIZE ry)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
GdEllipse(dp->psd, dp->x + x, dp->y + y, rx, ry, TRUE);
|
GdEllipse(dp->psd, dp->x + x, dp->y + y, rx, ry, TRUE);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Draw an arc, pie or ellipse in the specified drawable using
|
* Draw an arc, pie or ellipse in the specified drawable using
|
* the specified graphics context. Integer only.
|
* the specified graphics context. Integer only.
|
*/
|
*/
|
void
|
void
|
GrArc(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GrArc(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GR_SIZE rx, GR_SIZE ry, GR_COORD ax, GR_COORD ay,
|
GR_SIZE rx, GR_SIZE ry, GR_COORD ax, GR_COORD ay,
|
GR_COORD bx, GR_COORD by, int type)
|
GR_COORD bx, GR_COORD by, int type)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
GdArc(dp->psd, dp->x + x, dp->y + y, rx, ry,
|
GdArc(dp->psd, dp->x + x, dp->y + y, rx, ry,
|
dp->x+ax, dp->y+ay, dp->x+bx, dp->y+by, type);
|
dp->x+ax, dp->y+ay, dp->x+bx, dp->y+by, type);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Draw an arc or pie in the specified drawable using
|
* Draw an arc or pie in the specified drawable using
|
* the specified graphics context. Requires floating point.
|
* the specified graphics context. Requires floating point.
|
*/
|
*/
|
void
|
void
|
GrArcAngle(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GrArcAngle(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GR_SIZE rx, GR_SIZE ry, GR_COORD angle1, GR_COORD angle2, int type)
|
GR_SIZE rx, GR_SIZE ry, GR_COORD angle1, GR_COORD angle2, int type)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
GdArcAngle(dp->psd, dp->x + x, dp->y + y, rx, ry,
|
GdArcAngle(dp->psd, dp->x + x, dp->y + y, rx, ry,
|
angle1, angle2, type);
|
angle1, angle2, type);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Draw a rectangular area in the specified drawable using the specified
|
* Draw a rectangular area in the specified drawable using the specified
|
* graphics, as determined by the specified bit map. This differs from
|
* graphics, as determined by the specified bit map. This differs from
|
* rectangle drawing in that the rectangle is drawn using the foreground
|
* rectangle drawing in that the rectangle is drawn using the foreground
|
* color and possibly the background color as determined by the bit map.
|
* color and possibly the background color as determined by the bit map.
|
* Each row of bits is aligned to the next bitmap word boundary (so there
|
* Each row of bits is aligned to the next bitmap word boundary (so there
|
* is padding at the end of the row). The background bit values are only
|
* is padding at the end of the row). The background bit values are only
|
* written if the usebackground flag is set in the GC.
|
* written if the usebackground flag is set in the GC.
|
*/
|
*/
|
void
|
void
|
GrBitmap(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE width,
|
GrBitmap(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE width,
|
GR_SIZE height, GR_BITMAP *imagebits)
|
GR_SIZE height, GR_BITMAP *imagebits)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
GdBitmap(dp->psd, dp->x + x, dp->y + y, width, height,
|
GdBitmap(dp->psd, dp->x + x, dp->y + y, width, height,
|
imagebits);
|
imagebits);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
/* draw a multicolor image at x, y*/
|
/* draw a multicolor image at x, y*/
|
void
|
void
|
GrDrawImageBits(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GrDrawImageBits(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GR_IMAGE_HDR *pimage)
|
GR_IMAGE_HDR *pimage)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
GdDrawImage(dp->psd, dp->x + x, dp->y + y, pimage);
|
GdDrawImage(dp->psd, dp->x + x, dp->y + y, pimage);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
#if !((DOS_DJGPP) || (__PACIFIC__) || (DOS_TURBOC))
|
#if !((DOS_DJGPP) || (__PACIFIC__) || (DOS_TURBOC))
|
/* Load an image file from disk and display it at the specified coordinates*/
|
/* Load an image file from disk and display it at the specified coordinates*/
|
void
|
void
|
GrDrawImageFromFile(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GrDrawImageFromFile(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GR_SIZE width, GR_SIZE height, char* path, int flags)
|
GR_SIZE width, GR_SIZE height, char* path, int flags)
|
{
|
{
|
#if defined(HAVE_FILEIO)
|
#if defined(HAVE_FILEIO)
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
GdDrawImageFromFile(dp->psd, dp->x + x, dp->y + y,
|
GdDrawImageFromFile(dp->psd, dp->x + x, dp->y + y,
|
width, height, path, flags);
|
width, height, path, flags);
|
break;
|
break;
|
}
|
}
|
#endif
|
#endif
|
}
|
}
|
|
|
/* load image from file and cache it*/
|
/* load image from file and cache it*/
|
GR_IMAGE_ID
|
GR_IMAGE_ID
|
GrLoadImageFromFile(char *path, int flags)
|
GrLoadImageFromFile(char *path, int flags)
|
{
|
{
|
#if defined(HAVE_FILEIO)
|
#if defined(HAVE_FILEIO)
|
GR_IMAGE_ID id;
|
GR_IMAGE_ID id;
|
GR_IMAGE * imagep;
|
GR_IMAGE * imagep;
|
|
|
id = GdLoadImageFromFile(&scrdev, path, flags);
|
id = GdLoadImageFromFile(&scrdev, path, flags);
|
if (!id)
|
if (!id)
|
return 0;
|
return 0;
|
|
|
imagep = (GR_IMAGE *) malloc(sizeof(GR_IMAGE));
|
imagep = (GR_IMAGE *) malloc(sizeof(GR_IMAGE));
|
if (imagep == NULL) {
|
if (imagep == NULL) {
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
GdFreeImage(id);
|
GdFreeImage(id);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
imagep->id = id;
|
imagep->id = id;
|
imagep->owner = curclient;
|
imagep->owner = curclient;
|
imagep->next = listimagep;
|
imagep->next = listimagep;
|
|
|
listimagep = imagep;
|
listimagep = imagep;
|
return id;
|
return id;
|
#else
|
#else
|
return 0;
|
return 0;
|
#endif
|
#endif
|
}
|
}
|
|
|
/* Draw an image from a buffer */
|
/* Draw an image from a buffer */
|
|
|
void
|
void
|
GrDrawImageFromBuffer(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GrDrawImageFromBuffer(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GR_SIZE width, GR_SIZE height,
|
GR_SIZE width, GR_SIZE height,
|
void *buffer, int size, int flags)
|
void *buffer, int size, int flags)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
GdDrawImageFromBuffer(dp->psd, dp->x + x, dp->y + y,
|
GdDrawImageFromBuffer(dp->psd, dp->x + x, dp->y + y,
|
width, height, buffer, size, flags);
|
width, height, buffer, size, flags);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
/* load image from the given buffer and cache it*/
|
/* load image from the given buffer and cache it*/
|
|
|
GR_IMAGE_ID
|
GR_IMAGE_ID
|
GrLoadImageFromBuffer(void *buffer, int size, int flags)
|
GrLoadImageFromBuffer(void *buffer, int size, int flags)
|
{
|
{
|
GR_IMAGE_ID id;
|
GR_IMAGE_ID id;
|
GR_IMAGE * imagep;
|
GR_IMAGE * imagep;
|
|
|
id = GdLoadImageFromBuffer(&scrdev, buffer, size, flags);
|
id = GdLoadImageFromBuffer(&scrdev, buffer, size, flags);
|
if (!id) return(0);
|
if (!id) return(0);
|
|
|
imagep = (GR_IMAGE *) malloc(sizeof(GR_IMAGE));
|
imagep = (GR_IMAGE *) malloc(sizeof(GR_IMAGE));
|
if (imagep == NULL) {
|
if (imagep == NULL) {
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
GdFreeImage(id);
|
GdFreeImage(id);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
imagep->id = id;
|
imagep->id = id;
|
imagep->owner = curclient;
|
imagep->owner = curclient;
|
imagep->next = listimagep;
|
imagep->next = listimagep;
|
|
|
listimagep = imagep;
|
listimagep = imagep;
|
return id;
|
return id;
|
}
|
}
|
|
|
|
|
/* draw cached image*/
|
/* draw cached image*/
|
void
|
void
|
GrDrawImageToFit(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GrDrawImageToFit(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GR_SIZE width, GR_SIZE height, GR_IMAGE_ID imageid)
|
GR_SIZE width, GR_SIZE height, GR_IMAGE_ID imageid)
|
{
|
{
|
#if defined(HAVE_FILEIO)
|
#if defined(HAVE_FILEIO)
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
GdDrawImageToFit(dp->psd, dp->x + x, dp->y + y,
|
GdDrawImageToFit(dp->psd, dp->x + x, dp->y + y,
|
width, height, imageid);
|
width, height, imageid);
|
break;
|
break;
|
|
|
}
|
}
|
#endif
|
#endif
|
}
|
}
|
|
|
/* free cached image*/
|
/* free cached image*/
|
void
|
void
|
GrFreeImage(GR_IMAGE_ID id)
|
GrFreeImage(GR_IMAGE_ID id)
|
{
|
{
|
#if defined(HAVE_FILEIO)
|
#if defined(HAVE_FILEIO)
|
GR_IMAGE *imagep;
|
GR_IMAGE *imagep;
|
GR_IMAGE *previmagep;
|
GR_IMAGE *previmagep;
|
|
|
for (imagep = listimagep; imagep; imagep = imagep->next) {
|
for (imagep = listimagep; imagep; imagep = imagep->next) {
|
if (imagep->id == id) {
|
if (imagep->id == id) {
|
|
|
if (listimagep == imagep)
|
if (listimagep == imagep)
|
listimagep = imagep->next;
|
listimagep = imagep->next;
|
else {
|
else {
|
previmagep = listimagep;
|
previmagep = listimagep;
|
while (previmagep->next != imagep)
|
while (previmagep->next != imagep)
|
previmagep = previmagep->next;
|
previmagep = previmagep->next;
|
|
|
previmagep->next = imagep->next;
|
previmagep->next = imagep->next;
|
}
|
}
|
|
|
GdFreeImage(imagep->id);
|
GdFreeImage(imagep->id);
|
free(imagep);
|
free(imagep);
|
return;
|
return;
|
}
|
}
|
}
|
}
|
#endif
|
#endif
|
}
|
}
|
|
|
/* return cached image information*/
|
/* return cached image information*/
|
void
|
void
|
GrGetImageInfo(GR_IMAGE_ID id, GR_IMAGE_INFO *iip)
|
GrGetImageInfo(GR_IMAGE_ID id, GR_IMAGE_INFO *iip)
|
{
|
{
|
#if defined(HAVE_FILEIO)
|
#if defined(HAVE_FILEIO)
|
GdGetImageInfo(id, iip);
|
GdGetImageInfo(id, iip);
|
#else
|
#else
|
memset(iip, 0, sizeof(GR_IMAGE_INFO));
|
memset(iip, 0, sizeof(GR_IMAGE_INFO));
|
#endif
|
#endif
|
}
|
}
|
#endif /* !defined (DOS_DJGPP)|| (__PACIFIC__) || (DOS_TURBOC)) */
|
#endif /* !defined (DOS_DJGPP)|| (__PACIFIC__) || (DOS_TURBOC)) */
|
|
|
/*
|
/*
|
* Draw a rectangular area in the specified drawable using the specified
|
* Draw a rectangular area in the specified drawable using the specified
|
* graphics context. This differs from rectangle drawing in that the
|
* graphics context. This differs from rectangle drawing in that the
|
* color values for each pixel in the rectangle are specified.
|
* color values for each pixel in the rectangle are specified.
|
* The color table is indexed row by row.
|
* The color table is indexed row by row.
|
*/
|
*/
|
void
|
void
|
GrArea(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE width,
|
GrArea(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE width,
|
GR_SIZE height, void *pixels, int pixtype)
|
GR_SIZE height, void *pixels, int pixtype)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
GdArea(dp->psd, dp->x + x, dp->y + y, width, height,
|
GdArea(dp->psd, dp->x + x, dp->y + y, width, height,
|
pixels, pixtype);
|
pixels, pixtype);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Copy a rectangle from one drawable to another or the same
|
* Copy a rectangle from one drawable to another or the same
|
*/
|
*/
|
void
|
void
|
GrCopyArea(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GrCopyArea(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
|
GR_SIZE width, GR_SIZE height, GR_DRAW_ID source,
|
GR_SIZE width, GR_SIZE height, GR_DRAW_ID source,
|
GR_COORD srcx, GR_COORD srcy, int op)
|
GR_COORD srcx, GR_COORD srcy, int op)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
GR_WINDOW *swp;
|
GR_WINDOW *swp;
|
GR_PIXMAP *spp = NULL;
|
GR_PIXMAP *spp = NULL;
|
GR_DRAW_TYPE type;
|
GR_DRAW_TYPE type;
|
PSD srcpsd;
|
PSD srcpsd;
|
|
|
srcpsd = NULL;
|
srcpsd = NULL;
|
|
|
swp = GsFindWindow(source);
|
swp = GsFindWindow(source);
|
type = GsPrepareDrawing(id, gc, &dp);
|
type = GsPrepareDrawing(id, gc, &dp);
|
if (type == GR_DRAW_TYPE_NONE)
|
if (type == GR_DRAW_TYPE_NONE)
|
return;
|
return;
|
|
|
if (swp) {
|
if (swp) {
|
srcpsd = swp->psd;
|
srcpsd = swp->psd;
|
srcx += swp->x;
|
srcx += swp->x;
|
srcy += swp->y;
|
srcy += swp->y;
|
} else {
|
} else {
|
spp = GsFindPixmap(source);
|
spp = GsFindPixmap(source);
|
if (spp)
|
if (spp)
|
srcpsd = spp->psd;
|
srcpsd = spp->psd;
|
}
|
}
|
if (!srcpsd)
|
if (!srcpsd)
|
return;
|
return;
|
|
|
#if DYNAMICREGIONS
|
#if DYNAMICREGIONS
|
/*
|
/*
|
* Skip blit and send expose event if window is partly
|
* Skip blit and send expose event if window is partly
|
* obscured and source and destination are onscreen.
|
* obscured and source and destination are onscreen.
|
* Also check that receiving window's first client has
|
* Also check that receiving window's first client has
|
* selected for expose events. This keeps brain-dead
|
* selected for expose events. This keeps brain-dead
|
* programs that don't process exposure events somewhat working.
|
* programs that don't process exposure events somewhat working.
|
*/
|
*/
|
if (swp && (srcpsd == dp->psd) && swp->eventclients &&
|
if (swp && (srcpsd == dp->psd) && swp->eventclients &&
|
(swp->eventclients->eventmask & GR_EVENT_MASK_EXPOSURE)) {
|
(swp->eventclients->eventmask & GR_EVENT_MASK_EXPOSURE)) {
|
MWRECT rc;
|
MWRECT rc;
|
extern MWCLIPREGION *clipregion;
|
extern MWCLIPREGION *clipregion;
|
|
|
/* clip blit rectangle to source screen/bitmap size*/
|
/* clip blit rectangle to source screen/bitmap size*/
|
if(srcx+width > srcpsd->xvirtres)
|
if(srcx+width > srcpsd->xvirtres)
|
width = srcpsd->xvirtres - srcx;
|
width = srcpsd->xvirtres - srcx;
|
if(srcy+height > srcpsd->yvirtres)
|
if(srcy+height > srcpsd->yvirtres)
|
height = srcpsd->yvirtres - srcy;
|
height = srcpsd->yvirtres - srcy;
|
|
|
rc.left = srcx;
|
rc.left = srcx;
|
rc.top = srcy;
|
rc.top = srcy;
|
rc.right = srcx + width;
|
rc.right = srcx + width;
|
rc.bottom = srcy + height;
|
rc.bottom = srcy + height;
|
|
|
/*
|
/*
|
* if source isn't entirely within clip region, then
|
* if source isn't entirely within clip region, then
|
* the blit is partly obscured and will copy some garbage.
|
* the blit is partly obscured and will copy some garbage.
|
* In this case, skip the blit, punt, and deliver an
|
* In this case, skip the blit, punt, and deliver an
|
* exposure event instead for proper display.
|
* exposure event instead for proper display.
|
*/
|
*/
|
if (GdRectInRegion(clipregion, &rc) != MWRECT_ALLIN) {
|
if (GdRectInRegion(clipregion, &rc) != MWRECT_ALLIN) {
|
GsDeliverExposureEvent(swp, dp->x+x, dp->y+y,
|
GsDeliverExposureEvent(swp, dp->x+x, dp->y+y,
|
width, height);
|
width, height);
|
return;
|
return;
|
}
|
}
|
}
|
}
|
#endif
|
#endif
|
/* perform blit*/
|
/* perform blit*/
|
GdCheckCursor(srcpsd, srcx, srcy, srcx+width, srcy+height); /* FIXME*/
|
GdCheckCursor(srcpsd, srcx, srcy, srcx+width, srcy+height); /* FIXME*/
|
GdBlit(dp->psd, dp->x+x, dp->y+y, width, height, srcpsd, srcx, srcy,op);
|
GdBlit(dp->psd, dp->x+x, dp->y+y, width, height, srcpsd, srcx, srcy,op);
|
GdFixCursor(srcpsd); /* FIXME*/
|
GdFixCursor(srcpsd); /* FIXME*/
|
}
|
}
|
|
|
|
|
/*
|
/*
|
* Read the color values from the specified rectangular area of the
|
* Read the color values from the specified rectangular area of the
|
* specified drawable into a supplied buffer. If the drawable is a
|
* specified drawable into a supplied buffer. If the drawable is a
|
* window which is obscured by other windows, then the returned values
|
* window which is obscured by other windows, then the returned values
|
* will include the values from the covering windows. Regions outside
|
* will include the values from the covering windows. Regions outside
|
* of the screen boundaries, or unmapped windows will return black.
|
* of the screen boundaries, or unmapped windows will return black.
|
*/
|
*/
|
void
|
void
|
GrReadArea(GR_DRAW_ID id,GR_COORD x,GR_COORD y,GR_SIZE width,GR_SIZE height,
|
GrReadArea(GR_DRAW_ID id,GR_COORD x,GR_COORD y,GR_SIZE width,GR_SIZE height,
|
GR_PIXELVAL *pixels)
|
GR_PIXELVAL *pixels)
|
{
|
{
|
GR_WINDOW *wp;
|
GR_WINDOW *wp;
|
GR_PIXMAP *pp = NULL;
|
GR_PIXMAP *pp = NULL;
|
|
|
if ((wp = GsFindWindow(id)) == NULL && (pp = GsFindPixmap(id)) == NULL){
|
if ((wp = GsFindWindow(id)) == NULL && (pp = GsFindPixmap(id)) == NULL){
|
GsError(GR_ERROR_BAD_WINDOW_ID, id);
|
GsError(GR_ERROR_BAD_WINDOW_ID, id);
|
return;
|
return;
|
}
|
}
|
|
|
if (wp != NULL) {
|
if (wp != NULL) {
|
if (wp->unmapcount || (x >= wp->width) || (y >= wp->height) ||
|
if (wp->unmapcount || (x >= wp->width) || (y >= wp->height) ||
|
(x + width <= 0) || (y + height <= 0)) {
|
(x + width <= 0) || (y + height <= 0)) {
|
/* long count;
|
/* long count;
|
* GR_PIXELVAL black;
|
* GR_PIXELVAL black;
|
*
|
*
|
* black = GdFindColor(BLACK);
|
* black = GdFindColor(BLACK);
|
* count = width * height;
|
* count = width * height;
|
* while (count-- > 0)
|
* while (count-- > 0)
|
* *pixels++ = black;
|
* *pixels++ = black;
|
*/
|
*/
|
return;
|
return;
|
}
|
}
|
GdReadArea(wp->psd, wp->x+x, wp->y+y, width, height, pixels);
|
GdReadArea(wp->psd, wp->x+x, wp->y+y, width, height, pixels);
|
}
|
}
|
if (pp != NULL) {
|
if (pp != NULL) {
|
if ((x >= pp->width) || (y >= pp->height) ||
|
if ((x >= pp->width) || (y >= pp->height) ||
|
(x + width <= 0) || (y + height <= 0)) {
|
(x + width <= 0) || (y + height <= 0)) {
|
return;
|
return;
|
}
|
}
|
GdReadArea(pp->psd, x, y, width, height, pixels);
|
GdReadArea(pp->psd, x, y, width, height, pixels);
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Draw a point in the specified drawable using the specified
|
* Draw a point in the specified drawable using the specified
|
* graphics context.
|
* graphics context.
|
*/
|
*/
|
void
|
void
|
GrPoint(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y)
|
GrPoint(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
GdPoint(dp->psd, dp->x + x, dp->y + y);
|
GdPoint(dp->psd, dp->x + x, dp->y + y);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Draw points in the specified drawable using the specified
|
* Draw points in the specified drawable using the specified
|
* graphics context.
|
* graphics context.
|
*/
|
*/
|
void
|
void
|
GrPoints(GR_DRAW_ID id, GR_GC_ID gc, GR_COUNT count, GR_POINT *pointtable)
|
GrPoints(GR_DRAW_ID id, GR_GC_ID gc, GR_COUNT count, GR_POINT *pointtable)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
GR_POINT *pp;
|
GR_POINT *pp;
|
GR_COUNT i;
|
GR_COUNT i;
|
PSD psd;
|
PSD psd;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
psd = dp->psd;
|
psd = dp->psd;
|
break;
|
break;
|
default:
|
default:
|
return;
|
return;
|
}
|
}
|
|
|
pp = pointtable;
|
pp = pointtable;
|
for (i = count; i-- > 0; pp++) {
|
for (i = count; i-- > 0; pp++) {
|
GdPoint(psd, pp->x + dp->x, pp->y + dp->y);
|
GdPoint(psd, pp->x + dp->x, pp->y + dp->y);
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Draw a polygon in the specified drawable using the specified
|
* Draw a polygon in the specified drawable using the specified
|
* graphics context. The polygon is only complete if the first
|
* graphics context. The polygon is only complete if the first
|
* point is repeated at the end.
|
* point is repeated at the end.
|
*/
|
*/
|
void
|
void
|
GrPoly(GR_DRAW_ID id, GR_GC_ID gc, GR_COUNT count, GR_POINT *pointtable)
|
GrPoly(GR_DRAW_ID id, GR_GC_ID gc, GR_COUNT count, GR_POINT *pointtable)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
GR_POINT *pp;
|
GR_POINT *pp;
|
GR_COUNT i;
|
GR_COUNT i;
|
PSD psd;
|
PSD psd;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
psd = dp->psd;
|
psd = dp->psd;
|
break;
|
break;
|
default:
|
default:
|
return;
|
return;
|
}
|
}
|
|
|
/*
|
/*
|
* Here for drawing to a window.
|
* Here for drawing to a window.
|
* Relocate all the points relative to the window.
|
* Relocate all the points relative to the window.
|
*/
|
*/
|
pp = pointtable;
|
pp = pointtable;
|
for (i = count; i-- > 0; pp++) {
|
for (i = count; i-- > 0; pp++) {
|
pp->x += dp->x;
|
pp->x += dp->x;
|
pp->y += dp->y;
|
pp->y += dp->y;
|
}
|
}
|
|
|
GdPoly(psd, count, pointtable);
|
GdPoly(psd, count, pointtable);
|
|
|
#ifdef NONETWORK
|
#ifdef NONETWORK
|
/*
|
/*
|
* The following is only necessary when the server
|
* The following is only necessary when the server
|
* isn't a separate process. We don't want to change the
|
* isn't a separate process. We don't want to change the
|
* user's arguments!
|
* user's arguments!
|
*/
|
*/
|
pp = pointtable;
|
pp = pointtable;
|
for (i = count; i-- > 0; pp++) {
|
for (i = count; i-- > 0; pp++) {
|
pp->x -= dp->x;
|
pp->x -= dp->x;
|
pp->y -= dp->y;
|
pp->y -= dp->y;
|
}
|
}
|
#endif
|
#endif
|
}
|
}
|
|
|
/*
|
/*
|
* Draw a filled polygon in the specified drawable using the specified
|
* Draw a filled polygon in the specified drawable using the specified
|
* graphics context. The last point may be a duplicate of the first
|
* graphics context. The last point may be a duplicate of the first
|
* point, but this is not required.
|
* point, but this is not required.
|
*/
|
*/
|
void
|
void
|
GrFillPoly(GR_DRAW_ID id, GR_GC_ID gc, GR_COUNT count, GR_POINT *pointtable)
|
GrFillPoly(GR_DRAW_ID id, GR_GC_ID gc, GR_COUNT count, GR_POINT *pointtable)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
GR_POINT *pp;
|
GR_POINT *pp;
|
GR_COUNT i;
|
GR_COUNT i;
|
PSD psd;
|
PSD psd;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
psd = dp->psd;
|
psd = dp->psd;
|
break;
|
break;
|
default:
|
default:
|
return;
|
return;
|
}
|
}
|
|
|
/*
|
/*
|
* Here for drawing to a window.
|
* Here for drawing to a window.
|
* Relocate all the points relative to the window.
|
* Relocate all the points relative to the window.
|
*/
|
*/
|
pp = pointtable;
|
pp = pointtable;
|
for (i = count; i-- > 0; pp++) {
|
for (i = count; i-- > 0; pp++) {
|
pp->x += dp->x;
|
pp->x += dp->x;
|
pp->y += dp->y;
|
pp->y += dp->y;
|
}
|
}
|
|
|
GdFillPoly(psd, count, pointtable);
|
GdFillPoly(psd, count, pointtable);
|
|
|
#ifdef NONETWORK
|
#ifdef NONETWORK
|
/*
|
/*
|
* The following is only necessary when the server
|
* The following is only necessary when the server
|
* isn't a separate process. We don't want to change the
|
* isn't a separate process. We don't want to change the
|
* user's arguments!
|
* user's arguments!
|
*/
|
*/
|
pp = pointtable;
|
pp = pointtable;
|
for (i = count; i-- > 0; pp++) {
|
for (i = count; i-- > 0; pp++) {
|
pp->x -= dp->x;
|
pp->x -= dp->x;
|
pp->y -= dp->y;
|
pp->y -= dp->y;
|
}
|
}
|
#endif
|
#endif
|
}
|
}
|
|
|
/*
|
/*
|
* Draw a text string in the specified drawable using the
|
* Draw a text string in the specified drawable using the
|
* specified graphics context.
|
* specified graphics context.
|
*/
|
*/
|
void
|
void
|
GrText(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, void *str,
|
GrText(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, void *str,
|
GR_COUNT count, int flags)
|
GR_COUNT count, int flags)
|
{
|
{
|
GR_DRAWABLE *dp;
|
GR_DRAWABLE *dp;
|
|
|
/* default to baseline alignment if none specified*/
|
/* default to baseline alignment if none specified*/
|
if((flags&(MWTF_TOP|MWTF_BASELINE|MWTF_BOTTOM)) == 0)
|
if((flags&(MWTF_TOP|MWTF_BASELINE|MWTF_BOTTOM)) == 0)
|
flags |= MWTF_BASELINE;
|
flags |= MWTF_BASELINE;
|
|
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
switch (GsPrepareDrawing(id, gc, &dp)) {
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_WINDOW:
|
case GR_DRAW_TYPE_PIXMAP:
|
case GR_DRAW_TYPE_PIXMAP:
|
GdText(dp->psd, dp->x + x, dp->y + y, str, count,flags);
|
GdText(dp->psd, dp->x + x, dp->y + y, str, count,flags);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
/* Return the system palette entries*/
|
/* Return the system palette entries*/
|
void
|
void
|
GrGetSystemPalette(GR_PALETTE *pal)
|
GrGetSystemPalette(GR_PALETTE *pal)
|
{
|
{
|
/* return 0 count if not in palettized mode*/
|
/* return 0 count if not in palettized mode*/
|
memset(pal, 0, sizeof(GR_PALETTE *));
|
memset(pal, 0, sizeof(GR_PALETTE *));
|
|
|
if(rootwp->psd->pixtype == MWPF_PALETTE) {
|
if(rootwp->psd->pixtype == MWPF_PALETTE) {
|
pal->count = (int)rootwp->psd->ncolors;
|
pal->count = (int)rootwp->psd->ncolors;
|
GdGetPalette(rootwp->psd, 0, pal->count, pal->palette);
|
GdGetPalette(rootwp->psd, 0, pal->count, pal->palette);
|
}
|
}
|
}
|
}
|
|
|
/* Set the system palette entries from first for count*/
|
/* Set the system palette entries from first for count*/
|
void
|
void
|
GrSetSystemPalette(GR_COUNT first, GR_PALETTE *pal)
|
GrSetSystemPalette(GR_COUNT first, GR_PALETTE *pal)
|
{
|
{
|
GdSetPalette(rootwp->psd, first, pal->count, pal->palette);
|
GdSetPalette(rootwp->psd, first, pal->count, pal->palette);
|
if (first == 0)
|
if (first == 0)
|
GsRedrawScreen();
|
GsRedrawScreen();
|
}
|
}
|
|
|
/* Convert passed color value to pixel value, depending on system mode*/
|
/* Convert passed color value to pixel value, depending on system mode*/
|
void
|
void
|
GrFindColor(GR_COLOR c, GR_PIXELVAL *retpixel)
|
GrFindColor(GR_COLOR c, GR_PIXELVAL *retpixel)
|
{
|
{
|
*retpixel = GdFindColor(c);
|
*retpixel = GdFindColor(c);
|
}
|
}
|
|
|
/* visible =0, no cursor change; =1, show; else hide*/
|
/* visible =0, no cursor change; =1, show; else hide*/
|
void
|
void
|
GrInjectPointerEvent(GR_COORD x, GR_COORD y, int button, int visible)
|
GrInjectPointerEvent(GR_COORD x, GR_COORD y, int button, int visible)
|
{
|
{
|
if (visible != 0) {
|
if (visible != 0) {
|
if (visible == 1)
|
if (visible == 1)
|
GdShowCursor(&scrdev);
|
GdShowCursor(&scrdev);
|
else
|
else
|
GdHideCursor(&scrdev);
|
GdHideCursor(&scrdev);
|
}
|
}
|
|
|
GdMoveMouse(x, y);
|
GdMoveMouse(x, y);
|
GsHandleMouseStatus(x, y, button);
|
GsHandleMouseStatus(x, y, button);
|
}
|
}
|
|
|
void
|
void
|
GrInjectKeyboardEvent(GR_WINDOW_ID wid, GR_KEY keyvalue, GR_KEYMOD modifiers,
|
GrInjectKeyboardEvent(GR_WINDOW_ID wid, GR_KEY keyvalue, GR_KEYMOD modifiers,
|
GR_SCANCODE scancode, GR_BOOL pressed)
|
GR_SCANCODE scancode, GR_BOOL pressed)
|
{
|
{
|
/* create a keyboard event */
|
/* create a keyboard event */
|
GsDeliverKeyboardEvent(wid,
|
GsDeliverKeyboardEvent(wid,
|
pressed? GR_EVENT_TYPE_KEY_DOWN: GR_EVENT_TYPE_KEY_UP,
|
pressed? GR_EVENT_TYPE_KEY_DOWN: GR_EVENT_TYPE_KEY_UP,
|
keyvalue, modifiers, scancode);
|
keyvalue, modifiers, scancode);
|
}
|
}
|
|
|
/*
|
/*
|
* Set certain window properties, according to flags value
|
* Set certain window properties, according to flags value
|
* passed in props.
|
* passed in props.
|
*/
|
*/
|
void
|
void
|
GrSetWMProperties(GR_WINDOW_ID wid, GR_WM_PROPERTIES *props)
|
GrSetWMProperties(GR_WINDOW_ID wid, GR_WM_PROPERTIES *props)
|
{
|
{
|
GR_WINDOW *wp;
|
GR_WINDOW *wp;
|
int tl = 0; /* Initialized to avoid warning */
|
int tl = 0; /* Initialized to avoid warning */
|
|
|
/* Find the window structure (generate an error if it doesn't exist) */
|
/* Find the window structure (generate an error if it doesn't exist) */
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if(!wp) {
|
if(!wp) {
|
GsError(GR_ERROR_BAD_WINDOW_ID, wid);
|
GsError(GR_ERROR_BAD_WINDOW_ID, wid);
|
return;
|
return;
|
}
|
}
|
|
|
/* Set window properties*/
|
/* Set window properties*/
|
if (props->flags & GR_WM_FLAGS_PROPS)
|
if (props->flags & GR_WM_FLAGS_PROPS)
|
wp->props = props->props;
|
wp->props = props->props;
|
|
|
/* Set window title*/
|
/* Set window title*/
|
if (props->flags & GR_WM_FLAGS_TITLE) {
|
if (props->flags & GR_WM_FLAGS_TITLE) {
|
/* Remove the old title if it exists */
|
/* Remove the old title if it exists */
|
if(wp->title)
|
if(wp->title)
|
free(wp->title);
|
free(wp->title);
|
|
|
/* Calculate the space needed to store the new title */
|
/* Calculate the space needed to store the new title */
|
if(props->title)
|
if(props->title)
|
tl = strlen(props->title) + 1;
|
tl = strlen(props->title) + 1;
|
|
|
/* Check for empty title*/
|
/* Check for empty title*/
|
if(!props->title || tl == 1) {
|
if(!props->title || tl == 1) {
|
wp->title = NULL;
|
wp->title = NULL;
|
} else {
|
} else {
|
/* Otherwise, allocate some space for the new title */
|
/* Otherwise, allocate some space for the new title */
|
if(!(wp->title = malloc(tl)))
|
if(!(wp->title = malloc(tl)))
|
GsError(GR_ERROR_MALLOC_FAILED, wid);
|
GsError(GR_ERROR_MALLOC_FAILED, wid);
|
else
|
else
|
memcpy(wp->title, props->title, tl);
|
memcpy(wp->title, props->title, tl);
|
}
|
}
|
}
|
}
|
|
|
/* Set window background*/
|
/* Set window background*/
|
if (props->flags & GR_WM_FLAGS_BACKGROUND) {
|
if (props->flags & GR_WM_FLAGS_BACKGROUND) {
|
if (wp->background != props->background) {
|
if (wp->background != props->background) {
|
wp->background = props->background;
|
wp->background = props->background;
|
GsExposeArea(wp, wp->x, wp->y, wp->width, wp->height,
|
GsExposeArea(wp, wp->x, wp->y, wp->width, wp->height,
|
NULL);
|
NULL);
|
}
|
}
|
}
|
}
|
|
|
/* Set window border size*/
|
/* Set window border size*/
|
if (props->flags & GR_WM_FLAGS_BORDERSIZE) {
|
if (props->flags & GR_WM_FLAGS_BORDERSIZE) {
|
if (wp->bordersize != props->bordersize) {
|
if (wp->bordersize != props->bordersize) {
|
GsWpUnmapWindow(wp, GR_TRUE);
|
GsWpUnmapWindow(wp, GR_TRUE);
|
wp->bordersize = props->bordersize;
|
wp->bordersize = props->bordersize;
|
GsWpMapWindow(wp, GR_TRUE);
|
GsWpMapWindow(wp, GR_TRUE);
|
}
|
}
|
}
|
}
|
|
|
/* Set window border color*/
|
/* Set window border color*/
|
if (props->flags & GR_WM_FLAGS_BORDERCOLOR) {
|
if (props->flags & GR_WM_FLAGS_BORDERCOLOR) {
|
if (wp->bordercolor != props->bordercolor) {
|
if (wp->bordercolor != props->bordercolor) {
|
wp->bordercolor = props->bordercolor;
|
wp->bordercolor = props->bordercolor;
|
if (wp->bordersize)
|
if (wp->bordersize)
|
GsDrawBorder(wp);
|
GsDrawBorder(wp);
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Return all window properties
|
* Return all window properties
|
*/
|
*/
|
void
|
void
|
GrGetWMProperties(GR_WINDOW_ID wid, GR_WM_PROPERTIES *props)
|
GrGetWMProperties(GR_WINDOW_ID wid, GR_WM_PROPERTIES *props)
|
{
|
{
|
GR_WINDOW *wp;
|
GR_WINDOW *wp;
|
|
|
/* Find the window structure, no error on invalid window id*/
|
/* Find the window structure, no error on invalid window id*/
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if(!wp) {
|
if(!wp) {
|
/* set flags to 0 on bad window id*/
|
/* set flags to 0 on bad window id*/
|
memset(props, 0, sizeof(GR_WM_PROPERTIES));
|
memset(props, 0, sizeof(GR_WM_PROPERTIES));
|
return;
|
return;
|
}
|
}
|
|
|
/* Return everything, regardless of props->flags*/
|
/* Return everything, regardless of props->flags*/
|
props->flags = GR_WM_FLAGS_PROPS | GR_WM_FLAGS_TITLE |
|
props->flags = GR_WM_FLAGS_PROPS | GR_WM_FLAGS_TITLE |
|
GR_WM_FLAGS_BACKGROUND | GR_WM_FLAGS_BORDERSIZE |
|
GR_WM_FLAGS_BACKGROUND | GR_WM_FLAGS_BORDERSIZE |
|
GR_WM_FLAGS_BORDERCOLOR;
|
GR_WM_FLAGS_BORDERCOLOR;
|
props->props = wp->props;
|
props->props = wp->props;
|
props->title = wp->title;
|
props->title = wp->title;
|
props->background = wp->background;
|
props->background = wp->background;
|
props->bordersize = wp->bordersize;
|
props->bordersize = wp->bordersize;
|
props->bordercolor = wp->bordercolor;
|
props->bordercolor = wp->bordercolor;
|
}
|
}
|
|
|
void
|
void
|
GrCloseWindow(GR_WINDOW_ID wid)
|
GrCloseWindow(GR_WINDOW_ID wid)
|
{
|
{
|
GR_WINDOW *wp;
|
GR_WINDOW *wp;
|
|
|
/* Find the window structure (generate an error if it doesn't exist) */
|
/* Find the window structure (generate an error if it doesn't exist) */
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if(!wp) {
|
if(!wp) {
|
/*
|
/*
|
* no error for now, client/server problems
|
* no error for now, client/server problems
|
* with nxwm when sent
|
* with nxwm when sent
|
*/
|
*/
|
/*GsError(GR_ERROR_BAD_WINDOW_ID, wid);*/
|
/*GsError(GR_ERROR_BAD_WINDOW_ID, wid);*/
|
return;
|
return;
|
}
|
}
|
|
|
/* Send a CLOSE_REQ event to the client */
|
/* Send a CLOSE_REQ event to the client */
|
GsDeliverGeneralEvent(wp, GR_EVENT_TYPE_CLOSE_REQ, NULL);
|
GsDeliverGeneralEvent(wp, GR_EVENT_TYPE_CLOSE_REQ, NULL);
|
}
|
}
|
|
|
void
|
void
|
GrKillWindow(GR_WINDOW_ID wid)
|
GrKillWindow(GR_WINDOW_ID wid)
|
{
|
{
|
GR_WINDOW *wp;
|
GR_WINDOW *wp;
|
|
|
/* Find the window structure (generate an error if it doesn't exist) */
|
/* Find the window structure (generate an error if it doesn't exist) */
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if(!wp) {
|
if(!wp) {
|
GsError(GR_ERROR_BAD_WINDOW_ID, wid);
|
GsError(GR_ERROR_BAD_WINDOW_ID, wid);
|
return;
|
return;
|
}
|
}
|
|
|
/* Forcibly kill the connection to the client */
|
/* Forcibly kill the connection to the client */
|
GsClose(wp->owner->id);
|
GsClose(wp->owner->id);
|
}
|
}
|
|
|
/*
|
/*
|
* GrGetSystemColor color scheme definitions
|
* GrGetSystemColor color scheme definitions
|
*/
|
*/
|
/* define color scheme: A (tan), B (winstd) or C (old)*/
|
/* define color scheme: A (tan), B (winstd) or C (old)*/
|
#define A
|
#define A
|
|
|
#define A_RGB(r,g,b)
|
#define A_RGB(r,g,b)
|
#define B_RGB(r,g,b)
|
#define B_RGB(r,g,b)
|
#define C_RGB(r,g,b)
|
#define C_RGB(r,g,b)
|
|
|
#ifdef A
|
#ifdef A
|
#undef A_RGB
|
#undef A_RGB
|
#define A_RGB(r,g,b) GR_RGB(r,g,b),
|
#define A_RGB(r,g,b) GR_RGB(r,g,b),
|
#endif
|
#endif
|
#ifdef B
|
#ifdef B
|
#undef B_RGB
|
#undef B_RGB
|
#define B_RGB(r,g,b) GR_RGB(r,g,b),
|
#define B_RGB(r,g,b) GR_RGB(r,g,b),
|
#endif
|
#endif
|
#ifdef C
|
#ifdef C
|
#undef C_RGB
|
#undef C_RGB
|
#define C_RGB(r,g,b) GR_RGB(r,g,b),
|
#define C_RGB(r,g,b) GR_RGB(r,g,b),
|
#endif
|
#endif
|
|
|
#define MAXSYSCOLORS 20 /* # of GR_COLOR_* system colors*/
|
#define MAXSYSCOLORS 20 /* # of GR_COLOR_* system colors*/
|
|
|
static GR_COLOR sysColors[MAXSYSCOLORS] = {
|
static GR_COLOR sysColors[MAXSYSCOLORS] = {
|
/* desktop background*/
|
/* desktop background*/
|
GR_RGB( 0, 128, 128), /* GR_COLOR_DESKTOP */
|
GR_RGB( 0, 128, 128), /* GR_COLOR_DESKTOP */
|
|
|
/* caption colors*/
|
/* caption colors*/
|
A_RGB(128, 0, 0) /* GR_COLOR_ACTIVECAPTION */
|
A_RGB(128, 0, 0) /* GR_COLOR_ACTIVECAPTION */
|
B_RGB(128, 0, 128) /* GR_COLOR_ACTIVECAPTION */
|
B_RGB(128, 0, 128) /* GR_COLOR_ACTIVECAPTION */
|
C_RGB(128, 0, 128) /* GR_COLOR_ACTIVECAPTION */
|
C_RGB(128, 0, 128) /* GR_COLOR_ACTIVECAPTION */
|
GR_RGB(255, 255, 255), /* GR_COLOR_ACTIVECAPTIONTEXT */
|
GR_RGB(255, 255, 255), /* GR_COLOR_ACTIVECAPTIONTEXT */
|
A_RGB(162, 141, 104) /* GR_COLOR_INACTIVECAPTION */
|
A_RGB(162, 141, 104) /* GR_COLOR_INACTIVECAPTION */
|
B_RGB(128, 128, 128) /* GR_COLOR_INACTIVECAPTION */
|
B_RGB(128, 128, 128) /* GR_COLOR_INACTIVECAPTION */
|
C_RGB( 0, 64, 128) /* GR_COLOR_INACTIVECAPTION */
|
C_RGB( 0, 64, 128) /* GR_COLOR_INACTIVECAPTION */
|
GR_RGB(192, 192, 192), /* GR_COLOR_INACTIVECAPTIONTEXT */
|
GR_RGB(192, 192, 192), /* GR_COLOR_INACTIVECAPTIONTEXT */
|
|
|
/* 3d border shades*/
|
/* 3d border shades*/
|
GR_RGB( 0, 0, 0), /* GR_COLOR_WINDOWFRAME */
|
GR_RGB( 0, 0, 0), /* GR_COLOR_WINDOWFRAME */
|
A_RGB(162, 141, 104) /* GR_COLOR_BTNSHADOW */
|
A_RGB(162, 141, 104) /* GR_COLOR_BTNSHADOW */
|
B_RGB(128, 128, 128) /* GR_COLOR_BTNSHADOW */
|
B_RGB(128, 128, 128) /* GR_COLOR_BTNSHADOW */
|
C_RGB(128, 128, 128) /* GR_COLOR_BTNSHADOW */
|
C_RGB(128, 128, 128) /* GR_COLOR_BTNSHADOW */
|
A_RGB(213, 204, 187) /* GR_COLOR_3DLIGHT */
|
A_RGB(213, 204, 187) /* GR_COLOR_3DLIGHT */
|
B_RGB(223, 223, 223) /* GR_COLOR_3DLIGHT */
|
B_RGB(223, 223, 223) /* GR_COLOR_3DLIGHT */
|
C_RGB(192, 192, 192) /* GR_COLOR_3DLIGHT */
|
C_RGB(192, 192, 192) /* GR_COLOR_3DLIGHT */
|
A_RGB(234, 230, 221) /* GR_COLOR_BTNHIGHLIGHT */
|
A_RGB(234, 230, 221) /* GR_COLOR_BTNHIGHLIGHT */
|
B_RGB(255, 255, 255) /* GR_COLOR_BTNHIGHLIGHT */
|
B_RGB(255, 255, 255) /* GR_COLOR_BTNHIGHLIGHT */
|
C_RGB(223, 223, 223) /* GR_COLOR_BTNHIGHLIGHT */
|
C_RGB(223, 223, 223) /* GR_COLOR_BTNHIGHLIGHT */
|
|
|
/* top level application window backgrounds/text*/
|
/* top level application window backgrounds/text*/
|
A_RGB(213, 204, 187) /* GR_COLOR_APPWINDOW */
|
A_RGB(213, 204, 187) /* GR_COLOR_APPWINDOW */
|
B_RGB(192, 192, 192) /* GR_COLOR_APPWINDOW */
|
B_RGB(192, 192, 192) /* GR_COLOR_APPWINDOW */
|
C_RGB(160, 160, 160) /* GR_COLOR_APPWINDOW */
|
C_RGB(160, 160, 160) /* GR_COLOR_APPWINDOW */
|
GR_RGB( 0, 0, 0), /* GR_COLOR_APPTEXT */
|
GR_RGB( 0, 0, 0), /* GR_COLOR_APPTEXT */
|
|
|
/* button control backgrounds/text (usually same as app window colors)*/
|
/* button control backgrounds/text (usually same as app window colors)*/
|
A_RGB(213, 204, 187) /* GR_COLOR_BTNFACE */
|
A_RGB(213, 204, 187) /* GR_COLOR_BTNFACE */
|
B_RGB(192, 192, 192) /* GR_COLOR_BTNFACE */
|
B_RGB(192, 192, 192) /* GR_COLOR_BTNFACE */
|
C_RGB(160, 160, 160) /* GR_COLOR_BTNFACE */
|
C_RGB(160, 160, 160) /* GR_COLOR_BTNFACE */
|
GR_RGB( 0, 0, 0), /* GR_COLOR_BTNTEXT */
|
GR_RGB( 0, 0, 0), /* GR_COLOR_BTNTEXT */
|
|
|
/* edit/listbox control backgrounds/text, selected highlights*/
|
/* edit/listbox control backgrounds/text, selected highlights*/
|
GR_RGB(255, 255, 255), /* GR_COLOR_WINDOW */
|
GR_RGB(255, 255, 255), /* GR_COLOR_WINDOW */
|
GR_RGB( 0, 0, 0), /* GR_COLOR_WINDOWTEXT */
|
GR_RGB( 0, 0, 0), /* GR_COLOR_WINDOWTEXT */
|
GR_RGB(128, 0, 0), /* GR_COLOR_HIGHLIGHT */
|
GR_RGB(128, 0, 0), /* GR_COLOR_HIGHLIGHT */
|
GR_RGB(255, 255, 255), /* GR_COLOR_HIGHLIGHTTEXT */
|
GR_RGB(255, 255, 255), /* GR_COLOR_HIGHLIGHTTEXT */
|
GR_RGB( 64, 64, 64), /* GR_COLOR_GRAYTEXT */
|
GR_RGB( 64, 64, 64), /* GR_COLOR_GRAYTEXT */
|
|
|
/* menu backgrounds/text*/
|
/* menu backgrounds/text*/
|
A_RGB(213, 204, 187) /* GR_COLOR_MENU */
|
A_RGB(213, 204, 187) /* GR_COLOR_MENU */
|
B_RGB(192, 192, 192) /* GR_COLOR_MENU */
|
B_RGB(192, 192, 192) /* GR_COLOR_MENU */
|
C_RGB(160, 160, 160) /* GR_COLOR_MENU */
|
C_RGB(160, 160, 160) /* GR_COLOR_MENU */
|
GR_RGB( 0, 0, 0), /* GR_COLOR_MENUTEXT */
|
GR_RGB( 0, 0, 0), /* GR_COLOR_MENUTEXT */
|
};
|
};
|
|
|
/* Return system-defined color*/
|
/* Return system-defined color*/
|
GR_COLOR
|
GR_COLOR
|
GrGetSysColor(int index)
|
GrGetSysColor(int index)
|
{
|
{
|
if(index >= 0 && index < MAXSYSCOLORS)
|
if(index >= 0 && index < MAXSYSCOLORS)
|
return sysColors[index];
|
return sysColors[index];
|
return 0;
|
return 0;
|
}
|
}
|
|
|
void
|
void
|
GrSetScreenSaverTimeout(GR_TIMEOUT timeout)
|
GrSetScreenSaverTimeout(GR_TIMEOUT timeout)
|
{
|
{
|
MWTIMER *timer;
|
MWTIMER *timer;
|
|
|
screensaver_delay = timeout * 1000;
|
screensaver_delay = timeout * 1000;
|
|
|
if((timer = GdFindTimer(GsActivateScreenSaver)))
|
if((timer = GdFindTimer(GsActivateScreenSaver)))
|
GdDestroyTimer(timer);
|
GdDestroyTimer(timer);
|
|
|
/* 0 timeout cancels timer*/
|
/* 0 timeout cancels timer*/
|
if (timeout == 0)
|
if (timeout == 0)
|
return;
|
return;
|
|
|
GdAddTimer(screensaver_delay, GsActivateScreenSaver,
|
GdAddTimer(screensaver_delay, GsActivateScreenSaver,
|
GsActivateScreenSaver);
|
GsActivateScreenSaver);
|
}
|
}
|
|
|
void
|
void
|
GrSetSelectionOwner(GR_WINDOW_ID wid, GR_CHAR *typelist)
|
GrSetSelectionOwner(GR_WINDOW_ID wid, GR_CHAR *typelist)
|
{
|
{
|
GR_WINDOW_ID oldwid = selection_owner.wid;
|
GR_WINDOW_ID oldwid = selection_owner.wid;
|
|
|
if(selection_owner.typelist) free(selection_owner.typelist);
|
if(selection_owner.typelist) free(selection_owner.typelist);
|
|
|
selection_owner.wid = wid;
|
selection_owner.wid = wid;
|
|
|
if(wid) {
|
if(wid) {
|
if(!(selection_owner.typelist = strdup(typelist))) {
|
if(!(selection_owner.typelist = strdup(typelist))) {
|
GsError(GR_ERROR_MALLOC_FAILED, wid);
|
GsError(GR_ERROR_MALLOC_FAILED, wid);
|
selection_owner.wid = 0;
|
selection_owner.wid = 0;
|
}
|
}
|
} else selection_owner.typelist = NULL;
|
} else selection_owner.typelist = NULL;
|
|
|
GsDeliverSelectionChangedEvent(oldwid, wid);
|
GsDeliverSelectionChangedEvent(oldwid, wid);
|
}
|
}
|
|
|
GR_WINDOW_ID
|
GR_WINDOW_ID
|
GrGetSelectionOwner(GR_CHAR **typelist)
|
GrGetSelectionOwner(GR_CHAR **typelist)
|
{
|
{
|
*typelist = selection_owner.typelist;
|
*typelist = selection_owner.typelist;
|
return selection_owner.wid;
|
return selection_owner.wid;
|
}
|
}
|
|
|
void
|
void
|
GrRequestClientData(GR_WINDOW_ID wid, GR_WINDOW_ID rid, GR_SERIALNO serial,
|
GrRequestClientData(GR_WINDOW_ID wid, GR_WINDOW_ID rid, GR_SERIALNO serial,
|
GR_MIMETYPE mimetype)
|
GR_MIMETYPE mimetype)
|
{
|
{
|
GsDeliverClientDataReqEvent(rid, wid, serial, mimetype);
|
GsDeliverClientDataReqEvent(rid, wid, serial, mimetype);
|
}
|
}
|
|
|
void
|
void
|
GrSendClientData(GR_WINDOW_ID wid, GR_WINDOW_ID did, GR_SERIALNO serial,
|
GrSendClientData(GR_WINDOW_ID wid, GR_WINDOW_ID did, GR_SERIALNO serial,
|
GR_LENGTH len, GR_LENGTH thislen, void *data)
|
GR_LENGTH len, GR_LENGTH thislen, void *data)
|
{
|
{
|
void *p;
|
void *p;
|
|
|
if(!(p = malloc(len))) {
|
if(!(p = malloc(len))) {
|
GsError(GR_ERROR_MALLOC_FAILED, wid);
|
GsError(GR_ERROR_MALLOC_FAILED, wid);
|
return; /* FIXME note no error to application*/
|
return; /* FIXME note no error to application*/
|
}
|
}
|
memcpy(p, data, thislen);
|
memcpy(p, data, thislen);
|
|
|
GsDeliverClientDataEvent(did, wid, serial, len, thislen, p);
|
GsDeliverClientDataEvent(did, wid, serial, len, thislen, p);
|
}
|
}
|
|
|
/*
|
/*
|
* Set a window's background pixmap. Note that this doesn't
|
* Set a window's background pixmap. Note that this doesn't
|
* cause a screen refresh, use GrClearWindow if required.
|
* cause a screen refresh, use GrClearWindow if required.
|
*/
|
*/
|
void
|
void
|
GrSetBackgroundPixmap(GR_WINDOW_ID wid, GR_WINDOW_ID pixmap, int flags)
|
GrSetBackgroundPixmap(GR_WINDOW_ID wid, GR_WINDOW_ID pixmap, int flags)
|
{
|
{
|
GR_WINDOW *wp;
|
GR_WINDOW *wp;
|
GR_PIXMAP *pp = NULL;
|
GR_PIXMAP *pp = NULL;
|
|
|
if (!(wp = GsFindWindow(wid))) {
|
if (!(wp = GsFindWindow(wid))) {
|
GsError(GR_ERROR_BAD_WINDOW_ID, wid);
|
GsError(GR_ERROR_BAD_WINDOW_ID, wid);
|
return;
|
return;
|
}
|
}
|
|
|
if (pixmap && !(pp = GsFindPixmap(pixmap))) {
|
if (pixmap && !(pp = GsFindPixmap(pixmap))) {
|
GsError(GR_ERROR_BAD_WINDOW_ID, pixmap);
|
GsError(GR_ERROR_BAD_WINDOW_ID, pixmap);
|
return;
|
return;
|
}
|
}
|
wp->bgpixmap = pp;
|
wp->bgpixmap = pp;
|
wp->bgpixmapflags = flags;
|
wp->bgpixmapflags = flags;
|
}
|
}
|
|
|
void
|
void
|
GrGetFontList(GR_FONTLIST ***fonts, int *numfonts)
|
GrGetFontList(GR_FONTLIST ***fonts, int *numfonts)
|
{
|
{
|
GdGetFontList(fonts,numfonts);
|
GdGetFontList(fonts,numfonts);
|
}
|
}
|
|
|
void
|
void
|
GrFreeFontList(GR_FONTLIST ***fonts, int num)
|
GrFreeFontList(GR_FONTLIST ***fonts, int num)
|
{
|
{
|
GdFreeFontList(fonts, num);
|
GdFreeFontList(fonts, num);
|
}
|
}
|
|
|
/*
|
/*
|
* Return window parent and list of children.
|
* Return window parent and list of children.
|
* Caller must free() children list after use.
|
* Caller must free() children list after use.
|
*/
|
*/
|
void
|
void
|
GrQueryTree(GR_WINDOW_ID wid, GR_WINDOW_ID *parentid, GR_WINDOW_ID **children,
|
GrQueryTree(GR_WINDOW_ID wid, GR_WINDOW_ID *parentid, GR_WINDOW_ID **children,
|
GR_COUNT *nchildren)
|
GR_COUNT *nchildren)
|
{
|
{
|
GR_WINDOW *wp;
|
GR_WINDOW *wp;
|
GR_WINDOW *cp;
|
GR_WINDOW *cp;
|
GR_WINDOW_ID *retarray;
|
GR_WINDOW_ID *retarray;
|
GR_COUNT n = 0;
|
GR_COUNT n = 0;
|
|
|
wp = GsFindWindow(wid);
|
wp = GsFindWindow(wid);
|
if (!wp) {
|
if (!wp) {
|
*parentid = 0;
|
*parentid = 0;
|
nochildren:
|
nochildren:
|
*children = NULL;
|
*children = NULL;
|
*nchildren = 0;
|
*nchildren = 0;
|
return;
|
return;
|
}
|
}
|
*parentid = wp->parent? wp->parent->id: 0;
|
*parentid = wp->parent? wp->parent->id: 0;
|
|
|
/* count children for alloc*/
|
/* count children for alloc*/
|
for(cp=wp->children; cp; cp=cp->siblings)
|
for(cp=wp->children; cp; cp=cp->siblings)
|
++n;
|
++n;
|
if (n == 0)
|
if (n == 0)
|
goto nochildren;
|
goto nochildren;
|
|
|
/* alloc return child array*/
|
/* alloc return child array*/
|
retarray = (GR_WINDOW_ID *)malloc(n * sizeof(GR_WINDOW_ID));
|
retarray = (GR_WINDOW_ID *)malloc(n * sizeof(GR_WINDOW_ID));
|
if (!retarray) {
|
if (!retarray) {
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
GsError(GR_ERROR_MALLOC_FAILED, 0);
|
goto nochildren;
|
goto nochildren;
|
}
|
}
|
|
|
/* fill in return array*/
|
/* fill in return array*/
|
n = 0;
|
n = 0;
|
for(cp=wp->children; cp; cp=cp->siblings) {
|
for(cp=wp->children; cp; cp=cp->siblings) {
|
retarray[n++] = cp->id;
|
retarray[n++] = cp->id;
|
}
|
}
|
*children = retarray;
|
*children = retarray;
|
*nchildren = n;
|
*nchildren = n;
|
}
|
}
|
|
|
|
|
static int next_timer_id = 1000;
|
static int next_timer_id = 1000;
|
|
|
/**
|
/**
|
* GrCreateTimer:
|
* GrCreateTimer:
|
* @wid: the ID of the window to use as a destination for GR_TIMER_EVENT
|
* @wid: the ID of the window to use as a destination for GR_TIMER_EVENT
|
* events that result from this timer.
|
* events that result from this timer.
|
* @period: the timer period in milliseconds
|
* @period: the timer period in milliseconds
|
* @Returns: the ID of the newly created timer, or 0 if failure.
|
* @Returns: the ID of the newly created timer, or 0 if failure.
|
*
|
*
|
* Creates a Nano-X timer with the specified period.
|
* Creates a Nano-X timer with the specified period.
|
* NOTE: There is a potential for more GR_TIMER_EVENTS to be queued
|
* NOTE: There is a potential for more GR_TIMER_EVENTS to be queued
|
* in the connection between the Nano-X server and client. The client
|
* in the connection between the Nano-X server and client. The client
|
* should be able to handle late arriving GR_TIMER_EVENTs.
|
* should be able to handle late arriving GR_TIMER_EVENTs.
|
*/
|
*/
|
GR_TIMER_ID
|
GR_TIMER_ID
|
GrCreateTimer (GR_WINDOW_ID wid, GR_TIMEOUT period)
|
GrCreateTimer (GR_WINDOW_ID wid, GR_TIMEOUT period)
|
{
|
{
|
GR_TIMER *timer;
|
GR_TIMER *timer;
|
|
|
/* Create a nano-X layer timr */
|
/* Create a nano-X layer timr */
|
timer = (GR_TIMER*) malloc (sizeof (GR_TIMER));
|
timer = (GR_TIMER*) malloc (sizeof (GR_TIMER));
|
if (timer == NULL)
|
if (timer == NULL)
|
{
|
{
|
GsError (GR_ERROR_MALLOC_FAILED, 0);
|
GsError (GR_ERROR_MALLOC_FAILED, 0);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* Create a device independent layer timer */
|
/* Create a device independent layer timer */
|
timer->timer = GdAddPeriodicTimer (period, GsTimerCB, timer);
|
timer->timer = GdAddPeriodicTimer (period, GsTimerCB, timer);
|
if (timer->timer == NULL)
|
if (timer->timer == NULL)
|
{
|
{
|
free (timer);
|
free (timer);
|
GsError (GR_ERROR_MALLOC_FAILED, 0);
|
GsError (GR_ERROR_MALLOC_FAILED, 0);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/*
|
/*
|
* Fill in the rest of the timer structure, and
|
* Fill in the rest of the timer structure, and
|
* link the new timer into the servers list of timers.
|
* link the new timer into the servers list of timers.
|
*/
|
*/
|
timer->id = next_timer_id++;
|
timer->id = next_timer_id++;
|
timer->owner = curclient;
|
timer->owner = curclient;
|
timer->wid = wid;
|
timer->wid = wid;
|
timer->next = list_timer;
|
timer->next = list_timer;
|
list_timer = timer;
|
list_timer = timer;
|
|
|
return timer->id;
|
return timer->id;
|
}
|
}
|
|
|
/**
|
/**
|
* GrDestroyTimer:
|
* GrDestroyTimer:
|
* @tid: the ID of the timer to destroy
|
* @tid: the ID of the timer to destroy
|
*
|
*
|
* Destroys a timer previously created with GrCreateTimer().
|
* Destroys a timer previously created with GrCreateTimer().
|
*/
|
*/
|
void
|
void
|
GrDestroyTimer (GR_TIMER_ID tid)
|
GrDestroyTimer (GR_TIMER_ID tid)
|
{
|
{
|
GR_TIMER *timer;
|
GR_TIMER *timer;
|
GR_TIMER *prev_timer;
|
GR_TIMER *prev_timer;
|
|
|
/* Find the timer structure that corresponds to "tid" */
|
/* Find the timer structure that corresponds to "tid" */
|
timer = GsFindTimer (tid);
|
timer = GsFindTimer (tid);
|
if (timer == NULL)
|
if (timer == NULL)
|
return;
|
return;
|
|
|
if (tid == cache_timer_id)
|
if (tid == cache_timer_id)
|
{
|
{
|
cache_timer_id = 0;
|
cache_timer_id = 0;
|
cache_timer = NULL;
|
cache_timer = NULL;
|
}
|
}
|
|
|
/* Delete the timer from the device independent engine layer */
|
/* Delete the timer from the device independent engine layer */
|
GdDestroyTimer (timer->timer);
|
GdDestroyTimer (timer->timer);
|
|
|
/* Pull the timer out of the servers list */
|
/* Pull the timer out of the servers list */
|
if (list_timer == timer)
|
if (list_timer == timer)
|
{
|
{
|
list_timer = timer->next;
|
list_timer = timer->next;
|
}
|
}
|
else
|
else
|
{
|
{
|
prev_timer = list_timer;
|
prev_timer = list_timer;
|
while (prev_timer->next != timer)
|
while (prev_timer->next != timer)
|
{
|
{
|
prev_timer = prev_timer->next;
|
prev_timer = prev_timer->next;
|
}
|
}
|
prev_timer->next = timer->next;
|
prev_timer->next = timer->next;
|
}
|
}
|
free (timer);
|
free (timer);
|
}
|
}
|
|
|
/**
|
/**
|
* GrSetPortraitMode
|
* GrSetPortraitMode
|
* @newmode: new portrait mode
|
* @newmode: new portrait mode
|
*
|
*
|
* Sets new server portrait mode and redraws all windows.
|
* Sets new server portrait mode and redraws all windows.
|
*/
|
*/
|
void
|
void
|
GrSetPortraitMode(int portraitmode)
|
GrSetPortraitMode(int portraitmode)
|
{
|
{
|
GsSetPortraitMode(portraitmode);
|
GsSetPortraitMode(portraitmode);
|
}
|
}
|
|
|