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.
778 lines
20 KiB
778 lines
20 KiB
/* File: D:\WACKER\tdll\termupd.c (Created: 11-Dec-1993)
|
|
*
|
|
* Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
|
|
* All rights reserved
|
|
*
|
|
* $Revision: 7 $
|
|
* $Date: 3/27/02 1:35p $
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#pragma hdrstop
|
|
|
|
#include <stdlib.h>
|
|
#include <limits.h>
|
|
|
|
#include "stdtyp.h"
|
|
#include "assert.h"
|
|
#include "session.h"
|
|
#include <emu\emu.h>
|
|
#include <emu\emu.hh>
|
|
#include "update.h"
|
|
#include "update.hh"
|
|
#include "backscrl.h"
|
|
#include "timers.h"
|
|
#include "tdll.h"
|
|
#include "htchar.h"
|
|
#include "term.h"
|
|
#include "term.hh"
|
|
#include "mc.h"
|
|
|
|
static void termUpdate(const HHTERM hhTerm);
|
|
static int termReallocBkBuf(const HHTERM hhTerm, const int iLines);
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* termGetUpdate
|
|
*
|
|
* DESCRIPTION:
|
|
* Queries the update records and emulator to update the terminal image.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhTerm - internal terminal handle.
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*/
|
|
void termGetUpdate(const HHTERM hhTerm, const int fRedraw)
|
|
{
|
|
ECHAR **pachTxt,
|
|
*pachTermTxt,
|
|
*pachEmuTxt;
|
|
PSTATTR *pstAttr,
|
|
pstTermAttr,
|
|
pstEmuAttr;
|
|
int i, j, k, m;
|
|
BYTE *pabLines;
|
|
|
|
// const iRows = hhTerm->iRows;
|
|
// const iCols = hhTerm->iCols;
|
|
const iRows = MAX_EMUROWS;
|
|
const iCols = MAX_EMUCOLS;
|
|
|
|
const HEMU hEmu = sessQueryEmuHdl(hhTerm->hSession);
|
|
const HHUPDATE hUpd = (HHUPDATE)sessQueryUpdateHdl(hhTerm->hSession);
|
|
|
|
/* --- Lock emulators so we have execlusive access --- */
|
|
|
|
emuLock(hEmu);
|
|
|
|
pachTxt = emuGetTxtBuf(hEmu);
|
|
pstAttr = emuGetAttrBuf(hEmu);
|
|
|
|
// Now check to see what needs updating...
|
|
|
|
if (hUpd->bUpdateType == UPD_LINE)
|
|
{
|
|
struct stLineMode *pstLine = &hUpd->stLine;
|
|
|
|
if (pstLine->iLine != -1)
|
|
{
|
|
// The emulators can place the cursor one past the number
|
|
// of columns. Why, I don't know, so we check and adjust
|
|
// so we don't overwrite our client arrays.
|
|
|
|
pstLine->xEnd = min(pstLine->xEnd, iCols);
|
|
assert(pstLine->xBeg <= pstLine->xEnd);
|
|
|
|
k = (pstLine->iLine + hUpd->iTopline) % MAX_EMUROWS;
|
|
|
|
pachEmuTxt = pachTxt[k] + pstLine->xBeg;
|
|
pachTermTxt = hhTerm->fplpstrTxt[k] + pstLine->xBeg;
|
|
|
|
pstEmuAttr = pstAttr[k] + pstLine->xBeg;
|
|
pstTermAttr = hhTerm->fppstAttr[k] + pstLine->xBeg;
|
|
|
|
for (k = pstLine->xEnd - pstLine->xBeg ; k >= 0 ; --k)
|
|
{
|
|
// Televideo uses \xFF as a NULL character.
|
|
|
|
if (*pachEmuTxt == ETEXT('\0') || *pachEmuTxt == ETEXT('\xFF'))
|
|
*pachTermTxt = ETEXT(' ');
|
|
|
|
else
|
|
*pachTermTxt = *pachEmuTxt;
|
|
|
|
*pstTermAttr = *pstEmuAttr;
|
|
|
|
pachTermTxt += 1;
|
|
pachEmuTxt += 1;
|
|
|
|
pstTermAttr += 1;
|
|
pstEmuAttr += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
else if (hUpd->bUpdateType == UPD_SCROLL)
|
|
{
|
|
struct stScrlMode *pstScrl = &hUpd->stScrl;
|
|
|
|
hUpd->iLines = hhTerm->iBkLines =
|
|
backscrlGetNumLines(sessQueryBackscrlHdl(hhTerm->hSession));
|
|
|
|
/* -------------- Backscroll portion ------------- */
|
|
|
|
if ((i = min(hhTerm->iBkLines, pstScrl->iBksScrlInc)) > 0)
|
|
termGetBkLines(hhTerm, i, -i, BKPOS_ABSOLUTE);
|
|
|
|
/* -------------- Terminal portion ------------- */
|
|
|
|
if (pstScrl->iScrlInc != 0)
|
|
{
|
|
if (pstScrl->iScrlInc > 0)
|
|
{
|
|
i = max(0, pstScrl->yEnd - pstScrl->iScrlInc + 1);
|
|
m = pstScrl->yEnd;
|
|
}
|
|
|
|
else
|
|
{
|
|
i = pstScrl->yBeg;
|
|
m = min(iRows, pstScrl->yBeg - pstScrl->iScrlInc - 1);
|
|
}
|
|
|
|
|
|
k = ((i + hUpd->iTopline) % MAX_EMUROWS);
|
|
|
|
for (; i <= m ; ++i)
|
|
{
|
|
// Server and Client have different size emulator images
|
|
// for historical reasons. Server side has 2 extra characters
|
|
// per row.
|
|
|
|
pachTermTxt = hhTerm->fplpstrTxt[k];
|
|
pachEmuTxt = pachTxt[k];
|
|
|
|
pstTermAttr = hhTerm->fppstAttr[k];
|
|
pstEmuAttr = pstAttr[k];
|
|
|
|
// Update the terminal buffer now.
|
|
|
|
for (j = 0 ; j < iCols ; ++j, ++pachTermTxt, ++pachEmuTxt)
|
|
{
|
|
// Televideo uses \xFF as a NULL character.
|
|
|
|
if (*pachEmuTxt == ETEXT('\0') ||
|
|
*pachEmuTxt == ETEXT('\xFF'))
|
|
{
|
|
*pachTermTxt = ETEXT(' ');
|
|
}
|
|
|
|
else
|
|
{
|
|
*pachTermTxt = *pachEmuTxt;
|
|
}
|
|
}
|
|
|
|
MemCopy(pstTermAttr, pstEmuAttr, iCols * sizeof(STATTR));
|
|
|
|
if (++k >= MAX_EMUROWS)
|
|
k = 0;
|
|
}
|
|
}
|
|
|
|
// Check for lines now.
|
|
|
|
k = hUpd->iTopline;
|
|
pabLines = pstScrl->auchLines + pstScrl->iFirstLine;
|
|
|
|
for (j = 0 ; j < iRows ; ++j, ++pabLines)
|
|
{
|
|
if (*pabLines != 0)
|
|
{
|
|
pachEmuTxt = pachTxt[k];
|
|
pachTermTxt = hhTerm->fplpstrTxt[k];
|
|
|
|
pstEmuAttr = pstAttr[k];
|
|
pstTermAttr = hhTerm->fppstAttr[k];
|
|
|
|
// Update the terminal buffer now.
|
|
|
|
for (i = 0 ; i < iCols ; ++i, ++pachTermTxt, ++pachEmuTxt)
|
|
{
|
|
// Televideo uses \xFF as a NULL character.
|
|
|
|
if (*pachEmuTxt == ETEXT('\0') ||
|
|
*pachEmuTxt == ETEXT('\xFF'))
|
|
{
|
|
*pachTermTxt = ETEXT(' ');
|
|
}
|
|
|
|
else
|
|
{
|
|
*pachTermTxt = *pachEmuTxt;
|
|
}
|
|
}
|
|
|
|
MemCopy(pstTermAttr, pstEmuAttr, iCols * sizeof(STATTR));
|
|
}
|
|
|
|
if (++k >= MAX_EMUROWS)
|
|
k = 0;
|
|
}
|
|
|
|
// Another ugly situation. Because we can mark stuff in the
|
|
// backscroll buffer and still have updates coming in, we have
|
|
// to bump the marking region by the scrollinc to keep everything
|
|
// synchronized. Note, we don't need to check for Marking locks
|
|
// because we could not have been here had any been in place.
|
|
|
|
if (hhTerm->ptBeg.y < 0 || hhTerm->ptEnd.y < 0)
|
|
{
|
|
hhTerm->ptBeg.y -= pstScrl->iScrlInc;
|
|
hhTerm->ptEnd.y -= pstScrl->iScrlInc;
|
|
}
|
|
|
|
// Update emulator's topline field now.
|
|
|
|
hhTerm->iTopline = hUpd->iTopline;
|
|
}
|
|
|
|
// Save a copy of the update handle in term. This way we can
|
|
// release our lock and paint without blocking the emulator.
|
|
|
|
*(HHUPDATE)hhTerm->hUpdate = *hUpd;
|
|
updateReset(hUpd);
|
|
|
|
/* --- Important to remember to unlock emulator --- */
|
|
|
|
emuUnlock(hEmu);
|
|
|
|
/* --- Now let the terminal figure out how to paint itself. --- */
|
|
|
|
if (fRedraw)
|
|
termUpdate(hhTerm);
|
|
|
|
return;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* termUpdate
|
|
*
|
|
* DESCRIPTION:
|
|
* Invalidates the proper portions of the terminal buffers, updates
|
|
* scrollbars, and generally takes care of the busy work of keeping
|
|
* the terminal screen up to date.
|
|
*
|
|
* ARGUMENTS:
|
|
* hwnd - terminal window handle
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*/
|
|
static void termUpdate(const HHTERM hhTerm)
|
|
{
|
|
RECT rc;
|
|
int i, j, l;
|
|
BYTE *pauchLines;
|
|
SCROLLINFO scrinf;
|
|
const HHUPDATE hUpd = (HHUPDATE)hhTerm->hUpdate;
|
|
|
|
GetClientRect(hhTerm->hwnd, &rc);
|
|
|
|
// Adjust rectangle not to include indent/outdent areas. This
|
|
// will be ignored if we are scrolling the whole terminal.
|
|
|
|
rc.left += hhTerm->xIndent + (hhTerm->iHScrlPos ? 0 : hhTerm->xBezel);
|
|
rc.right = min(((hhTerm->iCols * hhTerm->xChar) + hhTerm->xIndent + hhTerm->xBezel),
|
|
rc.right);
|
|
|
|
if (hUpd->bUpdateType == UPD_LINE)
|
|
{
|
|
if (hUpd->stLine.iLine != -1)
|
|
{
|
|
rc.top = (hUpd->stLine.iLine -
|
|
hhTerm->iVScrlPos + 1) * hhTerm->yChar;
|
|
|
|
rc.bottom = rc.top + hhTerm->yChar;
|
|
|
|
rc.left = ((hUpd->stLine.xBeg -
|
|
hhTerm->iHScrlPos) * hhTerm->xChar)
|
|
+ hhTerm->xIndent + hhTerm->xBezel;
|
|
|
|
rc.right = ((hUpd->stLine.xEnd -
|
|
hhTerm->iHScrlPos + 1) * hhTerm->xChar)
|
|
+ hhTerm->xIndent + hhTerm->xBezel;
|
|
|
|
// Invalidate entire line when doing italics
|
|
//
|
|
if (hhTerm->fItalic)
|
|
{
|
|
rc.left = 0;
|
|
rc.right = hhTerm->cx;
|
|
}
|
|
|
|
InvalidateRect(hhTerm->hwnd, &rc, FALSE);
|
|
}
|
|
}
|
|
|
|
else if (hUpd->bUpdateType == UPD_SCROLL)
|
|
{
|
|
// Scroll range will change because new text is
|
|
// scrolling into the backscroll region.
|
|
|
|
i = hhTerm->iVScrlMin;
|
|
j = hhTerm->iVScrlMax;
|
|
|
|
if (i == j)
|
|
hhTerm->fBump = FALSE;
|
|
|
|
l = 0;
|
|
|
|
// If bezel is drawn, make sure we have room
|
|
//
|
|
if (hhTerm->xBezel)
|
|
{
|
|
if ((hhTerm->cy % hhTerm->yChar) < (hhTerm->xBezel + 1))
|
|
l = 1;
|
|
}
|
|
|
|
hhTerm->iVScrlMin = min(-hUpd->iLines,
|
|
hhTerm->iRows - hhTerm->iTermHite + 1 + l);
|
|
|
|
// This forces the terminal paint correctly if the minimum
|
|
// number of lines changes such that the current vertical
|
|
// scrolling position is no longer valid. mrw:6/19/95
|
|
//
|
|
if (hhTerm->iVScrlPos < hhTerm->iVScrlMin)
|
|
hhTerm->iVScrlPos = hhTerm->iVScrlMin;
|
|
|
|
if (i != hhTerm->iVScrlMin)
|
|
{
|
|
scrinf.cbSize= sizeof(scrinf);
|
|
scrinf.fMask = SIF_DISABLENOSCROLL | SIF_RANGE | SIF_PAGE;
|
|
scrinf.nMin = hhTerm->iVScrlMin;
|
|
scrinf.nMax = hhTerm->iVScrlMax + hhTerm->iTermHite - 1;
|
|
scrinf.nPage = (unsigned int)hhTerm->iTermHite;
|
|
SetScrollInfo(hhTerm->hwnd, SB_VERT, &scrinf, TRUE);
|
|
}
|
|
|
|
// This is subtle but necessary. When the window is
|
|
// large enough to show full terminal and backscroll
|
|
// and the backscroll is empty, iVScrlPos is 0. The
|
|
// moment the backscroll buffer becomes larger than
|
|
// the backscroll area displayed, the iVScrlPos becomes
|
|
// iVScrlMax in the case where text is coming in at the
|
|
// bottom of the terminal screen. We could update the
|
|
// scrollbar on every pass, but this causes an annoying
|
|
// flicker in the scrollbar. This next piece of code
|
|
// catches the transition from backscroll smaller than
|
|
// displayed area to backscroll greater than displayed
|
|
// area and updates the scrollbar position.
|
|
|
|
// DbgOutStr("bump=%d, Min=%d, Max=%d\r\n",
|
|
// hhTerm->fBump, hhTerm->iVScrlMin, hhTerm->iVScrlMax, 0, 0);
|
|
|
|
if (!hhTerm->fBump && hhTerm->iVScrlMin != hhTerm->iVScrlMax)
|
|
{
|
|
// DbgOutStr("Pos = %d\r\n", hhTerm->iVScrlPos, 0, 0, 0, 0);
|
|
|
|
scrinf.cbSize= sizeof(scrinf);
|
|
scrinf.fMask = SIF_DISABLENOSCROLL | SIF_POS;
|
|
scrinf.nPos = hhTerm->iVScrlPos;
|
|
SetScrollInfo(hhTerm->hwnd, SB_VERT, &scrinf, TRUE);
|
|
hhTerm->fBump = TRUE;
|
|
}
|
|
|
|
// Scroll specified area.
|
|
|
|
rc.top = max(0, hUpd->stScrl.yBeg -
|
|
hhTerm->iVScrlPos + 1) * hhTerm->yChar;
|
|
|
|
rc.bottom = min(hhTerm->iTermHite,
|
|
(hUpd->stScrl.yEnd -
|
|
hhTerm->iVScrlPos + 2)) * hhTerm->yChar;
|
|
|
|
// use iOffset to check for cursor erase operation.
|
|
|
|
if (!hhTerm->fBackscrlLock)
|
|
{
|
|
HideCursors(hhTerm);
|
|
|
|
ScrollWindow(hhTerm->hwnd, 0, -hhTerm->yChar *
|
|
hUpd->stScrl.iScrlInc, (LPRECT)0, &rc);
|
|
|
|
DbgOutStr("scroll %d", -hhTerm->yChar * hUpd->stScrl.iScrlInc,
|
|
0, 0, 0, 0);
|
|
}
|
|
|
|
// Examine the lines portion of update record.
|
|
|
|
// Note, this is a negative area rectangle (ie. top is larger
|
|
// than bottom).
|
|
//
|
|
rc.top = INT_MAX;
|
|
rc.bottom = 0;
|
|
|
|
pauchLines = hUpd->stScrl.auchLines +
|
|
hUpd->stScrl.iFirstLine;
|
|
|
|
for (j = 0 ; j < hhTerm->iRows ; ++j, ++pauchLines)
|
|
{
|
|
if (*pauchLines != (UCHAR)0)
|
|
{
|
|
//iPaintEnd = max(iPaintEnd, j+1);
|
|
DbgOutStr("pauchLines->%d\r\n", j, 0, 0, 0, 0);
|
|
|
|
// Map invalid line to terminal.
|
|
|
|
l = (j - hhTerm->iVScrlPos + 1) * hhTerm->yChar;
|
|
|
|
if (l >= 0)
|
|
{
|
|
rc.top = min(rc.top, l);
|
|
rc.bottom = max(rc.bottom, l + hhTerm->yChar);
|
|
}
|
|
|
|
InvalidateRect(hhTerm->hwnd, &rc, FALSE);
|
|
}
|
|
}
|
|
} /* else */
|
|
|
|
// Update the host cursor position according to the update record.
|
|
// mrw:6/19/95 - comparison was backwards.
|
|
//
|
|
if (hhTerm->ptHstCur.y != hUpd->iRow || hhTerm->ptHstCur.x != hUpd->iCol)
|
|
{
|
|
HideCursors(hhTerm);
|
|
hhTerm->ptHstCur.y = hUpd->iRow;
|
|
hhTerm->ptHstCur.x = hUpd->iCol;
|
|
}
|
|
|
|
// Important to paint now. If we wait, and the
|
|
// backscroll region is also invalid, Windows will take
|
|
// the union of these two rectangles and paint a much
|
|
// larger region of the screen than is needed or wanted.
|
|
// Note: UpdateWindow does nothing if the update region
|
|
// in empty.
|
|
|
|
UpdateWindow(hhTerm->hwnd);
|
|
|
|
// Now take care of the backscroll buffer.
|
|
|
|
i = hUpd->stScrl.iBksScrlInc;
|
|
|
|
if (i && hUpd->bUpdateType == UPD_SCROLL)
|
|
{
|
|
rc.top = 0;
|
|
rc.bottom = min(hhTerm->iTermHite, -hhTerm->iVScrlPos) * hhTerm->yChar;
|
|
|
|
if (rc.bottom > rc.top && !hhTerm->fBackscrlLock)
|
|
{
|
|
HideCursors(hhTerm);
|
|
ScrollWindow(hhTerm->hwnd, 0, -hhTerm->yChar * i, (LPRECT)0, &rc);
|
|
UpdateWindow(hhTerm->hwnd);
|
|
}
|
|
|
|
else if (hhTerm->fBackscrlLock)
|
|
{
|
|
hhTerm->iVScrlPos -= i;
|
|
scrinf.cbSize= sizeof(scrinf);
|
|
scrinf.fMask = SIF_DISABLENOSCROLL | SIF_POS;
|
|
scrinf.nPos = hhTerm->iVScrlPos;
|
|
SetScrollInfo(hhTerm->hwnd, SB_VERT, &scrinf, TRUE);
|
|
}
|
|
}
|
|
|
|
// Important to do this again before we turn the host cursor
|
|
// back on.
|
|
// Note: UpdateWindow does nothing if the update region
|
|
// is empty.
|
|
|
|
UpdateWindow(hhTerm->hwnd);
|
|
ShowCursors(hhTerm);
|
|
return;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* termGetBkLines
|
|
*
|
|
* DESCRIPTION:
|
|
* This function is uglier than ulgy. This function updates the local
|
|
* backscroll buffer after it has been filled by backscrlCFillLocalBk().
|
|
* This function only graps the actual number of lines it needs to update
|
|
* the local backscroll page. The reason it is complex is because the
|
|
* server also stores it's backscroll buffer in pages. If this routine
|
|
* requires data from more than one page, it must repeatedly ask the
|
|
* server until the request is satisfied. Some assumptions are made
|
|
* here (and in backscrlCFillLocalBk()). First and foremost, requests
|
|
* are never made beyond the backscroll region. The caller's of these
|
|
* routines does this right now. Second, if x number of lines are asked
|
|
* for, this routine will continue to try until it meets the request.
|
|
* Again, the callers are smart enough not to exceed the backscroll ranges.
|
|
*
|
|
* ARGUMENTS:
|
|
* HHTERM hhTerm -- internal terminal handle
|
|
* int iScrlInc -- the # of lines and the direction scrolled
|
|
* int yBeg -- depends on sType
|
|
* int iType -- if BKPOS_THUMBPOS, yBeg is the thumb pos.
|
|
* if BKPOS_ABSOLUTE, yBeg is absolute pos.
|
|
*
|
|
* RETURNS:
|
|
* nothing
|
|
*
|
|
*/
|
|
void termGetBkLines(const HHTERM hhTerm, const int iScrlInc, int yBeg, int sType)
|
|
{
|
|
int i, j, k, l;
|
|
int iWant, iGot;
|
|
int iOffset;
|
|
ECHAR *pachTxt, // terminal buffer
|
|
*pachBkTxt; // engine buffer
|
|
const HBACKSCRL hBackscrl = sessQueryBackscrlHdl(hhTerm->hSession);
|
|
|
|
if (abs(iScrlInc) > hhTerm->iPhysicalBkRows)
|
|
{
|
|
termFillBk(hhTerm, yBeg);
|
|
return;
|
|
}
|
|
|
|
// Get needed backscroll text from server
|
|
|
|
if (iScrlInc < 0)
|
|
{
|
|
assert(sType != BKPOS_ABSOLUTE);
|
|
i = iScrlInc;
|
|
|
|
// l is a wrap counter and is calculated for speed.
|
|
//
|
|
l = hhTerm->iNextBkLn = (hhTerm->iNextBkLn +
|
|
hhTerm->iPhysicalBkRows + iScrlInc) % hhTerm->iPhysicalBkRows;
|
|
}
|
|
|
|
else
|
|
{
|
|
if (sType == BKPOS_THUMBPOS)
|
|
{
|
|
yBeg += hhTerm->iTermHite - iScrlInc;
|
|
assert(yBeg < 0);
|
|
}
|
|
|
|
i = 0;
|
|
}
|
|
|
|
// Since backscroll memory is pages we have to make multiple requests.
|
|
//
|
|
for (iWant=abs(iScrlInc), iGot=0 ; iWant > 0 ; iWant-=iGot, yBeg+=iGot)
|
|
{
|
|
if (backscrlGetBkLines(hBackscrl, yBeg, iWant, &iGot, &pachBkTxt,
|
|
&iOffset) == FALSE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pachBkTxt += iOffset;
|
|
|
|
// Apply text to backscroll buffer
|
|
|
|
if (iScrlInc < 0)
|
|
{
|
|
for (k=0 ; (i < 0) && (k < iGot) ; ++i, ++k)
|
|
{
|
|
pachTxt = hhTerm->fplpstrBkTxt[l];
|
|
|
|
for (j = 0 ; j < MAX_EMUCOLS && *pachBkTxt != ETEXT('\n') ; ++j)
|
|
{
|
|
assert(*pachBkTxt);
|
|
*pachTxt++ = *pachBkTxt++;
|
|
}
|
|
|
|
for ( ; j < MAX_EMUCOLS ; ++j)
|
|
*pachTxt++ = ' ';
|
|
|
|
pachBkTxt += 1; // Blow past newline marker...
|
|
|
|
if (++l >= hhTerm->iPhysicalBkRows)
|
|
l = 0;
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
for (k=0 ; (i < iScrlInc) && (k < iGot) ; ++i, ++k)
|
|
{
|
|
pachTxt = hhTerm->fplpstrBkTxt[hhTerm->iNextBkLn];
|
|
|
|
for (j = 0 ; j < MAX_EMUCOLS && *pachBkTxt != ETEXT('\n') ; ++j)
|
|
{
|
|
assert(*pachBkTxt != ETEXT('\0'));
|
|
*pachTxt++ = *pachBkTxt++;
|
|
}
|
|
|
|
for ( ; j < MAX_EMUCOLS ; ++j)
|
|
*pachTxt++ = ETEXT(' ');
|
|
|
|
if (++hhTerm->iNextBkLn >= hhTerm->iPhysicalBkRows)
|
|
hhTerm->iNextBkLn = 0;
|
|
|
|
pachBkTxt += 1; // Blow past newline marker...
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* termFillBk
|
|
*
|
|
* DESCRIPTION:
|
|
* This routine fills an entire local (refering a view) backscroll buffer.
|
|
* It is called only three times. Whenever the transistion is made from
|
|
* active backscrolling to static backscrolling. When the Scroll
|
|
* increment during a static backscroll operation is greater than the size
|
|
* of the view (and therefore the number of lines in the backscroll buffer
|
|
* as denoted by hhTerm->iPhysicalBkRows). And when the terminal window
|
|
* is resized.
|
|
*
|
|
* ARGUMENTS:
|
|
* HHTERM hhTerm -- internal terminal handle
|
|
* int iTermHite -- # of rows that will fit on current terminal
|
|
* int iBkPos -- where to start in backscroll
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*/
|
|
void termFillBk(const HHTERM hhTerm, const int iBkPos)
|
|
{
|
|
int i, j;
|
|
int iWant,
|
|
iGot,
|
|
yBeg;
|
|
int iOffset;
|
|
ECHAR **fplpstrBkTxt,
|
|
*pachTxt, // terminal buffer
|
|
*pachBkTxt; //
|
|
const HBACKSCRL hBackscrl = sessQueryBackscrlHdl(hhTerm->hSession);
|
|
|
|
if (hhTerm->iTermHite > hhTerm->iMaxPhysicalBkRows)
|
|
{
|
|
if (termReallocBkBuf(hhTerm, hhTerm->iTermHite) != 0)
|
|
{
|
|
assert(FALSE);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* --- Empty the rest of terminal's backscroll buffer --- */
|
|
|
|
for (i = 0 ; i < hhTerm->iPhysicalBkRows ; ++i)
|
|
ECHAR_Fill(hhTerm->fplpstrBkTxt[i], EMU_BLANK_CHAR, MAX_EMUCOLS);
|
|
|
|
/* --- Grab whatever we can from the engine's backscroll buffer --- */
|
|
|
|
hhTerm->iPhysicalBkRows = hhTerm->iTermHite;
|
|
hhTerm->iNextBkLn = 0;
|
|
|
|
// mrw: 2/29/96 - moved the check for an empty buffer to past where
|
|
// the iPhyscialRows gets set.
|
|
//
|
|
if (hhTerm->iBkLines == 0)
|
|
return;
|
|
|
|
//*yBeg = iBkPos;
|
|
yBeg = max(-hhTerm->iBkLines, iBkPos);
|
|
iWant = min(hhTerm->iTermHite, abs(yBeg));
|
|
fplpstrBkTxt = hhTerm->fplpstrBkTxt + (hhTerm->iTermHite - iWant);
|
|
|
|
for (iGot=0 ; iWant > 0 ; iWant-=iGot, yBeg+=iGot)
|
|
{
|
|
if (backscrlGetBkLines(hBackscrl, yBeg, iWant, &iGot, &pachBkTxt,
|
|
&iOffset) == FALSE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pachBkTxt += iOffset;
|
|
|
|
for (i = 0 ; i < iGot ; ++i, ++fplpstrBkTxt)
|
|
{
|
|
pachTxt = *fplpstrBkTxt;
|
|
|
|
for (j = 0 ; j < MAX_EMUCOLS && *pachBkTxt != ETEXT('\n') ; ++j)
|
|
{
|
|
assert(*pachBkTxt);
|
|
*pachTxt++ = *pachBkTxt++;
|
|
}
|
|
|
|
for ( ; j < MAX_EMUCOLS ; ++j)
|
|
*pachTxt++ = ETEXT(' ');
|
|
|
|
pachBkTxt += 1;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* termReallocBkBuf
|
|
*
|
|
* DESCRIPTION:
|
|
* This happens when the user changes to a smaller font which allows more
|
|
* rows on the screen.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhTerm - private terminal handle
|
|
* iLines - number of lines to realloc
|
|
*
|
|
* RETURNS:
|
|
* 0=OK, 1=error
|
|
*
|
|
*/
|
|
static int termReallocBkBuf(const HHTERM hhTerm, const int iLines)
|
|
{
|
|
int i;
|
|
ECHAR** pTempfplpstrBkTxt = NULL;
|
|
|
|
if (iLines < hhTerm->iMaxPhysicalBkRows)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
pTempfplpstrBkTxt =
|
|
(ECHAR**)realloc(hhTerm->fplpstrBkTxt,
|
|
(unsigned int)iLines * sizeof(ECHAR *));
|
|
|
|
if (pTempfplpstrBkTxt == NULL)
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
hhTerm->fplpstrBkTxt = pTempfplpstrBkTxt;
|
|
}
|
|
|
|
for (i = hhTerm->iMaxPhysicalBkRows ; i < iLines ; ++i)
|
|
{
|
|
if ((hhTerm->fplpstrBkTxt[i] = malloc(MAX_EMUCOLS * sizeof(ECHAR)))
|
|
== 0)
|
|
{
|
|
assert(FALSE);
|
|
return 1;
|
|
}
|
|
|
|
ECHAR_Fill(hhTerm->fplpstrBkTxt[i], EMU_BLANK_CHAR, MAX_EMUCOLS);
|
|
}
|
|
|
|
hhTerm->iMaxPhysicalBkRows = iLines;
|
|
return 0;
|
|
}
|