📄 srvfunc.c
字号:
regionp = GsFindRegion(region);
if (regionp)
GdOffsetRegion(regionp->rgn, dx, dy);
}
/*
* Return the bounding box for the specified region.
*/
int
GrGetRegionBox(GR_REGION_ID region, GR_RECT *rect)
{
GR_REGION *regionp;
MWRECT rc;
int ret_val;
regionp = GsFindRegion(region);
if (regionp == NULL) {
memset(rect, 0, sizeof(GR_RECT));
return MWREGION_ERROR;
}
ret_val = GdGetRegionBox(regionp->rgn, &rc);
/* convert MW rect to Nano-X rect*/
rect->x = rc.left;
rect->y = rc.top;
rect->width = rc.right - rc.left;
rect->height = rc.bottom - rc.top;
return ret_val;
}
static int nextfontid = 1000;
/*
* Allocate a new GC with default parameters.
* The GC is owned by the current client.
*/
GR_FONT_ID
GrCreateFont(GR_CHAR *name, GR_COORD height, GR_LOGFONT *plogfont)
{
GR_FONT *fontp;
fontp = (GR_FONT *) malloc(sizeof(GR_FONT));
if (fontp == NULL) {
GsError(GR_ERROR_MALLOC_FAILED, 0);
return 0;
}
if (plogfont)
fontp->pfont = GdCreateFont(&scrdev, NULL, 0, plogfont);
else
fontp->pfont = GdCreateFont(&scrdev, name, height, NULL);
fontp->id = nextfontid++;
fontp->owner = curclient;
fontp->next = listfontp;
listfontp = fontp;
return fontp->id;
}
/* Set the font size for the passed font*/
void
GrSetFontSize(GR_FONT_ID fontid, GR_COORD size)
{
GR_FONT *fontp;
fontp = GsFindFont(fontid);
if (fontp)
GdSetFontSize(fontp->pfont, size);
}
/* Set the font rotation in tenths of degrees for the passed font*/
void
GrSetFontRotation(GR_FONT_ID fontid, int tenthdegrees)
{
GR_FONT *fontp;
fontp = GsFindFont(fontid);
if (fontp)
GdSetFontRotation(fontp->pfont, tenthdegrees);
}
/* Set the font size for the passed font*/
void
GrSetFontAttr(GR_FONT_ID fontid, int setflags, int clrflags)
{
GR_FONT *fontp;
fontp = GsFindFont(fontid);
if (fontp)
GdSetFontAttr(fontp->pfont, setflags, clrflags);
}
/*
* Unload and deallocate an existing font.
*/
void
GrDestroyFont(GR_FONT_ID fontid)
{
GR_FONT *fontp;
GR_FONT *prevfontp;
fontp = GsFindFont(fontid);
if (fontp == NULL)
return;
if (listfontp == fontp)
listfontp = fontp->next;
else {
prevfontp = listfontp;
while (prevfontp->next != fontp)
prevfontp = prevfontp->next;
prevfontp->next = fontp->next;
}
GdDestroyFont(fontp->pfont);
free(fontp);
}
/*
* Return useful information about the specified font.
* Font #0 returns info about the standard font.
*/
void
GrGetFontInfo(GR_FONT_ID font, GR_FONT_INFO *fip)
{
GR_FONT *fontp;
PMWFONT pf;
if (font == 0)
pf = stdfont;
else {
fontp = GsFindFont(font);
if (!fontp) {
memset(fip, 0, sizeof(GR_FONT_INFO));
return;
}
pf = fontp->pfont;
}
GdGetFontInfo(pf, fip);
}
/*
* Select events for a window for this client.
* The events are a bitmask for the events desired.
*/
void
GrSelectEvents(GR_WINDOW_ID wid, GR_EVENT_MASK eventmask)
{
GR_WINDOW *wp; /* window structure */
GR_EVENT_CLIENT *evp; /* event-client structure */
wp = GsFindWindow(wid);
if (wp == NULL)
return;
/*
* See if this client is already in the event client list.
* If so, then just replace the events he is selecting for.
*/
for (evp = wp->eventclients; evp; evp = evp->next) {
if (evp->client == curclient) {
evp->eventmask = eventmask;
return;
}
}
/*
* 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.
*/
evp = (GR_EVENT_CLIENT *) malloc(sizeof(GR_EVENT_CLIENT));
if (evp == NULL) {
GsError(GR_ERROR_MALLOC_FAILED, wid);
return;
}
evp->client = curclient;
evp->eventmask = eventmask;
evp->next = wp->eventclients;
wp->eventclients = evp;
/*
* If it's a request for child updates to the root window,
* then search entire list and send map events for
* mapped windows now. This allows a window manager
* to get the mapped window list without another API call.
*/
if (wid==GR_ROOT_WINDOW_ID && (eventmask & GR_EVENT_MASK_CHLD_UPDATE)) {
for (wp = listwp; wp; wp = wp->next) {
if (wp->unmapcount == 0)
GsDeliverUpdateEvent(wp, GR_UPDATE_MAP,
wp->x, wp->y, wp->width, wp->height);
}
}
}
static GR_WINDOW *
NewWindow(GR_WINDOW *pwp, GR_COORD x, GR_COORD y, GR_SIZE width,
GR_SIZE height, GR_SIZE bordersize, GR_COLOR background,
GR_COLOR bordercolor)
{
GR_WINDOW *wp; /* new window*/
if (width <= 0 || height <= 0 || bordersize < 0) {
GsError(GR_ERROR_BAD_WINDOW_SIZE, 0);
return NULL;
}
wp = (GR_WINDOW *) malloc(sizeof(GR_WINDOW));
if (wp == NULL) {
GsError(GR_ERROR_MALLOC_FAILED, 0);
return NULL;
}
wp->id = nextid++;
wp->psd = rootwp->psd;
wp->parent = pwp;
wp->children = NULL;
wp->siblings = pwp->children;
wp->next = listwp;
wp->x = pwp->x + x;
wp->y = pwp->y + y;
wp->width = width;
wp->height = height;
wp->bordersize = bordersize;
wp->background = background;
wp->bgpixmap = NULL;
wp->bgpixmapflags = GR_BACKGROUND_TILE;
wp->bordercolor = bordercolor;
wp->nopropmask = 0;
wp->eventclients = NULL;
wp->owner = curclient;
wp->cursorid = pwp->cursorid;
wp->mapped = GR_FALSE;
wp->unmapcount = pwp->unmapcount + 1;
wp->output = GR_TRUE;
wp->props = 0;
wp->title = NULL;
pwp->children = wp;
listwp = wp;
return wp;
}
/*
* Allocate a new window which is a child of the specified window.
* The window inherits the cursor of the parent window.
* The window is owned by the current client.
*/
GR_WINDOW_ID
GrNewWindow(GR_WINDOW_ID parent, GR_COORD x, GR_COORD y, GR_SIZE width,
GR_SIZE height, GR_SIZE bordersize, GR_COLOR background,
GR_COLOR bordercolor)
{
GR_WINDOW *pwp; /* parent window */
GR_WINDOW *wp; /* new window */
pwp = GsFindWindow(parent);
if (pwp == NULL)
return 0;
if (!pwp->output) {
GsError(GR_ERROR_INPUT_ONLY_WINDOW, pwp->id);
return 0;
}
wp = NewWindow(pwp, x, y, width, height, bordersize, background,
bordercolor);
return wp? wp->id: 0;
}
/*
* 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
* return events. The window inherits the cursor of the parent window.
* The window is owned by the current client.
*/
GR_WINDOW_ID
GrNewInputWindow(GR_WINDOW_ID parent, GR_COORD x, GR_COORD y,
GR_SIZE width, GR_SIZE height)
{
GR_WINDOW *pwp; /* parent window */
GR_WINDOW *wp; /* new window */
pwp = GsFindWindow(parent);
if (pwp == NULL)
return 0;
wp = NewWindow(pwp, x, y, width, height, 0, BLACK, BLACK);
if (wp) {
/* convert to input-only window*/
wp->output = GR_FALSE;
return wp->id;
}
return 0;
}
/*
* Allocate a pixmap, can be used with any drawing functions
* for offscreen drawing
*/
GR_WINDOW_ID
GrNewPixmap(GR_SIZE width, GR_SIZE height, void * pixels)
{
GR_PIXMAP *pp;
PSD psd;
int size, linelen, bpp, planes;
if (width <= 0 || height <= 0) {
/* no error for now, server will desynchronize w/app*/
/*GsError(GR_ERROR_BAD_WINDOW_SIZE, 0);*/
return 0;
}
/*
* allocate offscreen psd. If screen driver doesn't
* support blitting, this will fail. Use root window screen
* device for compatibility for now.
*/
planes = rootwp->psd->planes;
bpp = rootwp->psd->bpp;
psd = rootwp->psd->AllocateMemGC(rootwp->psd);
if (!psd)
return 0;
pp = (GR_PIXMAP *) malloc(sizeof(GR_PIXMAP));
if (pp == NULL) {
GsError(GR_ERROR_MALLOC_FAILED, 0);
psd->FreeMemGC(psd);
return 0;
}
GdCalcMemGCAlloc(psd, width, height, 0, 0, &size, &linelen);
/* Allocate space for pixel values */
if (!pixels) {
pixels = calloc(size, 1);
psd->flags |= PSF_ADDRMALLOC;
}
if (!pixels) {
free(pp);
psd->FreeMemGC(psd);
GsError(GR_ERROR_MALLOC_FAILED, 0);
return 0;
}
pp->id = nextid++;
pp->next = listpp;
pp->psd = psd;
pp->x = 0;
pp->y = 0;
pp->width = width;
pp->height = height;
pp->owner = curclient;
psd->MapMemGC(psd, width, height, planes, bpp, linelen, size,
pixels);
listpp = pp;
return pp->id;
}
/*
* Map the window to make it (and possibly its children) visible on the screen.
*/
void
GrMapWindow(GR_WINDOW_ID wid)
{
GR_WINDOW *wp; /* window structure */
wp = GsFindWindow(wid);
if (!wp || wp->mapped)
return;
wp->mapped = GR_TRUE;
GsWpMapWindow(wp, GR_FALSE);
}
/*
* Unmap the window to make it and its children invisible on the screen.
*/
void
GrUnmapWindow(GR_WINDOW_ID wid)
{
GR_WINDOW *wp; /* window structure */
wp = GsFindWindow(wid);
if (!wp || !wp->mapped)
return;
GsWpUnmapWindow(wp, GR_FALSE);
wp->mapped = GR_FALSE;
}
/*
* Clear the associated area of a window to its background color
* or pixmap. Generate expose event for window if exposeflag set.
*/
void
GrClearArea(GR_WINDOW_ID wid, GR_COORD x, GR_COORD y, GR_SIZE width,
GR_SIZE height, GR_BOOL exposeflag)
{
GR_WINDOW *wp; /* window structure */
wp = GsPrepareWindow(wid);
if (wp) {
if (width == 0)
width = wp->width;
if (height == 0)
height = wp->height;
GsWpClearWindow(wp, x, y, width, height, exposeflag);
}
}
/* Return window with keyboard focus.*/
GR_WINDOW_ID
GrGetFocus(void)
{
return focuswp->id;
}
/*
* Set the focus to a particular window.
* This makes keyboard events only visible to that window or children of it,
* depending on the pointer location.
*/
void
GrSetFocus(GR_WINDOW_ID wid)
{
GR_WINDOW *wp; /* window structure */
wp = GsFindWindow(wid);
if (wp == NULL)
return;
if (wp->unmapcount) {
GsError(GR_ERROR_UNMAPPED_FOCUS_WINDOW, wid);
return;
}
/* Check if window wants focus, if not, ignore call*/
if (wp->props & GR_WM_PROPS_NOFOCUS)
return;
focusfixed = (wp != rootwp);
GsWpSetFocus(wp);
}
/*
* Create a new server-based cursor resource.
*/
static int nextcursorid = 1000;
GR_CURSOR_ID
GrNewCursor(GR_SIZE width, GR_SIZE height, GR_COORD hotx, GR_COORD hoty,
GR_COLOR foreground, GR_COLOR background, GR_BITMAP *fgbitmap,
GR_BITMAP *bgbitmap)
{
GR_CURSOR *cp;
int bytes;
/*
* Make sure the size of the bitmap is reasonable.
*/
if (width <= 0 || width > MWMAX_CURSOR_SIZE ||
height <= 0 || height > MWMAX_CURSOR_SIZE) {
GsError(GR_ERROR_BAD_CURSOR_SIZE, 0);
return 0;
}
cp = (GR_CURSOR *)malloc(sizeof(GR_CURSOR));
if (cp == NULL) {
GsError(GR_ERROR_MALLOC_FAILED, 0);
return 0;
}
/* fill in cursor structure*/
cp->cursor.width = width;
cp->cursor.height = height;
cp->cursor.hotx = hotx;
cp->cursor.hoty = hoty;
cp->cursor.fgcolor = foreground;
cp->cursor.bgcolor = background;
bytes = GR_BITMAP_SIZE(width, height) * sizeof(GR_BITMAP);
memcpy(&cp->cursor.image, fgbitmap, bytes);
memcpy(&cp->cursor.mask, bgbitmap, bytes);
cp->id = nextcursorid++;
cp->owner = curclient;
cp->next = listcursorp;
listcursorp = cp;
return cp->id;
}
/*
* Destroy a server-based cursor.
*/
void
GrDestroyCursor(GR_CURSOR_ID cid)
{
GR_CURSOR *cursorp;
GR_CURSOR *prevcursorp;
cursorp = GsFindCursor(cid);
if (cursorp == NULL)
return;
if (listcursorp == cursorp)
listcursorp = cursorp->next;
else {
prevcursorp = listcursorp;
while (prevcursorp->next != cursorp)
prevcursorp = prevcursorp->next;
prevcursorp->next = cursorp->next;
}
if (curcursor == cursorp)
curcursor = NULL;
free(cursorp);
GsCheckCursor();
}
/*
* Specify a cursor for a window.
* This cursor will only be used within that window, and by default
* for its new children. If the cursor is currently within this
* window, it will be changed to the new one immediately.
* If the new cursor id is 0, revert to the root window cursor.
*/
void
GrSetWindowCursor(GR_WINDOW_ID wid, GR_CURSOR_ID cid)
{
GR_WINDOW *wp;
GR_CURSOR *cp; /* cursor structure */
wp = GsFindWindow(wid);
if (wp == NULL)
return;
if (cid == 0)
cp = stdcursor;
else {
cp = GsFindCursor(cid);
if (!cp)
return; /* FIXME add server errmsg*/
}
wp->cursorid = cid;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -