LOCAL void dfb_setattrs(DFBDISPLAY *mod, struct TVRequest *req) { struct attrdata data; struct THook hook; DFBWINDOW *v = req->tvr_Op.SetAttrs.Window; data.v = v; data.num = 0; data.mod = mod; data.sizechanged = TFALSE; TInitHook(&hook, setattrfunc, &data); TForEachTag(req->tvr_Op.SetAttrs.Tags, &hook); req->tvr_Op.SetAttrs.Num = data.num; if (data.sizechanged) { TIMSG *imsg; v->wminwidth = v->wminwidth <= 0 ? 1 : v->wminwidth; v->wminheight = v->wminheight <= 0 ? 1 : v->wminheight; v->wmaxwidth = v->wmaxwidth <= 0 ? 1000000 : v->wmaxwidth; v->wmaxheight = v->wmaxheight <= 0 ? 1000000 : v->wmaxheight; if (v->wmaxwidth > 0) v->winwidth = TMIN(v->winwidth, v->wmaxwidth); if (v->wmaxheight > 0) v->winheight = TMIN(v->winheight, v->wmaxheight); if (v->wminwidth > 0) v->winwidth = TMAX(v->winwidth, v->wminwidth); if (v->wminheight > 0) v->winheight = TMAX(v->winheight, v->wminheight); v->window->Resize(v->window, v->winwidth, v->winheight); if ((v->eventmask & TITYPE_NEWSIZE) && getimsg(mod, v, &imsg, TITYPE_NEWSIZE)) { imsg->timsg_Width = v->winwidth; imsg->timsg_Height = v->winheight; TAddTail(&v->imsgqueue, &imsg->timsg_Node); } if ((v->eventmask & TITYPE_REFRESH) && getimsg(mod, v, &imsg, TITYPE_REFRESH)) { imsg->timsg_X = v->winleft; imsg->timsg_Y = v->wintop; imsg->timsg_Width = v->winwidth; imsg->timsg_Height = v->winheight; TAddTail(&v->imsgqueue, &imsg->timsg_Node); } } }
LOCAL void exec_returnmsg(TEXECBASE *exec, TAPTR mem, TUINT status) { struct TMessage *msg = TGETMSGPTR(mem); struct TMsgPort *replyport = msg->tmsg_RPort; if (replyport) { TAPTR hal = exec->texb_HALBase; THALLock(hal, &replyport->tmp_Lock); TAddTail(&replyport->tmp_MsgList, (struct TNode *) msg); msg->tmsg_Flags = status; if (replyport->tmp_Hook) TCALLHOOKPKT(replyport->tmp_Hook, replyport, (TTAG) msg); THALUnlock(hal, &replyport->tmp_Lock); THALSignal(hal, &replyport->tmp_SigTask->tsk_Thread, replyport->tmp_Signal); } else { exec_Free(exec, mem); /* free one-way msg transparently */ TDBPRINTF(TDB_TRACE,("message returned to memory manager\n")); } }
static TBOOL exec_init(TEXECBASE *exec, TTAGITEM *tags) { TAPTR *halp, hal; halp = (TAPTR *) TGetTag(tags, TExecBase_HAL, TNULL); if (!halp) return TFALSE; hal = *halp; THALFillMem(hal, exec, sizeof(TEXECBASE), 0); exec->texb_HALBase = hal; if (THALInitLock(hal, &exec->texb_Lock)) { if (exec_initmm(exec, &exec->texb_MsgMemManager, TNULL, TMMT_Message, TNULL)) { if (exec_initmm(exec, &exec->texb_BaseMemManager, TNULL, TMMT_MemManager, TNULL)) { exec->texb_Module.tmd_Handle.thn_Hook.thk_Data = exec; exec->texb_Module.tmd_Handle.thn_Name = TMODNAME_EXEC; exec->texb_Module.tmd_Handle.thn_Owner = (struct TModule *) exec; exec->texb_Module.tmd_ModSuper = (struct TModule *) exec; exec->texb_Module.tmd_InitTask = TNULL; /* inserted later */ exec->texb_Module.tmd_HALMod = TNULL; /* inserted later */ exec->texb_Module.tmd_NegSize = EXEC_NUMVECTORS * sizeof(TAPTR); exec->texb_Module.tmd_PosSize = sizeof(TEXECBASE); exec->texb_Module.tmd_RefCount = 1; exec->texb_Module.tmd_Flags = TMODF_INITIALIZED | TMODF_VECTORTABLE; TInitList(&exec->texb_IntModList); exec->texb_InitModNode.tmin_Modules = (struct TInitModule *) TGetTag(tags, TExecBase_ModInit, TNULL); if (exec->texb_InitModNode.tmin_Modules) { TAddTail(&exec->texb_IntModList, &exec->texb_InitModNode.tmin_Node); } TInitList(&exec->texb_AtomList); TInitList(&exec->texb_TaskList); TInitList(&exec->texb_TaskInitList); TInitList(&exec->texb_TaskExitList); TInitList(&exec->texb_ModList); TAddHead(&exec->texb_ModList, (struct TNode *) exec); TAddHead(&exec->texb_ModList, (struct TNode *) hal); return TTRUE; } TDESTROY(&exec->texb_MsgMemManager); } THALDestroyLock(hal, &exec->texb_Lock); } return TFALSE; }
static void CALLBACK hal_timeproc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) { struct TNode *node, *nnode; if (TryEnterCriticalSection(&g_hws->hsp_DevLock)) { TTIME curtime; hal_getsystime(g_hal, &curtime); node = g_hws->hsp_ReqList.tlh_Head.tln_Succ; for (; (nnode = node->tln_Succ); node = nnode) { struct TTimeRequest *tr = (struct TTimeRequest *) node; if (TCmpTime(&curtime, &tr->ttr_Data.ttr_Time) >= 0) { TRemove(node); TAddTail(&g_ReplyList, node); } } node = g_ReplyList.tlh_Head.tln_Succ; for (; (nnode = node->tln_Succ); node = nnode) { struct TTimeRequest *tr = (struct TTimeRequest *) node; TRemove(node); if (!hal_replytimereq(tr)) TAddHead(&g_ReplyList, node); } LeaveCriticalSection(&g_hws->hsp_DevLock); } }
static TBOOL hal_replytimereq(struct TTimeRequest *tr) { TBOOL success = TFALSE; struct TMessage *msg = TGETMSGPTR(tr); struct TMsgPort *mp = msg->tmsg_RPort; CRITICAL_SECTION *mplock = THALGetObject((TAPTR) &mp->tmp_Lock, CRITICAL_SECTION); if (TryEnterCriticalSection(mplock)) { struct TTask *sigtask = mp->tmp_SigTask; struct HALThread *t = THALGetObject((TAPTR) &sigtask->tsk_Thread, struct HALThread); if (TryEnterCriticalSection(&t->hth_SigLock)) { tr->ttr_Req.io_Error = 0; msg->tmsg_Flags = TMSG_STATUS_REPLIED | TMSGF_QUEUED; TAddTail(&mp->tmp_MsgList, &msg->tmsg_Node); if (mp->tmp_Signal & ~t->hth_SigState) { t->hth_SigState |= mp->tmp_Signal; SetEvent(t->hth_SigEvent); } LeaveCriticalSection(&t->hth_SigLock); success = TTRUE; } LeaveCriticalSection(mplock); } return success; }
LOCAL TINT rfb_sendevent(struct rfb_Display *mod, TUINT type, TUINT code, TINT x, TINT y) { TIMSG *msg; if (!rfb_getimsg(mod, TNULL, &msg, type)) return 0; msg->timsg_Code = code; msg->timsg_MouseX = x; msg->timsg_MouseY = y; TINT res = 1; switch (type) { case TITYPE_MOUSEMOVE: rfb_passevent_mousemove(mod, msg); break; case TITYPE_MOUSEBUTTON: rfb_passevent_mousebutton(mod, msg); break; case TITYPE_KEYUP: case TITYPE_KEYDOWN: rfb_passevent_keyboard(mod, msg); break; default: TDBPRINTF(TDB_ERROR, ("illegal message type\n")); res = 0; } /* put back prototype message */ TAddTail(&mod->rfb_IMsgPool, &msg->timsg_Node); return res; }
LOCAL TAPTR dfb_hostopenfont(DFBDISPLAY *mod, TTAGITEM *tags) { struct fnt_attr fattr; struct FontNode *fn; TAPTR font = TNULL; TAPTR exec = TGetExecBase(mod); /* fetch user specified attributes */ fattr.fname = (TSTRPTR) TGetTag(tags, TVisual_FontName, (TTAG) FNT_DEFNAME); fattr.fpxsize = (TINT) TGetTag(tags, TVisual_FontPxSize, (TTAG) FNT_DEFPXSIZE); /* not yet fattr.fitalic = (TBOOL) TGetTag(tags, TVisual_FontItalic, (TTAG) TFALSE); fattr.fbold = (TBOOL) TGetTag(tags, TVisual_FontBold, (TTAG) TFALSE); fattr.fscale = (TBOOL) TGetTag(tags, TVisual_FontScaleable, (TTAG) TFALSE); */ if (fattr.fname) { fn = TExecAlloc0(exec, mod->dfb_MemMgr, sizeof(struct FontNode)); if (fn) { fn->handle.thn_Owner = mod; if (hostopenfont(mod, fn, &fattr)) { /* load succeeded, save font attributes */ fn->pxsize = fattr.fpxsize; fn->font->GetHeight(fn->font, &fn->height); fn->font->GetAscender(fn->font, &fn->ascent); fn->font->GetDescender(fn->font, &fn->descent); /* not yet if (fattr.fitalic) fn->attr = FNT_ITALIC; if (fattr.fbold) fn->attr |= FNT_BOLD; */ /* append to the list of open fonts */ TDBPRINTF(TDB_INFO, ("O '%s' %dpx\n", fattr.fname, fattr.fpxsize)); TAddTail(&mod->dfb_fm.openfonts, &fn->handle.thn_Node); font = (TAPTR)fn; } else { /* load failed, free fontnode */ TDBPRINTF(TDB_INFO,("X unable to load '%s'\n", fattr.fname)); TExecFree(exec, fn); } } else TDBPRINTF(TDB_FAIL,("out of memory :(\n")); } else TDBPRINTF(TDB_ERROR,("X invalid fontname '%s' specified\n", fattr.fname)); return font; }
LOCAL void rfb_putbackmsg(struct rfb_Display *mod, TIMSG *msg) { TAPTR TExecBase = TGetExecBase(mod); TLock(mod->rfb_InstanceLock); TAddTail(&mod->rfb_IMsgPool, &msg->timsg_Node); TUnlock(mod->rfb_InstanceLock); }
static void TTASKENTRY hal_devfunc(struct TTask *task) { TAPTR exec = TGetExecBase(task); struct THALBase *hal = TExecGetHALBase(exec); struct HALSpecific *hps = hal->hmb_Specific; struct HALThread *thread = TlsGetValue(hps->hsp_TLSIndex); TAPTR port = TExecGetUserPort(exec, task); struct TTimeRequest *msg; TUINT sig = 0; TTIME waittime, curtime; struct TNode *nnode, *node; waittime.ttm_Sec = 2000000000; waittime.ttm_USec = 0; for (;;) { sig = hal_timedwaitevent(hal, thread, &waittime, TTASK_SIG_ABORT | TTASK_SIG_USER); if (sig & TTASK_SIG_ABORT) break; EnterCriticalSection(&hps->hsp_DevLock); hal_getsystime(hal, &curtime); while ((msg = TExecGetMsg(exec, port))) { TAddTime(&msg->ttr_Data.ttr_Time, &curtime); TAddTail(&hps->hsp_ReqList, (struct TNode *) msg); } waittime.ttm_Sec = 2000000000; waittime.ttm_USec = 0; node = hps->hsp_ReqList.tlh_Head; for (; (nnode = node->tln_Succ); node = nnode) { struct TTimeRequest *tr = (struct TTimeRequest *) node; TTIME *tm = &tr->ttr_Data.ttr_Time; if (TCmpTime(&curtime, tm) >= 0) { TRemove(node); tr->ttr_Req.io_Error = 0; TExecReplyMsg(exec, node); continue; } if (TCmpTime(tm, &waittime) < 0) waittime = *tm; } LeaveCriticalSection(&hps->hsp_DevLock); } TDBPRINTF(2,("goodbye from HAL device\n")); }
/* parses a single fontname or a comma separated list of fontnames ** and returns a list of fontnames, spaces are NOT filtered, so ** "helvetica, fixed" will result in "helvetica" and " fixed" */ static void fnt_getfnnodes(DFBDISPLAY *mod, struct TList *fnlist, TSTRPTR fname) { TINT i, p = 0; TBOOL lastrun = TFALSE; TINT fnlen = strlen(fname); TAPTR exec = TGetExecBase(mod); for (i = 0; i < fnlen; i++) { if (i == fnlen-1) lastrun = TTRUE; if (fname[i] == ',' || lastrun) { TINT len = (i > p) ? (lastrun ? (i-p+1) : (i-p)) : fnlen+1; TSTRPTR ts = TExecAlloc0(exec, mod->dfb_MemMgr, len+1); if (ts) { struct fnt_node *fnn; TExecCopyMem(exec, fname+p, ts, len); fnn = TExecAlloc0(exec, mod->dfb_MemMgr, sizeof(struct fnt_node)); if (fnn) { /* add fnnode to fnlist */ fnn->fname = ts; TAddTail(fnlist, &fnn->node); } else { TDBPRINTF(TDB_FAIL,("out of memory :(\n")); break; } } else { TDBPRINTF(TDB_FAIL,("out of memory :(\n")); break; } p = i+1; } } }
static void fnt_getfnnodes(struct rfb_Display *mod, struct TList *fnlist, TSTRPTR fname) { TINT i, p = 0; TBOOL lastrun = TFALSE; TINT fnlen = strlen(fname); TAPTR TExecBase = mod->rfb_ExecBase; for (i = 0; i < fnlen; i++) { if (i == fnlen - 1) lastrun = TTRUE; if (fname[i] == ',' || lastrun) { TINT len = (i > p) ? (lastrun ? (i - p + 1) : (i - p)) : fnlen + 1; TSTRPTR ts = TAlloc0(mod->rfb_MemMgr, len + 1); if (ts) { struct fnt_node *fnn; memcpy(ts, fname + p, len); fnn = TAlloc0(mod->rfb_MemMgr, sizeof(struct fnt_node)); if (fnn) { /* add fnnode to fnlist */ fnn->fname = ts; TAddTail(fnlist, &fnn->node); } else { TDBPRINTF(20, ("out of memory :(\n")); break; } } else { TDBPRINTF(20, ("out of memory :(\n")); break; } p = i + 1; } } }
LOCAL void dfb_allocpen(DFBDISPLAY *mod, struct TVRequest *req) { DFBWINDOW *v = req->tvr_Op.AllocPen.Window; TUINT rgb = req->tvr_Op.AllocPen.RGB; struct DFBPen *pen = TExecAlloc(mod->dfb_ExecBase, mod->dfb_MemMgr, sizeof(struct DFBPen)); if (pen) { pen->a = rgb >> 24; pen->r = ((rgb >> 16) & 0xff); pen->g = ((rgb >> 8) & 0xff); pen->b = rgb & 0xff; TAddTail(&v->penlist, &pen->node); req->tvr_Op.AllocPen.Pen = (TVPEN) pen; return; } req->tvr_Op.AllocPen.Pen = TVPEN_UNDEFINED; }
LOCAL void fb_allocpen(WINDISPLAY *mod, struct TVRequest *req) { struct TExecBase *TExecBase = TGetExecBase(mod); WINWINDOW *v = req->tvr_Op.AllocPen.Window; TUINT rgb = req->tvr_Op.AllocPen.RGB; struct FBPen *pen = TAlloc(mod->fbd_MemMgr, sizeof(struct FBPen)); if (pen) { COLORREF col = RGB2COLORREF(rgb); pen->rgb = rgb; pen->col = col; pen->brush = CreateSolidBrush(col); pen->pen = CreatePen(PS_SOLID, 0, col); TAddTail(&v->penlist, &pen->node); req->tvr_Op.AllocPen.Pen = (TVPEN) pen; return; } req->tvr_Op.AllocPen.Pen = TVPEN_UNDEFINED; }
LOCAL TUINT exec_sendmsg(TEXECBASE *TExecBase, struct TTask *task, struct TMsgPort *port, TAPTR mem) { TAPTR hal = TExecBase->texb_HALBase; struct TMessage *msg = TGETMSGPTR(mem); TAPTR reply; /* replyport is task's syncport */ msg->tmsg_RPort = &task->tsk_SyncPort; /* sender is local address space */ msg->tmsg_Sender = TNULL; THALLock(hal, &port->tmp_Lock); TAddTail(&port->tmp_MsgList, (struct TNode *) msg); msg->tmsg_Flags = TMSG_STATUS_SENT | TMSGF_QUEUED; if (port->tmp_Hook) TCALLHOOKPKT(port->tmp_Hook, port, (TTAG) msg); THALUnlock(hal, &port->tmp_Lock); THALSignal(hal, &port->tmp_SigTask->tsk_Thread, port->tmp_Signal); for (;;) { THALWait(TExecBase->texb_HALBase, task->tsk_SyncPort.tmp_Signal); reply = TGetMsg(msg->tmsg_RPort); if (reply) { TUINT status = msg->tmsg_Flags; TDBASSERT(99, reply == mem); msg->tmsg_Flags = 0; return status; } TDBPRINTF(TDB_FAIL,("signal on syncport, no message!\n")); } }
LOCAL TAPTR rfb_hostopenfont(struct rfb_Display *mod, TTAGITEM *tags) { struct fnt_attr fattr; struct rfb_FontNode *fn; TAPTR font = TNULL; /* fetch user specified attributes */ fattr.fname = (TSTRPTR) TGetTag(tags, TVisual_FontName, (TTAG) FNT_DEFNAME); fattr.fpxsize = (TINT) TGetTag(tags, TVisual_FontPxSize, (TTAG) FNT_DEFPXSIZE); if (fattr.fname) { fn = TExecAlloc0(mod->rfb_ExecBase, mod->rfb_MemMgr, sizeof(struct rfb_FontNode)); if (fn) { fn->handle.thn_Owner = mod; if (hostopenfont(mod, fn, &fattr)) { /* load succeeded, save font attributes */ fn->pxsize = fattr.fpxsize; fn->height = fn->face->size->metrics.height >> 6; fn->ascent = fn->face->size->metrics.ascender >> 6; fn->descent = fn->face->size->metrics.descender >> 6; /* append to the list of open fonts */ TDBPRINTF(TDB_INFO, ("O '%s' %dpx\n", fattr.fname, fattr.fpxsize)); TAddTail(&mod->rfb_FontManager.openfonts, &fn->handle.thn_Node); font = (TAPTR) fn; } else {
static TBOOL x11_processkey(struct X11Display *mod, struct X11Window *v, XKeyEvent *ev, TBOOL keydown) { KeySym keysym; XComposeStatus compose; char buffer[10]; TIMSG *imsg; TUINT evtype = 0; TUINT newqual; TUINT evmask = v->eventmask; TBOOL newkey = TFALSE; x11_setmousepos(mod, v, ev->x, ev->y); XLookupString(ev, buffer, 10, &keysym, &compose); switch (keysym) { case XK_Shift_L: newqual = TKEYQ_LSHIFT; break; case XK_Shift_R: newqual = TKEYQ_RSHIFT; break; case XK_Control_L: newqual = TKEYQ_LCTRL; break; case XK_Control_R: newqual = TKEYQ_RCTRL; break; case XK_Alt_L: newqual = TKEYQ_LALT; break; case XK_Alt_R: newqual = TKEYQ_RALT; break; default: newqual = 0; } if (newqual != 0) { if (keydown) mod->x11_KeyQual |= newqual; else mod->x11_KeyQual &= ~newqual; } if (keydown && (evmask & TITYPE_KEYDOWN)) evtype = TITYPE_KEYDOWN; else if (!keydown && (evmask & TITYPE_KEYUP)) evtype = TITYPE_KEYUP; if (evtype && x11_getimsg(mod, v, &imsg, evtype)) { imsg->timsg_Qualifier = mod->x11_KeyQual; if (keysym >= XK_F1 && keysym <= XK_F12) { imsg->timsg_Code = (TUINT) (keysym - XK_F1) + TKEYC_F1; newkey = TTRUE; } else if (keysym < 256) { /* cooked ASCII/Latin-1 code */ imsg->timsg_Code = keysym; newkey = TTRUE; } else if (keysym >= XK_KP_0 && keysym <= XK_KP_9) { imsg->timsg_Code = (TUINT) (keysym - XK_KP_0) + 48; imsg->timsg_Qualifier |= TKEYQ_NUMBLOCK; newkey = TTRUE; } else { newkey = TTRUE; switch (keysym) { case XK_Left: imsg->timsg_Code = TKEYC_CRSRLEFT; break; case XK_Right: imsg->timsg_Code = TKEYC_CRSRRIGHT; break; case XK_Up: imsg->timsg_Code = TKEYC_CRSRUP; break; case XK_Down: imsg->timsg_Code = TKEYC_CRSRDOWN; break; case XK_Escape: imsg->timsg_Code = TKEYC_ESC; break; case XK_Delete: imsg->timsg_Code = TKEYC_DEL; break; case XK_BackSpace: imsg->timsg_Code = TKEYC_BCKSPC; break; case XK_ISO_Left_Tab: case XK_Tab: imsg->timsg_Code = TKEYC_TAB; break; case XK_Return: imsg->timsg_Code = TKEYC_RETURN; break; case XK_Help: imsg->timsg_Code = TKEYC_HELP; break; case XK_Insert: imsg->timsg_Code = TKEYC_INSERT; break; case XK_Page_Up: imsg->timsg_Code = TKEYC_PAGEUP; break; case XK_Page_Down: imsg->timsg_Code = TKEYC_PAGEDOWN; break; case XK_Home: imsg->timsg_Code = TKEYC_POSONE; break; case XK_End: imsg->timsg_Code = TKEYC_POSEND; break; case XK_Print: imsg->timsg_Code = TKEYC_PRINT; break; case XK_Scroll_Lock: imsg->timsg_Code = TKEYC_SCROLL; break; case XK_Pause: imsg->timsg_Code = TKEYC_PAUSE; break; case XK_KP_Enter: imsg->timsg_Code = TKEYC_RETURN; imsg->timsg_Qualifier |= TKEYQ_NUMBLOCK; break; case XK_KP_Decimal: imsg->timsg_Code = '.'; imsg->timsg_Qualifier |= TKEYQ_NUMBLOCK; break; case XK_KP_Add: imsg->timsg_Code = '+'; imsg->timsg_Qualifier |= TKEYQ_NUMBLOCK; break; case XK_KP_Subtract: imsg->timsg_Code = '-'; imsg->timsg_Qualifier |= TKEYQ_NUMBLOCK; break; case XK_KP_Multiply: imsg->timsg_Code = '*'; imsg->timsg_Qualifier |= TKEYQ_NUMBLOCK; break; case XK_KP_Divide: imsg->timsg_Code = '/'; imsg->timsg_Qualifier |= TKEYQ_NUMBLOCK; break; default: if (keysym > 31 && keysym <= 0x20ff) imsg->timsg_Code = keysym; else if (keysym >= 0x01000100 && keysym <= 0x0110ffff) imsg->timsg_Code = keysym - 0x01000000; else newkey = TFALSE; break; } } if (!newkey && newqual) { imsg->timsg_Code = TKEYC_NONE; newkey = TTRUE; } if (newkey) { ptrdiff_t len = (ptrdiff_t) utf8encode(imsg->timsg_KeyCode, imsg->timsg_Code) - (ptrdiff_t) imsg->timsg_KeyCode; imsg->timsg_KeyCode[len] = 0; TAddTail(&v->imsgqueue, &imsg->timsg_Node); } else { /* put back message: */ TAddTail(&mod->x11_imsgpool, &imsg->timsg_Node); } } return newkey; }
static TBOOL x11_processvisualevent(struct X11Display *mod, struct X11Window *v, TAPTR msgstate, XEvent *ev) { TAPTR TExecBase = TGetExecBase(mod); TIMSG *imsg; switch (ev->type) { case ClientMessage: if ((v->eventmask & TITYPE_CLOSE) && (Atom) ev->xclient.data.l[0] == v->atom_wm_delete_win) { if (x11_getimsg(mod, v, &imsg, TITYPE_CLOSE)) TAddTail(&v->imsgqueue, &imsg->timsg_Node); } break; case ConfigureNotify: if (mod->x11_RequestInProgress && (v->flags & X11WFL_WAIT_RESIZE)) { TReplyMsg(mod->x11_RequestInProgress); mod->x11_RequestInProgress = TNULL; v->flags &= ~X11WFL_WAIT_RESIZE; TDBPRINTF(TDB_INFO, ("Released request (ConfigureNotify)\n")); } v->winleft = ev->xconfigure.x; v->wintop = ev->xconfigure.y; if ((v->winwidth != ev->xconfigure.width || v->winheight != ev->xconfigure.height)) { v->flags |= X11WFL_WAIT_EXPOSE; v->winwidth = ev->xconfigure.width; v->winheight = ev->xconfigure.height; if (v->eventmask & TITYPE_NEWSIZE) { if (x11_getimsg(mod, v, &imsg, TITYPE_NEWSIZE)) { imsg->timsg_Width = v->winwidth; imsg->timsg_Height = v->winheight; TAddTail(&v->imsgqueue, &imsg->timsg_Node); } TDBPRINTF(TDB_TRACE, ("Configure: NEWSIZE: %d %d\n", v->winwidth, v->winheight)); } } break; case EnterNotify: case LeaveNotify: if (v->eventmask & TITYPE_MOUSEOVER) { if (x11_getimsg(mod, v, &imsg, TITYPE_MOUSEOVER)) { imsg->timsg_Code = (ev->type == EnterNotify); TAddTail(&v->imsgqueue, &imsg->timsg_Node); } } break; case MapNotify: if (mod->x11_RequestInProgress) { TReplyMsg(mod->x11_RequestInProgress); mod->x11_RequestInProgress = TNULL; v->flags |= X11WFL_WAIT_EXPOSE; TDBPRINTF(TDB_TRACE, ("Released request (MapNotify)\n")); } break; case Expose: if (v->flags & X11WFL_WAIT_EXPOSE) v->flags &= ~X11WFL_WAIT_EXPOSE; else if ((v->eventmask & TITYPE_REFRESH) && x11_getimsg(mod, v, &imsg, TITYPE_REFRESH)) { imsg->timsg_X = ev->xexpose.x; imsg->timsg_Y = ev->xexpose.y; imsg->timsg_Width = ev->xexpose.width; imsg->timsg_Height = ev->xexpose.height; TAddTail(&v->imsgqueue, &imsg->timsg_Node); TDBPRINTF(TDB_TRACE, ("Expose: REFRESH: %d %d %d %d\n", imsg->timsg_X, imsg->timsg_Y, imsg->timsg_Width, imsg->timsg_Height)); } break; case GraphicsExpose: if (mod->x11_CopyExposeHook) { TINT rect[4]; rect[0] = ev->xgraphicsexpose.x; rect[1] = ev->xgraphicsexpose.y; rect[2] = rect[0] + ev->xgraphicsexpose.width - 1; rect[3] = rect[1] + ev->xgraphicsexpose.height - 1; TCallHookPkt(mod->x11_CopyExposeHook, mod->x11_RequestInProgress->tvr_Op.CopyArea.Window, (TTAG) rect); } if (ev->xgraphicsexpose.count > 0) break; /* no more graphics expose events, fallthru: */ case NoExpose: if (mod->x11_RequestInProgress) { TReplyMsg(mod->x11_RequestInProgress); mod->x11_RequestInProgress = TNULL; mod->x11_CopyExposeHook = TNULL; TDBPRINTF(TDB_TRACE, ("Released request (NoExpose)\n")); } else TDBPRINTF(TDB_INFO, ("NoExpose: TITYPE_REFRESH not set\n")); break; case FocusIn: case FocusOut: mod->x11_KeyQual = 0; if (v->eventmask & TITYPE_FOCUS) { if (x11_getimsg(mod, v, &imsg, TITYPE_FOCUS)) { imsg->timsg_Code = (ev->type == FocusIn); TAddTail(&v->imsgqueue, &imsg->timsg_Node); } } break; case MotionNotify: { struct TNode *next, *node = mod->x11_vlist.tlh_Head.tln_Succ; x11_setmousepos(mod, v, ev->xmotion.x, ev->xmotion.y); v->mousex = mod->x11_ScreenMouseX - v->winleft; v->mousey = mod->x11_ScreenMouseY - v->wintop; for (; (next = node->tln_Succ); node = next) { struct X11Window *v = (struct X11Window *) node; if (v->eventmask & TITYPE_MOUSEMOVE && x11_getimsg(mod, v, &imsg, TITYPE_MOUSEMOVE)) TAddTail(&v->imsgqueue, &imsg->timsg_Node); } break; } case ButtonRelease: case ButtonPress: x11_setmousepos(mod, v, ev->xbutton.x, ev->xbutton.y); if (v->eventmask & TITYPE_MOUSEBUTTON) { if (x11_getimsg(mod, v, &imsg, TITYPE_MOUSEBUTTON)) { unsigned int button = ev->xbutton.button; if (ev->type == ButtonPress) { switch (button) { case Button1: imsg->timsg_Code = TMBCODE_LEFTDOWN; break; case Button2: imsg->timsg_Code = TMBCODE_MIDDLEDOWN; break; case Button3: imsg->timsg_Code = TMBCODE_RIGHTDOWN; break; case Button4: imsg->timsg_Code = TMBCODE_WHEELUP; break; case Button5: imsg->timsg_Code = TMBCODE_WHEELDOWN; break; } } else { switch (button) { case Button1: imsg->timsg_Code = TMBCODE_LEFTUP; break; case Button2: imsg->timsg_Code = TMBCODE_MIDDLEUP; break; case Button3: imsg->timsg_Code = TMBCODE_RIGHTUP; break; } } TAddTail(&v->imsgqueue, &imsg->timsg_Node); } } break; case KeyRelease: x11_processkey(mod, v, (XKeyEvent *) ev, TFALSE); break; case KeyPress: x11_processkey(mod, v, (XKeyEvent *) ev, TTRUE); break; case SelectionRequest: { XSelectionRequestEvent *req = (XSelectionRequestEvent *) ev; XEvent replyevent; XSelectionEvent *reply = &replyevent.xselection; memset(&replyevent, 0, sizeof replyevent); reply->type = SelectionNotify; reply->serial = ev->xany.send_event; reply->send_event = True; reply->display = req->display; reply->requestor = req->requestor; reply->selection = req->selection; reply->property = req->property; reply->target = None; reply->time = req->time; if (req->target == mod->x11_XA_TARGETS) { XChangeProperty(mod->x11_Display, req->requestor, req->property, XA_ATOM, 32, PropModeReplace, (unsigned char *) &mod->x11_XA_UTF8_STRING, 1); } else if (req->target == mod->x11_XA_UTF8_STRING) { XSelectionEvent *rcopy = TAlloc(TNULL, sizeof *reply); if (rcopy && x11_getimsg(mod, v, &imsg, TITYPE_REQSELECTION)) { *rcopy = *reply; imsg->timsg_Requestor = (TTAG) rcopy; imsg->timsg_Code = req->selection == mod->x11_XA_PRIMARY ? 2 : 1; TAddTail(&v->imsgqueue, &imsg->timsg_Node); break; } TFree(rcopy); } else reply->property = None; XSendEvent(mod->x11_Display, req->requestor, 0, NoEventMask, &replyevent); XSync(mod->x11_Display, False); break; } } return TFALSE; }
LOCAL void fb_openwindow(WINDISPLAY *mod, struct TVRequest *req) { struct TExecBase *TExecBase = TGetExecBase(mod); TTAGITEM *tags = req->tvr_Op.OpenWindow.Tags; WINWINDOW *win; req->tvr_Op.OpenWindow.Window = TNULL; for (;;) { RECT wrect; BITMAPINFOHEADER *bmi; TUINT style; TUINT exstyle; TIMSG *imsg; const char *classname; TSTRPTR title; win = TAlloc0(mod->fbd_MemMgr, sizeof(WINWINDOW)); if (win == TNULL) break; TInitList(&win->penlist); InitializeCriticalSection(&win->fbv_LockExtents); win->fbv_Width = (TUINT) TGetTag(tags, TVisual_Width, FB_DEF_WIDTH); win->fbv_Height = (TUINT) TGetTag(tags, TVisual_Height, FB_DEF_HEIGHT); win->fbv_Left = (TUINT) TGetTag(tags, TVisual_WinLeft, 0xffffffff); win->fbv_Top = (TUINT) TGetTag(tags, TVisual_WinTop, 0xffffffff); win->fbv_Title = (TSTRPTR) TGetTag(tags, TVisual_Title, (TTAG) "TEKlib Visual"); win->fbv_Borderless = TGetTag(tags, TVisual_Borderless, TFALSE); win->fbv_UserData = TGetTag(tags, TVisual_UserData, TNULL); win->fbv_MinWidth = (TINT) TGetTag(tags, TVisual_MinWidth, (TTAG) -1); win->fbv_MinHeight = (TINT) TGetTag(tags, TVisual_MinHeight, (TTAG) -1); win->fbv_MaxWidth = (TINT) TGetTag(tags, TVisual_MaxWidth, (TTAG) -1); win->fbv_MaxHeight = (TINT) TGetTag(tags, TVisual_MaxHeight, (TTAG) -1); if (win->fbv_Borderless) { style = (WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS) & ~WS_BORDER; classname = FB_DISPLAY_CLASSNAME_POPUP; title = NULL; exstyle = WS_EX_TOPMOST | WS_EX_TOOLWINDOW; } else { style = WS_OVERLAPPEDWINDOW; classname = FB_DISPLAY_CLASSNAME; title = win->fbv_Title; exstyle = 0; } wrect.left = wrect.right = wrect.top = wrect.bottom = 0; AdjustWindowRectEx(&wrect, style, FALSE, exstyle); win->fbv_BorderWidth = wrect.right - wrect.left; win->fbv_BorderHeight = wrect.bottom - wrect.top; win->fbv_BorderLeft = -wrect.left; win->fbv_BorderTop = -wrect.top; if (!win->fbv_Borderless) { TINT m1, m2, m3, m4; win_getminmax(win, &m1, &m2, &m3, &m4, TTRUE); win->fbv_Width = TCLAMP(m1, (TINT) win->fbv_Width, m3); win->fbv_Height = TCLAMP(m2, (TINT) win->fbv_Height, m4); } if (win->fbv_Left != 0xffffffff && win->fbv_Top != 0xffffffff) { wrect.left = win->fbv_Left; wrect.top = win->fbv_Top; wrect.right = win->fbv_Left + win->fbv_Width; wrect.bottom = win->fbv_Top + win->fbv_Height; if (!AdjustWindowRectEx(&wrect, style, FALSE, exstyle)) break; win->fbv_Left = wrect.left; win->fbv_Top = wrect.top; win->fbv_HWnd = CreateWindowEx(exstyle, classname, title, style, win->fbv_Left, win->fbv_Top, wrect.right - wrect.left - win->fbv_BorderWidth, wrect.bottom - wrect.top - win->fbv_BorderHeight, (HWND) NULL, (HMENU) NULL, mod->fbd_HInst, (LPVOID) NULL); } else { win->fbv_HWnd = CreateWindowEx(exstyle, classname, title, style, CW_USEDEFAULT, CW_USEDEFAULT, win->fbv_Width, win->fbv_Height, (HWND) NULL, (HMENU) NULL, mod->fbd_HInst, (LPVOID) NULL); } if (win->fbv_HWnd == TNULL) break; GetWindowRect(win->fbv_HWnd, &wrect); win->fbv_Left = wrect.left + win->fbv_BorderLeft; win->fbv_Top = wrect.top + win->fbv_BorderHeight; win->fbv_Width = wrect.right - wrect.left - win->fbv_BorderWidth; win->fbv_Height = wrect.bottom - wrect.top - win->fbv_BorderHeight; SetWindowLongPtr(win->fbv_HWnd, GWLP_USERDATA, (LONG_PTR) win); win->fbv_HDC = GetDC(win->fbv_HWnd); win->fbv_Display = mod; win->fbv_InputMask = (TUINT) TGetTag(tags, TVisual_EventMask, 0); win->fbv_IMsgPort = req->tvr_Op.OpenWindow.IMsgPort; bmi = &win->fbv_DrawBitMap; bmi->biSize = sizeof(BITMAPINFOHEADER); bmi->biPlanes = 1; bmi->biBitCount = 32; bmi->biCompression = BI_RGB; bmi->biSizeImage = 0; bmi->biXPelsPerMeter = 1; bmi->biYPelsPerMeter = 1; bmi->biClrUsed = 0; bmi->biClrImportant = 0; TInitList(&win->fbv_IMsgQueue); req->tvr_Op.OpenWindow.Window = win; /* init default font */ win->fbv_CurrentFont = mod->fbd_FontManager.deffont; mod->fbd_FontManager.defref++; if (win->fbv_InputMask & TITYPE_INTERVAL) ++mod->fbd_NumInterval; /* register default font */ /*TDBPRINTF(TDB_TRACE,("Add window: %p\n", win->window));*/ /* add window on top of window stack: */ TAddHead(&mod->fbd_VisualList, &win->fbv_Node); SetBkMode(win->fbv_HDC, TRANSPARENT); ShowWindow(win->fbv_HWnd, SW_SHOWNORMAL); UpdateWindow(win->fbv_HWnd); if ((win->fbv_InputMask & TITYPE_FOCUS) && (fb_getimsg(mod, win, &imsg, TITYPE_FOCUS))) { imsg->timsg_Code = 1; TAddTail(&win->fbv_IMsgQueue, &imsg->timsg_Node); } if ((win->fbv_InputMask & TITYPE_REFRESH) && (fb_getimsg(mod, win, &imsg, TITYPE_REFRESH))) { imsg->timsg_X = 0; imsg->timsg_Y = 0; imsg->timsg_Width = win->fbv_Width; imsg->timsg_Height = win->fbv_Height; TAddTail(&win->fbv_IMsgQueue, &imsg->timsg_Node); } return; } TDBPRINTF(TDB_ERROR,("Window open failed\n")); fb_closeall(mod, win, TFALSE); }
static int CALLBACK fontenumcb( ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme, int fonttype, LPARAM param) { LOGFONT *lf = &lpelfe->elfLogFont; TSTRPTR fullname = (TSTRPTR) lpelfe->elfFullName; TSTRPTR style = (TSTRPTR) lpelfe->elfStyle; TSTRPTR script = (TSTRPTR) lpelfe->elfScript; struct FontQueryHandle *fqh = (struct FontQueryHandle *) param; WINDISPLAY *mod = fqh->handle.thn_Owner; struct TExecBase *TExecBase = TGetExecBase(mod); struct FontQueryNode *fqn; if (fqh->match_depth == 0) { LOGFONT logfont; memcpy(&logfont, lf, sizeof(LOGFONT)); fqh->match_depth = 1; TDBPRINTF(TDB_INFO,("fontenum - entering recursion\n")); logfont.lfCharSet = ANSI_CHARSET; logfont.lfPitchAndFamily = 0; EnumFontFamiliesEx( mod->fbd_DeviceHDC, &logfont, (FONTENUMPROCA) fontenumcb, (LPARAM) fqh, 0); fqh->match_depth = 0; return TTRUE; } if (fqh->fscale && !(fonttype & TRUETYPE_FONTTYPE)) return TTRUE; if (fqh->fitalic && !lf->lfItalic) return TTRUE; if (fqh->fbold && (lf->lfWeight < FW_BOLD)) return TTRUE; TDBPRINTF(TDB_INFO,("entry:'%s' style:'%s' script:'%s' type:%04x weight:%d italic:%d recurs:%d, size:%d\n", fullname, style, script, fonttype, lf->lfWeight, !!lf->lfItalic, fqh->match_depth, lf->lfHeight)); fqn = TAlloc(TNULL, sizeof(struct FontQueryNode) + strlen(fullname) + 1); if (fqn == TNULL) return TFALSE; strcpy((char *) (fqn + 1), fullname); fqn->tags[0].tti_Tag = TVisual_FontName; fqn->tags[0].tti_Value = (TTAG) (fqn + 1); fqn->tags[1].tti_Tag = TVisual_FontItalic; fqn->tags[1].tti_Value = !!lf->lfItalic; fqn->tags[2].tti_Tag = TVisual_FontBold; fqn->tags[2].tti_Value = (lf->lfWeight >= FW_BOLD); fqn->tags[3].tti_Tag = TTAG_DONE; TAddTail(&fqh->reslist, &fqn->node); return TTRUE; }
static void hostqueryfonts(DFBDISPLAY *mod, struct FontQueryHandle *fqh, struct fnt_attr *fattr) { TINT i, nfont, fcount = 0; struct TNode *node, *next; TAPTR exec = TGetExecBase(mod); struct dirent **dirlist; TUINT matchflg = 0; /* scan default font directory */ nfont = scandir(FNT_DEFDIR, &dirlist, 0, alphasort); if (nfont < 0) { perror("scandir"); return; } if (nfont > 0) { /* found fonts in default font directory */ for (node = fattr->fnlist.tlh_Head; (next = node->tln_Succ); node = next) { struct fnt_node *fnn = (struct fnt_node *)node; /* build matchflag, font pxsize attribute is ignored, because it's not relevant when matching ttf fonts */ matchflg = FNT_MATCH_NAME; /* not yet if (fattr->fitalic != FNTQUERY_UNDEFINED) matchflg |= FNT_MATCH_SLANT; if (fattr->fbold != FNTQUERY_UNDEFINED) matchflg |= FNT_MATCH_WEIGHT; */ for (i = 0; i < nfont; i++) { if (fnt_matchfont(mod, dirlist[i]->d_name, fnn->fname, fattr, matchflg) == matchflg) { struct FontQueryNode *fqnode; /* create fqnode and fill in attributes */ fqnode = fnt_getfqnode(mod, dirlist[i]->d_name, fattr->fpxsize); if (!fqnode) break; /* compare fqnode with nodes in result list */ if (fnt_checkfqnode(&fqh->reslist, fqnode) == 0) { if (fcount < fattr->fnum) { /* fqnode is unique, add to result list */ TAddTail(&fqh->reslist, &fqnode->node); fcount++; } else { /* max count of desired results reached */ TExecFree(exec, (TSTRPTR)fqnode->tags[0].tti_Value); TExecFree(exec, fqnode); break; } } else { /* fqnode is not unique, destroy it */ TDBPRINTF(TDB_ERROR,("X node is not unique\n")); TExecFree(exec, (TSTRPTR)fqnode->tags[0].tti_Value); TExecFree(exec, fqnode); } } } if (fcount == fattr->fnum) break; } /* end of fnlist iteration */ } /* endif fonts found */ else TDBPRINTF(TDB_WARN,("X no fonts found in '%s'\n", FNT_DEFDIR)); while (nfont--) free(dirlist[nfont]); free(dirlist); }
EXPORT void hal_beginio(struct THALBase *hal, struct TTimeRequest *req) { struct HALSpecific *hws = hal->hmb_Specific; TAPTR exec = hws->hsp_ExecBase; TTIME curtime; TINT64 x = 0; switch (req->ttr_Req.io_Command) { /* execute asynchronously */ case TTREQ_WAITLOCALDATE: /* microseconds west of GMT: */ x = hal_getdstfromlocaldate(hal, &req->ttr_Data.ttr_Date); x *= 1000000; case TTREQ_WAITUNIVERSALDATE: x += req->ttr_Data.ttr_Date.tdt_Int64; x -= 11644473600000000ULL; req->ttr_Data.ttr_Date.tdt_Int64 = x; #ifndef USE_MMTIMER hal_getsystime(hal, &curtime); TSubTime(&req->ttr_Data.ttr_Time, &curtime); #endif goto addtimereq; case TTREQ_WAITTIME: #ifdef USE_MMTIMER hal_getsystime(hal, &curtime); TAddTime(&req->ttr_Data.ttr_Time, &curtime); #endif addtimereq: { #ifdef USE_MMTIMER struct TMessage *msg = TGETMSGPTR(req); EnterCriticalSection(&hws->hsp_DevLock); msg->tmsg_Flags = TMSG_STATUS_SENT | TMSGF_QUEUED; msg->tmsg_RPort = req->ttr_Req.io_ReplyPort; TAddTail(&hws->hsp_ReqList, (struct TNode *) req); LeaveCriticalSection(&hws->hsp_DevLock); #else TExecPutMsg(exec, TExecGetUserPort(exec, hws->hsp_DevTask), req->ttr_Req.io_ReplyPort, req); #endif return; } /* execute synchronously */ default: case TTREQ_GETUNIVERSALDATE: { TINT timezone_bias; hal_getsysdate(hal, &req->ttr_Data.ttr_Date, &timezone_bias); break; } case TTREQ_GETLOCALDATE: hal_getsysdate(hal, &req->ttr_Data.ttr_Date, TNULL); break; case TTREQ_GETSYSTEMTIME: hal_getsystime(hal, &req->ttr_Data.ttr_Time); break; #if 0 case TTREQ_GETDSFROMDATE: req->ttr_Data.ttr_DSSec = hal_dsfromdate(hal, &req->ttr_Data.ttr_Date.ttr_Date); break; #endif } req->ttr_Req.io_Error = 0; if (!(req->ttr_Req.io_Flags & TIOF_QUICK)) { /* async operation indicated; reply to self */ TExecReplyMsg(exec, req); } }
LOCAL TBOOL fbp_copyarea_int(struct rfb_Display *mod, struct rfb_Window *v, TINT dx, TINT dy, TINT *dr) { struct RectPool *pool = &mod->rfb_RectPool; struct Region R; if (!rfb_getlayermask(mod, &R, dr, v, 0, 0)) return TFALSE; if (R.rg_Rects.rl_NumNodes == 0) { region_free(pool, &R); return TFALSE; } TINT yinc = dy < 0 ? -1 : 1; TINT y, i, h; TINT dy0 = dr[1]; TINT dy1 = dr[3]; h = dy1 - dy0 + 1; if (yinc > 0) { TINT t = dy0; dy0 = dy1; dy1 = t; } TINT bpp = TVPIXFMT_BYTES_PER_PIXEL(v->rfbw_PixBuf.tpb_Format); if (R.rg_Rects.rl_NumNodes == 1) { /* optimization for a single rectangle */ struct RectNode *rn = (struct RectNode *) TFIRSTNODE(&R.rg_Rects.rl_List); TINT x0 = rn->rn_Rect[0]; TINT y0 = rn->rn_Rect[1]; TINT x1 = rn->rn_Rect[2]; TINT y1 = rn->rn_Rect[3]; h = y1 - y0 + 1; dy0 = y0; dy1 = y1; if (yinc > 0) { TINT t = dy0; dy0 = dy1; dy1 = t; } #if defined(ENABLE_VNCSERVER) if (mod->rfb_VNCTask && !(v->rfbw_Flags & RFBWFL_BACKBUFFER)) rfb_vnc_copyrect(mod, v, dx, dy, x0, y0, x1, y1, yinc); else #endif { /* update own buffer */ for (i = 0, y = dy0; i < h; ++i, y -= yinc) CopyLineOver(v, x0 - dx, y - dy, x0, y, (x1 - x0 + 1) * bpp); } /* update sub device */ TINT d[4]; d[0] = rn->rn_Rect[0]; d[1] = rn->rn_Rect[1]; d[2] = rn->rn_Rect[2]; d[3] = rn->rn_Rect[3]; if (v->rfbw_Flags & RFBWFL_BACKBUFFER) rfb_markdirty(mod, v, d); else rfb_copyrect_sub(mod, d, dx, dy); } else { struct TNode *n; struct TList r, t; TInitList(&r); TInitList(&t); while ((n = TRemHead(&R.rg_Rects.rl_List))) TAddTail(&r, n); for (i = 0, y = dy0; i < h; ++i, y -= yinc) { struct TNode *rnext, *rnode = r.tlh_Head.tln_Succ; for (; (rnext = rnode->tln_Succ); rnode = rnext) { struct RectNode *rn = (struct RectNode *) rnode; if (y >= rn->rn_Rect[1] && y <= rn->rn_Rect[3]) { struct TNode *prednode = TNULL; struct TNode *tnext, *tnode = t.tlh_Head.tln_Succ; for (; (tnext = tnode->tln_Succ); tnode = tnext) { struct RectNode *tn = (struct RectNode *) tnode; if (rn->rn_Rect[2] < tn->rn_Rect[0]) break; prednode = tnode; } TRemove(rnode); TInsert(&t, rnode, prednode); /* insert after prednode */ } } while (!TISLISTEMPTY(&t)) { TINT x0, x1; if (dx < 0) { struct RectNode *E = (struct RectNode *) TRemHead(&t); x0 = E->rn_Rect[0]; x1 = E->rn_Rect[2]; TAddTail(&r, &E->rn_Node); while (!TISLISTEMPTY(&t)) { struct RectNode *N = (struct RectNode *) TFIRSTNODE(&t); if (N->rn_Rect[0] == x1 + 1) { x1 = N->rn_Rect[2]; TAddTail(&r, TRemHead(&t)); continue; } break; } } else { struct RectNode *E = (struct RectNode *) TRemTail(&t); x0 = E->rn_Rect[0]; x1 = E->rn_Rect[2]; TAddTail(&r, &E->rn_Node); while (!TISLISTEMPTY(&t)) { struct RectNode *N = (struct RectNode *) TLASTNODE(&t); if (N->rn_Rect[2] == x0 - 1) { x0 = N->rn_Rect[0]; TAddTail(&r, TRemTail(&t)); continue; } break; } } CopyLineOver(v, x0 - dx, y - dy, x0, y, (x1 - x0 + 1) * bpp); } } while ((n = TRemHead(&r))) { struct RectNode *rn = (struct RectNode *) n; /* this would be incorrect, unfortunately: */ /* rfb_copyrect_sub(mod, rn->rn_Rect, dx, dy); */ rfb_markdirty(mod, v, rn->rn_Rect); TAddTail(&R.rg_Rects.rl_List, n); } } region_free(pool, &R); return TTRUE; /* do expose */ }