- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
852 lines
26 KiB
C++
852 lines
26 KiB
C++
// Borland C++ - (C) Copyright 1991 by Borland International
|
|
|
|
//*******************************************************************
|
|
//
|
|
// program - TstApp.c
|
|
// purpose - A windows program to send messages to msgwnd server.
|
|
// This illustrates how DDE messages can be sent from
|
|
// one application and received by another.
|
|
//
|
|
// To use this program, build MSGWND and TSTAPP. There
|
|
// are project files for this. When you run TSTAPP, MSGWND
|
|
// will be started automatically.
|
|
//
|
|
//*******************************************************************
|
|
|
|
#define STRICT
|
|
#include <windows.h>
|
|
#include <dde.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <bios.h>
|
|
#include <ctype.h>
|
|
#include <io.h>
|
|
#include <dos.h>
|
|
#include <windowsx.h>
|
|
|
|
#include "tstapp.h"
|
|
#include "msgproc.h"
|
|
#include "ddeclnt.h"
|
|
|
|
#define MAX_QRT_LEN 100
|
|
|
|
typedef struct scrollkeys
|
|
{
|
|
WORD wVirtkey;
|
|
int iMessage;
|
|
WORD wRequest;
|
|
} SCROLLKEYS;
|
|
|
|
SCROLLKEYS key2scroll [] =
|
|
{
|
|
{VK_HOME, WM_COMMAND, IDM_HOME},
|
|
{VK_END, WM_VSCROLL, SB_BOTTOM},
|
|
{VK_PRIOR, WM_VSCROLL, SB_PAGEUP},
|
|
{VK_NEXT, WM_VSCROLL, SB_PAGEDOWN},
|
|
{VK_UP, WM_VSCROLL, SB_LINEUP},
|
|
{VK_DOWN, WM_VSCROLL, SB_LINEDOWN},
|
|
{VK_LEFT, WM_HSCROLL, SB_PAGEUP},
|
|
{VK_RIGHT, WM_HSCROLL, SB_PAGEDOWN}
|
|
};
|
|
|
|
# define NUMKEYS (sizeof key2scroll / sizeof key2scroll[0])
|
|
|
|
// data initialized by first instance
|
|
typedef struct tagSETUPDATA
|
|
{
|
|
char szAppName[10]; // name of application
|
|
} SETUPDATA;
|
|
|
|
SETUPDATA SetUpData;
|
|
|
|
// Data that can be referenced throughout the
|
|
// program but not passed to other instances
|
|
|
|
HINSTANCE hInst; // hInstance of application
|
|
HWND hWndMain; // hWnd of main window
|
|
//char szAppName[10]; // name of application
|
|
|
|
int xChar, yChar, yCharnl;
|
|
int xClient, yClient;
|
|
|
|
LOGFONT cursfont;
|
|
HFONT holdsfont;
|
|
HFONT hnewsfont;
|
|
|
|
RECT wrect;
|
|
|
|
// window scroll/paint stuff
|
|
int nVscrollMax, nHscrollMax;
|
|
int nVscrollPos, nHscrollPos;
|
|
int numlines;
|
|
int maxwidth;
|
|
int nVscrollInc, nHscrollInc;
|
|
int nPaintBeg, nPaintEnd;
|
|
int nPageMaxLines;
|
|
|
|
// for scroll print
|
|
RECT rect;
|
|
int blanklen;
|
|
char blanks[256];
|
|
|
|
// to keep lines
|
|
# define MAX_KEEP 50
|
|
HANDLE hkeep[MAX_KEEP + 1];
|
|
int hwm_keep;
|
|
|
|
// function prototypes
|
|
|
|
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|
LPSTR lpszCmdLine, int cmdShow);
|
|
|
|
void InitTstApp(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|
LPSTR lpszCmdLine, int cmdShow);
|
|
void InitTstAppFirst(HINSTANCE hInstance);
|
|
void InitTstAppEvery(HINSTANCE hInstance, int cmdShow);
|
|
void CloseTstApp(void);
|
|
BOOL FAR PASCAL _export About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
|
|
LRESULT CALLBACK _export TstAppWndProc(HWND hWnd, UINT message,
|
|
WPARAM wParam, LPARAM lParam);
|
|
|
|
void SetupScroll(HWND hWnd);
|
|
void TstAppPaint(HWND hWnd);
|
|
void ScrollPrint(HWND hWnd, char *str);
|
|
void ClearKeep(void);
|
|
|
|
//*******************************************************************
|
|
// WinMain - TstApp main
|
|
//
|
|
// paramaters:
|
|
// hInstance - The instance of this instance of this
|
|
// application.
|
|
// hPrevInstance - The instance of the previous instance
|
|
// of this application. This will be 0
|
|
// if this is the first instance.
|
|
// lpszCmdLine - A long pointer to the command line that
|
|
// started this application.
|
|
// cmdShow - Indicates how the window is to be shown
|
|
// initially. ie. SW_SHOWNORMAL, SW_HIDE,
|
|
// SW_MIMIMIZE.
|
|
//
|
|
// returns:
|
|
// wParam from last message.
|
|
//
|
|
//*******************************************************************
|
|
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|
LPSTR lpszCmdLine, int cmdShow)
|
|
{
|
|
MSG msg;
|
|
|
|
InitTstApp(hInstance, hPrevInstance, lpszCmdLine, cmdShow);
|
|
|
|
while (GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
return(msg.wParam);
|
|
}
|
|
|
|
//*******************************************************************
|
|
|
|
#if !defined(__WIN32__)
|
|
//*******************************************************************
|
|
// InitTstAppAdded - done only for added instances of TstApp
|
|
//
|
|
// paramaters:
|
|
// hPrevInstance - The instance of the previous instance
|
|
// of this application.
|
|
//
|
|
//*******************************************************************
|
|
void InitTstAppAdded(HINSTANCE hPrevInstance)
|
|
{
|
|
// get the results of the initialization of first instance
|
|
GetInstanceData(hPrevInstance, (BYTE*) &SetUpData, sizeof(SETUPDATA));
|
|
}
|
|
#endif
|
|
|
|
//*******************************************************************
|
|
// InitTstApp - init the TstApp application
|
|
//
|
|
// paramaters:
|
|
// hInstance - The instance of this instance of this
|
|
// application.
|
|
// hPrevInstance - The instance of the previous instance
|
|
// of this application. This will be 0
|
|
// if this is the first instance.
|
|
// lpszCmdLine - A long pointer to the command line that
|
|
// started this application.
|
|
// cmdShow - Indicates how the window is to be shown
|
|
// initially. ie. SW_SHOWNORMAL, SW_HIDE,
|
|
// SW_MIMIMIZE.
|
|
//
|
|
//*******************************************************************
|
|
# pragma argsused
|
|
void InitTstApp(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|
LPSTR lpszCmdLine, int cmdShow)
|
|
{
|
|
#if defined(__WIN32__)
|
|
InitTstAppFirst(hInstance);
|
|
#else
|
|
if (! hPrevInstance)
|
|
InitTstAppFirst(hInstance);
|
|
else
|
|
InitTstAppAdded(hPrevInstance);
|
|
#endif
|
|
|
|
InitTstAppEvery(hInstance, cmdShow);
|
|
}
|
|
|
|
//*******************************************************************
|
|
// InitTstAppFirst - done only for first instance of TstApp
|
|
//
|
|
// paramaters:
|
|
// hInstance - The instance of this instance of this
|
|
// application.
|
|
//
|
|
//*******************************************************************
|
|
void InitTstAppFirst(HINSTANCE hInstance)
|
|
{
|
|
WNDCLASS wcTstAppClass;
|
|
|
|
LoadString(hInstance, IDS_NAME, (LPSTR) SetUpData.szAppName, 10);
|
|
|
|
// fill in window class information
|
|
|
|
wcTstAppClass.lpszClassName = SetUpData.szAppName;
|
|
wcTstAppClass.hInstance = hInstance;
|
|
wcTstAppClass.lpfnWndProc = TstAppWndProc;
|
|
wcTstAppClass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wcTstAppClass.hIcon = LoadIcon(hInstance, SetUpData.szAppName);
|
|
wcTstAppClass.lpszMenuName = (LPSTR) SetUpData.szAppName;
|
|
wcTstAppClass.hbrBackground = GetStockObject(WHITE_BRUSH);
|
|
wcTstAppClass.style = CS_HREDRAW | CS_VREDRAW;
|
|
wcTstAppClass.cbClsExtra = 0;
|
|
wcTstAppClass.cbWndExtra = 0;
|
|
|
|
// register the class
|
|
|
|
RegisterClass(&wcTstAppClass);
|
|
}
|
|
|
|
//*******************************************************************
|
|
// InitTstAppEvery - done for every instance of TstApp
|
|
// Will create the window and sets a fixed font
|
|
// for tabular display.
|
|
//
|
|
// paramaters:
|
|
// hInstance - The instance of this instance of this
|
|
// application.
|
|
// cmdShow - Indicates how the window is to be shown
|
|
// initially. ie. SW_SHOWNORMAL, SW_HIDE,
|
|
// SW_MIMIMIZE.
|
|
//
|
|
//*******************************************************************
|
|
void InitTstAppEvery(HINSTANCE hInstance, int cmdShow)
|
|
{
|
|
TEXTMETRIC tm;
|
|
HDC hDC;
|
|
|
|
hInst = hInstance; // save for use by window procs
|
|
|
|
hWndMain = CreateWindow(
|
|
SetUpData.szAppName, // window class name
|
|
SetUpData.szAppName, // window title
|
|
WS_OVERLAPPEDWINDOW | // type of window
|
|
WS_HSCROLL |
|
|
WS_VSCROLL,
|
|
CW_USEDEFAULT, // x window location
|
|
0, // y
|
|
500, // cx and size
|
|
150, // cy
|
|
NULL, // no parent for this window
|
|
NULL, // use the class menu
|
|
hInstance, // who created this window
|
|
NULL // no parms to pass on
|
|
);
|
|
|
|
hDC = GetDC(hWndMain);
|
|
|
|
// build fied screen font
|
|
cursfont.lfHeight = 6;
|
|
cursfont.lfWidth = 6;
|
|
cursfont.lfEscapement = 0;
|
|
cursfont.lfOrientation = 0;
|
|
cursfont.lfWeight = FW_NORMAL;
|
|
cursfont.lfItalic = FALSE;
|
|
cursfont.lfUnderline = FALSE;
|
|
cursfont.lfStrikeOut = FALSE;
|
|
cursfont.lfCharSet = ANSI_CHARSET;
|
|
cursfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
|
cursfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
|
cursfont.lfQuality = DEFAULT_QUALITY;
|
|
cursfont.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
|
|
strcpy((char *)cursfont.lfFaceName, "System");
|
|
|
|
hnewsfont = CreateFontIndirect((LPLOGFONT) &cursfont);
|
|
holdsfont = SelectObject(hDC, hnewsfont);
|
|
|
|
// get text metrics for paint
|
|
GetTextMetrics(hDC, &tm);
|
|
xChar = tm.tmAveCharWidth;
|
|
yChar = tm.tmHeight + tm.tmExternalLeading;
|
|
yCharnl = tm.tmHeight;
|
|
|
|
// init blank line
|
|
blanklen = 255;
|
|
memset(blanks, ' ', blanklen);
|
|
|
|
ReleaseDC(hWndMain, hDC);
|
|
|
|
ShowWindow(hWndMain, cmdShow);
|
|
UpdateWindow(hWndMain);
|
|
}
|
|
|
|
//*******************************************************************
|
|
// CloseTstApp - done at termination of every instance of TstApp
|
|
// This is where wrapup code that should be run
|
|
// at the termination of the application should go.
|
|
//
|
|
//*******************************************************************
|
|
void CloseTstApp()
|
|
{
|
|
ClearKeep();
|
|
CloseMsgWnd();
|
|
DeleteObject(hnewsfont);
|
|
}
|
|
|
|
//*******************************************************************
|
|
// About - handle about dialog box messages
|
|
//
|
|
// paramaters:
|
|
// hDlg - The window handle for this dialog box
|
|
// message - The message number
|
|
// wParam - The WPARAM parameter for this message
|
|
// lParam - The LPARAM parameter for this message
|
|
//
|
|
//*******************************************************************
|
|
# pragma argsused
|
|
BOOL FAR PASCAL _export About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (message == WM_INITDIALOG)
|
|
return(TRUE);
|
|
|
|
else if (message == WM_COMMAND)
|
|
{
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
|
{
|
|
case IDOK:
|
|
EndDialog(hDlg, TRUE);
|
|
return(TRUE);
|
|
|
|
default:
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
//*******************************************************************
|
|
|
|
//*******************************************************************
|
|
// TstAppWndProc - every message for this instance will come here
|
|
//
|
|
// Handle the messages for this application.
|
|
//
|
|
// paramaters:
|
|
// hWnd - The window handle for this message
|
|
// message - The message number
|
|
// wParam - The WPARAM parameter for this message
|
|
// lParam - The LPARAM parameter for this message
|
|
//
|
|
// returns:
|
|
// depends on message.
|
|
//
|
|
//*******************************************************************
|
|
LRESULT CALLBACK _export TstAppWndProc(HWND hWnd, UINT message,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static int msgno;
|
|
|
|
FARPROC lpproc;
|
|
char buf[128];
|
|
int i;
|
|
HANDLE hTmp;
|
|
LPSTR lpTmp;
|
|
|
|
switch (message)
|
|
{
|
|
case WMU_DDE_CLOSED:
|
|
// This message is sent by the ddeclnt module when the dde
|
|
// conversation is terminated.
|
|
CloseMsgWnd();
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
|
{
|
|
case IDM_QUIT:
|
|
// User has selected QUIT from menu.
|
|
PostMessage(hWnd, WM_CLOSE, 0, 0L);
|
|
break;
|
|
|
|
case IDM_HOME:
|
|
// Home key was hit.
|
|
SendMessage(hWnd, WM_HSCROLL, GET_WM_COMMAND_MPS (SB_TOP, 0, 0));
|
|
SendMessage(hWnd, WM_VSCROLL, GET_WM_COMMAND_MPS (SB_TOP, 0, 0));
|
|
break;
|
|
|
|
case IDM_ABOUT:
|
|
// User has selected ABOUT from menu.
|
|
lpproc = MakeProcInstance((FARPROC)About, hInst);
|
|
DialogBox(hInst,
|
|
MAKEINTRESOURCE(ABOUT),
|
|
hWnd,
|
|
(DLGPROC)lpproc);
|
|
FreeProcInstance(lpproc);
|
|
break;
|
|
|
|
case IDM_MESSAGE:
|
|
// User has selected MSG from menu.
|
|
|
|
// Format the message to send.
|
|
sprintf(buf, "TstApp hWnd %04X Msg # %04d: ", hWnd, ++msgno);
|
|
|
|
// Show it in our window.
|
|
ScrollPrint(hWnd, buf);
|
|
|
|
// Send it via dde to msgwnd application.
|
|
SendMsgWndMsg(hWnd, "print", buf);
|
|
break;
|
|
|
|
case IDM_CLEAR:
|
|
// User has selected CLEAR from menu.
|
|
|
|
// Tell msgwnd applicaton to clear its window.
|
|
SendMsgWndMsg(hWnd, "clear", NULL);
|
|
break;
|
|
|
|
case IDM_LINES:
|
|
// User has selected LINES from menu.
|
|
|
|
// Ask msgwnd applicaton how many lines it has recieved.
|
|
hTmp = GetLines(hWnd);
|
|
if (hTmp)
|
|
{
|
|
lpTmp = GlobalLock(hTmp);
|
|
if (lpTmp)
|
|
{
|
|
_fstrcpy(buf, lpTmp);
|
|
ScrollPrint(hWnd, buf);
|
|
GlobalUnlock(hTmp);
|
|
}
|
|
|
|
GlobalFree(hTmp);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
// Save size of window client area.
|
|
|
|
yClient = HIWORD(lParam);
|
|
xClient = LOWORD(lParam);
|
|
|
|
// Go setup scroll ranges and file display area based upon
|
|
// client area size.
|
|
|
|
SetupScroll(hWnd);
|
|
break;
|
|
|
|
case WM_VSCROLL:
|
|
// React to the various vertical scroll related actions.
|
|
switch (GET_WM_VSCROLL_CODE(wParam, lParam))
|
|
{
|
|
case SB_TOP:
|
|
nVscrollInc = -nVscrollPos;
|
|
break;
|
|
|
|
case SB_BOTTOM:
|
|
nVscrollInc = nVscrollMax - nVscrollPos;
|
|
break;
|
|
|
|
case SB_LINEUP:
|
|
nVscrollInc = -1;
|
|
break;
|
|
|
|
case SB_LINEDOWN:
|
|
nVscrollInc = 1;
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
nVscrollInc = -max(1, yClient / yChar);
|
|
break;
|
|
|
|
case SB_PAGEDOWN:
|
|
nVscrollInc = max(1, yClient / yChar);
|
|
break;
|
|
|
|
case SB_THUMBPOSITION:
|
|
nVscrollInc = GET_WM_VSCROLL_POS(wParam, lParam) - nVscrollPos;
|
|
break;
|
|
|
|
case SB_THUMBTRACK:
|
|
nVscrollInc = GET_WM_VSCROLL_POS(wParam, lParam) - nVscrollPos;
|
|
break;
|
|
|
|
default:
|
|
nVscrollInc = 0;
|
|
}
|
|
|
|
nVscrollInc = max(-nVscrollPos,
|
|
min(nVscrollInc, nVscrollMax - nVscrollPos));
|
|
if (nVscrollInc)
|
|
{
|
|
nVscrollPos += nVscrollInc;
|
|
ScrollWindow(hWnd, 0, -yChar * nVscrollInc, NULL, NULL);
|
|
SetScrollPos(hWnd, SB_VERT, nVscrollPos, TRUE);
|
|
UpdateWindow(hWnd);
|
|
}
|
|
break;
|
|
|
|
case WM_HSCROLL:
|
|
// React to the various horizontal scroll related actions.
|
|
switch (GET_WM_HSCROLL_CODE(wParam, lParam))
|
|
{
|
|
case SB_LINEUP:
|
|
nHscrollInc = -1;
|
|
break;
|
|
|
|
case SB_LINEDOWN:
|
|
nHscrollInc = 1;
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
nHscrollInc = -8;
|
|
break;
|
|
|
|
case SB_PAGEDOWN:
|
|
nHscrollInc = 8;
|
|
break;
|
|
|
|
case SB_THUMBPOSITION:
|
|
nHscrollInc = GET_WM_HSCROLL_POS(wParam, lParam) - nHscrollPos;
|
|
break;
|
|
|
|
case SB_THUMBTRACK:
|
|
nHscrollInc = GET_WM_HSCROLL_POS(wParam, lParam) - nHscrollPos;
|
|
break;
|
|
|
|
default:
|
|
nHscrollInc = 0;
|
|
}
|
|
|
|
nHscrollInc = max(-nHscrollPos,
|
|
min(nHscrollInc, nHscrollMax - nHscrollPos));
|
|
if (nHscrollInc)
|
|
{
|
|
nHscrollPos += nHscrollInc;
|
|
ScrollWindow(hWnd, -xChar * nHscrollInc, 0, NULL, NULL);
|
|
SetScrollPos(hWnd, SB_HORZ, nHscrollPos, TRUE);
|
|
UpdateWindow(hWnd);
|
|
}
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
// Translate various keydown messages to appropriate horizontal
|
|
// and vertical scroll actions.
|
|
|
|
for (i = 0; i < NUMKEYS; i++)
|
|
{
|
|
if (wParam == key2scroll[i].wVirtkey)
|
|
{
|
|
SendMessage(hWnd, key2scroll[i].iMessage,
|
|
key2scroll[i].wRequest, 0L);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
// Go paint the client area of the window with the appropriate
|
|
// part of the selected file.
|
|
|
|
TstAppPaint(hWnd);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
// This is the end if we were closed by a DestroyWindow call.
|
|
CloseTstApp(); // take any necessary wrapup action.
|
|
PostQuitMessage(0); // this is the end...
|
|
break;
|
|
|
|
case WM_QUERYENDSESSION:
|
|
// If we return TRUE we are saying it's ok with us to end the
|
|
// windows session.
|
|
CloseTstApp(); // take any necessary wrapup action.
|
|
return((long) TRUE); // we agree to end session.
|
|
|
|
case WM_CLOSE:
|
|
// Tell windows to terminate us.
|
|
DestroyWindow(hWnd);
|
|
break;
|
|
|
|
default:
|
|
// Let windows handle all messages we choose to ignore.
|
|
return(DefWindowProc(hWnd, message, wParam, lParam));
|
|
}
|
|
|
|
return(0L);
|
|
}
|
|
|
|
//*******************************************************************
|
|
// SetupScroll - setup scroll ranges
|
|
//
|
|
// Setup the vertical and horizontal scroll ranges and positions
|
|
// of the applicatons main window based on:
|
|
//
|
|
// numlines - The maximum number of lines to display.
|
|
// maxwidth - The maximum width of any line to display.
|
|
//
|
|
// The resulting variables, nVscrollPos and nPageMaxLines, are used
|
|
// by the function TstAppPaint to determine what part of the selected
|
|
// file to display in the window.
|
|
//
|
|
// paramaters:
|
|
// hWnd - The callers window handle
|
|
//
|
|
//*******************************************************************
|
|
void SetupScroll(HWND hWnd)
|
|
{
|
|
// numlines established during open
|
|
nVscrollMax = max(0, numlines - yClient / yChar);
|
|
nVscrollPos = min(nVscrollPos, nVscrollMax);
|
|
|
|
nHscrollMax = max(0, maxwidth - xClient / xChar);
|
|
nHscrollPos = min(nHscrollPos, nHscrollMax);
|
|
|
|
SetScrollRange (hWnd, SB_VERT, 0, nVscrollMax, FALSE);
|
|
SetScrollPos (hWnd, SB_VERT, nVscrollPos, TRUE);
|
|
|
|
SetScrollRange (hWnd, SB_HORZ, 0, nHscrollMax, FALSE);
|
|
SetScrollPos (hWnd, SB_HORZ, nHscrollPos, TRUE);
|
|
|
|
nPageMaxLines = min(numlines, yClient / yChar);
|
|
|
|
rect.left = 0;
|
|
rect.top = 0;
|
|
rect.right = xClient;
|
|
rect.bottom = yClient;
|
|
|
|
blanklen = rect.right / xChar + 1;
|
|
}
|
|
|
|
//*******************************************************************
|
|
// TstAppPaint - paint the main window
|
|
//
|
|
// This function is responsible for redisplaying a portion of the saved
|
|
// strings. Which strings it displays depends on the current scroll
|
|
// position.
|
|
//
|
|
// paramaters:
|
|
// hWnd - The callers window handle
|
|
//
|
|
//*******************************************************************
|
|
void TstAppPaint(HWND hWnd)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HDC hDC;
|
|
char currec[256];
|
|
int ypos;
|
|
LPSTR lcp;
|
|
int i;
|
|
int ndone;
|
|
|
|
// Get display context.
|
|
BeginPaint(hWnd, (LPPAINTSTRUCT) &ps);
|
|
hDC = ps.hdc;
|
|
|
|
// Select fixed font.
|
|
SelectObject(hDC, hnewsfont);
|
|
|
|
// Setup scroll ranges.
|
|
SetupScroll(hWnd);
|
|
|
|
// See if we have any lines to show.
|
|
if (hwm_keep)
|
|
{
|
|
// Y position of bottom line in client area.
|
|
ypos = rect.bottom - yChar;
|
|
|
|
// Index into keep list of first line (from bottom) to show.
|
|
i = nVscrollMax - nVscrollPos;
|
|
|
|
ndone = 1;
|
|
while (ndone)
|
|
{
|
|
lcp = GlobalLock(hkeep[i]);
|
|
if (lcp)
|
|
{
|
|
// We must fill line with blanks to width of window
|
|
// or else some previous longet text might show through.
|
|
_fstrcpy(currec, blanks);
|
|
|
|
// Line to show.
|
|
_fstrncpy(currec, lcp, _fstrlen(lcp));
|
|
|
|
// Send to window.
|
|
TextOut(hDC,
|
|
xChar * (-nHscrollPos + 0),
|
|
ypos,
|
|
currec,
|
|
blanklen);
|
|
|
|
// New Y is one character height higher.
|
|
ypos -= yChar;
|
|
|
|
GlobalUnlock(hkeep[i]);
|
|
}
|
|
|
|
// Index of next keep string to show.
|
|
i++;
|
|
|
|
// No use drawing lines beyond top of client area.
|
|
// They would not show, so don't wast the energy.
|
|
if (ypos < -yChar)
|
|
ndone = 0;
|
|
|
|
// Have we done all of the lines?
|
|
if (i > (hwm_keep - 1))
|
|
ndone = 0;
|
|
}
|
|
}
|
|
|
|
// Release the display context.
|
|
EndPaint(hWnd, (LPPAINTSTRUCT) &ps);
|
|
}
|
|
|
|
//*******************************************************************
|
|
// ScrollPrint - saves string sent to it and cause it to display
|
|
//
|
|
// This function gets a string and saves it in a list of strings.
|
|
// The oldest string is deleted when the list reaches its maximum
|
|
// size.
|
|
//
|
|
// Depending on the scroll position at the time the string is recieved
|
|
// one of two methods of displaying the string will be used:
|
|
//
|
|
// If the scroll position was at the bottom, the window is scrolled up
|
|
// one line, the bottom line is made invalid, and windows is told to
|
|
// repaint. This will cause only the new string to be output, resulting
|
|
// in minimum redraw on the screen.
|
|
//
|
|
// If the scroll position was not at the bottom of the window because
|
|
// the user had been looking at previous messages, windows will be told
|
|
// to redraw the entire window starting with the new string.
|
|
//
|
|
// paramaters:
|
|
// hWnd - The window to put the message in.
|
|
// str - the string to print in window.
|
|
//
|
|
//*******************************************************************
|
|
void ScrollPrint(HWND hWnd, char *str)
|
|
{
|
|
int i;
|
|
int lstr;
|
|
LPSTR lcp;
|
|
RECT trect;
|
|
|
|
// If our keep stack is full free oldest member.
|
|
if (hwm_keep >= MAX_KEEP)
|
|
GlobalFree(hkeep[hwm_keep]);
|
|
|
|
// Move all handles to make room for new one.
|
|
for (i = hwm_keep; i > 0; i--)
|
|
hkeep[i] = hkeep[i - 1];
|
|
|
|
// If keep stack not yet full add one to high watter mark.
|
|
if (hwm_keep < MAX_KEEP)
|
|
hwm_keep++;
|
|
|
|
// Make sure we know how many saved lines there are.
|
|
numlines = hwm_keep;
|
|
|
|
// Length of new string.
|
|
lstr = strlen(str);
|
|
|
|
// Is it longer than any previous string.
|
|
if (lstr > maxwidth)
|
|
maxwidth = lstr;
|
|
|
|
// Get storage to save it.
|
|
hkeep[0] = GlobalAlloc(GMEM_MOVEABLE, (DWORD) (lstr + 1));
|
|
if (hkeep[0])
|
|
{
|
|
// Lock it down to get address.
|
|
lcp = GlobalLock(hkeep[0]);
|
|
if (lcp)
|
|
{
|
|
// Save string.
|
|
_fstrcpy(lcp, str);
|
|
GlobalUnlock(hkeep[0]);
|
|
}
|
|
}
|
|
|
|
// See what we have to do to display it efficently.
|
|
if (!(nVscrollMax - nVscrollPos))
|
|
{
|
|
// We are scrolled to bottom of list.
|
|
|
|
// Scroll contents of window up one character hehght.
|
|
ScrollWindow(hWnd, 0, -yChar, &rect, &rect);
|
|
|
|
// Set scroll position to last line
|
|
nVscrollPos = numlines - yChar / yClient;
|
|
|
|
// Tell windows to repaint only the bottom line of window.
|
|
GetClientRect(hWnd, &trect);
|
|
trect.top = trect.bottom - yChar;
|
|
InvalidateRect(hWnd, &trect, TRUE);
|
|
}
|
|
else
|
|
{
|
|
// We are not scrolled to bottom of list.
|
|
|
|
// Set scroll position to last line.
|
|
nVscrollPos = numlines - yChar / yClient;
|
|
|
|
// Tell windows to repaint the entire window.
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
}
|
|
|
|
//*******************************************************************
|
|
// ClearKeep - free all saved strings
|
|
//
|
|
//
|
|
//*******************************************************************
|
|
void ClearKeep()
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < hwm_keep; i++)
|
|
{
|
|
GlobalFree(hkeep[i]);
|
|
hkeep[i] = 0;
|
|
}
|
|
|
|
// Reset counters.
|
|
numlines = hwm_keep = 0;
|
|
}
|
|
|
|
//*******************************************************************
|