📄 overlap.c
字号:
/*
COW : Character Oriented Windows
overlap.c : Overlapping Window Support
*/
#define COW
#include <cow.h>
#define WINDOW
#include <uwindow.h>
#include <uevent.h>
#include <umenu.h>
#include <uisa.h>
#include <uscreen.h>
#include <vkey.h>
#include <kkeyboar.h>
#include <kinput.h>
#include "event.h"
#include "screen.h"
#include "util.h"
#include "dialog.h"
#include "window.h"
#include "shadow.h"
#include "overlap.h"
#ifdef WINDOW_OVERLAP /* entire file */
extern void MemSetW(WORD, WORD, WORD, WORD);
extern PWND pwndClip;
/* forward */
STATIC VOID ThinkWindowAndSiblings(PWND);
STATIC BOOL FAllocDragSave(void);
STATIC VOID InitDragRrc(PWND);
STATIC VOID SaveDragRrc(void);
STATIC VOID RestoreDragRrc(void);
STATIC VOID DisplayDrag(void);
STATIC VOID EndDrag(void);
STATIC BOOL FAdjustDragRrc(int *, int *);
PRIVATE BOOL fDragging = FALSE; /* am moving a window */
PRIVATE OWDS owds; /* current window drag status */
/* is valid only if fDragging == TRUE */
/*
-- OWDF's contain the overlapping window drag flags
-- rgowdf contains the initial settings for when a mouse clicks
on the window.
-- owdfKeyboardMove/Size contain the initial settings for keyboard
moves and sizes
-- format: { fMouse, fButton, fOutline, fXDrag, fYDrag, fEscapeMove, message}
*/
PRIVATE OWDF rgowdf[] =
{
{ 1, 1, 0, 0, 0, 0, WM_CLOSE }, /* top left corner */
{ 1, 0, 1, 0, 0, 0, WM_MOVE }, /* top side */
{ 1, 1, 0, 0, 0, 0, WM_ZOOM }, /* top right corner */
{ 1, 0, 1, 0, 0, 0, WM_MOVE }, /* left side */
{ 0, 0, 0, 0, 0, 0, 0 }, /* middle */
{ 1, 0, 1, 1, 0, 0, WM_SIZE }, /* right side */
{ 1, 0, 1, 0, 0, 0, WM_MOVE }, /* bottom left corner */
{ 1, 0, 1, 0, 1, 0, WM_SIZE }, /* bottom side */
{ 1, 0, 1, 1, 1, 0, WM_SIZE } /* bottom right corner */
};
PRIVATE OWDF owdfKeyboardMove = { 0, 0, 1, 0, 0, 0, WM_MOVE };
PRIVATE OWDF owdfKeyboardSize = { 0, 0, 1, 1, 1, 0, WM_SIZE };
PRIVATE PWND pwndCur; /* current drawing window */
PRIVATE WORD psOverlap; /* overlapping window table */
VOID FARPUBLIC
AddChildHead(pwndParent, pwndChild)
/*
-- add child to head of child list
*/
PWND pwndParent, pwndChild;
{
StartPublic();
Assert(pwndParent != NULL && pwndChild != NULL);
pwndChild->pwndSibling = pwndParent->pwndChild;
pwndChild->pwndParent = pwndParent;
pwndParent->pwndChild = pwndChild;
if (pwndParent->style & WS_CLIPOUT)
{
pwndChild->style |= WS_CLIPOUT;
ClipoutWindowAndSiblings(pwndChild->pwndChild);
}
StopPublic();
}
VOID FARPRIVATE
ClipoutWindowAndSiblings(pwnd)
/*
-- pwnd inherits the clipout type along with its children
*/
PWND pwnd;
{
while (pwnd != NULL)
{
pwnd->style |= WS_CLIPOUT;
ClipoutWindowAndSiblings(pwnd->pwndChild);
pwnd = pwnd->pwndSibling;
}
}
BOOL FARPUBLIC
FIsTopWindow(pwnd)
PWND pwnd;
{
StartPublic();
ReturnPublic(pwnd->pwndSibling == NULL, BOOL);
}
PWND FARPUBLIC
PwndGetTopWindow(pwnd)
PWND pwnd;
{
StartPublic();
while (pwnd->pwndSibling != NULL)
pwnd = pwnd->pwndSibling;
ReturnPublic(pwnd, PWND);
}
VOID FARPUBLIC
AddChildTail(pwndParent, pwndChild)
PWND pwndParent, pwndChild;
/*
-- add child to tail of child list
*/
{
StartPublic();
PWND pwndCur, pwndPrev;
Assert(pwndParent != NULL && pwndChild != NULL);
if ((pwndPrev = pwndParent->pwndChild) == NULL)
pwndParent->pwndChild = pwndChild;
else
{
while ((pwndCur = pwndPrev->pwndSibling) != NULL)
pwndPrev = pwndCur;
pwndPrev->pwndSibling = pwndChild;
}
pwndChild->pwndParent = pwndParent;
if (pwndParent->style & WS_CLIPOUT)
{
pwndChild->style |= WS_CLIPOUT;
ClipoutWindowAndSiblings(pwndChild->pwndChild);
}
StopPublic();
}
VOID FARPRIVATE
DrawThisWndProc(pwnd)
REGISTER PWND pwnd;
/*
-- sets the current window for clipping purposes
-- NULL means no overlap clipping
*/
{
if (!(pwnd->style & WS_CLIPOUT) || !(psOverlap))
{
/* window isn't clipout type or there is no overlap table */
pwndCur = NULL;
return;
}
pwndCur = pwnd;
}
STATIC VOID
ThinkWindowAndSiblings(pwnd)
REGISTER PWND pwnd;
/*
-- fills the overlap table for pwnd and its children
-- the overlap table is an array that maps screen positions onto the
window that is in the foreground at a given position
-- this is accomplished by walking through the tree and filling the
table for each window. hence the window that is lower in the
tree has higher priority and overwrites window that are higher.
*/
{
while (pwnd != NULL)
{
WORD off; /* pointer to array position */
AY ay;
ARC arc;
WORD cwRow; /* Count of words in each row */
if ((pwnd->pwndParent != NULL) && (pwnd->style & WS_CLIPOUT))
{
if ((pwnd->style & WS_TYPE) == WS_SCROLL)
{
Assert(pwnd->pwndParent->pwndParent != NULL);
IntersectRect((PRRC) &arc,
(PRRC) &pwnd->arcWindow, (PRRC)
&pwnd->pwndParent->pwndParent->arcClipping);
}
else
{
IntersectRect((PRRC) &arc,
(PRRC) &pwnd->arcWindow,
(PRRC) &pwnd->pwndParent->arcClipping);
}
}
else
arc = pwnd->arcWindow;
off = (arc.ayTop * axMac + arc.axLeft) * sizeof(PWND);
cwRow = arc.axRight - arc.axLeft;
if (cwRow != 0)
{
/* Now simply work through each row */
for (ay = arc.ayTop; ay < arc.ayBottom; ay++)
{
Assert(sizeof(PWND) == sizeof(WORD));
/* otherwise this won't work */
MemSetW(psOverlap, off,(WORD)pwnd,cwRow);
off += axMac * sizeof(PWND);
}
}
ThinkWindowAndSiblings(pwnd->pwndChild);
pwnd = pwnd->pwndSibling;
}
}
VOID FARPUBLIC
RethinkDisplay()
/*
-- recalculate overlap table
*/
{
StartPublic();
/* first fill in base windows */
if (psOverlap != 0)
MemSetW(psOverlap, 0, NULL, axMac * ayMac);
ThinkWindowAndSiblings(pwndRoot);
StopPublic();
}
VOID FARPUBLIC
RedrawDamagedRegions()
/*
-- This function will redraw only the damaged regions of the screen
-- Especially after a window has been moved/Deleted/ etc.
*/
{
StartPublic();
#ifdef LATER
-- Put optimizer in here
#endif /* LATER */
RethinkDisplay(); /* For now just rethink display on draw */
DrawWindow(NULL); /* All windows */
StopPublic();
}
VOID FARPUBLIC
DrawOverlapShadow(pwnd)
PWND pwnd;
/*
-- does a shadow for an overlapping window
*/
{
StartPublic();
AX daxShadowSave = daxShadow;
Assert(pwnd->pwndParent != NULL);
pwndClip = pwnd->pwndParent;
DrawThisWnd(pwnd->pwndParent);
ShadowArc(&pwnd->arcWindow);
daxShadow /= 2;
DrawThisWnd(NULL);
ShadowArc(&pwnd->arcWindow);
daxShadow = daxShadowSave;
pwndClip = NULL;
StopPublic();
}
BOOL FARPUBLIC
FWindowToTop(pwnd)
PWND pwnd;
/*
-- bring window to tail of child list
*/
{
StartPublic();
PWND pwndParent = pwnd->pwndParent;
PWND pwndOldTop = PwndGetTopWindow(pwnd);
Assert(pwndParent != NULL && pwnd != NULL);
if(SendMessage( pwndOldTop, WM_ACTIVATE, FALSE, 0L))
{
if(SendMessage(pwnd, WM_ACTIVATE, TRUE, 0L))
{
RemoveChild(pwnd);
AddChildTail(pwndParent, pwnd);
ThinkWindowAndSiblings(pwndOldTop);
DrawWindow(pwndOldTop);
DrawWindow(pwnd);
UpdateCursor();
ReturnPublic(TRUE,BOOL);
}
}
ReturnPublic(FALSE,BOOL);
}
BOOL FARPUBLIC
FMoveSizeWithKeyboard(pwnd,fMove)
PWND pwnd;
BOOL fMove; /* true move false size */
/*
-- Moves or sizes the window with the cursor
*/
{
StartPublic();
MSG msg;
PWND pwndRootOld = pwndRoot;
PWND pwndFocusOld = pwndFocus;
PWND pwndCaptureOld = pwndCapture;
PFFN_FILTER pfnFilterOld = pfnFilter;
AssertSz(((pwnd->style & WS_CLIPOUT) && (pwnd->style & WS_OVERLAP)),
"can only move overlap windows");
Assert(!fDragging);
if (!FIsTopWindow(pwnd))
{
if (!FWindowToTop(pwnd))
ReturnPublic(FALSE,BOOL);
}
if (fMove)
owds.owdf = owdfKeyboardMove;
else
owds.owdf = owdfKeyboardSize;
owds.pwndMoving = pwnd;
owds.pwndBackground = pwnd->pwndParent;
if (!FAllocDragSave()) ReturnPublic(FALSE,BOOL);
InitDragRrc(pwnd);
fDragging = TRUE; /* we are dragging and owds is valid */
SaveDragRrc();
DisplayDrag();
pfnFilter = DummyFilter;
pwndRoot = NULL; /* set stuff to null so mouse input
doesn't muck us up */
pwndFocus = NULL;
pwndCapture = NULL;
UpdateCursor();
/* we don't return control to the application until we're
done dragging */
while(fDragging)
{
PollKeyboard();
while (PeekMessage(&msg))
DispatchMessage(&msg);
}
pfnFilter = pfnFilterOld;
pwndRoot = pwndRootOld;
pwndFocus = pwndFocusOld;
pwndCapture = pwndCaptureOld;
EndDrag();
if (owds.owdf.fEscapeMove)
{
owds.owdf.fEscapeMove = 0;
ReturnPublic(FALSE,BOOL);
}
UpdateCursor();
ReturnPublic(TRUE,BOOL);
}
BOOL PASCAL
OverlapFilter(pmsg)
PMSG pmsg;
/*
-- Does handling for overlapping windows
*/
{
AX ax; /* The Abs position of event */
AY ay; /* The Abs position of event */
short iZoneX,iZoneY; /* Location inside the window */
PWND pwnd = pmsg->pwnd;
ax = LOBYTE(HIWORD(pmsg->lParam)); /* Get x, y position */
ay = HIBYTE (HIWORD(pmsg->lParam));
switch (pmsg->message)
{
case WM_LBUTTONDOWN:
if (fDragging)
return(FALSE);
if (!(pwnd->style & WS_CLIPOUT))
return(FALSE);
/*
* find the overlapping window that we have
* clicked upon and then bring it to the top
* if it is not already there
*/
{
PWND pwndNewTop;
pwndNewTop = pwnd;
while (!(pwndNewTop->style & WS_OVERLAP)
&&(pwndNewTop != NULL))
pwndNewTop = pwndNewTop->pwndParent;
if ((pwndNewTop == NULL) || (!pwndNewTop->fEnabled))
return(FALSE);
if (!FIsTopWindow(pwndNewTop))
{
if (!FWindowToTop(pwndNewTop)) return(FALSE);
}
}
if (!(pwnd->style & WS_OVERLAP))
return(FALSE);
/* (iZoneY * 3 + iZoneX) yields:
* 0 - Top left corner * 1 - Top side
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -