Category : Recently Uploaded Files
Archive   : RSXWDK2S.ZIP
Filename : WINIO.C

 
Output of file : WINIO.C contained in archive : RSXWDK2S.ZIP
/*
WINIO.C
Stdio (e.g. printf) functionality for Windows - implementation
Dave Maxey - 1991
revisions by Andrew Schulman - 1991
originally in Microsoft Systems Journal, July 1991
revised for use by article in MSJ, September 1991

*****
changed for GNU C by Rainer Schnitker

*/

#include
#include
#include
#include
#include
#include "wmhandlr.h"
#include "winio.h"

#ifdef __GNUC__
#define _fmemcpy memcpy
#define _fmemset memset
#endif

/* PROTOTYPES in alphabetic order */

void winio_addchars(BYTE *, unsigned);
void winio_adjust_caret(void);
void winio_append2buffer(BYTE *, unsigned);
int winio_chInput(void);
void winio_compute_repaint(void);
int winio_initialize_buffers(unsigned);
int winio_initialize_class(HANDLE);
void winio_initialize_state(void);
int winio_initialize_window(HANDLE, HANDLE, int);
void winio_make_avail(unsigned);
BYTE far * winio_nextline(BYTE far *);
BYTE far * winio_prevline(BYTE far *);
void winio_set_font(void);
void winio_settitle(BYTE *pchTitle);
LRESULT winio_wmpaint(HWND, UINT, WPARAM, LPARAM);
LRESULT winio_wmsize(HWND, UINT, WPARAM, LPARAM);
LRESULT winio_wmdestroy(HWND, UINT, WPARAM, LPARAM);
LRESULT winio_wmchar(HWND, UINT, WPARAM, LPARAM);
LRESULT winio_wmkeydown(HWND, UINT, WPARAM, LPARAM);
LRESULT winio_wmhscroll(HWND, UINT, WPARAM, LPARAM);
LRESULT winio_wmvscroll(HWND, UINT, WPARAM, LPARAM);
LRESULT winio_wmsetfocus(HWND, UINT, WPARAM, LPARAM);
LRESULT winio_wmkillfocus(HWND, UINT, WPARAM, LPARAM);

/* this doesn't get declared in stdio.h if _WINDOWS is defined */
/* although it is in the Windows libraries! */
#ifndef __GO32__
int vsprintf(char *, const char *, va_list);
#else
int vsprintf(char *, const char *, ...);
#endif

#define winio_caret_visible() \
((yCurrLine <= (yTopOfWin + yWinHeight)) && \
(xCurrPos <= (xLeftOfWin + xWinWidth)) && \
(xCurrPos >= xLeftOfWin))

#define CHECK_INIT() if (! tWinioVisible) return FALSE

#define MAX_X 127
#define TABSIZE 8
#define TYPE_AHEAD 256
#define WINIO_DEFAULT_BUFFER 8192
#define MIN_DISCARD 256
#define CARET_WIDTH 2

/* For scrolling procedures */
#define USE_PARAM 10000
#define DO_NOTHING 10001

static BYTE winio_class[15] = "winio_class";
static BYTE winio_icon[15] = "winio_icon";
static BYTE winio_title[128] = "Stdio Window";
static unsigned long bufsize = WINIO_DEFAULT_BUFFER;
static unsigned long kbsize = TYPE_AHEAD;
static unsigned bufused, bufSOI;
static unsigned curr_font = SYSTEM_FIXED_FONT;
static int tWinioVisible = FALSE;
static int tCaret = FALSE, tFirstTime = TRUE;
static int cxChar, cyChar, cxScroll, cyScroll, cxWidth, cyHeight;
static int xWinWidth, yWinHeight, xCurrPos;
static int xLeftOfWin, yTopOfWin, yCurrLine;
static unsigned pchKbIn, pchKbOut;
static BYTE far *fpBuffer, far *fpTopOfWin, far *fpCurrLine;
static BYTE far *fpKeyboard;
static HANDLE hBuffer, hKeyboard;
static HWND hwnd;
static BOOL tTerminate = TRUE;
static BOOL tPaint = TRUE;
static BOOL tEcho = TRUE;
static DESTROY_FUNC destroy_func;
static int control_c = 0;

typedef struct {
int hSB, vSB;
} recVKtoSB;

/* This table defines, by scroll message, what increment to try */
/* and scroll horizontally. PGUP and PGDN entries are updated */
/* in the winio_wmsize function. */
static int cScrollLR[SB_ENDSCROLL + 1] =
/*UP DOWN PGUP PGDN POS TRACK TOP BOT ENDSCROLL */
{ -1, +1, -1, +1, USE_PARAM, USE_PARAM, -MAX_X, MAX_X, DO_NOTHING};

/* This table defines, by scroll message, what increment to try */
/* and scroll horizontally. PGUP and PGDN entries are updated */
/* in the winio_wmsize function, and the TOP & BOTTOM entries */
/* are updated by addchar function. */
static int cScrollUD[SB_ENDSCROLL + 1] =
/*UP DOWN PGUP PGDN POS TRACK TOP BOT ENDSCROLL */
{ -1, +1, -1, +1, USE_PARAM, USE_PARAM, -1, +1, DO_NOTHING};

/* This table associates horizontal and vertical scroll */
/* messages that should be generated by the arrow and page keys */
static recVKtoSB VKtoSB[VK_DOWN - VK_PRIOR + 1] =
/* VK_PRIOR VK_NEXT */
{ { DO_NOTHING, SB_PAGEUP }, { DO_NOTHING, SB_PAGEDOWN },
/* VK_END VK_HOME */
{ SB_TOP, SB_BOTTOM }, { SB_TOP, SB_TOP },
/* VK_LEFT VK_UP */
{ SB_LINEUP, DO_NOTHING }, { DO_NOTHING, SB_LINEUP },
/* VK_RIGHT VK_DOWN */
{ SB_LINEDOWN, DO_NOTHING },{ DO_NOTHING, SB_LINEDOWN } };

/* =================================================================== */
/* the interface functions themselves..... */
/* =================================================================== */

int winio_fputchar(int c)
{
CHECK_INIT();
winio_addchars((BYTE *)&c, 1);
return c;
}

int winio_fgetchar(void)
{
int ch;
CHECK_INIT();
ch = winio_chInput();
if (tEcho)
winio_fputchar(ch);
return ch;
}

char *winio_gets(char *pchTmp)
{
char *pch = pchTmp;
int c;

CHECK_INIT();
bufSOI = bufused; /* mark beginning of line to limit backspace */
do {
if ((c = winio_fgetchar()) == '\n')
c = '\0';
switch (c)
{
case '\b' : if (pch > pchTmp) pch--; break;
case 0x03 : winio_fputchar('^');
winio_fputchar('C');
winio_fputchar('\n');
c=0; *pchTmp = 0; break;
case 0x1b : pch = pchTmp; break;
case EOF : bufSOI = -1; return NULL;
default : *pch = (BYTE) c; pch++;
}
} while (c);
bufSOI = -1;
return pchTmp;
}

int winio_kbhit(void)
{
CHECK_INIT();
return (pchKbIn == pchKbOut);
}

int winio_puts(const char *s)
{
BYTE c = '\n';
CHECK_INIT();
winio_addchars((BYTE *) s, strlen(s));
winio_addchars(&c, 1);
return 0;
}

int winio_read_kbd(int echo, int wait, int signal)
{
int ch;
CHECK_INIT();
if (!wait && !winio_kbhit())
return -1;
ch = winio_chInput();
if (echo)
winio_fputchar(ch);
return ch;
}

int winio_get_controlc(void)
{
int tmp = control_c ;
control_c = 0;
return tmp;
}

/* --------------------------------------------------------------- */
/* USED INTERNALLY - pops up an error window and returns FALSE */
/* --------------------------------------------------------------- */
static int fail(BYTE *s)
{
MessageBox(NULL,s,"ERROR",MB_OK);
return FALSE;
}

/* --------------------------------------------------------------- */
/* pops up a message window */
/* --------------------------------------------------------------- */
BOOL winio_warn(BOOL confirm, const BYTE *fmt, ...)
{
BYTE s[256];
va_list marker;

va_start(marker, fmt);
vsprintf(s, fmt, marker);
va_end(marker);

return (MessageBox(NULL, s, winio_title,
confirm? MB_OKCANCEL : MB_OK) == IDOK);
}

/* --------------------------------------------------------------- */
/* The application must call this function before using any of the */
/* covered stdio type calls. We need the parameter info in order */
/* to create the window. The function allocates the buffer and */
/* creates the window. It returns TRUE or FALSE. */
/* --------------------------------------------------------------- */
int winio_init(HANDLE hInstance, HANDLE hPrevInstance,
int nCmdShow, unsigned wBufSize)
{
if (tWinioVisible)
return FALSE;

if (! winio_initialize_buffers(wBufSize))
return FALSE;

winio_initialize_state();

if (! winio_initialize_window(hInstance, hPrevInstance, nCmdShow))
return FALSE;

tWinioVisible = TRUE;

atexit(winio_end); /* hook into exit chain */

winio_yield();
return TRUE;
}

/* --------------------------------------------------------------- */
/* Clear the contents of the buffer. */
/* --------------------------------------------------------------- */
void winio_clear(void)
{
_fmemset(fpBuffer,0,(int) bufsize - 1);
fpCurrLine = fpTopOfWin = fpBuffer;
*fpBuffer = '\0';
xCurrPos = 0;
yCurrLine = 0;
yTopOfWin = 0;
xLeftOfWin = 0;
bufused = 0;

if (tWinioVisible)
{
SetScrollRange(hwnd, SB_VERT, 1, yCurrLine + 1, FALSE);
SetScrollPos(hwnd, SB_VERT, yTopOfWin + 1, TRUE);
}
}

/* --------------------------------------------------------------- */
/* Return the window handle of the underlying Windows object. */
/* Can be used by an application to customize the WINIO window */
/* --------------------------------------------------------------- */
HWND winio_hwnd(void)
{
return hwnd;
}

/* --------------------------------------------------------------- */
/* This function is called by winio_init(). It initializes a number */
/* of global variables, including the WM_ handler table. */
/* --------------------------------------------------------------- */
void winio_initialize_state()
{
winio_clear();
destroy_func = 0;

/* set up our message handlers */
wmhandler_init();
wmhandler_set(WM_PAINT, winio_wmpaint);
wmhandler_set(WM_SIZE, winio_wmsize);
wmhandler_set(WM_DESTROY, winio_wmdestroy);
wmhandler_set(WM_CHAR, winio_wmchar);
wmhandler_set(WM_HSCROLL, winio_wmhscroll);
wmhandler_set(WM_VSCROLL, winio_wmvscroll);
wmhandler_set(WM_SETFOCUS, winio_wmsetfocus);
wmhandler_set(WM_KILLFOCUS, winio_wmkillfocus);
wmhandler_set(WM_KEYDOWN, winio_wmkeydown);
}

/* --------------------------------------------------------------- */
/* This function is called by winio_init(). It initializes our */
/* Windows class, and some global variables */
/* --------------------------------------------------------------- */
int winio_initialize_window(HANDLE hInst, HANDLE hPrev, int nCmdShow)
{
static RECT start;
int cx, cy, inc;

cx = GetSystemMetrics(SM_CXSCREEN);
cy = GetSystemMetrics(SM_CYSCREEN);
inc = GetSystemMetrics(SM_CYCAPTION);
cxScroll = GetSystemMetrics(SM_CXVSCROLL);
cyScroll = GetSystemMetrics(SM_CYHSCROLL);

if (hPrev)
{
/* note: other WINIO apps are NOT other instances! */
GetInstanceData(hPrev, (NPSTR) &start, sizeof(RECT));
start.top += inc;
start.left += inc;
if (start.top > (cy >> 2))
start.top = cy >> 3;
if (start.left > (cx >> 2))
start.left = cx >> 3;
}
else
{
if (! winio_initialize_class(hInst))
return fail("Could not create class");

start.left = inc;
start.right = cx - 4 * inc;
start.top = inc;
start.bottom = cy - 4 * inc;
}

hwnd = CreateWindow(winio_class, NULL,
WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
start.left, start.top, start.right, start.bottom,
NULL, NULL, hInst, NULL);
if (! hwnd)
return fail("Could not create window");

winio_set_font();

/*
if (nCmdShow==SW_MINIMIZE)
nCmdShow=SW_SHOWMINIMIZED;
*/

ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

return TRUE;
}

/* ----------------------------------------------------------------------- */
/* Initializes Window Class */
/* ----------------------------------------------------------------------- */
int winio_initialize_class(HANDLE hInst)
{
WNDCLASS wc;

wc.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNCLIENT;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(hInst, winio_icon);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = winio_class;

return RegisterClass(&wc);
}

/* ----------------------------------------------------------------------- */
/* Uses GlobalAlloc() to allocate the display and keyboard buffers */
/* ----------------------------------------------------------------------- */
int winio_initialize_buffers(unsigned wBufSize)
{
if (wBufSize)
bufsize = max(wBufSize, 1024);

if (! (hBuffer = GlobalAlloc(GMEM_MOVEABLE, bufsize)))
return fail("Could not allocate/nconsole I/O buffer");

fpBuffer = GlobalLock(hBuffer); /* keep locked; assume protected mode */

if (! (hKeyboard = GlobalAlloc(GMEM_MOVEABLE, kbsize)))
return fail("Could not allocate/type ahead buffer");

fpKeyboard = GlobalLock(hKeyboard);

*fpBuffer = '\0';
fpBuffer++;

return TRUE;
}

/* ----------------------------------------------------------------------- */
/* Undoes the work of the above. Allows an application to close the window */
/* Terminates the prog. */
/* ----------------------------------------------------------------------- */
void winio_yield2();
void winio_end()
{
winio_settitle("inactive");
while (tWinioVisible == TRUE)
winio_yield();
}

/* ------------------------------------------------------------------- */
/* Closes the window by sending it a WM_DESTROY message. Note that it */
/* does not disable the _onclose defined function. So the user program */
/* handler will be triggered. Does NOT cause the app. to terminate. */
/* ------------------------------------------------------------------- */
void winio_close()
{
tTerminate = FALSE;
DestroyWindow(hwnd);
tTerminate = TRUE;
}

/* ------------------------------------------------------------------- */
/* processes any outstanding events waiting. These may be characters */
/* typed at the keyboard, WM_PAINT messages, etc. It is called */
/* internally but should also be used liberally by the application */
/* within loops. */
/* ------------------------------------------------------------------- */
void winio_yield()
{
MSG msg;
if (! tWinioVisible) /* CHECK_INIT() */
return;

while (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

void winio_yield2()
{
MSG msg;

if (! tWinioVisible) /* CHECK_INIT() */
return;
if (InSendMessage()) /* chech deadlock */
return;

for (;;) {
if (! GetMessage(&msg, NULL, 0, 0))
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
if (! PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
break;
}
}


/* ------------------------------------------------------------------- */
/* Let the application install an exit routine, called back from */
/* winio_wmdestroy(). Deinstall by winio_onclose(NULL) */
/* ------------------------------------------------------------------- */
void winio_onclose(DESTROY_FUNC exitfunc)
{
destroy_func = exitfunc;
}

/* ------------------------------------------------------------------- */
/* This function allows the font of the window to be modified, and may */
/* be used BEFORE winio_init. Currently, only SYSTEM_, ANSI_, and */
/* OEM_FIXED_FONTs are supported. */
/* ------------------------------------------------------------------- */
BOOL winio_setfont(WORD wFont)
{
if ((wFont != SYSTEM_FIXED_FONT) &&
(wFont != ANSI_FIXED_FONT) &&
(wFont != OEM_FIXED_FONT))
return FALSE;
curr_font = wFont;
if (tWinioVisible)
{
winio_set_font();
if (tPaint)
InvalidateRect(hwnd, NULL, TRUE);
}
return TRUE;
}

/* ------------------------------------------------------------------- */
/* This function allows the title of the window to be modified, and may */
/* be used BEFORE winio_init. */
/* ------------------------------------------------------------------- */
void winio_settitle(BYTE *pchTitle)
{
strncpy(winio_title, pchTitle, 127);
winio_title[127] = '\0';
if (tWinioVisible)
SetWindowText(hwnd, winio_title);
}

/* ------------------------------------------------------------------- */
/* This function allows the caller to specifiy immediate or deferred */
/* screen updates. The call may not be issued before winio_init(). */
/* ------------------------------------------------------------------- */
BOOL winio_setpaint(BOOL on)
{
BOOL ret = tPaint;

CHECK_INIT();
if (tPaint == on)
InvalidateRect(hwnd, NULL, TRUE);
return ret;
}

/* ------------------------------------------------------------------- */
/* This function changes the behavior of getchar(), whose default */
/* is to echo characters, unlike DOS. winio_setecho(FALSE) restores */
/* the non-echo DOS behavior. */
/* ------------------------------------------------------------------- */
BOOL winio_setecho(BOOL flag)
{
BOOL ret = tEcho;
tEcho = flag;
return ret;
}

/* --------------------------------------------------------------- */
/* Our WM_PAINT handler. It sends the currrent 'in view' piece of */
/* the buffer to the window. Note that an embedded NULL character */
/* signifies an end of line, not '\n'. */
/* --------------------------------------------------------------- */
LRESULT winio_wmpaint(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
BYTE far *pchSOL = fpTopOfWin;
BYTE far *pchEOL;
int i, j, xStart;
int xLeft, xRight, yTop, yBottom;

hdc = BeginPaint(hwnd, &ps);

xLeft = (ps.rcPaint.left / cxChar) + xLeftOfWin;
xRight = (ps.rcPaint.right / cxChar) + xLeftOfWin;
yTop = ps.rcPaint.top / cyChar;
yBottom = ps.rcPaint.bottom / cyChar;
SelectObject(hdc, GetStockObject(curr_font));

for (i = 0; i < yTop; i++) /* lines above repaint region */
{
while (*pchSOL)
pchSOL++;
pchSOL++;
}

if (i <= yCurrLine) /* something needs repainting.. */
{
for (i = yTop; i <= yBottom; i++) /* lines in repaint region */
{
for (j = 0; (j < xLeft) && (*pchSOL); j++, pchSOL++)
; /* Scroll right */
pchEOL = pchSOL;
xStart = j - xLeftOfWin;
for (j = 0; (*pchEOL) ; j++, pchEOL++) ; /* end of line */
TextOut(hdc, cxChar * xStart, cyChar * i, pchSOL,
min(j, xRight - xLeft + 2));
if ((unsigned)(pchEOL - fpBuffer) >= bufused)
break;
pchSOL = ++pchEOL;
}
}

EndPaint(hwnd, &ps);
winio_adjust_caret();
return 0;
}

/* --------------------------------------------------------------- */
/* Our WM_SIZE handler. It updates the internal record of our */
/* window size, minus the scroll bars, and recalcs the scroll bar */
/* ranges. */
/* --------------------------------------------------------------- */
LRESULT winio_wmsize(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
cxWidth = LOWORD(lParam);
cyHeight = HIWORD(lParam);

xWinWidth = (cxWidth - cxScroll ) / cxChar;
yWinHeight = (cyHeight - cyScroll ) / cyChar;

cScrollLR[SB_PAGEUP] = -xWinWidth / 2;
cScrollLR[SB_PAGEDOWN] = +xWinWidth / 2;
cScrollUD[SB_PAGEUP] = -yWinHeight + 1;
cScrollUD[SB_PAGEDOWN] = +yWinHeight - 1;

SetScrollRange(hwnd, SB_HORZ, 1, MAX_X, FALSE);
SetScrollPos(hwnd, SB_HORZ, xLeftOfWin + 1, TRUE);

SetScrollRange(hwnd, SB_VERT, 1, yCurrLine + 1, FALSE);
SetScrollPos(hwnd, SB_VERT, yTopOfWin + 1, TRUE);

return 0;
}

/* --------------------------------------------------------------- */
/* Our WM_DESTROY handler. It frees up storage associated with the */
/* window, and resets its state to uninitialized. */
/* --------------------------------------------------------------- */
LRESULT winio_wmdestroy(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (destroy_func)
(*destroy_func)();
GlobalUnlock(hBuffer);
GlobalUnlock(hKeyboard);
GlobalFree(hBuffer);
GlobalFree(hKeyboard);
tWinioVisible = FALSE;
if (tTerminate) {
exit(0);
PostQuitMessage(0);
}
return 0;
}

/* --------------------------------------------------------------- */
/* Our WM_BYTE handler. It adds the BYTE to the internal kb buffer */
/* if there is room otherwise it queues a BEEP */
/* --------------------------------------------------------------- */
LRESULT winio_wmchar(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
BYTE far *lpchKeybd = fpKeyboard;
unsigned pchSave = pchKbIn;

pchKbIn++;
if (pchKbIn == TYPE_AHEAD)
pchKbIn = 0;
if (pchKbIn == pchKbOut)
{
MessageBeep(0);
pchKbIn = pchSave;
}
else {
*(lpchKeybd + pchSave) = LOBYTE(wParam);
if (LOBYTE(wParam)==0x03)
control_c = 1;
}

return 0;
}

/* --------------------------------------------------------------- */
/* Our WM_KEYDOWN handler. This handles what would be called */
/* function keys in the DOS world. In this case the function keys */
/* operate as scroll bar controls, so we generate messages to the */
/* scroll message handlers below. */
/* --------------------------------------------------------------- */
LRESULT winio_wmkeydown(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int hSB, vSB;

if ((wParam < VK_PRIOR) || (wParam > VK_DOWN))
return 0;

hSB = VKtoSB[wParam - VK_PRIOR].hSB;
vSB = VKtoSB[wParam - VK_PRIOR].vSB;
if (hSB != DO_NOTHING)
SendMessage(hwnd, WM_HSCROLL, hSB, 0L);
if (vSB != DO_NOTHING)
SendMessage(hwnd, WM_VSCROLL, vSB, 0L);
return 0;
}

/* --------------------------------------------------------------- */
/* Our WM_HSCROLL handler. It adjusts what part of the buffer */
/* is visible. It operates as left/right arrow keys. */
/* --------------------------------------------------------------- */
LRESULT winio_wmhscroll(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int cxSave = xLeftOfWin,
xInc = cScrollLR[wParam];

if (xInc == DO_NOTHING)
return 0;
else if (xInc == USE_PARAM)
xLeftOfWin = LOWORD(lParam) - 1;
else
xLeftOfWin += xInc;

if ((xLeftOfWin = max(0, min(MAX_X - 1, xLeftOfWin))) == cxSave)
return 0;

ScrollWindow(hwnd, (cxSave - xLeftOfWin) * cxChar, 0, NULL, NULL);
SetScrollPos(hwnd, SB_HORZ, xLeftOfWin + 1, TRUE);
UpdateWindow(hwnd);

return 0;
}

/* --------------------------------------------------------------- */
/* Our WM_VSCROLL handler. It adjusts what part of the buffer */
/* is visible. It operates as page and line up/down keys. */
/* --------------------------------------------------------------- */
LRESULT winio_wmvscroll(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int cySave = yTopOfWin,
yInc = cScrollUD[wParam],
i;

if (yInc == DO_NOTHING)
return 0;
else if (yInc == USE_PARAM)
yTopOfWin = LOWORD(lParam) - 1;
else
yTopOfWin += yInc;

if ((yTopOfWin = max(0, min(yCurrLine, yTopOfWin))) == cySave)
return 0;

if (yTopOfWin > cySave)
for (i = cySave; i < yTopOfWin; i++)
fpTopOfWin = winio_nextline(fpTopOfWin);
else
for (i = cySave; i > yTopOfWin; i--)
fpTopOfWin = winio_prevline(fpTopOfWin);

ScrollWindow(hwnd, 0, (cySave - yTopOfWin) * cyChar, NULL, NULL);
SetScrollPos(hwnd, SB_VERT, yTopOfWin + 1, TRUE);
UpdateWindow(hwnd);

return 0;
}

/* --------------------------------------------------------------- */
/* Our WM_SETFOCUS handler. It sets up the text caret. */
/* --------------------------------------------------------------- */
LRESULT winio_wmsetfocus(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
CreateCaret(hwnd, NULL, CARET_WIDTH, cyChar);

if ((tCaret = winio_caret_visible()))
{
SetCaretPos((xCurrPos - xLeftOfWin) * cxChar,
(yCurrLine - yTopOfWin) * cyChar);
ShowCaret(hwnd);
}

return 0;
}

/* --------------------------------------------------------------- */
/* Our WM_KILLFOCUS handler. It destroys the text caret. */
/* --------------------------------------------------------------- */
LRESULT winio_wmkillfocus(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (tCaret)
{
HideCaret(hwnd);
tCaret = FALSE;
}
DestroyCaret();
return 0;
}

void winio_set_font(void)
{
HDC hdc;
TEXTMETRIC tm;

hdc = GetDC(hwnd);
SelectObject(hdc, GetStockObject(curr_font));
GetTextMetrics(hdc,&tm);
ReleaseDC(hwnd,hdc);
cxChar = tm.tmAveCharWidth;
cyChar = tm.tmHeight+tm.tmExternalLeading;
xWinWidth = (cxWidth - cxScroll ) / cxChar;
yWinHeight = (cyHeight - cyScroll ) / cyChar;
}

/* --------------------------------------------------------------- */
/* Adjusts the position of the caret, and shows or hides it, as */
/* appropriate. */
/* --------------------------------------------------------------- */
void winio_adjust_caret()
{
int t = winio_caret_visible();

if (t)
SetCaretPos((xCurrPos - xLeftOfWin) * cxChar,
(yCurrLine - yTopOfWin) * cyChar);
if (t && (! tCaret))
ShowCaret(hwnd);
if ((! t) && tCaret)
HideCaret(hwnd);
tCaret = t;
}

/* --------------------------------------------------------------- */
/* Computes, on the basis of what has just been updated, what area */
/* of the window needs to be repainted. */
/* --------------------------------------------------------------- */
void winio_compute_repaint(void)
{
RECT rc;
static int xCP = 0, yCL = 0;
int tWholeWin = FALSE;

if (yCurrLine > (yTopOfWin + yWinHeight))
{
yTopOfWin = 0;
fpTopOfWin = fpBuffer;
while (yTopOfWin < (yCurrLine - ((yWinHeight + 1) / 2)))
{
fpTopOfWin = winio_nextline(fpTopOfWin);
yTopOfWin++;
}
tWholeWin = TRUE;
}

if ((xCurrPos < xLeftOfWin) || (xCurrPos > (xLeftOfWin + xWinWidth)))
{
xLeftOfWin = 0;
while (xLeftOfWin < (xCurrPos - ((xWinWidth + 1) / 2)))
xLeftOfWin++;
tWholeWin = TRUE;
}

if (tWholeWin)
InvalidateRect(hwnd, NULL, TRUE);
else
{
rc.left = ((yCL == yCurrLine) ?
(min(xCP, xCurrPos) - xLeftOfWin) * cxChar : 0);
rc.top = (yCL - yTopOfWin) * cyChar;
rc.right = (xWinWidth + 1) * cxChar;
rc.bottom = (yCurrLine - yTopOfWin + 1) * cyChar;
InvalidateRect(hwnd, &rc, TRUE);
}

yCL = yCurrLine;
xCP = xCurrPos;
}

/* --------------------------------------------------------------- */
/* Adds the supplied cch-long string to the display buffer, and */
/* ensures any changed part of the window is repainted. */
/* --------------------------------------------------------------- */
void winio_addchars(BYTE *pch, unsigned cch)
{
int ycSave = yCurrLine;
int ytSave = yTopOfWin;
int xSave = xLeftOfWin;

winio_make_avail(cch);

winio_append2buffer(pch, cch);

if (ycSave != yCurrLine)
SetScrollRange(hwnd, SB_VERT, 1, yCurrLine + 1, FALSE);

if (! tPaint)
return;

winio_compute_repaint();

cScrollUD[SB_TOP] = -yCurrLine;
cScrollUD[SB_BOTTOM] = yCurrLine;
if (ytSave != yTopOfWin)
SetScrollPos(hwnd, SB_VERT, yTopOfWin + 1, TRUE);

if (xSave != xLeftOfWin)
SetScrollPos(hwnd, SB_HORZ, xLeftOfWin + 1, TRUE);

winio_yield();
}

/* --------------------------------------------------------------- */
/* Add chars onto the display buffer, wrapping at end of line, */
/* expanding tabs, etc. */
/* --------------------------------------------------------------- */
void winio_append2buffer(BYTE *pch, unsigned cch)
{
unsigned i;

for (i = 0; i < cch; i++, pch++)
{
switch (*pch)
{
case '\n' :
*pch = '\0';
*(fpBuffer + bufused) = '\0';
bufused++;
fpCurrLine = fpBuffer + bufused;
yCurrLine++;
xCurrPos = 0;
bufSOI = bufused;
break;
case '\t' :
do {
*(fpBuffer + bufused) = ' ';
bufused++;
xCurrPos++;
} while ((xCurrPos % TABSIZE) != 0);
break;
case EOF :
break;
case '\b' :
if (bufused > bufSOI)
{
bufused--;
xCurrPos--;
}
break;
case 0x1b :
while (bufused > bufSOI)
{
bufused--;
xCurrPos--;
}
break;
case 0x07 :
MessageBeep(0);
break;
default :
if (*pch > 0x1a)
{
if (xCurrPos >= MAX_X)
{
*(fpBuffer + bufused) = '\0';
bufused++;
xCurrPos = 0;
yCurrLine++;
fpCurrLine = fpBuffer + bufused;
}
xCurrPos++;
*(fpBuffer + bufused) = *pch;
bufused++;
}
}
}

*(fpBuffer + bufused) = '\0'; /* '\0' terminator after end of buffer */
}

/* --------------------------------------------------------------- */
/* If we have run out of room in the display buffer, drop whole */
/* lines, and move the remaining buffer up. */
/* --------------------------------------------------------------- */
void winio_make_avail(unsigned cch)
{
unsigned cDiscard = 0;
BYTE far *fpTmp;
unsigned i;

if ((unsigned long)(bufused + cch + TABSIZE) < bufsize)
return;

fpTmp = fpBuffer;
cDiscard = ((max(MIN_DISCARD, cch + 1) + MIN_DISCARD - 1)
/ MIN_DISCARD) /* this gives a whole number of */
* MIN_DISCARD; /* our allocation units. */
fpTmp += (LONG) cDiscard;
fpTmp = winio_nextline(fpTmp);
cDiscard = fpTmp - fpBuffer;
_fmemcpy(fpBuffer, fpTmp, bufused - cDiscard + 1);
bufused -= cDiscard;
if ((int) bufSOI != -1) bufSOI -= cDiscard;
fpTmp = fpBuffer + (LONG) bufused;
for (i = 0; i < cDiscard; i++) *fpTmp++ = '\0';
fpCurrLine = fpBuffer;
xCurrPos = yCurrLine = 0;
for (i = 0; i < bufused; i++)
{
if (*fpCurrLine)
xCurrPos++;
else
{
xCurrPos = 0;
yCurrLine++;
}
fpCurrLine++;
}
xLeftOfWin = yTopOfWin = -9999;

InvalidateRect(hwnd, NULL, TRUE);
}


/* ------------------------------------------------------------------- */
/* These two routines find the beginning of the next, and previous */
/* lines relative to their input pointer */
/* ------------------------------------------------------------------- */

BYTE far *winio_nextline(BYTE far *p) { while (*p) p++; return ++p; }
BYTE far *winio_prevline(BYTE far *p) { p--; do p--; while (*p); return ++p; }

/* ------------------------------------------------------------------- */
/* Waits for a character to appear in the keyboard buffer, yielding */
/* while nothing is available. Then inserts it into the buffer. */
/* ------------------------------------------------------------------- */
int winio_chInput(void)
{
BYTE far *lpchKeyBd;
BYTE c;

CHECK_INIT();
while (pchKbIn == pchKbOut)
winio_yield();

lpchKeyBd = fpKeyboard;
c = *(lpchKeyBd + pchKbOut);

pchKbOut++;
if (pchKbOut == TYPE_AHEAD)
pchKbOut = 0;

/* Do CR/LF and EOF translation */
return (c == 0x1a) ? EOF : (c == '\r') ? '\n' : c;
}


  3 Responses to “Category : Recently Uploaded Files
Archive   : RSXWDK2S.ZIP
Filename : WINIO.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/