⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 srvfunc.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * Copyright (c) 1999, 2000, 2001 Greg Haerr <greg@censoft.com>
 * Copyright (c) 2000 Alex Holden <alex@linuxhacker.org>
 * Copyright (c) 1991 David I. Bell
 * Permission is granted to use, distribute, or modify this source,
 * provided that this copyright notice remains intact.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MWINCLUDECOLORS
#include "serv.h"

static int	nextid = GR_ROOT_WINDOW_ID + 1;

static void CheckNextEvent(GR_EVENT *ep, GR_BOOL doSelect);

/*
 * Return information about the screen for clients to use.
 */
void 
GrGetScreenInfo(GR_SCREEN_INFO *sip)
{
	GdGetScreenInfo(rootwp->psd, sip);

	/* virtual/workspace screen sizing*/
#if 0
	/* force small screen for emulation purposes*/
	sip->vs_width = 240;	/* PDA*/
	sip->vs_height = 320;
	sip->ws_width = 240;
	sip->ws_height = 298;
#else
	/* set workspace equal to screen area minus 22 pixel taskbar*/
	sip->vs_width = sip->cols;
	sip->vs_height = sip->rows;
	sip->ws_width = sip->cols;
	sip->ws_height = sip->rows - 22;
#endif
}

/*
 * 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,
 * and the height above the bottom of the font of the baseline for the font.
 */
void 
GrGetGCTextSize(GR_GC_ID gc, void *str, int count, int flags,
	GR_SIZE *retwidth, GR_SIZE *retheight, GR_SIZE *retbase)
{
	GR_GC		*gcp;
	GR_FONT		*fontp;
	PMWFONT		pf;

	gcp = GsFindGC(gc);
	if (gcp == NULL)
		fontp = NULL;
	else
		fontp = GsFindFont(gcp->fontid);
	pf = fontp? fontp->pfont: stdfont;
	GdGetTextSize(pf, str, count, retwidth, retheight, retbase, flags);
}

#if NONETWORK
/*
 * 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
 * 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.
 */
void
GrGetNextEvent(GR_EVENT *ep)
{
	GrGetNextEventTimeout(ep, 0L);
}

/*
 * Return the next event from the event queue, or
 * wait for a new one if one is not ready.  If timeout
 * is nonzero, return timeout event if time elapsed.
 */
void
GrGetNextEventTimeout(GR_EVENT *ep, GR_TIMEOUT timeout)
{
	/* If no event ready, wait for one*/
	/* Note: won't work for multiple clients*/
	/* This is OK, since only static linked apps call this function*/
	while(curclient->eventhead == NULL)
		GsSelect(timeout);
	CheckNextEvent(ep, GR_FALSE);
}

/*
 * Wait until an event is available for a client, and then peek at it.
 */
void
GrPeekWaitEvent(GR_EVENT *ep)
{
	while(curclient->eventhead == NULL)
		GsSelect(0L);
	GrPeekEvent(ep);
}
#endif

/*
 * 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 it is an error event, then a user-specified routine is called
 * if it was defined, otherwise we clean up and exit.
 */
void
GrCheckNextEvent(GR_EVENT *ep)
{
	CheckNextEvent(ep, GR_TRUE);
}

static void
CheckNextEvent(GR_EVENT *ep, GR_BOOL doSelect)
{
	GR_EVENT_LIST *	elp;

#if NONETWORK
	/* Since we're bound to server, select() is only called 
	 * thru here
	 */
	if(doSelect)
		GsSelect(0L);
#endif
	/* Copy first event if any*/
	if(!GrPeekEvent(ep))
		return;

	/* Get first event again*/
	elp = curclient->eventhead;

	/* Remove first event from queue*/
	curclient->eventhead = elp->next;
	if (curclient->eventtail == elp)
		curclient->eventtail = NULL;

	elp->next = eventfree;
	eventfree = elp;
}

/*
 * 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
 * else a null event type.  The event is still left in the queue, however.
 */
int
GrPeekEvent(GR_EVENT *ep)
{
	GR_EVENT_LIST *	elp;

	elp = curclient->eventhead;
	if(elp == NULL) {
		ep->type = GR_EVENT_TYPE_NONE;
		return 0;
	}

	/* copy event out*/
	*ep = elp->event;
	return 1;
}

/*
 * Return information about a window id.
 */
void
GrGetWindowInfo(GR_WINDOW_ID wid, GR_WINDOW_INFO *infoptr)
{
	GR_WINDOW	*wp;		/* window structure */
	GR_PIXMAP	*pp;
	GR_EVENT_CLIENT	*evp;		/* event-client structure */

	/* first check window list*/
	wp = GsFindWindow(wid);
	if (wp) {
		infoptr->wid = wid;
		/* report parent-relative x,y coordinates*/
		infoptr->x = wp->x - (wp->parent ? wp->parent->x : 0);
		infoptr->y = wp->y - (wp->parent ? wp->parent->y : 0);
		infoptr->width = wp->width;
		infoptr->height = wp->height;
		infoptr->parent = wp->parent? wp->parent->id: 0;
		infoptr->child = wp->children? wp->children->id: 0;
		infoptr->sibling = wp->siblings? wp->siblings->id: 0;
		infoptr->mapped = wp->mapped;
		infoptr->unmapcount = wp->unmapcount;
		infoptr->inputonly = !wp->output;
		infoptr->bordersize = wp->bordersize;
		infoptr->bordercolor = wp->bordercolor;
		infoptr->background = wp->background;
		infoptr->props = wp->props;
		infoptr->cursor = wp->cursorid;
		infoptr->processid = wp->owner? wp->owner->processid: 0;
		infoptr->eventmask = 0;

		for (evp = wp->eventclients; evp; evp = evp->next) {
			if (evp->client == curclient)
				infoptr->eventmask = evp->eventmask;
		}
		return;
	}

	/* then pixmap list*/
	pp = GsFindPixmap(wid);
	if (pp) {
		infoptr->wid = wid;
		infoptr->x = pp->x;
		infoptr->y = pp->y;
		infoptr->width = pp->width;
		infoptr->height = pp->height;
		infoptr->parent = 0;
		infoptr->child = 0;
		infoptr->sibling = 0;
		infoptr->mapped = GR_FALSE;
		infoptr->unmapcount = 0;
		infoptr->inputonly = GR_FALSE;
		infoptr->bordersize = 0;
		infoptr->bordercolor = 0;
		infoptr->background = 0;
		infoptr->eventmask = 0;
		infoptr->cursor = 0;
		infoptr->processid = pp->owner? pp->owner->processid: 0;
		return;
	}

	/* No error if window id is invalid.*/
	memset(infoptr, 0, sizeof(GR_WINDOW_INFO));
}

/*
 * Destroy an existing window and all of its children.
 * Also used to destroy a pixmap.
 */
void
GrDestroyWindow(GR_WINDOW_ID wid)
{
	GR_WINDOW	*wp;		/* window structure */
	GR_PIXMAP	*pp;
	GR_PIXMAP	*prevpp;
	PSD		psd;

	wp = GsFindWindow(wid);
	if (wp) {
		GsWpDestroyWindow(wp);
	} else {
		pp = GsFindPixmap(wid);
		if (pp) {
			psd = pp->psd;
			/* deallocate pixmap memory*/
			if (psd->flags & PSF_ADDRMALLOC)
				free(psd->addr);

			/* deallocate mem gc*/
			psd->FreeMemGC(psd);

			/*
			 * Remove this pixmap from the complete list of pixmaps.
			 */
			prevpp = listpp;
			if (prevpp == pp)
				listpp = pp->next;
			else {
				while (prevpp->next != pp)
					prevpp = prevpp->next;
				prevpp->next = pp->next;
			}

			/*
			 * Forget various information if they related to this
			 * pixmap.  Then finally free the structure.
			 */
			if (pp == cachepp) {
				cachepixmapid = 0;
				cachepp = NULL;
			}
			free(pp);
		}
	}
}


/*
 * Raise a window to the highest level among its siblings.
 */
void
GrRaiseWindow(GR_WINDOW_ID wid)
{
	GR_WINDOW	*wp;		/* window structure */
	GR_WINDOW	*prevwp;	/* previous window pointer */
	GR_BOOL		overlap;	/* TRUE if there was overlap */

	wp = GsFindWindow(wid);
	if ((wp == NULL) || (wp == rootwp))
		return;

	/*
	 * If this is already the highest window then we are done.
	 */
	prevwp = wp->parent->children;
	if (prevwp == wp)
		return;

	/*
	 * Find the sibling just before this window so we can unlink it.
	 * Also, determine if any sibling ahead of us overlaps the window.
	 * Remember that for exposure events.
	 */
	overlap = GR_FALSE;
	while (prevwp->siblings != wp) {
		overlap |= GsCheckOverlap(prevwp, wp);
		prevwp = prevwp->siblings;
	}
	overlap |= GsCheckOverlap(prevwp, wp);

	/*
	 * Now unlink the window and relink it in at the front of the
	 * sibling chain.
	 */
	prevwp->siblings = wp->siblings;
	wp->siblings = wp->parent->children;
	wp->parent->children = wp;

	/*
	 * Finally redraw the window if necessary.
	 */
	if (overlap) {
		GsDrawBorder(wp);
		GsExposeArea(wp, wp->x, wp->y, wp->width, wp->height, NULL);
	}
}

/*
 * Lower a window to the lowest level among its siblings.
 */
void GrLowerWindow(GR_WINDOW_ID wid)
{
	GR_WINDOW	*wp;		/* window structure */
	GR_WINDOW	*prevwp;	/* previous window pointer */
	GR_WINDOW	*sibwp;		/* sibling window */
	GR_WINDOW	*expwp;		/* siblings being exposed */

	wp = GsFindWindow(wid);
	if ((wp == NULL) || (wp == rootwp))
		return;
	if (wp->siblings == NULL)
		return;

	/*
	 * Find the sibling just before this window so we can unlink us.
	 */
	prevwp = wp->parent->children;
	if (prevwp != wp) {
		while (prevwp->siblings != wp)
			prevwp = prevwp->siblings;
	}

	/*
	 * Remember the first sibling that is after us, so we can
	 * generate exposure events for the remaining siblings.  Then
	 * walk down the sibling chain looking for the last sibling.
	 */
	expwp = wp->siblings;
	sibwp = wp;
	while (sibwp->siblings)
		sibwp = sibwp->siblings;

	/*
	 * Now unlink the window and relink it in at the end of the
	 * sibling chain.
	 */
	if (prevwp == wp)
		wp->parent->children = wp->siblings;
	else
		prevwp->siblings = wp->siblings;
	sibwp->siblings = wp;

	wp->siblings = NULL;

	/*
	 * Finally redraw the sibling windows which this window covered
	 * if they overlapped our window.
	 */
	while (expwp && (expwp != wp)) {
		if (GsCheckOverlap(wp, expwp)) {
			GsExposeArea(expwp, wp->x - wp->bordersize,
				wp->y - wp->bordersize,
				wp->width + wp->bordersize * 2,
				wp->height + wp->bordersize * 2, NULL);
		}
		expwp = expwp->siblings;
	}
}

/* Offset a window position and all children by offx,offy*/
static void
OffsetWindow(GR_WINDOW *wp, GR_COORD offx, GR_COORD offy)
{
	GR_WINDOW	*cp;

	wp->x += offx;
	wp->y += offy;
	for(cp=wp->children; cp; cp=cp->siblings)
		OffsetWindow(cp, offx, offy);
}

/* deliver an update move event to window and all children*/
static void
DeliverUpdateMoveEventAndChildren(GR_WINDOW *wp)
{
	GR_WINDOW *	childwp;

	GsDeliverUpdateEvent(wp, GR_UPDATE_MOVE, wp->x, wp->y,
		wp->width, wp->height);

	for (childwp = wp->children; childwp; childwp = childwp->siblings)
		DeliverUpdateMoveEventAndChildren(childwp);
}

/*
 * Move the window to the specified position relative to its parent.
 */
void
GrMoveWindow(GR_WINDOW_ID wid, GR_COORD x, GR_COORD y)
{
	GR_WINDOW	*wp;		/* window structure */
	GR_COORD	offx, offy;

	wp = GsFindWindow(wid);
	if (wp == NULL)
		return;
	if (wp == rootwp) {
		GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid);
		return;
	}

	x += wp->parent->x;
	y += wp->parent->y;
	offx = x - wp->x;
	offy = y - wp->y;

	if (wp->x == x && wp->y == y)
		return;

	/*** move algorithms not requiring unmap/map ***/
#if 1
	/* perform screen blit if topmost and mapped - no flicker!*/
	if (wp->mapped && wp == wp->parent->children
		&& wp->parent->id == GR_ROOT_WINDOW_ID

		/* temp don't blit in portrait mode, still buggy*/
		&& !(wp->psd->portrait & (MWPORTRAIT_LEFT|MWPORTRAIT_RIGHT))
	   ) {
		int 		oldx = wp->x;
		int 		oldy = wp->y;
		GR_WINDOW_ID 	pixid = GrNewPixmap(wp->width, wp->height,NULL);
		GR_GC_ID	gc = GrNewGC();
		GR_WINDOW * 	stopwp = wp;
		int		X, Y, W, H;

		/* must hide cursor first or GdFixCursor() will show it*/
		GdHideCursor(rootwp->psd);

		/* turn off clipping of root's children*/
		GrSetGCMode(gc, GR_MODE_COPY|GR_MODE_EXCLUDECHILDREN);

		/* copy topmost window contents offscreen*/
		GrCopyArea(pixid, gc, 0, 0, wp->width, wp->height,
			GR_ROOT_WINDOW_ID, oldx, oldy, MWROP_COPY);

		/* calc new window offsets*/
		OffsetWindow(wp, offx, offy);

		/* force recalc of clip region*/
		clipwp = NULL;

		/* copy window bits to new location*/
		GrCopyArea(GR_ROOT_WINDOW_ID, gc, wp->x, wp->y, wp->width,
			wp->height, pixid, 0, 0, MWROP_COPY);

		/*
		 * If any portion of the window was offscreen
		 * and is coming onscreen, must send expose events
		 * to this window as well.
		 */
		if ((oldx < 0 && wp->x > oldx) ||
		    (oldy < 0 && wp->y > oldy) ||
		    (oldx+wp->width > rootwp->width && wp->x < oldx) ||
		    (oldy+wp->height > rootwp->height && wp->y < oldy))
			stopwp = NULL;

		/* 
		 * Calculate bounded exposed area and
		 * redraw anything lower than stopwp window.
		 */
		X = MWMIN(oldx, wp->x);
		Y = MWMIN(oldy, wp->y);
		W = MWMAX(oldx, wp->x) + wp->width - X;
		H = MWMAX(oldy, wp->y) + wp->height - Y;
		GsExposeArea(rootwp, X, Y, W, H, stopwp);

		GdShowCursor(rootwp->psd);
		GrDestroyGC(gc);
		GrDestroyWindow(pixid);
		DeliverUpdateMoveEventAndChildren(wp);
		return;
	}
#endif
#if 0
	/* perform quick move and expose if topmost and mapped - no blit*/
	if (wp->mapped && wp == wp->parent->children) {
		int	oldx = wp->x;
		int	oldy = wp->y;
		int	X, Y, W, H;

		OffsetWindow(wp, offx, offy);

		/* force recalc of clip region*/
		clipwp = NULL;

		X = MWMIN(oldx, wp->x);
		Y = MWMIN(oldy, wp->y);
		W = MWMAX(oldx, wp->x) + wp->width - X;
		H = MWMAX(oldy, wp->y) + wp->height - Y;
		GsExposeArea(rootwp, X, Y, W, H, NULL);
		DeliverUpdateMoveEventAndChildren(wp);
		return;
	}
#endif
	/*
	 * This method will redraw the window entirely,
	 * resulting in considerable flicker.
	 */
	GsWpUnmapWindow(wp, GR_TRUE);
	OffsetWindow(wp, offx, offy);
	GsWpMapWindow(wp, GR_FALSE);
	DeliverUpdateMoveEventAndChildren(wp);
}

/*
 * Resize the window to be the specified size.
 */
void
GrResizeWindow(GR_WINDOW_ID wid, GR_SIZE width, GR_SIZE height)
{
	GR_WINDOW	*wp;		/* window structure */

	wp = GsFindWindow(wid);
	if (wp == NULL)
		return;
	if (wp == rootwp) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -