Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1239 lines
34 KiB

/* zmwin.c - windowing functions for ZM.c
*
* HISTORY:
* 09-Mar-87 danl Move GetAliases to KeyManager
* 09-Mar-87 danl Move DoScipt to first in KeyManager
* 11-Apr-1987 mz Use PASCAL/INTERNAL
* 15-Apr-1987 mz Fix up insufficient arguments
* 05-May-87 danl Add fCheckMail
* 15-Jun-87 danl KeyManager: always call GetAliases
* 19-Jun-87 danl CheckMail: output current time
* 29-Jun-87 danl Display current time at left of cmd title
* 01-Jul-87 danl test idoc, inote against -1 not ERROR
* 03-Jul-87 danl Make local string for time display: CheckMail
* 15-Jul-87 danl Use fNotifyTools flags
* 20-Jul-87 danl Use ReadKey instead of _getch
* 21-Aug-1987 mz Change references from MAXARG to MAXLINELEN
* Speed up BlankWindow
* 24-Aug-1987 mz Remove unneeded argument to DownloadMail
* 02-Sep-87 danl BlankWindow: more speed up
* 24-Sep-87 danl Add ySize to ClearScrn call
* 19-Nov-87 sz Add code for BeepOnMail
* 17-Mar-1988 mz Only do periodic mail stuff if allowed
* 12-Oct-1989 leefi v1.10.73, added inclusion of <io.h>
* 12-Oct-1989 leefi v1.10.73, added inclusion of <stdlib.h>
* 12-Oct-1989 leefi v1.10.73, added inclusion of <stdio.h>
* 12-Oct-1989 leefi v1.10.73, added inclusion of <string.h>
*
*/
#define INCL_DOSINFOSEG
#include <assert.h>
#include <malloc.h>
#include <time.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <stdarg.h>
#include "wzport.h"
#include <tools.h>
#include "dh.h"
#include "zm.h"
extern BOOL screenWriteInProgress; /* if whole window write in progress */
extern PCHAR_INFO pLocalScreen; /* local screen buffer */
HW winList = NULL; /* head of window list, active on top */
/* SendMessage - address a message to a particular window
*
* hWnd window for message
* command command for message
*/
VOID SendMessage (HW hWnd, INT command, ...)
{
va_list vaPtr;
if ( hWnd != NULL ) {
va_start (vaPtr, command);
(*(hWnd->wndProc)) (hWnd, command, va_arg (vaPtr, WDATA));
va_end (vaPtr);
}
}
/* SpacePad - pad out a line to a specific length with spaces.
*
* SpacePad is used to forcibly blank the remainder of a line during display.
* BlankLine is not useful here as we are displaying a significant portion
* of the line with other-than-white-space.
*
* p pointer to beginning of NUL-terminated line
* n length of line to pad out to.
*/
VOID PASCAL INTERNAL SpacePad (PSTR p, INT n)
{
register INT c = strlen (p);
if (c < n)
memset(p + c, ' ', n - c);
}
/* GenClip - generalized clipping/intersection of two boxes
*
* bgBox background box being obscured
* fgBox foreground box doing the obscuring
* pVisBox pointer to a subset of bgBox that will be visible
* pIntBox pointer to intersection box
*/
VOID PASCAL INTERNAL GenClip (BOX bgBox, BOX fgBox, PBOX pVisBox, PINT pcVis, PBOX pIntBox, PINT pcInt)
{
PBOX pBox = NULL;
if (pcVis != NULL)
*pcVis = 0;
if (pcInt != NULL)
*pcInt = 0;
/* test for absence of clipping */
if (bgBox.bottom < fgBox.top || bgBox.top > fgBox.bottom || bgBox.right <
fgBox.left || bgBox.left > fgBox.right) {
if (pVisBox != NULL) {
*pVisBox = bgBox;
(*pcVis)++;
}
return;
}
pBox = pVisBox;
/* clip the top portion of background box */
if (INRANGE (bgBox.top, fgBox.top, bgBox.bottom)) {
if (bgBox.top <= fgBox.top - 1 && pBox != NULL) {
*pBox = bgBox;
pBox->bottom = fgBox.top - 1;
pBox++;
(*pcVis)++;
}
bgBox.top = fgBox.top;
}
/* clip the bottom portion of background box */
if (INRANGE (bgBox.top, fgBox.bottom, bgBox.bottom)) {
if (fgBox.bottom + 1 <= bgBox.bottom && pBox != NULL) {
*pBox = bgBox;
pBox->top = fgBox.bottom + 1;
pBox++;
(*pcVis)++;
}
bgBox.bottom = fgBox.bottom;
}
/* clip the left portion of the background box */
if (INRANGE (bgBox.left, fgBox.left, bgBox.right)) {
if (bgBox.left <= fgBox.left - 1 && pBox != NULL) {
*pBox = bgBox;
pBox->right = fgBox.left - 1;
pBox++;
(*pcVis)++;
}
bgBox.left = fgBox.left;
}
/* clip the right portion of the background box */
if (INRANGE (bgBox.left, fgBox.right, bgBox.right)) {
if (fgBox.right + 1 <= bgBox.right && pBox != NULL) {
*pBox = bgBox;
pBox->left = fgBox.right + 1;
(*pcVis)++;
}
bgBox.right = fgBox.right;
}
if (pIntBox != NULL) {
*pIntBox = bgBox;
if (pcInt != NULL)
*pcInt = 1;
}
return;
}
/* ApplyVis - apply a procedure to all visible portions of a box that are
* obscured by all windows starting at a particular one and ending at another.
*
* box box that is being clipped
* hWndStart beginning window to start clipping on
* hWndStop window to terminate clipping
* proc procedure to call on each visible portion
* arg first of arguments to be passed to procedure
*/
VOID PASCAL INTERNAL ApplyVis (BOX box, HW hWndStart, HW hWndStop, PVISPROC proc, INT x, LPSTR p, INT a)
{
INT cBox, i;
BOX vis[4];
if (hWndStart == NULL || hWndStart == hWndStop)
(*proc) (hWndStop, box, x, p, a);
else {
GenClip (box, hWndStart->win, vis, &cBox, NULL, NULL);
for (i = 0; i < cBox; i++)
ApplyVis (vis[i], hWndStart->pNext, hWndStop, proc, x, p, a);
}
}
/* TextBox - display text for a window.
*
* TextBox is called by WzTextOut to display known, visible text from a window.
* The regions displayed are enumerated by ApplyVis.
*
* hWnd handle of window being displayed
* box box being output relative to screen
* x leftmost point in original string
* p pointer to original string
* a attribute for screen
*/
VOID PASCAL INTERNAL TextBox (HW hWnd, BOX box, INT x, LPSTR p, INT a)
{
CHAR buf[MAXLINELEN];
INT cch = box.right - box.left + 1;
int i;
hWnd; /* unused parameter */
//
// write to local screen buffer - will also write line if minor update
//
for ( i = 0; i < cch; i++ ) {
pLocalScreen[xSize * box.top + box.left + i].Char.AsciiChar
= *(p + box.left - x + i);
pLocalScreen[xSize * box.top + box.left + i].Attributes = (WORD) a;
}
if ( ! screenWriteInProgress) {
Move (p + box.left - x, buf, cch);
LineOut (box.left, box.top, buf, cch, a);
}
}
/* WinOut - display window text mapping entire window.
*
* hWnd window handle to output
* x, y position relative to origin of entire window
* p pointer to character string to display
* c number of bytes to display
* a attribute to display
*/
VOID PASCAL INTERNAL WinOut (HW hWnd, INT x, INT y, LPSTR p, INT c, INT a)
{
BOX line;
INT i;
/* convert text output into a box */
line.top = line.bottom = y + hWnd->win.top;
line.left = x + hWnd->win.left;
line.right = line.left + c - 1;
/* clip text box into intersection of box with window */
GenClip (line, hWnd->win, NULL, NULL, &line, &i);
if (i == 0)
return;
/* apply textbox to all visible windows */
ApplyVis (line, winList, hWnd, TextBox, line.left, p, a );
}
/* StreamOut - stream text out at the cursor location of hWnd. move text into
* content region if present. handle all CR's and LF's
*
* arguements:
* hWnd window handle to preform output in
* pStr pointer to string to output
* c number of chars to output
* style text style, attribute byte passed to winout
*
* returns:
* no return values
*
*/
VOID PASCAL INTERNAL StreamOut ( HW hWnd, PSTR pStr, INT c, INT style )
{
PSTR pEnd = NULL;
CHAR chEnd, chTmp;
INT width = TWINWIDTH ( hWnd );
INT height = TWINHEIGHT ( hWnd );
INT i, temp;
chEnd = *( pStr + c );
*( pStr + c ) = '\0';
while ( c-- != 0 ) {
if ( *pStr == '\r' ) {
hWnd->crsrX = 0;
pStr++;
} else if ( *pStr == '\n' ) {
( hWnd->crsrY )++;
if ( hWnd->crsrY >= height ) {
( hWnd->crsrY )--;
ScrollWindow ( hWnd, 1, FORWARD );
}
pStr++;
} else if ( *pStr == '\b' ) {
( hWnd->crsrX )--;
if ( hWnd->crsrX < 0 ) {
hWnd->crsrX = width - 1;
( hWnd->crsrY )--;
if ( hWnd->crsrY < 0 ) {
hWnd->crsrY = 0;
ScrollWindow ( hWnd, 1, BACKWRD );
}
}
WzTextOut ( hWnd, hWnd->crsrX, hWnd->crsrY, strBLANK, 1,
DefNorm);
pStr++;
} else
{
pEnd = strbscan ( pStr, strCRLF );
chTmp = *pEnd;
*pEnd = '\0';
i = strlen ( pStr );
while ( i > 0 ) {
temp = min ( width - hWnd->crsrX, i );
WzTextOut ( hWnd, hWnd->crsrX, hWnd->crsrY,
pStr, temp, style );
hWnd->crsrX += temp;
if ( hWnd->crsrX >= width ) {
hWnd->crsrX = 0;
( hWnd->crsrY )++;
if ( hWnd->crsrY >= height ) {
( hWnd->crsrY )--;
ScrollWindow ( hWnd, 1,
FORWARD );
}
}
pStr += temp;
i -= temp;
}
*pEnd = chTmp;
pStr = pEnd;
}
if ( winList == hWnd )
SetCursor ( hWnd, hWnd->crsrX, hWnd->crsrY );
}
*pStr = chEnd;
return;
}
/* WzTextOut - display text at a particular position in the window. Perform
* all clipping necessary. Perform the text output inside the
* border with specified style.
*
* hWnd window handle to output.
* x, y position relative to origin of text window to begin display
* p pointer to character string to output
* c number of bytes to display
* style text style, attribute byte passed to winOut
*/
VOID PASCAL INTERNAL WzTextOut (HW hWnd, INT x, INT y, LPSTR p, INT c, INT style )
{
BOX aBox;
INT w = TWINWIDTH (hWnd);
INT i;
if ( y >= 0 && y < TWINHEIGHT ( hWnd ) && x >= 0 && x < w ) {
x += hWnd->lLeft;
y += 1;
/* update window content region? */
if ( hWnd->pContent != NULL ) {
/* clip text to window content region, note off set from hWnd->win */
aBox.top = aBox.bottom = hWnd->win.top + y;
aBox.left = hWnd->win.left + x;
aBox.right = aBox.left + c;
GenClip ( aBox, hWnd->win, NULL, NULL, &aBox, &i );
/* translate resultant box to window content region coordinates */
aBox.top -= ( hWnd->win.top + 1 );
aBox.left -= ( hWnd->win.left + hWnd->lLeft );
aBox.right -= ( hWnd->win.left + hWnd->lLeft );
if ( i != 0 )
Move ( ( LPSTR ) p, ( LPSTR ) hWnd->pContent +
( ( aBox.top * w ) + aBox.left ) * sizeof ( CHAR
), aBox.right - aBox.left );
}
WinOut (hWnd, x, y, p, min(c, w - x + 1), style);
}
}
/* ClearLine - draw a blank line
*
* hWnd handle of window to blank
* i index of line to blank
*/
VOID PASCAL INTERNAL ClearLine (HW hWnd, INT i)
{
INT w = TWINWIDTH (hWnd);
CHAR line[MAXLINELEN];
memset ( line, ' ', w);
WzTextOut (hWnd, 0, i, line, w, DefNorm);
}
/* DisplayTitle - display title line of a window
*
* hWnd handle of window
*/
VOID PASCAL INTERNAL DisplayTitle (HW hWnd)
{
INT len;
INT w = TWINWIDTH (hWnd);
CHAR line[MAXLINELEN];
PSTR p = line;
INT i = hWnd->lLeft + hWnd->lRight;
if ( hWnd->lLeft )
*p++ = (CHAR) C_TL;
memset ( p, C_H, w);
p += w;
if ( hWnd->lRight )
*p = (CHAR) C_TR;
if (hWnd->pTitle != NULL) {
len = min ( strlen (hWnd->pTitle), (size_t)w );
memmove ( & line[(w + i - len)/2], (hWnd->pTitle), len);
}
WinOut (hWnd, 0, 0, line, w + i, DefNorm);
CheckTimeDisplay ( -1L );
}
/* DisplayFooter - display footer in bottom border
*
* hWnd handle of window
*/
VOID PASCAL INTERNAL DisplayFooter (HW hWnd)
{
INT len;
INT w = TWINWIDTH (hWnd);
CHAR line[MAXLINELEN];
PSTR p = line;
INT y;
INT i = hWnd->lLeft + hWnd->lRight;
if ( !hWnd->lBottom )
return;
if ( hWnd->lLeft )
*p++ = (CHAR) C_BL;
memset (p, C_H, w);
p += w;
if ( hWnd->lRight )
*p = (CHAR) C_BR;
if (hWnd->pFooter != NULL) {
len = min ( strlen (hWnd->pFooter), (size_t)w - 2 );
memmove ( & line[ 2 ], (hWnd->pFooter), len);
}
if ( ( hWnd->pFooter !=NULL) && !strcmpis ( hWnd->pFooter, strMORE ) ) {
y = hWnd->win.bottom - hWnd->win.top;
WinOut (hWnd, 0, y, line, 2, DefNorm );
WinOut (hWnd, 2, y, line + 2, len, DefBold );
WinOut (hWnd, 2 + len, y, line + 2 + len, w - len -2 + i, DefNorm );
}
else
WinOut (hWnd, 0, hWnd->win.bottom - hWnd->win.top, line, w + i, DefNorm);
}
/* BlankWindow - draw a blank window.
*
* hWnd handle of window to blank
* fBorder TRUE => draw border, FALSE => erase border
*/
VOID PASCAL INTERNAL BlankWindow (HW hWnd, FLAG fBorder)
{
INT w = TWINWIDTH (hWnd);
INT iBorder = hWnd->lLeft + hWnd->lRight;
INT i;
CHAR line[MAXLINELEN];
PSTR p = line;
if (fBorder) {
/* generate upper border */
DisplayTitle (hWnd);
/* generate content line
* some code removed and optimized N.B. if fBorder then we only
* draw border, we do NOT blank content
*/
if ( iBorder ) {
*p = (CHAR) C_V;
for (i = 0; i < TWINHEIGHT (hWnd); i++) {
WinOut (hWnd, 0, i+1, p, 1, DefNorm);
WinOut (hWnd, w + iBorder - 1, i + 1, p, 1, DefNorm);
}
}
DisplayFooter (hWnd);
} else {
memset (line, ' ', w + iBorder);
for (i = 0; i < TWINHEIGHT (hWnd) + 2; i++)
WinOut (hWnd, 0, i, line, w + iBorder, DefNorm);
}
}
/* ScrollWindow - scrolls a window which has a content region
*
* arguements:
* hWnd handle of window
* numLines number of lines to scroll it
* dir direction
* any +num scrolls window down (contents go up)
* any -num scrolls window up (contents go down)
* returns:
* no return value
*
*/
VOID PASCAL INTERNAL ScrollWindow ( HW hWnd, INT numLines, INT direction )
{
INT width = TWINWIDTH ( hWnd );
INT height = TWINHEIGHT ( hWnd );
INT cbContent;
INT cbBlank;
INT cbMove;
if ((hWnd->pContent == NULL) || (numLines <= 0) || (direction == 0))
return;
numLines = min (height, numLines);
cbContent = width * height * sizeof ( CHAR );
cbBlank = width * numLines * sizeof ( CHAR );
cbMove = cbContent - cbBlank;
/* cbContent number of bytes in total content region
* cbBlank number of bytes of blanking
* cbMove number of bytes to move
*/
if (direction > 0) {
if (cbMove > 0)
Move ((LPSTR) (hWnd->pContent + cbBlank),
(LPSTR) hWnd->pContent, cbMove);
Fill ((LPSTR) (hWnd->pContent + cbMove), ' ', cbBlank);
}
else {
if (cbMove > 0)
Move ((LPSTR) hWnd->pContent,
(LPSTR) (hWnd->pContent + cbBlank), cbMove);
Fill ((LPSTR) hWnd->pContent, ' ', cbBlank);
}
//
// If the window is on the top,
// or, if the command window is on top and this is the second window,
// use video scrolling. don't use video scrolling for command window.
//
if ( (hWnd != hCommand) &&
( (hWnd == winList) ||
( (winList == hCommand) && (hWnd == winList->pNext) ) ) ) {
if (direction > 0 && numLines > 0)
ScrollUp (hWnd->win.left+hWnd->lLeft, hWnd->win.top+1,
hWnd->win.right-hWnd->lRight, hWnd->win.bottom-hWnd->lBottom,
numLines, DefNorm);
else
if (direction < 0 && numLines > 0)
ScrollDn (hWnd->win.left+hWnd->lLeft, hWnd->win.top+1,
hWnd->win.right-hWnd->lRight, hWnd->win.bottom-hWnd->lBottom,
numLines, DefNorm);
else
DrawWindow ( hWnd, FALSE );
}
else
DrawWindow ( hWnd, FALSE );
return;
}
/* DrawWindow - displays a window and border on the the screen
*
* hWnd handle of window
* fBorder TRUE => redraw border, FALSE => just repaint
*/
VOID PASCAL INTERNAL DrawWindow (HW hWnd, FLAG fBorder)
{
INT i;
#ifdef NT
SMALL_RECT screenArea;
//
// write whole screen as a block to the console for better performance
//
startScreenWrite ( );
#endif
if (fBorder)
BlankWindow (hWnd, TRUE);
/* display all content lines */
for (i = 0; i < TWINHEIGHT (hWnd); i++)
(*(hWnd->wndProc)) (hWnd, PAINT, i);
#ifdef NT
screenArea.Left = ( SHORT ) hWnd->win.left;
screenArea.Top = ( SHORT ) hWnd->win.top;
screenArea.Right = ( SHORT ) hWnd->win.right;
screenArea.Bottom = (SHORT ) hWnd->win.bottom;
endScreenWrite ( &screenArea );
#endif
}
/* FitWinToScrn - make sure a box can fit on the screen, shrink it if necessary.
*
* arguments:
* pBox pointer to box to check
*
* return value:
* none. box pointed to by pBox is set to fit on screen
*
* IMPORTANT:
* FitWinToScrn ( ) assumes all box coordinates are positive.
*/
VOID PASCAL INTERNAL FitWinToScrn ( PBOX pBox )
{
pBox->top = ( pBox->top >= ySize ) ? ySize - 1 : pBox->top;
pBox->left = ( pBox->left >= xSize ) ? xSize - 1 : pBox->left;
pBox->bottom = ( pBox->bottom >= ySize ) ? ySize - 1 : pBox->bottom;
pBox->right = ( pBox->right >= xSize ) ? xSize - 1 : pBox->right;
return;
}
/* CreateWindow - create a new window instance and put it on the top of the
* window pile on the screen. Display the window too.
*
* x, y location of upper left corner of window on screen
* xSize, ySize dimensions of the window
* if xSize < 0 then permissible to not show left/right
* border if they are at screen edge
* if ySize < 0 then do not show bottom border
* wndProc window procedure to call for input
* keyProc procedure to call for undefined keys
* data optional extra data to be passed to window procedure
*
* returns handle to window
*/
HW PASCAL INTERNAL CreateWindow (PSTR pTitle, INT x, INT y, INT width, INT height, PWNDPROC wndProc, PKEYPROC keyProc, WDATA data)
{
FLAG fNoVBorder = FALSE;
FLAG fNoHBorder = FALSE;
HW hTmp;
if ((hTmp = (HW ) ZMalloc (sizeof (*hTmp))) == NULL)
return NULL;
hTmp->pTitle = pTitle == NULL ? pTitle : ZMMakeStr (pTitle);
hTmp->pFooter = NULL;
/* default pContent to NULL */
hTmp->pContent = NULL;
hTmp->contSize = 0;
hTmp->crsrX = 0;
hTmp->crsrY = 0;
if ( width < 0 ) {
width = -width;
fNoVBorder = !fWinBorders;
}
if ( height < 0 ) {
height = - height;
fNoHBorder = !fWinBorders;
}
SetRect ( &( hTmp->win ), y, x, y + height - 1, x + width - 1 );
FitWinToScrn ( &( hTmp->win ) );
hTmp->lLeft = ( fNoVBorder && hTmp->win.left == 0 ? 0 : 1 );
hTmp->lRight = ( fNoVBorder && hTmp->win.right == xSize - 1 ? 0 : 1 );
hTmp->lBottom= ( fNoHBorder ? 0 : 1 );
hTmp->fsFlag = WF_BLINK;
hTmp->wndProc = wndProc;
hTmp->keyProc = keyProc;
hTmp->pNext = winList;
winList = hTmp;
(*wndProc) (hTmp, CREATE, data);
DrawWindow ( hTmp, TRUE );
SetCursor ( hTmp, hTmp->crsrX, hTmp->crsrY );
return hTmp;
}
/* defWndProc - default window proc
*
* Handles most common operations
*/
VOID PASCAL INTERNAL defWndProc (HW hWnd, INT command, WDATA data)
{
INT width = TWINWIDTH (hWnd);
INT height = TWINHEIGHT (hWnd);
switch (command) {
/* Paint a line on the screen. If there's a content area and
* the line to be painted is within the screen, output it
* from the content area
*/
case PAINT:
if (hWnd->pContent != NULL)
if ((INT)data < height)
WzTextOut (hWnd, 0, (INT)data, hWnd->pContent + data * width,
width, DefNorm);
break;
case CLOSE:
if (hWnd->pContent)
PoolFree (hWnd->pContent);
break;
case DISPLAY:
SendMessage (hWnd, DISPLAYSTR, data);
SendMessage (hWnd, DISPLAYSTR, strCRLF);
break;
case DISPLAYSTR:
StreamOut ( hWnd, (PSTR) data, strlen ((PSTR) data), DefNorm);
break;
case REGENCONT:
if (hWnd->pContent != NULL)
Fill (hWnd->pContent, ' ', height * width);
break;
default:
break;
}
}
/* BringToTop - bring a background window to the top position. Draw it on
* the screen if requested. Place the cursor at crsrX, crsrY
*
* hWnd handle of window to be made top
* fDisplay TRUE => window is to be displayed
*/
VOID PASCAL INTERNAL BringToTop (HW hWnd, FLAG fDisplay)
{
HW hTmp, hPrev;
hTmp = winList;
hPrev = NULL;
while (hTmp != NULL)
if (hTmp == hWnd)
break;
else {
hPrev = hTmp;
hTmp = hTmp->pNext;
}
if (hPrev != NULL) {
hPrev->pNext = hTmp->pNext;
hTmp->pNext = winList;
winList = hTmp;
}
if (fDisplay)
DrawWindow (hWnd, TRUE);
SetCursor ( hWnd, hWnd->crsrX, hWnd->crsrY );
return;
}
/* CloseWindow - remove a window from display.
*
* The only difficult part is to get each obscured window to redraw
* themselves when the specified window is removed. We first blank the
* window by redrawing (via WinOut) the window, determine the
* intersections of all windows lower in the pile than the selected one, and
* then calling their window procedures to paint the specified intersections.
*
* hWnd handle of window to close
*/
VOID PASCAL INTERNAL CloseWindow (HW hWnd)
{
HW hTmp;
BOX box;
INT i;
#ifdef NT
SMALL_RECT screenArea;
#endif
hTmp = hWnd->pNext;
BringToTop (hWnd, FALSE);
winList = winList->pNext;
#ifdef NT
//
// write whole screen as a block to the console for better performance
//
startScreenWrite ( );
#endif
BlankWindow (hWnd, FALSE);
#ifdef NT
screenArea.Left = ( SHORT ) hWnd->win.left;
screenArea.Top = ( SHORT ) hWnd->win.top;
screenArea.Right = ( SHORT ) hWnd->win.right;
screenArea.Bottom = (SHORT ) hWnd->win.bottom;
endScreenWrite ( &screenArea );
#endif NT
(*(hWnd->wndProc)) (hWnd, CLOSE, 0);
while (hTmp != NULL) {
GenClip (hTmp->win, hWnd->win, NULL, NULL, &box, &i);
if (i != 0)
DrawWindow (hTmp, TRUE);
hTmp = hTmp->pNext;
}
if (hWnd->pTitle != NULL)
ZMfree (hWnd->pTitle);
if (hWnd->pFooter != NULL)
ZMfree (hWnd->pFooter);
ZMfree (hWnd);
if (winList != NULL)
SetCursor ( winList, winList->crsrX, winList->crsrY );
return;
}
/* CloseAllWindows - remove everything from the display
* returns with winList empty.
*
* arguements:
* none
*
* return value:
* none
*
*/
VOID PASCAL INTERNAL CloseAllWindows (VOID)
{
HW hNextWnd = winList;
HW hWnd;
while ( hNextWnd != NULL )
{
hWnd = hNextWnd;
hNextWnd = hNextWnd->pNext;
CloseWindow ( hWnd );
}
return;
}
/* ResizeWindow - change the size of a window, update pContent.
*
* arguments:
* hWnd handle to window to resize
* pBox pointer to box to check
*
* return value:
* returns TRUE if window needs repainting
*
* IMPORTANT :
* ResizeWindow does not update the screen.
*/
FLAG PASCAL INTERNAL ResizeWindow ( HW hWnd, PBOX pBox )
{
INT windSize = 0;
FitWinToScrn ( pBox );
if (hWnd->win.left == pBox->left && hWnd->win.right == pBox->right &&
hWnd->win.top == pBox->top && hWnd->win.bottom == pBox->bottom)
return FALSE;
hWnd->win = *pBox;
if (hWnd->pContent != NULL) {
windSize = TWINWIDTH (hWnd) * TWINHEIGHT (hWnd) * sizeof(CHAR);
if ( (UINT)windSize > hWnd->contSize ) {
PoolFree ( hWnd->pContent );
hWnd->pContent = PoolAlloc ( windSize );
hWnd->contSize = windSize;
}
SendMessage ( hWnd, REGENCONT, NULL );
}
return TRUE;
}
/* SetWindowText - change the title of a window
*
* hWnd window whose title is to be changed
* pTitle new title to be changed
*/
VOID PASCAL INTERNAL SetWindowText (HW hWnd, PSTR pTitle)
{
if (hWnd->pTitle != NULL)
ZMfree (hWnd->pTitle);
if (pTitle != NULL)
hWnd->pTitle = ZMMakeStr (pTitle);
else
hWnd->pTitle = NULL;
DisplayTitle (hWnd);
}
/* SetWindowFooter - change the footer of a window
*
* hWnd window whose footer is to be changed
* pFooter new footer to be changed
*/
VOID PASCAL INTERNAL SetWindowFooter (HW hWnd, PSTR pFooter)
{
if (hWnd->pFooter != NULL)
ZMfree (hWnd->pFooter);
if (pFooter != NULL)
hWnd->pFooter = ZMMakeStr (pFooter);
else
hWnd->pFooter = NULL;
DisplayFooter (hWnd);
}
/* SetRect - set up the coordinates of the given box
*
* arguments :
* pBox pointer to box to set up.
* top top coordinate of box.
* left left coordinate of box.
* bottom bottom coordinate of box.
* right right coordinate of box.
*
* return value :
* none.
*/
VOID PASCAL INTERNAL SetRect (PBOX pBox, INT top, INT left, INT bottom, INT right)
{
pBox->top = top;
pBox->left = left;
pBox->bottom = bottom;
pBox->right = right;
return;
}
/* KeyManager - intercept keystrokes and hand them to the active window
*
* We use the top of winList as the current input focus. All input is handed
* to the window procedure EXCEPT for the tab key. The tab key is responsible
* for placing the top window on the bottom of the stack to cycle through the
* set of windows.
*
*/
VOID PASCAL INTERNAL KeyManager (VOID)
{
LONG now;
#if defined (HEAPCRAP)
INT fHeapChk;
#endif
/* do script first in case in contains a password command
*/
if ( pInitScript )
DoScript ( hCommand, pInitScript, 0 );
if (fMailAllowed) {
GetAliases ( fNotifyTools & F_LOADALIAS );
fNotifyTools &= ~(FLAG)F_LOADALIAS;
NotifyTools ( );
}
if ( fComposeOnBoot )
( *( winList->wndProc ) ) ( winList, KEY, 0 );
SendMessage ( hCommand, DISPPROMPT, TRUE );
while ( ( winList != NULL ) && ( !fQuit ) ) {
time ( &now );
CheckTimeDisplay ( now );
if ( pInitHdrCmd ) {
DoHeaders ( hCommand, pInitHdrCmd, TRUE );
SendMessage ( hCommand, DISPPROMPT, 0 );
ZMfree ( pInitHdrCmd );
pInitHdrCmd = NULL;
}
/* if system has not received a char for 10 sec then checkmail
*/
if (fMailAllowed)
CheckMail ( now );
/* time out password after (default) 6 hours in case user has
* left WZMAIL running and gone home
*/
if ( now > lTmPassword + lPasswordAge )
ResetPassword ( );
if ( now > lTmConnect + cSecConnect )
ZMDisconnect ( );
/* On multitasking systems, it is rude to go into polling loops.
*
* For OS/2, we have a separate thread dedicated to reading from the
* console. We clear a semaphore to let him read and then wait on
* a response semaphore with the specified timeout. This avoids
* polling.
*
* For real mode DOS, we presume that INT 16 (poll) will cause an
* explicit yield to other runnable threads.
*/
if (kbwait (60 * 1000)) {
fMailUnSeen = FALSE;
do {
(*winList->wndProc) ( winList, KEY, ReadKey() );
} while (!fQuit && kbwait (10000));
}
#if defined (HEAPCRAP)
if ( ( fHeapChk = heapchk ( ) ) != HEAPOK ) {
fprintf ( stderr, "%s\n",
( fHeapChk == HEAPBADBEGIN ? "Can't find heap" :
"Damaged heap" ) );
assert ( fHeapChk == HEAPOK );
}
#endif
}
return;
}
VOID PASCAL INTERNAL CheckTimeDisplay ( LONG lNow )
{
static INT minLast;
struct tm *ptmLocal = NULL;
PSTR p = NULL;
if ( lNow == -1L ) {
time ( &lNow );
minLast = -1;
}
ptmLocal = localtime ( &lNow );
if ( (hCommand != NULL) && (ptmLocal->tm_min != minLast) ) {
minLast = ptmLocal->tm_min;
p = asctime ( localtime ( &lNow ) );
WinOut ( hCommand, 2, 0, p, 16, DefNorm );
}
}
VOID PASCAL INTERNAL CheckMail ( LONG lNow )
{
FLAG fFirstTime = lTmLastMail == 0L;
INT idoc;
INT cMsg;
LONG lTemp;
PSTR p = NULL;
/* Don't do auto new mail
* if current folder is not default folder
* if wzmail invoked to compose a single message
* if user is typing a command
* if current folder is readonly
*/
if ( !fCurFldIsDefFld || fDirectComp || WindLevel != 0 || fReadOnlyCur )
return;
/* Do automail if fCheckMail or first time or
* (periodic checking and enough time has elapsed)
* For perf reasons, order of test is inverted
* Return if not fCheckMail if NOT first time &&
* (if not requested by user ( cSecNewmail == 0 => don't check ) or
* if not enough time elapsed )
*/
if ( !fCheckMail && !fFirstTime &&
( !cSecNewmail || ( lNow < lTmLastMail + cSecNewmail ) ) )
return;
fCheckMail = FALSE;
#if (defined (OS2) | defined (NT))
if (ISFULLSCREEN && ISVISIBLE)
#endif
{
SendMessage ( hCommand, DISPLAYSTR, "Checking mailbox ... " );
p = ZMMakeStr ( asctime ( localtime ( &lNow ) ) );
strcpy ( p+16, strBLANK );
SendMessage ( hCommand, DISPLAYSTR, p );
ZMfree ( p );
}
/* Don't let connection made by auto newmail keep lazy connection open
* DownloadMail updates lTmLastMail
* BUT ... the first time, allow lazy connection to be made on startup
*/
idoc = ( inoteBold != -1 ? mpInoteIdoc [ inoteBold ] : -1 );
if ( !fFirstTime )
lTemp = lTmConnect;
cMsg = DownloadMail (FALSE);
if ( !fFirstTime )
lTmConnect = lTemp;
Disconnect ( );
#if (defined (OS2) | defined (NT))
if (cMsg || (ISFULLSCREEN && ISVISIBLE))
#endif
SendMessage ( hCommand, CLRCMDLN, 0 );
/* if first time, then find the first unread message
* else don't change the "current" message
*/
if ( fFirstTime ) {
if ( ( idoc = NextUnread ( -1 ) ) != -1 )
SendMessage ( hHeaders, GOTOIDOCALL, idoc );
}
else {
if ( idoc != -1 )
SendMessage ( hHeaders, GOTOIDOCALL, idoc );
}
}
/* Bell - make some noise
*/
VOID PASCAL INTERNAL Bell (VOID)
{
write (1, "\x07", 1);
}
/* SetCursor - place the visible cursor in some window
*
* hWnd window for cursor
* x, y location of cursor in window
*/
VOID PASCAL INTERNAL SetCursor (HW hWnd, INT x, INT y)
{
if (!TESTFLAG (hWnd->fsFlag, WF_BLINK))
/* move cursor off screen
*/
#ifdef NT
cursorInvisible ();
#else
cursor ( xSize + 1, ySize + 1 );
#endif
else
if (INRANGE (0, x, TWINWIDTH (hWnd)) && INRANGE (0, y, TWINHEIGHT (hWnd))) {
cursorVisible ();
cursor (x + hWnd->lLeft + hWnd->win.left, y + 1 + hWnd->win.top);
}
}
/* ShowCursor - place the visible cursor in some window
*
* hWnd window for cursor
* fBlink TRUE -> blinking cursor, FALSE no cursor
*/
VOID PASCAL INTERNAL ShowCursor (HW hWnd, FLAG fBlink )
{
RSETFLAG (hWnd->fsFlag, WF_BLINK);
if (fBlink)
SETFLAG (hWnd->fsFlag, WF_BLINK);
if ( winList == hWnd )
{
SetCursor ( hWnd, hWnd->crsrX, hWnd->crsrY );
#ifdef NT
if (fBlink)
{
cursorVisible ();
}
#endif
}
}
/* RedrawScreen - blank the screen and redraw all windows in the pile.
*/
VOID PASCAL INTERNAL RedrawScreen (VOID)
{
HW hWnd = winList;
// ClearScrn ( DefNorm, ySize );
do {
DrawWindow ( hWnd, TRUE );
hWnd = hWnd->pNext;
} while ( hWnd != NULL );
SetCursor ( winList, winList->crsrX, winList->crsrY );
return;
}
VOID PASCAL INTERNAL FreeContents (VOID)
{
HW hWnd;
for (hWnd = winList; hWnd != NULL; hWnd = hWnd->pNext)
if (!TESTFLAG (hWnd->fsFlag, WF_NODISCARD) && hWnd->pContent != NULL) {
PoolFree(hWnd->pContent);
hWnd->pContent = NULL;
}
}
VOID PASCAL INTERNAL RestoreContents (VOID)
{
HW hWnd;
for (hWnd = winList; hWnd != NULL; hWnd = hWnd->pNext)
if ((hWnd->pContent == NULL) && (hWnd->contSize > 0))
if (hWnd->pContent = PoolAlloc(hWnd->contSize))
SendMessage ( hWnd, REGENCONT, NULL );
else {
ZMDisconnect();
ZMexit(-1, "Out of memory for window buffers\n");
}
}