📄 window.c
字号:
/*
COW : Character Oriented Windows
window.c : Window Support
This module contains the window relative output routines
as well as routines for accessing and changing the window
data structure.
*/
#define COW
#include <cow.h>
#define WINDOW
#include <uwindow.h>
#include <uevent.h>
#include <umenu.h>
#include <uscreen.h>
#include <uisa.h>
#include "event.h"
#include "screen.h"
#include "util.h"
#include "overlap.h"
#include "window.h"
#ifdef EXTRAS
#define chColorPrefix ((char) 0xfe) /* => special color prefix */
#endif
STATIC WORD fBlockCursor = 1; /* see SetCursorBlock() */
#ifdef WINDOW_OVERLAP
extern PWND pwndClip;
#endif /*WINDOW_OVERLAP*/
/* forward declarations for STATIC procedures */
STATIC VOID EnableWindowAndSiblings(PWND, BOOL);
STATIC VOID DrawWindowAndSiblings(PWND);
STATIC VOID TextOutColor(AX, AY, char *, WORD, WORD);
#ifdef WINDOW_OVERLAP
STATIC VOID MoveWindowAndSiblings(PWND, BYTE, BYTE);
STATIC VOID ValidateAWindow(PWND);
STATIC VOID ValidateWindowAndSiblings(PWND);
STATIC VOID ValidateWindowAndParents(PWND);
STATIC VOID MoveCursorClipped(PWND);
#endif /*WINDOW_OVERLAP*/
PUBLIC VOID FARPUBLIC
AddChild(pwndParent, pwndChild)
PWND pwndParent, pwndChild;
/* AddChild adds a child to the specified window. If pwndParent is
null then a child is added to the root directory. Child is added
to the end of the sibling chain. */
{
StartPublic();
PWND pwndCur, pwndPrev;
if (pwndParent)
{
if ((pwndPrev = pwndParent->pwndChild) == NULL)
pwndParent->pwndChild = pwndChild;
else
{
while ((pwndCur = pwndPrev->pwndSibling) != NULL)
pwndPrev = pwndCur;
pwndPrev->pwndSibling = pwndChild;
}
pwndChild->pwndSibling = NULL;
EnableWindow(pwndChild, pwndParent->fEnabled);
#ifdef WINDOW_OVERLAP
if (pwndParent->style & WS_CLIPOUT)
{
pwndChild->style |= WS_CLIPOUT;
ClipoutWindowAndSiblings(pwndChild->pwndChild);
}
#endif /*WINDOW_OVERLAP*/
}
else
{
pwndChild->pwndSibling = pwndRoot;
pwndRoot = pwndChild;
EnableWindow(pwndChild, TRUE);
}
pwndChild->pwndParent = pwndParent;
StopPublic();
}
PUBLIC VOID FARPUBLIC
EnableWindow(pwnd, fEnabled)
PWND pwnd;
BOOL fEnabled;
/* Enable or disable a window. All children are enabled or disabled as well */
{
StartPublic();
pwnd->fEnabled = (fEnabled != FALSE);
EnableWindowAndSiblings(pwnd->pwndChild, fEnabled);
StopPublic();
}
STATIC VOID
EnableWindowAndSiblings(pwnd, fEnabled)
REGISTER PWND pwnd;
BOOL fEnabled;
{
while (pwnd)
{
pwnd->fEnabled = (fEnabled != FALSE);
EnableWindowAndSiblings(pwnd->pwndChild, fEnabled);
pwnd = pwnd->pwndSibling;
}
}
PUBLIC VOID FARPUBLIC
RemoveChild(pwndChild)
/*
-- removes a child from its parent window
-- special case allows removal of root windows
*/
REGISTER PWND pwndChild;
{
StartPublic();
PWND pwndParent = pwndChild->pwndParent;
REGISTER PWND pwnd;
AssertSz(pwndChild, "RemoveChild(NULL)");
if (pwndParent == NULL)
{
/* should be a root window */
if (pwndChild == pwndRoot)
{
/* remove first root */
pwndRoot = pwndChild->pwndSibling;
}
else
{
pwnd = pwndRoot;
goto scan_sibling;
}
}
else if ((pwnd = pwndParent->pwndChild) == pwndChild)
{
/* remove first child */
pwndParent->pwndChild = pwndChild->pwndSibling;
}
else
{
scan_sibling:
while (pwnd->pwndSibling != pwndChild)
{
pwnd = pwnd->pwndSibling;
AssertSz(pwnd != NULL, "child window not found");
}
pwnd->pwndSibling = pwndChild->pwndSibling;
}
pwndChild->pwndParent = NULL;
pwndChild->pwndSibling = NULL;
StopPublic();
}
PUBLIC VOID FARPUBLIC
GetClientRrc(pwnd, prrc)
/*
-- create a rectangle that composes the entire clent area.
-- Note that the top left hand corner of the client rrc is
always 0,0 since all output is relative to this point.
*/
REGISTER PWND pwnd;
REGISTER PRRC prrc;
{
StartPublic();
prrc->ryTop = 0;
prrc->rxLeft = 0;
prrc->ryBottom = (pwnd->arcWindow.ayBottom)-(pwnd->arcWindow.ayTop);
prrc->rxRight = (pwnd->arcWindow.axRight)-(pwnd->arcWindow.axLeft);
if (pwnd->style & WS_BORDER)
{
/* border around window */
prrc->ryBottom -= 2 * dayBorder;
prrc->rxRight -= 2 * daxBorder;
#ifdef WINDOW_OVERLAP
if (pwnd->style & WS_OVERLAP)
{
if (pwnd->style & WS_HSCROLL)
prrc->ryBottom -= dayBorder;
if (pwnd->style & WS_VSCROLL)
prrc->rxRight -= daxBorder;
}
#endif /*WINDOW_OVERLAP*/
}
else
{
if (pwnd->style & WS_HSCROLL)
prrc->ryBottom -= dayBorder;
if (pwnd->style & WS_VSCROLL)
prrc->rxRight -= daxBorder;
}
StopPublic();
}
PUBLIC VOID FARPUBLIC
SetWindowSize(pwnd, drx, dry)
/*
-- changes the size of a window to be (drx, dry).
-- Actual window and client window are adjusted appropriately
*/
REGISTER PWND pwnd;
BYTE drx, dry;
{
StartPublic();
pwnd->arcWindow.axRight = pwnd->arcWindow.axLeft+drx;
pwnd->arcWindow.ayBottom = pwnd->arcWindow.ayTop+dry;
ValidateWindow(pwnd);
StopPublic();
}
PUBLIC VOID FARPUBLIC
SetWindowStyle(pwnd, style)
/*
-- change the style of the window.
*/
PWND pwnd;
WORD style;
{
StartPublic();
pwnd->style = style;
ValidateWindow(pwnd);
StopPublic();
}
#ifdef WINDOW_OVERLAP
PRIVATE VOID FARPRIVATE
ValidateWindow(pwnd)
/*
-- computes the clipping rectangle for a window and all of its children
*/
REGISTER PWND pwnd;
{
StartPublic();
ValidateWindowAndParents(pwnd->pwndParent);
ValidateAWindow(pwnd);
ValidateWindowAndSiblings(pwnd->pwndChild);
StopPublic();
}
STATIC VOID
ValidateAWindow(pwnd)
/*
-- computes the clipping rectangle for a window
*/
REGISTER PWND pwnd;
{
RRC rrc;
GetClientRrc(pwnd,&rrc);
pwnd->arcClipping = pwnd->arcWindow;
if (pwnd->style & WS_BORDER)
{
/* border around window */
pwnd->arcClipping.axLeft += daxBorder;
pwnd->arcClipping.ayTop += dayBorder;
}
pwnd->arcClipping.axRight = pwnd->arcClipping.axLeft + rrc.rxRight;
pwnd->arcClipping.ayBottom = pwnd->arcClipping.ayTop + rrc.ryBottom;
if ((pwnd->pwndParent != NULL) && (pwnd->style & WS_CLIPOUT))
{
if ((pwnd->style & WS_TYPE) == WS_SCROLL)
{
if (pwnd->pwndParent->pwndParent != NULL)
{
pwnd->arcClipping.axRight =
min(pwnd->arcClipping.axRight,
pwnd->pwndParent->pwndParent->arcClipping.axRight);
pwnd->arcClipping.ayBottom =
min(pwnd->arcClipping.ayBottom,
pwnd->pwndParent->pwndParent->arcClipping.ayBottom);
}
}
else
{
pwnd->arcClipping.axRight =
min(pwnd->arcClipping.axRight,
pwnd->pwndParent->arcClipping.axRight);
pwnd->arcClipping.ayBottom =
min(pwnd->arcClipping.ayBottom,
pwnd->pwndParent->arcClipping.ayBottom);
}
}
StopPublic();
}
STATIC VOID
ValidateWindowAndSiblings(pwnd)
/*
-- computes the clipping rectangle for a window and all of its children
*/
REGISTER PWND pwnd;
{
while (pwnd != NULL)
{
ValidateAWindow(pwnd);
ValidateWindowAndSiblings(pwnd->pwndChild);
pwnd = pwnd->pwndSibling;
}
}
STATIC VOID
ValidateWindowAndParents(pwnd)
/*
-- computes the clipping rectangle for a window and all of its children
*/
REGISTER PWND pwnd;
{
if (pwnd != NULL)
{
ValidateWindowAndParents(pwnd->pwndParent);
ValidateAWindow(pwnd);
}
}
#else
/* No Overlapping windows to worry about */
PRIVATE VOID FARPRIVATE
ValidateWindow(pwnd)
/*
-- computes the clipping rectangle for a window and all of its children
*/
REGISTER PWND pwnd;
{
StartPublic();
RRC rrc;
GetClientRrc(pwnd,&rrc);
pwnd->arcClipping = pwnd->arcWindow;
if (pwnd->style & WS_BORDER)
{
/* border around window */
pwnd->arcClipping.axLeft += daxBorder;
pwnd->arcClipping.ayTop += dayBorder;
}
pwnd->arcClipping.axRight = pwnd->arcClipping.axLeft + rrc.rxRight;
pwnd->arcClipping.ayBottom = pwnd->arcClipping.ayTop + rrc.ryBottom;
StopPublic();
}
#endif /*WINDOW_OVERLAP*/
PUBLIC VOID FARPUBLIC
DrawWindow(pwnd)
/*
-- draw window and children
*/
PWND pwnd;
{
StartPublic();
if (pwnd)
{
SendMessageShort(pwnd, WM_PAINT);
DrawWindowAndSiblings(pwnd->pwndChild);
}
else if (pwndRoot)
{
DrawMenubar();
DrawWindowAndSiblings(pwndRoot);
}
StopPublic();
}
STATIC VOID
DrawWindowAndSiblings(pwnd)
PWND pwnd;
{
while (pwnd != NULL)
{
SendMessageShort(pwnd, WM_PAINT);
DrawWindowAndSiblings(pwnd->pwndChild);
pwnd = pwnd->pwndSibling;
}
}
PUBLIC VOID FARPUBLIC
DrawBorder(pwnd, pbox, di, szTitle)
/*
-- draw a box around the window only if WS_STYLE includes WS_BORDER
-- MERGE ABS/REL
*/
REGISTER PWND pwnd;
BOX * pbox;
WORD di;
char * szTitle;
{
StartPublic();
if (pwnd->style & WS_BORDER)
{
#ifdef WINDOW_OVERLAP
if (pwnd->style & WS_CLIPOUT)
pwndClip = pwnd->pwndParent;
#endif /*WINDOW_OVERLAP*/
DrawThisWnd(pwnd);
DrawBoxArc(pbox, &pwnd->arcWindow, di,
!(pwnd->style & WS_VSCROLL),
!(pwnd->style & WS_HSCROLL),
szTitle);
#ifdef WINDOW_OVERLAP
if (pwnd->style & WS_CLIPOUT)
pwndClip = NULL;
#endif /*WINDOW_OVERLAP*/
}
StopPublic();
}
#ifdef EXTRAS
PRIVATE int FARPRIVATE
CchRealLenSz(sz)
/*
-- return string length (excluding special color characters)
*/
REG char * sz;
{
REG WORD cch;
cch = 0;
while (*sz != '\0')
{
if (*sz == chColorPrefix)
{
/* skip prefix and following character */
Assert(sz[1] != '\0');
sz += 2;
}
else
{
cch++;
sz++;
}
}
return cch;
}
VOID FARPRIVATE
TextOutColor(ax, ay, pch, cch, diOrig)
AX ax;
AY ay;
char * pch;
WORD cch;
WORD diOrig;
/*
-- text out with special color check
*/
{
REG char * pchT;
REG WORD cchT;
WORD di = diOrig;
cchT = 0;
while (1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -