Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1268 lines
34 KiB

/* File: D:\WACKER\tdll\termpnt.c (Created: 11-Dec-1993)
*
* Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
* All rights reserved
*
* $Revision: 3 $
* $Date: 5/09/01 4:38p $
*/
// #define DEBUGSTR 1
#include <windows.h>
#pragma hdrstop
#include "stdtyp.h"
#include "assert.h"
#include "timers.h"
#include "htchar.h"
#include <emu\emu.h>
#include "mc.h"
#include "term.hh"
static
void TextAttrOut(const HHTERM hhTerm,
const HDC hDC,
const int x,
const int y,
const ECHAR *lpachText,
const PSTATTR apstAttrs,
const int fForceRight,
const int nCount,
const int iRow,
const int iCol);
static int MapCells(const ECHAR *each, const int nStrLen, const int nCellPos);
void termPaint(const HHTERM hhTerm, const HWND hwnd)
{
PAINTSTRUCT ps;
RECT rc, rci;
HBRUSH hBrush;
HFONT hFont;
int i, j, k, l, m, n;
int iOffset;
int iPaintBeg;
int iPaintEnd;
int xr, xl;
ECHAR **fplpstrTxt;
POINT ptTemp;
const int iScrlInc = hhTerm->yChar;
const HDC hdc = BeginPaint(hwnd, &ps);
#ifndef CHAR_NARROW
int x;
int fRight;
ECHAR aechTmpBuf[MAX_EMUCOLS + 1];
#endif
SetTextAlign(hdc, TA_BOTTOM);
SelectObject(hdc, hhTerm->hbrushTerminal);
hFont = (HFONT)SelectObject(hdc, hhTerm->hFont);
iPaintBeg = max(hhTerm->iVScrlMin,
hhTerm->iVScrlPos + (ps.rcPaint.top / hhTerm->yChar));
iPaintEnd = min(hhTerm->iRows + 1, hhTerm->iVScrlPos +
((min(hhTerm->iTermHite * hhTerm->yChar, ps.rcPaint.bottom) +
hhTerm->yChar - 1) / hhTerm->yChar));
rc = ps.rcPaint;
/* -------------- xl is calculation of left edge. ------------- */
if (hhTerm->iHScrlPos == 0)
xl = 0;
else
xl = min(0, -(hhTerm->iHScrlPos * hhTerm->xChar)
- hhTerm->xBezel + hhTerm->xChar);
/* -------------- xr = right edge of text. ------------- */
xr = xl + (hhTerm->iCols * hhTerm->xChar) + hhTerm->xIndent
+ hhTerm->xBezel;
if (ps.rcPaint.bottom > (i = ((hhTerm->iTermHite
- (hhTerm->xBezel ? 1 : 0)) * hhTerm->yChar)))
{
// Only draw between bottom line and top of the bezel, since the
// bezel gets drawn below anyway. If no bezel, fill to the bottom
// of the terminal window.
//
rc.top = max(rc.top, i);
rc.bottom = min(rc.bottom,
hhTerm->cy - ((hhTerm->iVScrlMax == hhTerm->iVScrlPos) ?
hhTerm->xBezel : 0));
rc.left += (xl == 0 && iPaintEnd > 0 && rc.left == 0) ?
hhTerm->xBezel : 0;
rc.right = min(rc.right, xr + hhTerm->xIndent);
FillRect(hdc, &rc, (iPaintEnd < 0) ? hhTerm->hbrushBackScrl :
hhTerm->hbrushTerminal);
}
// Could be space beyond the emulator screen (ie. hi-res monitor)
// that needs filling with the approproiate color.
if (ps.rcPaint.right > xr)
{
rc.left = xr;
ptTemp.x = 0;
ptTemp.y = hhTerm->yBrushOrg;
ClientToScreen(hwnd, &ptTemp);
if (iPaintBeg <= 0)
{
rc.top = (-hhTerm->iVScrlPos + iPaintBeg) * hhTerm->yChar;
rc.bottom = (iPaintEnd <= 0) ? ps.rcPaint.bottom :
(-hhTerm->iVScrlPos + min(1, iPaintEnd)) * hhTerm->yChar;
rc.right = rc.left + hhTerm->xIndent + hhTerm->xBezel;
FillRect(hdc, &rc, hhTerm->hbrushBackScrl);
rc.right = ps.rcPaint.right;
if (i)
{
SetBkColor(hdc, hhTerm->crBackScrl);
SetBrushOrgEx(hdc, ptTemp.x, ptTemp.y, NULL);
rc.left += hhTerm->xIndent + hhTerm->xBezel;
if (hhTerm->xBezel)
FillRect(hdc, &rc, hhTerm->hbrushBackScrl);
else
FillRect(hdc, &rc, hhTerm->hbrushBackHatch);
rc.left -= hhTerm->xIndent + hhTerm->xBezel;
}
}
if (iPaintEnd >= 0)
{
rc.top = (-hhTerm->iVScrlPos + max(1, iPaintBeg)) * hhTerm->yChar
- hhTerm->yChar/2;
rc.bottom = ps.rcPaint.bottom;
rc.right = rc.left + hhTerm->xIndent;
FillRect(hdc, &rc, hhTerm->hbrushTerminal);
rc.right = ps.rcPaint.right;
if (i)
{
SetBkColor(hdc, hhTerm->crTerm);
SetBrushOrgEx(hdc, ptTemp.x, ptTemp.y, 0);
rc.left += hhTerm->xIndent + hhTerm->xBezel;
if (hhTerm->xBezel)
FillRect(hdc, &rc, hhTerm->hbrushBackScrl);
else
FillRect(hdc, &rc, hhTerm->hbrushTermHatch);
}
}
}
// Fill in the indent margin along the left side of the terminal.
if (ps.rcPaint.left < (hhTerm->xIndent +
(hhTerm->iHScrlPos ? 0 : hhTerm->xBezel)))
{
rc.left = ps.rcPaint.left;
rc.right = hhTerm->xIndent + (hhTerm->iHScrlPos ? 0 : hhTerm->xBezel);
// When scrolling down during marking, corners were left unpainted.
// This guy corrects that. - mrw
if (iPaintBeg < 0)
{
rc.top = (-hhTerm->iVScrlPos + iPaintBeg) * hhTerm->yChar;
rc.bottom = (-hhTerm->iVScrlPos + min(0,iPaintEnd)) * hhTerm->yChar;
FillRect(hdc, &rc, hhTerm->hbrushBackScrl);
}
if (iPaintEnd > 0)
{
// The top & bottom should only redraw from & to the bezel.
// that is all that's needed...
//
rc.top = (-hhTerm->iVScrlPos + max(1, iPaintBeg)) *
hhTerm->yChar;
rc.bottom = (hhTerm->iVScrlPos == hhTerm->iVScrlMax) ?
hhTerm->cy - hhTerm->xBezel : ps.rcPaint.bottom;
rc.left = max(ps.rcPaint.left,
((hhTerm->iHScrlPos == 0) ? hhTerm->xBezel : 0));
FillRect(hdc, &rc, hhTerm->hbrushTerminal);
}
// New outdented bezel style requires filling with gray between
// bezel and left edge.
if (hhTerm->iHScrlPos == 0 && ps.rcPaint.left <= OUTDENT &&
iPaintEnd > 0)
{
rc.top = (-hhTerm->iVScrlPos + max(0, iPaintBeg)) * hhTerm->yChar;
rc.bottom = (-hhTerm->iVScrlPos + iPaintEnd + 2) * hhTerm->yChar;
rc.right = OUTDENT;
rc.left = ps.rcPaint.left;
FillRect(hdc, &rc, hhTerm->hbrushBackScrl);
}
}
/* -------------- Paint bezel here ------------- */
if (hhTerm->xBezel)
{
/* -------------- Left edge ------------- */
if (iPaintEnd >= 0)
{
// n is the width of the thick gray section of the bezel.
// we surround the thick gray part with four lines of
// of white and gray lines. That's why we subtract 4.
n = hhTerm->xBezel - OUTDENT - 4;
/* -------------- Left edge ------------- */
rc.left = xl + OUTDENT;
rc.right = rc.left + hhTerm->xBezel;
k = ((hhTerm->iVScrlMax - hhTerm->iVScrlPos + hhTerm->iTermHite)
* hhTerm->yChar) + (hhTerm->cy % hhTerm->yChar);
rc.top = (-hhTerm->iVScrlPos * hhTerm->yChar) + OUTDENT;
rc.bottom = k - OUTDENT;
if (IntersectRect(&rci, &rc, &ps.rcPaint))
{
/* --- Paint outer border --- */
SelectObject(hdc, hhTerm->hWhitePen);
MoveToEx(hdc, rc.left, rc.top++, NULL);
LineTo(hdc, rc.left++, rc.bottom--);
MoveToEx(hdc, rc.left, rc.top++, NULL);
LineTo(hdc, rc.left++, rc.bottom--);
/* --- Paint middle portion --- */
rc.right = rc.left + n;
FillRect(hdc, &rc, hhTerm->hbrushBackScrl);
rc.left += n;
rc.top += n;
rc.bottom -= n;
/* --- Paint inner border --- */
SelectObject(hdc, hhTerm->hDkGrayPen);
MoveToEx(hdc, rc.left, rc.top++, NULL);
LineTo(hdc, rc.left++, rc.bottom--);
SelectObject(hdc, hhTerm->hBlackPen);
MoveToEx(hdc, rc.left, rc.top, NULL);
LineTo(hdc, rc.left, rc.bottom);
}
/* -------------- Bottom edge ------------- */
rc.left = xl + OUTDENT;
rc.right = xr + hhTerm->xIndent + hhTerm->xBezel - 1 - OUTDENT;
l = rc.right; // save for right side.
rc.bottom = k;
rc.top = rc.bottom - hhTerm->xBezel;
if (IntersectRect(&rci, &rc, &ps.rcPaint))
{
/* --- Paint from bezel to bottom of screen --- */
m = rc.top;
rc.top = rc.bottom - OUTDENT;
FillRect(hdc, &rc, hhTerm->hbrushBackScrl);
rc.top = m;
rc.bottom -= OUTDENT + 1;
/* --- Paint outer border --- */
SelectObject(hdc, hhTerm->hBlackPen);
MoveToEx(hdc, rc.left++, rc.bottom, NULL);
LineTo(hdc, rc.right--, rc.bottom--);
SelectObject(hdc, hhTerm->hDkGrayPen);
MoveToEx(hdc, rc.left++, rc.bottom, NULL);
LineTo(hdc, rc.right--, rc.bottom);
/* --- Paint middle portion --- */
rc.top = rc.bottom - n;
FillRect(hdc, &rc, hhTerm->hbrushBackScrl);
rc.left += n;
rc.right -= n-1;
rc.bottom -= n;
/* --- Paint inner border --- */
SelectObject(hdc, hhTerm->hWhitePen);
MoveToEx(hdc, rc.left++, rc.bottom, NULL);
LineTo(hdc, rc.right--, rc.bottom--);
MoveToEx(hdc, rc.left++, rc.bottom, NULL);
LineTo(hdc, rc.right--, rc.bottom--);
SelectObject(hdc, hhTerm->hDkGrayPen);
MoveToEx(hdc, rc.left++, rc.bottom, NULL);
LineTo(hdc, rc.right--, rc.bottom--);
/* --- Fill in the bottom below bezel --- */
rc.top = k;
rc.bottom = rc.top + OUTDENT;
rc.left = xl + OUTDENT;
rc.right = l + 1;
FillRect(hdc, &rc, hhTerm->hbrushBackScrl);
}
/* -------------- Right edge ------------- */
rc.top = (-hhTerm->iVScrlPos * hhTerm->yChar) + OUTDENT;
rc.bottom = k;
rc.right = l + OUTDENT + 1;
rc.left = rc.right - hhTerm->xBezel;
if (IntersectRect(&rci, &rc, &ps.rcPaint))
{
/* --- Paint outdent region --- */
rc.left = l;
FillRect(hdc, &rc, hhTerm->hbrushBackScrl);
rc.bottom -= OUTDENT;
rc.right -= OUTDENT + 1;
/* --- Paint outer border --- */
SelectObject(hdc, hhTerm->hBlackPen);
MoveToEx(hdc, rc.right, rc.top++, NULL);
LineTo(hdc, rc.right--, rc.bottom--);
SelectObject(hdc, hhTerm->hDkGrayPen);
MoveToEx(hdc, rc.right, rc.top++, NULL);
LineTo(hdc, rc.right, rc.bottom--);
/* --- Paint middle portion --- */
rc.left = rc.right - n;
FillRect(hdc, &rc, hhTerm->hbrushBackScrl);
rc.top += n-1;
rc.right -= n;
rc.bottom -= n-1;
/* --- Paint inner border --- */
SelectObject(hdc, hhTerm->hWhitePen);
MoveToEx(hdc, rc.right, rc.top++, NULL);
LineTo(hdc, rc.right--, rc.bottom--);
MoveToEx(hdc, rc.right, rc.top++, NULL);
LineTo(hdc, rc.right--, rc.bottom--);
SelectObject(hdc, hhTerm->hDkGrayPen);
MoveToEx(hdc, rc.right, rc.top++, NULL);
LineTo(hdc, rc.right--, rc.bottom--);
/* --- Fill area to right of bezel --- */
rc.left = l + 1;
rc.right = rc.left + OUTDENT;
rc.top = -hhTerm->iVScrlPos * hhTerm->yChar;
rc.bottom = k + OUTDENT;
FillRect(hdc, &rc, hhTerm->hbrushBackScrl);
}
}
}
// Paint backscroll buffer. Stuff going into the backscroll
// region is always on a line basis. You'll notice that the
// calculation for l in the terminal area portion is more
// complicated since stuff comes in at times on a character
// basis. l represents the number of characters in the
// character string to paint.
i = iPaintBeg;
if (i < iPaintEnd && i < 0)
{
j = (ps.rcPaint.left - hhTerm->xIndent
- (hhTerm->iHScrlPos ? 0 : hhTerm->xBezel)) / hhTerm->xChar;
j = max(j, 0);
k = (j * hhTerm->xChar) + hhTerm->xIndent
+ (hhTerm->iHScrlPos ? 0 : hhTerm->xBezel);
j += hhTerm->iHScrlPos - (hhTerm->xBezel && hhTerm->iHScrlPos ? 1:0);
l = min(hhTerm->iCols - j,
(ps.rcPaint.right + hhTerm->xChar - 1 - k) / hhTerm->xChar);
fplpstrTxt = hhTerm->fplpstrBkTxt;
m = hhTerm->iPhysicalBkRows;
if (hhTerm->fBackscrlLock == TRUE)
iOffset = (abs(hhTerm->iVScrlPos - i) + hhTerm->iNextBkLn) % m;
else
iOffset = (m + i + hhTerm->iNextBkLn) % m;
n = iScrlInc * (-hhTerm->iVScrlPos + i);
#ifdef CHAR_NARROW
for ( ; i < iPaintEnd && i < 0 ; i+=1, n+=iScrlInc)
{
TextAttrOut(hhTerm, hdc, k, n, fplpstrTxt[iOffset]+j,
(PSTATTR)0, FALSE, l, i, j);
if (++iOffset >= m)
iOffset = 0;
}
#else
// This little hack is here to display wide (Kanji) characters in
// the backscroll, without all of the fuss of adding attributes.
// It forces the backscroll to always paint the
// enitre row, and strips out the repeated left/right pairs
j = (OUTDENT - (hhTerm->iHScrlPos ? 0 : hhTerm->xBezel)) / hhTerm->xChar;
j = max(j, 0);
k = (j * hhTerm->xChar) + OUTDENT
+ (hhTerm->iHScrlPos ? 0 : hhTerm->xBezel);
j += hhTerm->iHScrlPos - (hhTerm->xBezel && hhTerm->iHScrlPos ? 1:0);
l = hhTerm->iCols - j;
for ( ; i < iPaintEnd && i < 0 ; i+=1, n+=iScrlInc)
{
// Hack for starting on the right half of a DB char
fRight = FALSE;
for (x = 0; x <= j; )
{
if (isDBCSChar(*(fplpstrTxt[iOffset]+x)))
{
fRight = (x == j) ? FALSE : TRUE;
x += 2;
}
else
{
fRight = FALSE;
x += 1;
}
}
memset(aechTmpBuf, 0, sizeof(aechTmpBuf));
StrCharStripDBCSString(aechTmpBuf, sizeof(aechTmpBuf),
fplpstrTxt[iOffset]+j); //mpt:12-11-97 too many parameters? , l * sizeof(ECHAR));
TextAttrOut(hhTerm, hdc, k, n, aechTmpBuf,
(PSTATTR)0, fRight, l, i, j);
if (++iOffset >= m)
iOffset = 0;
}
#endif
}
/* -------------- Paint divider bar if necessary ------------- */
for ( ; i == 0 ; ++i)
{
if (hhTerm->xBezel)
{
// n is the width of the thick gray section of the bezel.
// we surround the thick gray part with four lines of
// of white and gray lines. That's why we subtract 4.
n = hhTerm->xBezel - OUTDENT - 4;
rc.top = -hhTerm->iVScrlPos * hhTerm->yChar;
rc.bottom = rc.top + OUTDENT;
rc.left = ps.rcPaint.left;
rc.right = ps.rcPaint.right;
/* --- Paint gap above divider bar --- */
FillRect(hdc, &rc, hhTerm->hbrushBackScrl);
rc.left = xl + hhTerm->xBezel + hhTerm->xIndent;
rc.right = xr;
/* --- If hightlighting, paint gap above divider --- */
if (min(hhTerm->ptBeg.y, hhTerm->ptEnd.y) < 0 &&
max(hhTerm->ptBeg.y, hhTerm->ptEnd.y) > 0)
{
FillRect(hdc, &rc, hhTerm->hbrushHighlight);
}
rc.left = xl + OUTDENT;
rc.right = xr + hhTerm->xIndent + hhTerm->xBezel - OUTDENT - 1;
/* --- note: order is important, bottom, top --- */
rc.bottom = rc.top + hhTerm->yChar;
rc.top += OUTDENT;
/* --- Paint top outside border --- */
SelectObject(hdc, hhTerm->hWhitePen);
MoveToEx(hdc, rc.left++, rc.top, NULL);
LineTo(hdc, rc.right--, rc.top++);
MoveToEx(hdc, rc.left++, rc.top, NULL);
LineTo(hdc, rc.right--, rc.top++);
/* --- Paint middle section --- */
m = rc.bottom;
rc.bottom = rc.top + n;
FillRect(hdc, &rc, hhTerm->hbrushBackScrl);
rc.bottom = m;
rc.left += n;
rc.top += n;
rc.right -= n;
/* --- Paint bottom border --- */
SelectObject(hdc, hhTerm->hDkGrayPen);
MoveToEx(hdc, rc.left++, rc.top, NULL);
LineTo(hdc, rc.right--, rc.top++);
SelectObject(hdc, hhTerm->hBlackPen);
MoveToEx(hdc, rc.left++, rc.top, NULL);
LineTo(hdc, rc.right, rc.top++);
/* --- Fill in any space left below the bezel --- */
FillRect(hdc, &rc, hhTerm->hbrushTerminal);
if (min(hhTerm->ptBeg.y, hhTerm->ptEnd.y) < 0 &&
max(hhTerm->ptBeg.y, hhTerm->ptEnd.y) > 0)
{
rc.left = hhTerm->xIndent;
rc.left += (hhTerm->iHScrlPos) ? 0 : hhTerm->xBezel;
rc.right -= hhTerm->xIndent;
FillRect(hdc, &rc, hhTerm->hbrushHighlight);
}
}
else
{
j = (hhTerm->yChar * -hhTerm->iVScrlPos);
k = (hhTerm->yChar) / 3;
// Create highlight brush if textmarking crosses divider
if (min(hhTerm->ptBeg.y, hhTerm->ptEnd.y) < 0 &&
max(hhTerm->ptBeg.y, hhTerm->ptEnd.y) > 0)
{
hBrush = hhTerm->hbrushHighlight;
}
else
{
hBrush = 0;
}
rc = ps.rcPaint;
rc.top = j;
rc.bottom = j + k + (hhTerm->yChar % 3);
l = rc.right =
((hhTerm->iCols - hhTerm->iHScrlPos) * hhTerm->xChar)
+ hhTerm->xIndent + hhTerm->xIndent +
hhTerm->xBezel + hhTerm->xBezel;
FillRect(hdc, &rc, (hBrush != (HBRUSH)0) ?
hBrush :
hhTerm->hbrushBackScrl);
rc.top = rc.bottom;
rc.bottom = rc.top + k;
rc.right = ps.rcPaint.right;
FillRect(hdc, &rc, hhTerm->hbrushDivider);
rc.top = rc.bottom;
rc.bottom = j + hhTerm->yChar;
rc.right = l;
FillRect(hdc, &rc, (hBrush != (HBRUSH)0) ?
hBrush :
hhTerm->hbrushTerminal);
}
}
/* -------------- Paint the active terminal portion. ------------- */
xl = (hhTerm->iHScrlPos) ? 0 : hhTerm->xBezel;
if (i < iPaintEnd)
{
j = (ps.rcPaint.left - hhTerm->xIndent - xl) / hhTerm->xChar;
j = max(j, 0);
k = (j * hhTerm->xChar) + hhTerm->xIndent + xl;
j += hhTerm->iHScrlPos - (hhTerm->xBezel && hhTerm->iHScrlPos ? 1:0);
l = min(hhTerm->iCols - j,
(ps.rcPaint.right + hhTerm->xChar - 1 - k) / hhTerm->xChar);
// Formulas to convert from terminal to buffer row and back.
// b = (t - 1 + top) % rows
// t = (b + rows - top) % rows
// t is always between 1 and rows+1.
iOffset = (i - 1 + hhTerm->iTopline) % MAX_EMUROWS;
n = iScrlInc * (-hhTerm->iVScrlPos + i);
for ( ; i < iPaintEnd ; i += 1, n += iScrlInc)
{
TextAttrOut(hhTerm, hdc, k, n, hhTerm->fplpstrTxt[iOffset]+j,
hhTerm->fppstAttr[iOffset]+j, FALSE, l, i, j);
if (++iOffset >= MAX_EMUROWS)
iOffset = 0;
}
}
/* --- Draw cursors --- */
if (hhTerm->fHstCurOn)
{
hhTerm->fHstCurOn = FALSE;
PaintHostCursor(hhTerm, TRUE, hdc);
}
if (hhTerm->fLclCurOn)
{
hhTerm->fLclCurOn = FALSE;
PaintLocalCursor(hhTerm, TRUE, hdc);
}
/* --- cleanup time --- */
SelectObject(hdc, GetStockObject(WHITE_BRUSH));
SelectObject(hdc, GetStockObject(BLACK_PEN));
SelectObject(hdc, hFont);
EndPaint(hwnd, &ps);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* TextAttrOut
*
* DESCRIPTION:
* Draws text and attributes on the terminal screen. Optimizes call to
* TextOut based on attributes. For example, If attributes are all the
* same for a given line, then only one call to TextOut is made.
*
* ARGUMENTS:
* HHTERM hhTerm - internal terminal handle
* HDC hdc - Device context from WM_PAINT
* int x - x offset in pixels
* int y - y offset in pixels
* ECHAR *lpachText - long pointer to begining of text to print
* PSTATTR apstAttrs - Array of pointers to attribute structures
* int fForceRight - used for DBCS in the backscroll
* int nCount - number of characters to draw.
* int iRow - logical row being displayed
* int iCol - logical col being displayed
*
* RETURNS:
* void
*
*/
static void TextAttrOut(const HHTERM hhTerm,
const HDC hdc,
const int x,
const int y,
const ECHAR *lpachText,
const PSTATTR apstAttrs,
const int fForceRight,
const int nCount,
const int iRow,
const int iCol)
{
int i = 0, // track of how many chars drawn.
j, // number of characters in a run.
k, // offset where run began.
nXPos;
int nXStart, nYStart; // screen pos where chars are drawn.
#ifndef CHAR_NARROW
int nByteCount = 0;
#endif
int nBegAdj = 0;
int nEndAdj = 0;
int nStrLen = 0;
TCHAR achBuf[MAX_EMUCOLS * 2];
ECHAR aechTmp[MAX_EMUCOLS + 1];
PSTATTR pstAttr = 0;
unsigned int uTxtclr, uBkclr;
BOOL fUnderlnFont = FALSE;
BOOL fSymbolFont = FALSE;
BOOL fDblHiHi = FALSE;
BOOL fDblHiLo = FALSE;
BOOL fDblWiLf = FALSE;
BOOL fDblWiRt = FALSE;
BOOL fWiLf = FALSE;
BOOL fWiRt = FALSE;
BOOL fFirstPass = TRUE;
RECT rc;
DbgOutStr("TAO %d\r\n", iRow, 0, 0, 0, 0);
while (i < nCount)
{
k = i; // save offset of where this run begins in k.
if (iRow < 0)
{
int nCurPos;
long l,
lBeg,
lEnd;
BOOL fMarking = FALSE;
// Store the positions of the 1st char to draw
nCurPos = i;
// This check is a speed tweak. If the marking and backscrl
// locks are off, we know that no text is can be marked. This
// would be the normal case when stuff is streaming into the
// terminal so we save the work done of the else body by
// by checking and thus speed up the display.
// For Far East we have to force the backscroll to paint every
// character individualy. This is becuase MicroSquish is not
// able to provide fixed pitch fonts that are fixed pitch for
// DBCS characters.
//
if (hhTerm->fMarkingLock == FALSE &&
hhTerm->fBackscrlLock == FALSE &&
hhTerm->iEvenFont == TRUE)
{
SetBkColor(hdc, hhTerm->crBackScrl);
SetTextColor(hdc, hhTerm->crBackScrlTxt);
i = j = nCount;
}
else
{
#ifdef CHAR_NARROW
lBeg = hhTerm->ptBeg.y * hhTerm->iCols + hhTerm->ptBeg.x;
lEnd = hhTerm->ptEnd.y * hhTerm->iCols + hhTerm->ptEnd.x;
#else
// Hack city man :)
// In the mouse handling routines, we modify the selection
// cursor position so that you can't put it into the middle
// of a wide character. The problem is that at this
// point the repeated characters have been removed.
// Therefore we need to modify the cursor position to take
// into account the number of repeated characters that
// were removed from the string as of our current drawing
// position into that string.
// pant, pant, pant.
lBeg = hhTerm->ptBeg.x;
lEnd = hhTerm->ptEnd.x;
if (hhTerm->ptBeg.y == iRow)
{
lBeg = MapCells(lpachText , hhTerm->iCols, hhTerm->ptBeg.x);
}
if (hhTerm->ptEnd.y == iRow)
{
lEnd = MapCells(lpachText , hhTerm->iCols, hhTerm->ptEnd.x);
}
if (hhTerm->iEvenFont)
{
nBegAdj = lBeg - hhTerm->ptBeg.x;
nEndAdj = lEnd - hhTerm->ptEnd.x;
}
else
{
nBegAdj = 0;
nEndAdj = 0;
}
lBeg = hhTerm->ptBeg.y * hhTerm->iCols + lBeg;
lEnd = hhTerm->ptEnd.y * hhTerm->iCols + lEnd;
#endif
if (lBeg > lEnd)
{
l = lEnd;
lEnd = lBeg;
lBeg = l;
}
// IN_RANGE macro is inclusive so subtract one from sEnd
// which at this point is known to be larger than sBeg
lEnd -= 1;
l = iRow * hhTerm->iCols + i + iCol;
fMarking = (BOOL)IN_RANGE(l, lBeg, lEnd);
if (fMarking)
{
SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
}
else
{
SetBkColor(hdc, hhTerm->crBackScrl);
SetTextColor(hdc, hhTerm->crBackScrlTxt);
}
// For Far East we have to force the backscroll to paint every
// character individualy. This is becuase MicroSquish is not
// able to provide fixed pitch fonts that are fixed pitch for
// DBCS characters.
if (hhTerm->iEvenFont)
{
for (j = 0 ; i < nCount ; ++i, ++j, ++l)
{
if (fMarking != (BOOL)IN_RANGE(l, lBeg, lEnd))
break;
}
}
else
{
i++;
j = 1;
}
}
nXPos = k = i - j;
#ifndef CHAR_NARROW
if (nCurPos > 0) // Only copy the buffer if nCurPos > 0. REV: 04/11/2001.
{
MemCopy(aechTmp, lpachText , (unsigned)nCurPos * sizeof(ECHAR));
nXPos = CnvrtECHARtoMBCS(achBuf, sizeof(achBuf), aechTmp, (unsigned)nCurPos * sizeof(ECHAR));
//nXPos = StrCharGetByteCount(achBuf); // mrw;5/17/95
}
// 18-May-1995 DLW
// Added for the case where a DBCS string is started with half of
// the character, like when scrolling to the right
if (fForceRight && fFirstPass)
{
fWiRt = TRUE;
}
else
{
if (fForceRight)
nXPos = max(0, nXPos - 1);
}
#endif
}
// At this point we know were not painting in the backscrl area.
// Since the terminal area has attributes that backscrl does not
// have (ie. color, underlining, etc.) we need to do more work.
//
else
{
pstAttr = apstAttrs+i;
uTxtclr = pstAttr->txtclr;
uBkclr = pstAttr->bkclr;
// Test for attributes
if (pstAttr->revvid)
{
unsigned uTmp = uTxtclr;
uTxtclr = uBkclr;
uBkclr = uTmp;
}
if (pstAttr->hilite)
{
// Colors are arranged so that high intensity colors are
// in the lower half of the color array (currently 16
// colors corresponding to the IBM PC colors). This
// guy sets the color to the opposite intensity.
uTxtclr = (uTxtclr + (MAX_EMUCOLORS/2)) % MAX_EMUCOLORS;
if (uTxtclr == uBkclr)
uTxtclr = (uTxtclr + 1) % MAX_EMUCOLORS;
}
if (pstAttr->bklite)
{
uBkclr = (uBkclr + (MAX_EMUCOLORS/2)) % MAX_EMUCOLORS;
if (uBkclr == uTxtclr)
uBkclr = (uBkclr + 1) % MAX_EMUCOLORS;
}
if (pstAttr->blink)
{
int iBufRow;
if (hhTerm->iBlink == 0)
hhTerm->iBlink = 1;
if (hhTerm->iBlink == -1)
uTxtclr = uBkclr;
iBufRow = (iRow - 1 + hhTerm->iTopline) % MAX_EMUROWS;
hhTerm->abBlink[iBufRow] = (BYTE)TRUE;
}
if (pstAttr->undrln)
fUnderlnFont = TRUE;
if (pstAttr->blank)
uTxtclr = uBkclr;
// Only allow one double height attribute
//
if (pstAttr->dblhihi)
fDblHiHi = TRUE;
else if (pstAttr->dblhilo)
fDblHiLo = TRUE;
// Only allow one double wide attribute
//
if (pstAttr->dblwilf)
fDblWiLf = TRUE;
else if (pstAttr->dblwirt)
fDblWiRt = TRUE;
// Only allow one wide attribute
//
if (pstAttr->wilf)
fWiLf = TRUE;
else if (pstAttr->wirt)
fWiRt = TRUE;
// If the symbol attribute is on, use alternate font.
//
if (pstAttr->symbol)
fSymbolFont = TRUE;
// Find the longest run of characters with the same attributes.
//
for (j = 0 ; i < nCount ; ++i, ++j)
{
if (memcmp(pstAttr, apstAttrs+i, sizeof(STATTR)) != 0)
break;
}
/* --- Set text and background colors --- */
if (pstAttr->txtmrk)
{
SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
}
else
{
SetBkColor(hdc, hhTerm->pacrEmuColors[uBkclr]);
SetTextColor(hdc, hhTerm->pacrEmuColors[uTxtclr]);
}
/* --- How hard can it be to pick a font? --- */
if (fDblHiHi || fDblHiLo)
{
if (fDblWiLf || fDblWiRt)
{
if (fSymbolFont)
{
if (hhTerm->hSymDblHiWiFont == 0)
hhTerm->hSymDblHiWiFont = termMakeFont(hhTerm, 0, 1, 1, 1);
SelectObject(hdc, hhTerm->hSymDblHiWiFont);
}
else
{
if (hhTerm->hDblHiWiFont == 0)
hhTerm->hDblHiWiFont = termMakeFont(hhTerm, 0, 1, 1, 0);
SelectObject(hdc, hhTerm->hDblHiWiFont);
}
}
else
{
if (fSymbolFont)
{
if (hhTerm->hSymDblHiFont == 0)
hhTerm->hSymDblHiFont = termMakeFont(hhTerm, 0, 1, 0, 1);
SelectObject(hdc, hhTerm->hSymDblHiFont);
}
else
{
if (hhTerm->hDblHiFont == 0)
hhTerm->hDblHiFont = termMakeFont(hhTerm, 0, 1, 0, 0);
SelectObject(hdc, hhTerm->hDblHiFont);
}
}
}
else if (fDblWiLf || fDblWiRt)
{
if (fSymbolFont)
{
if (hhTerm->hSymDblWiFont == 0)
hhTerm->hSymDblWiFont = termMakeFont(hhTerm, 0, 0, 1, 1);
SelectObject(hdc, hhTerm->hSymDblWiFont);
}
else
{
if (hhTerm->hDblWiFont == 0)
hhTerm->hDblWiFont = termMakeFont(hhTerm, 0, 0, 1, 0);
SelectObject(hdc, hhTerm->hDblWiFont);
}
}
else if (fSymbolFont)
{
if (hhTerm->hSymFont == 0)
hhTerm->hSymFont = termMakeFont(hhTerm, 0, 0, 0, 1);
SelectObject(hdc, hhTerm->hSymFont);
}
nXPos = k = i - j;
}
// Ok, go ahead, paint that text, make my day...
// Guess I better explain myself here. When Windows synthesizes
// a font to get something like bold or italic, TextOut has a nasty
// habit of adding a pixel to the end of the string (be it a
// character or a run of characters). This is documented in the
// TEXTMETRIC structure in the description of tmOverHang. This has
// some unfortunate side effects (Don't believe me? Try defing the
// old stuff back in, select a bold font and do some hightlighting
// and scrolling). The solution is to explicitly clip so that text
// is drawn only where I say it can draw. This amounts in extra
// work but the end result seems no slower. - mrw
//
rc.left = x + (nXPos * hhTerm->xChar);
#if defined(FAR_EAST)
if (rc.left > (x + (hhTerm->iCols * hhTerm->xChar)))
rc.left = x + (hhTerm->iCols * hhTerm->xChar);
#endif
rc.right = rc.left + ((j - nEndAdj) * hhTerm->xChar);
if (rc.right > (x + (hhTerm->iCols * hhTerm->xChar)))
rc.right = x + (hhTerm->iCols * hhTerm->xChar);
rc.top = y;
rc.bottom = y + hhTerm->yChar;
// If we're painting the bottom half of a double high character,
// we need to raise the origin of where the character is drawn
// by an additional char height. The clipping rectangle insures
// that only the cell portion is actually drawn.
nYStart = (fDblHiHi) ? rc.bottom + hhTerm->yChar : rc.bottom;
// More painting tricks. If we're painting double wide characters
// we'll be painting them one at a time. Why you ask? Well, this
// routine tries to paint the longest run of characters with the
// same attributes. Just makes good windows sense. In the case
// of double wide however, the attributes come as double-wide left,
// double-wide right. Since the "double-wide" character has a
// different attribute in its left side and right side, this
// routine will paint each half one at a time (seperate calls to
// ExtTextOut()). This is useful and wanted. Because we clip
// the drawing area to the cell or cells region, we can draw the
// right half by offsetting the x origin by one character cell
// to the left. Windows clipping logic will only draw in the
// actual cell region so we get the right half of the character.
// Lot of explaination for one measely line of code.
//
nXStart = (fDblWiRt || fWiRt) ? rc.left - hhTerm->xChar : rc.left;
/* --- Hero of the day, ExtTextOut! --- */
MemCopy(aechTmp, lpachText + k, (unsigned int)j * sizeof(ECHAR));
nStrLen = CnvrtECHARtoMBCS(achBuf, sizeof(achBuf), aechTmp,
(unsigned)j * sizeof(ECHAR)); //mrw:5/17/95
achBuf[nStrLen] = TEXT('\0');
#if defined(FAR_EAST) // mrw:10/10/95 - ifdef'ed this code
if (!hhTerm->iEvenFont && !(fForceRight && fFirstPass))
{
// If this is a DBCS character we are painting, then we want to paint 2 cells
// instead of 1 (makes sense, DBCS characters are twice as wide as SBCS).
if (IsDBCSLeadByte(*achBuf))
{
rc.right += hhTerm->xChar;
rc.right = min(rc.right, x + (hhTerm->iCols * hhTerm->xChar));
}
}
#endif
ExtTextOut(hdc, nXStart, nYStart, ETO_CLIPPED | ETO_OPAQUE,
&rc, achBuf, (unsigned)nStrLen, 0);
// Experiment. Most terminals underline their fonts by placing
// underscores under the characters. The Windows underline font
// places a thin line through the baseline of the character.
// Many hosts use underlining in conjunction with box draw chars
// to envelop regions of the screen. The underscores complete
// envelope and don't give the apperance of part of the characters
// bleeding through. - mrw
//
if (fUnderlnFont)
{
// The double height makes the underscores too thick yet we
// want to maintain the double-wide or symbol font we may be
// using so check and recast the font to the samething without
// the height component. - mrw
//
if (fDblHiHi || fDblHiLo)
{
if (fDblWiLf || fDblWiRt)
{
if (fSymbolFont)
{
if (hhTerm->hSymDblWiFont == 0)
hhTerm->hSymDblWiFont = termMakeFont(hhTerm, 0, 0, 1, 1);
SelectObject(hdc, hhTerm->hSymDblWiFont);
}
else
{
if (hhTerm->hDblWiFont == 0)
hhTerm->hDblWiFont = termMakeFont(hhTerm, 0, 0, 1, 0);
SelectObject(hdc, hhTerm->hDblWiFont);
}
}
else if (fSymbolFont)
{
if (hhTerm->hSymFont == 0)
hhTerm->hSymFont = termMakeFont(hhTerm, 0, 0, 0, 1);
SelectObject(hdc, hhTerm->hSymFont);
}
else
{
SelectObject(hdc, hhTerm->hFont);
}
}
// Set background to transparent so only the underscore
// portion overpaints the character cell.
//
SetBkMode(hdc, TRANSPARENT);
ExtTextOut(hdc, nXStart, nYStart, ETO_CLIPPED,
&rc, hhTerm->underscores, (unsigned)j, 0);
SetBkMode(hdc, OPAQUE);
}
/* --- Reselect the regular font only if we had to switch --- */
if (fUnderlnFont || fDblHiHi || fDblHiLo || fDblWiLf || fDblWiRt
|| fSymbolFont)
{
SelectObject(hdc, hhTerm->hFont);
fUnderlnFont = FALSE;
fSymbolFont = FALSE;
fDblHiHi = FALSE;
fDblHiLo = FALSE;
fDblWiLf = FALSE;
fDblWiRt = FALSE;
}
fWiRt = FALSE;
fWiLf = FALSE;
fFirstPass = FALSE;
}
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* MapCells
*
* DESCRIPTION:
* Maps screen cell position to internal screen image (echar image) position
*
* ARGUMENTS:
* each - source string (does it start from beg of line?)
* nStrLen - length in bytes
* nCellPos - screen position to
*
* RETURNS:
* void
*
*/
static int MapCells(const ECHAR *each, const int nStrLen, const int nCellPos)
{
int i, nCount;
if (each == NULL)
{
assert(FALSE);
return 0;
}
for (i = 0, nCount = 0; nCount < nCellPos && i < nStrLen; i++)
{
if (isDBCSChar(each[i]))
{
nCount += 2;
}
else
{
nCount += 1;
}
}
return i;
}