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

1953 lines
61 KiB

/*
Enhanced NCSA Mosaic from Spyglass
"Guitar"
Copyright 1994 Spyglass, Inc.
All Rights Reserved
Author(s):
Eric W. Sink [email protected]
Jim Seidman [email protected]
*/
#include "all.h"
#ifdef FEATURE_IMG_THREADS
#include "safestrm.h"
#include "decoder.h"
#endif
#include "marquee.h"
#include "mci.h"
#include "blob.h"
#ifdef FEATURE_VRML
#include "vrml.h"
#endif
extern struct ImageInfo iiNotLoaded;
extern struct ImageInfo iiMissing;
#define MIN_HEIGHT_PLACETEXT (24)
#define MIN_WIDTH_PLACETEXT (30)
#define PLACE_BORDER (4)
#ifdef FEATURE_INTL
BOOL TextOutWithMIME(int iMimeCharSet, HDC hDC, int nX, int nY, LPCTSTR lpStr, int cch);
BOOL ExtTextOutWithMIME(int iMimeCharSet, HDC hDC, int nX, int nY, UINT fuOpt, CONST RECT *lprc, LPCTSTR lpStr, UINT cch, CONST int *lpDx);
void DrawYankedUnderLine(HDC hdc, struct _element *pel, int off_left, int off_top, struct GTRFont *pFont, COLORREF anchor_color, COLORREF anchor_color_beenthere);
#endif
static BOOL GDI_Rect(HDC hdc, RECT *r)
{
return Rectangle(hdc, r->left, r->top, r->right, r->bottom);
}
static void TW_DrawPlaceholder(struct Mwin *tw, int off_left, int off_top, struct _element *pel,BOOL bDrawIconText)
{
struct ImageInfo *myImage = pel->myImage;
RECT rText;
RECT rFrame;
RECT rto;
HBRUSH hBrush;
struct ImageInfo *pii;
int width;
int height;
int border;
if ((!bDrawIconText) && myImage->transparent >= 0) return;
ASSERT(pel); // there is an assumption that pel is never NULL here
#ifdef FEATURE_VRML
// Never draw the placeholder once the VRML window's been created
//
if (pel->pVrml && pel->pVrml->hWnd) return;
#endif
rto = pel->r;
#ifdef FEATURE_CLIENT_IMAGEMAP
border = (pel->lFlags & (ELEFLAG_ANCHOR | ELEFLAG_USEMAP)) ? pel->border : 0;
#else
border = (pel->lFlags & (ELEFLAG_ANCHOR)) ? pel->border : 0;
#endif
OffsetRect(&rto, -off_left, -off_top);
rto.left += border;
rto.right -= border;
rto.top += border;
rto.bottom -= border;
#ifdef DAYTONA_BUILD
if(OnNT351)
hBrush = (HBRUSH)GetSysColor(COLOR_BTNSHADOW);
else
hBrush = GetSysColorBrush(COLOR_3DDKSHADOW/*COLOR_BTNSHADOW*/);
#else
hBrush = GetSysColorBrush(COLOR_3DDKSHADOW/*COLOR_BTNSHADOW*/);
#endif
/* left */
rFrame.left = rto.left;
rFrame.right = rto.left + 1;
rFrame.top = rto.top;
rFrame.bottom = rto.bottom - 1;
FillRect(tw->hdc, &rFrame, hBrush);
/* top */
rFrame.left = rto.left;
rFrame.right = rto.right - 1;
rFrame.top = rto.top;
rFrame.bottom = rto.top + 1;
FillRect(tw->hdc, &rFrame, hBrush);
DeleteObject(hBrush);
#ifdef DAYTONA_BUILD
if(OnNT351)
hBrush = (HBRUSH)GetSysColor(COLOR_BTNFACE/*COLOR_3DLIGHT*//*COLOR_3DHIGHLIGHT*/);
else
hBrush = GetSysColorBrush(COLOR_BTNHIGHLIGHT/*COLOR_3DLIGHT*//*COLOR_3DHIGHLIGHT*/);
#else
hBrush = GetSysColorBrush(COLOR_BTNHIGHLIGHT/*COLOR_3DLIGHT*//*COLOR_3DHIGHLIGHT*/);
#endif
/* right */
rFrame.left = rto.right - 1;
rFrame.right = rto.right;
rFrame.top = rto.top;
rFrame.bottom = rto.bottom;
FillRect(tw->hdc, &rFrame, hBrush);
/* bottom */
rFrame.left = rto.left;
rFrame.right = rto.right;
rFrame.top = rto.bottom - 1;
rFrame.bottom = rto.bottom;
FillRect(tw->hdc, &rFrame, hBrush);
DeleteObject(hBrush);
rto.left += 1;
rto.right -= 1;
rto.top += 1;
rto.bottom -= 1;
/* Draw the appropriate icon */
if (myImage->flags & (IMG_MISSING | IMG_ERROR))
pii = &iiMissing;
else
pii = &iiNotLoaded;
// if we're a blob, and we failed to load, then note this.
// BUGBUG need to handle case were low src image is valid, but BLOB is not
if ( pel->pblob && (pel->pblob->dwFlags & BLOB_FLAGS_ERROR))
pii = &iiMissing;
rFrame = rto;
rFrame.top += PLACE_BORDER;
rFrame.left += PLACE_BORDER;
rFrame.bottom -= PLACE_BORDER;
rFrame.right -= PLACE_BORDER;
if ((rFrame.bottom - rFrame.top) > MIN_HEIGHT_PLACETEXT &&
(rFrame.right - rFrame.left) > (pii->width + (PLACE_BORDER + MIN_WIDTH_PLACETEXT)))
{
rFrame.right = rFrame.left + pii->width;
if ((rFrame.bottom - rFrame.top) > pii->height)
rFrame.bottom = rFrame.top + pii->height;
if (bDrawIconText && pel->textLen)
{
rText = rto;
rText.left = rFrame.right + PLACE_BORDER;
rText.top += 2 + PLACE_BORDER;
SelectObject(tw->hdc, wg.hFont);
DrawText(tw->hdc, &(tw->w3doc->pool[pel->textOffset]), pel->textLen, &rText, DT_LEFT | DT_WORDBREAK | DT_NOPREFIX);
}
}
else
{
if ((rFrame.bottom - rFrame.top) > pii->height)
rFrame.bottom = rFrame.top + pii->height;
if ((rFrame.right - rFrame.left) > pii->width)
rFrame.right = rFrame.left + pii->width;
}
if (bDrawIconText && pii->data && pii->pbmi)
{
width = rFrame.right - rFrame.left;
height = rFrame.bottom - rFrame.top;
if (width > 0 && height > 0)
StretchDIBits(tw->hdc, rFrame.left, rFrame.top,
width, height,
0, 0 + (pii->height-height), width, height,
pii->data, pii->pbmi, DIB_RGB_COLORS, SRCCOPY);
}
}
static void TW_DrawAnchorFrame(struct Mwin *tw, int off_left, int off_top, struct _element *pel,COLORREF anchor_color, COLORREF anchor_color_beenthere)
{
RECT rFrame;
HBRUSH hBrush;
if (pel->border <= 0) return;
if (pel->lFlags & ELEFLAG_VISITED)
{
hBrush = CreateSolidBrush(anchor_color_beenthere);
}
else
{
hBrush = CreateSolidBrush(anchor_color);
}
/* left */
rFrame.left = pel->r.left - off_left;
rFrame.right = pel->r.left - off_left + pel->border;
rFrame.top = pel->r.top - off_top;
rFrame.bottom = pel->r.bottom - off_top;
FillRect(tw->hdc, &rFrame, hBrush);
/* right */
rFrame.left = pel->r.right - off_left - pel->border;
rFrame.right = pel->r.right - off_left;
FillRect(tw->hdc, &rFrame, hBrush);
/* top */
rFrame.left = pel->r.left - off_left;
rFrame.right = pel->r.right - off_left;
rFrame.top = pel->r.top - off_top;
rFrame.bottom = pel->r.top - off_top + pel->border;
FillRect(tw->hdc, &rFrame, hBrush);
/* bottom */
rFrame.top = pel->r.bottom - off_top - pel->border;
rFrame.bottom = pel->r.bottom - off_top;
FillRect(tw->hdc, &rFrame, hBrush);
DeleteObject(hBrush);
}
//
// Get the non-dithered color that best matches the given color
//
// On entry:
// hDC: device context
// ActualColor: color to match
// hPalGuitar: (global) our half-tone palette
//
// Return:
// COLORREF of a non-dithered color that best matched the ActualColor
//
COLORREF GetBestColor( HDC hDC, COLORREF ActualColor )
{
// Are we 8-bit palette?
if (wg.eColorMode == 8)
{
// Yes, get nearest palette index and turn into a palette index COLORREF
int ix = GetNearestPaletteIndex( hPalGuitar, ActualColor );
return PALETTEINDEX(ix);
} else {
// No, use system to get nearest color
return GetNearestColor( hDC, ActualColor );
}
}
//
// Get the colr settings for a given top level window
//
// On entry:
// tw: top level window
// pBackgroundColor: address of background color
// pTextColor: address of text color
// pAnchorColor: address of anchor color
// pVisitedAnchorColor: address of visited anchor color
//
// On exit:
// *pBackgroundColor: background color
// *pTextColor: text color
// *pAnchorColor: anchor color
// *pVisitedAnchorColor: visited anchor color
//
static void GetCurrentColors( struct Mwin *tw,
COLORREF *pBackgroundColor, COLORREF *pTextColor,
COLORREF *pAnchorColor, COLORREF *pVisitedAnchorColor )
{
ASSERT( pBackgroundColor ); ASSERT( pTextColor );
ASSERT( pAnchorColor ); ASSERT( pVisitedAnchorColor );
//
// Get text and background color based on preference settings
//
if ( gPrefs.bUseDlgBoxColors ) {
*pTextColor = GetSysColor(COLOR_WINDOWTEXT);
*pBackgroundColor = GetSysColor(COLOR_3DFACE);
} else {
*pTextColor = gPrefs.window_text_color;
*pBackgroundColor = gPrefs.window_background_color;
}
*pVisitedAnchorColor = gPrefs.anchor_color_beenthere;
*pAnchorColor = gPrefs.anchor_color;
//
// Check to see if document is overriding the preference settings
//
if ( tw && tw->w3doc ) {
DOC_COLOR_INFO dci = tw->w3doc->docColorInfo;
if ( dci.flags & COLOR_INFO_FLAG_BACKGROUND )
*pBackgroundColor = dci.rgbBackgroundColor;
if ( dci.flags & COLOR_INFO_FLAG_TEXT )
*pTextColor = dci.rgbTextColor;
if ( dci.flags & COLOR_INFO_FLAG_VLINK )
*pVisitedAnchorColor = dci.rgbVisitedLinkColor;
if ( dci.flags & COLOR_INFO_FLAG_LINK )
*pAnchorColor = dci.rgbLinkColor;
}
//
// Adjust all colors to nearest color available
//
*pBackgroundColor = GetBestColor(tw->hdc, *pBackgroundColor);
*pTextColor = GetBestColor(tw->hdc, *pTextColor);
*pVisitedAnchorColor = GetBestColor(tw->hdc, *pVisitedAnchorColor);
*pAnchorColor = GetBestColor(tw->hdc, *pAnchorColor);
}
#define USE_BITBLT_COUNT 8
#define MIN_BITMAP_PIXELS 64
//
// Tile Background Image source onto the destination
//
// On entry:
// tw: top level window
// pRect: destination rectangle
// myImage: background image
// the_background_color: background color to use
// the_text_color: foreground color
//
// Returns:
// TRUE -> success
// FALSE -> failure
//
static int TileBackgroundImage( struct Mwin *tw, int off_left, int off_top, RECT *pRect, struct ImageInfo *myImage,
COLORREF the_background_color, COLORREF the_text_color )
{
int ix, iy;
RECT r = *pRect;
HBITMAP hBM = NULL;
HBITMAP hOldBM = NULL;
HDC hDCBM = NULL;
BOOL use_bm = FALSE;
BOOL done = FALSE;
BOOL result = TRUE;
int cx = myImage->width;
int cy = myImage->height;
UINT iUsage = (wg.eColorMode == 8 ? DIB_PAL_COLORS : DIB_RGB_COLORS);
int adj_cx = cx;
int adj_cy = cy;
int iy_count;
int ix_count;
int adj_iy_count = 1;
int adj_ix_count = 1;
OffsetRect( &r, off_left, off_top); // ajdust destination rect for tile offset
if ( cx == 0 || cy == 0 ) // make sure there's some work to be done
return FALSE;
iy_count = (cy - 1 + r.bottom - r.top) / cy; // number of cells wide
ix_count = (cx - 1 + r.right - r.left) / cx; // number of cells tall
//
// Now let's see if its worth it to make a bitmap and use BitBlt
//
// Note: On transparent images we always make a bitmap, as the double
// buffering averts screen flicker
//
if ( (myImage->transparent >= 0) || (iy_count * ix_count >= USE_BITBLT_COUNT) ) {
//
// For small images, we'll pre-tile into the bitmap
//
if ( cx * cy <= MIN_BITMAP_PIXELS * MIN_BITMAP_PIXELS ) {
int min_x_bitmap_pixels = min(pRect->right - pRect->left,MIN_BITMAP_PIXELS);
int min_y_bitmap_pixels = min(pRect->bottom - pRect->top,MIN_BITMAP_PIXELS);
adj_ix_count = (min_x_bitmap_pixels + (cx - 1)) / cx; // number of cells wide in bitmap
adj_iy_count = (min_y_bitmap_pixels + (cy - 1)) / cy; // number of cells tall in bitmap
adj_cx = cx * adj_ix_count;
adj_cy = cy * adj_iy_count;
}
hDCBM = CreateCompatibleDC( tw->hdc );
hBM = CreateCompatibleBitmap( tw->hdc, adj_cx, adj_cy );
if ( hDCBM && hBM ) {
GTR_RealizePalette( hDCBM );
hOldBM = SelectObject( hDCBM, hBM );
// Write top left cell's worth of bits
if ( myImage->transparent >= 0 ) {
DIBENV dibenv;
BOOL bSavebErase = tw->bErase;
// Setup dibenv for image draws
dibenv.colorBg = GetNearestColor(tw->hdc, the_background_color);
dibenv.colorFg = GetNearestColor(tw->hdc, the_text_color);
if (wg.eColorMode == 8)
{
dibenv.colorIdxBg = GetNearestPaletteIndex(hPalGuitar, dibenv.colorBg);
dibenv.colorIdxFg = GetNearestPaletteIndex(hPalGuitar, dibenv.colorFg);
}
dibenv.tw = tw;
dibenv.bFancyBg = (dibenv.colorBg != the_background_color);
dibenv.transparent = myImage->transparent;
dibenv.rectPaint.left = 0;
dibenv.rectPaint.top = 0;
dibenv.rectPaint.right = cx;
dibenv.rectPaint.bottom = cy;
tw->bErase = FALSE;
if ( dibenv.bFancyBg ) {
HBRUSH hBrush = CreateSolidBrush( the_background_color );
// Fill with background color
SetBrushOrgEx( hDCBM, 7 - (off_left % 8), 7 - (off_top % 8), NULL );
FillRect( hDCBM, &dibenv.rectPaint, hBrush );
DeleteObject( hBrush);
}
use_bm = MyStretchDIBits( hDCBM,
0, 0, cx, cy,
0, 0, cx, cy,
myImage->data, myImage->pbmi, iUsage, SRCCOPY, &dibenv );
tw->bErase = bSavebErase;
} else {
use_bm = StretchDIBits( hDCBM,
0, 0, cx, cy,
0, 0, cx, cy,
myImage->data, myImage->pbmi, iUsage, SRCCOPY );
}
// Now see if we need to pre-tile into bitmap
if ( use_bm && (adj_iy_count > 1 || adj_ix_count > 1) ) {
for ( ix = 0; ix < adj_ix_count; ix++ ) {
for ( iy = 0; iy < adj_iy_count; iy++ ) {
if ( ix != 0 || iy != 0 ) {
if ( !BitBlt( hDCBM, ix * cx, iy * cy, cx, cy,
hDCBM, 0, 0, SRCCOPY ) )
use_bm = FALSE;
}
}
}
// If all went well, we'll use the pre-tiled bitmap
if ( use_bm ) {
cx = adj_cx;
cy = adj_cy;
}
}
}
}
//
// Tile onto destination
//
for ( iy = r.top / cy; iy <= r.bottom / cy && !done; iy++ ) {
for ( ix = r.left / cx; ix <= r.right / cx && !done; ix++ ) {
if ( use_bm )
result = BitBlt( tw->hdc, ix * cx - off_left, iy * cy - off_top, cx, cy,
hDCBM, 0, 0, SRCCOPY );
else
result = StretchDIBits( tw->hdc,
ix * cx - off_left, iy * cy - off_top, cx, cy,
0, 0, cx, cy,
myImage->data, myImage->pbmi, iUsage, SRCCOPY );
done = !result;
}
}
//
// Clean up
//
if ( hDCBM && hBM )
SelectObject( hDCBM, hOldBM );
if ( hBM )
DeleteObject( hBM );
if ( hDCBM )
DeleteDC( hDCBM );
return result;
}
//
// FillRect the given rectangle with the given color
//
// On entry:
// tw: top level window
// pRectWnd: pointer to rect that need background filled
// background_color: color to use
//
// Note: Brush origin is set so that dithered background color is drawn correctly
// when window has been scrolled.
//
static void FillBackgroundRect( struct Mwin *tw, int off_left, int off_top, RECT *pRectWnd, COLORREF background_color )
{
HBRUSH hBrush = CreateSolidBrush( background_color );
SetBrushOrgEx( tw->hdc, 7 - (off_left % 8), 7 - (off_top % 8), NULL );
FillRect(tw->hdc, pRectWnd, hBrush);
DeleteObject(hBrush);
}
//
// Draw the background
//
// On entry:
// tw: top level window
// off_left, off_top: scroll offsets
// extra_off_left, extra_off_top: additional offset's, used by progressive rendering
// of gifs
// pRectWnd: pointer to rect that needs background painted
//
void TW_DrawBackground( struct Mwin *tw, int off_left, int off_top,
int extra_off_left, int extra_off_top, RECT *pRectWnd )
{
struct _element *pel;
struct ImageInfo *myImage;
BOOL did_bg_image = FALSE;
COLORREF the_background_color;
COLORREF the_text_color;
COLORREF dummy;
GetCurrentColors( tw, &the_background_color, &the_text_color, &dummy, &dummy );
if ( tw && tw->w3doc ) {
// If background image is fixed, ignore left and top
if ( tw->w3doc->bFixedBackground && gPrefs.bAutoLoadImages )
off_left = off_top = 0;
// Even for fixed background images, extra_off_left and extra_off_top should
// be honored.
off_left += extra_off_left;
off_top += extra_off_top;
GTR_RealizePalette(tw->hdc);
//
// Check to see if there is a background image
//
if ( tw->w3doc->nBackgroundImageElement != -1 ) {
pel = &(tw->w3doc->aElements[tw->w3doc->nBackgroundImageElement]);
myImage = pel->myImage;
if ( myImage && (myImage->flags & IMG_WHKNOWN) &&
((myImage->flags & (IMG_NOTLOADED | IMG_ERROR | IMG_MISSING)) == 0)
)
{
if (myImage->data && myImage->pbmi) {
did_bg_image =
TileBackgroundImage( tw, off_left, off_top, pRectWnd, myImage, the_background_color, the_text_color );
}
}
}
}
if ( !did_bg_image )
FillBackgroundRect( tw, off_left, off_top, pRectWnd, the_background_color );
}
//
// Set the text color to the correct color based on the given element
//
// On entry:
// tw: top level window struct
// pel: pointer to element that is about to be rendered
// anchor_color_beenthere: COLORREF of visited anchor
// anchor_color: COLORREF of non-visited anchor
//
// Returns:
// TRUE -> Did a SetTextColor() to the correct color for the given element
// FALSE -> Did not need to do a SetTextColor()
//
static BOOL SetCorrectTextColor( struct Mwin *tw, struct _element *pel,
COLORREF anchor_color_beenthere, COLORREF anchor_color )
{
if (pel->lFlags & ELEFLAG_ANCHOR)
{
if (pel->lFlags & ELEFLAG_VISITED)
SetTextColor(tw->hdc, anchor_color_beenthere);
else
SetTextColor(tw->hdc, anchor_color);
return TRUE;
} else if ( pel->fontColor != (COLORREF) -1 ) {
SetTextColor(tw->hdc, GetBestColor( tw->hdc, pel->fontColor) );
return TRUE;
}
return FALSE;
}
void TW_Draw(struct Mwin *tw, int off_left, int off_top, FRAME_INFO *pFrame, RECT * rWnd, BOOL bDrawFormControls,
struct _position *pposStart, struct _position *pposEnd, BOOL bTextOpaque, BOOL bPrinting)
{
int i;
COLORREF oldColor;
COLORREF oldBkColor;
COLORREF anchor_color_beenthere, anchor_color;
int oldMode;
UINT oldTA;
RECT rSect;
struct GTRFont *pFont;
HFONT hFontElement;
struct _element *pel;
int anchor_frame_width;
HBRUSH hBrush;
BOOL bInSelection = FALSE;
BOOL bSelStateChanging = FALSE;
int iStartingElement;
int iEndingElement;
struct ImageInfo *myImage;
int nLastFormattedLine;
int displayWidth, displayHeight;
COLORREF the_text_color, the_background_color;
DIBENV dibenv;
RECT rEntireWnd;
BOOL bChangedTextColor;
BOOL top_level = FALSE;
RECT org_rWnd = *rWnd;
int org_off_left = off_left;
int org_off_top = off_top;
#ifdef FEATURE_INTL
BOOL bDBCS;
BOOL bYankedUL;
#endif
XX_DMsg(DBG_DRAW, ("Entering TW_Draw\n"));
if (!tw)
return;
if (!tw->w3doc)
{
XX_DMsg(DBG_DRAW, ("w3doc == NULL: no draw\n"));
return;
}
if ( pFrame == NULL ) {
top_level = TRUE;
pFrame = &tw->w3doc->frame;
}
if ( bPrinting ) {
rEntireWnd = *rWnd;
} else {
TW_GetWindowWrapRect(tw, &rEntireWnd);
}
nLastFormattedLine = pFrame->nLastFormattedLine;
#ifdef FEATURE_IMG_THREADS
if (nLastFormattedLine >= 0 && pFrame->nLastLineButForImg >= 0 && !tw->w3doc->bIsShowPlaceholders)
{
nLastFormattedLine = pFrame->nLastLineButForImg-1;
#ifdef FEATURE_DBG_PLACE
XX_DMsg(DBG_IMAGE, ("draw [not placeholders] nLastFormattedLine: %d\n",nLastFormattedLine));
#endif
}
#endif
if (pFrame->nLineCount <= 0 || nLastFormattedLine < 0)
{
XX_DMsg(DBG_DRAW, ("No lines: no draw\n"));
return;
}
XX_DMsg(DBG_PAL, ("Draw: Calling GTR_RealizePalette\n"));
GTR_RealizePalette(tw->hdc);
GetCurrentColors( tw, &the_background_color, &the_text_color,
&anchor_color, &anchor_color_beenthere );
// Setup dibenv for image draws
dibenv.colorBg = GetNearestColor(tw->hdc, the_background_color);
dibenv.colorFg = GetNearestColor(tw->hdc, the_text_color);
if (wg.eColorMode == 8)
{
dibenv.colorIdxBg = GetNearestPaletteIndex(hPalGuitar, dibenv.colorBg);
dibenv.colorIdxFg = GetNearestPaletteIndex(hPalGuitar, dibenv.colorFg);
}
dibenv.tw = tw;
dibenv.bFancyBg = (dibenv.colorBg != the_background_color) ||
(TW_BackgroundImage(tw->w3doc) != NULL);
oldColor = SetTextColor(tw->hdc, the_text_color );
oldBkColor = SetBkColor(tw->hdc, (gPrefs.bGreyBackground) ?
RGB(192, 192, 192) : the_background_color );
oldMode = SetBkMode(tw->hdc, (bTextOpaque) ? OPAQUE : TRANSPARENT );
oldTA = SetTextAlign(tw->hdc, TA_TOP | TA_NOUPDATECP | TA_LEFT);
/* TODO should save old font */
// off_left and off_top convert from frame coord to client coord
off_left = tw->offl - off_left;
off_top = tw->offt - off_top;
OffsetRect(rWnd, off_left, off_top);
OffsetRect(&rEntireWnd, off_left, off_top);
anchor_frame_width = tw->w3doc->pStyles->image_anchor_frame;
if (pposStart)
{
i = 0;
iStartingElement = pposStart->elementIndex;
}
else
{
/* Find the first line that is in the window */
for (i = 0; i <= nLastFormattedLine; i++)
{
if (pFrame->pLineInfo[i].nYEnd >= rEntireWnd.top)
break;
}
if (i > nLastFormattedLine)
{
XX_DMsg(DBG_DRAW, ("Last formatted line is off top of screen!\n"));
i = nLastFormattedLine;
}
iStartingElement = pFrame->pLineInfo[i].nFirstElement;
}
if (pposEnd)
{
iEndingElement = pposEnd->elementIndex;
}
else
{
/* i still has a valid line number from before */
for (; i <= nLastFormattedLine; i++)
{
if (pFrame->pLineInfo[i].nYStart > rWnd->bottom)
{
/* this line is off the screen. Therefore we only have to go
up to the last element on the previous line. */
if (i > 0)
iEndingElement = pFrame->pLineInfo[i - 1].nLastElement;
else
iEndingElement = 0;
break;
}
}
if (i > nLastFormattedLine)
{
iEndingElement = pFrame->pLineInfo[nLastFormattedLine].nLastElement;
}
}
if (!pposStart && !pposEnd)
{
tw->w3doc->iFirstVisibleElement = -1;
if (off_top == 0)
{
tw->w3doc->iFirstVisibleElement = 0;
}
}
/*
Draw the elements which need to be redrawn
*/
if (pFrame->nLineCount)
{
// Set things up for the case where we're starting in the middle of
// of the selection
if ((tw->w3doc->selStart.elementIndex != -1) && (tw->w3doc->selEnd.elementIndex != -1))
{
int j;
for ( j = 0; j != -1 && j != iStartingElement; j = tw->w3doc->aElements[j].next )
{
if ( j == tw->w3doc->selStart.elementIndex )
bInSelection = TRUE;
if ( j == tw->w3doc->selEnd.elementIndex )
bInSelection = FALSE;
}
}
for (i = iStartingElement; i >= 0; i = tw->w3doc->aElements[i].frameNext )
{
pel = &(tw->w3doc->aElements[i]);
bSelStateChanging = FALSE;
#ifdef FEATURE_INTL
bYankedUL = FALSE;
#endif
if ((tw->w3doc->selStart.elementIndex != -1) &&
(tw->w3doc->selEnd.elementIndex != -1))
{
if ( pel->type != ELE_FRAME ) {
if (i == tw->w3doc->selStart.elementIndex)
{
bSelStateChanging = TRUE;
bInSelection = TRUE;
}
/* Note that if the selection starts and ends on the same
element, both of these ifs may succeed. */
if (i == tw->w3doc->selEnd.elementIndex)
{
bSelStateChanging = TRUE;
bInSelection = FALSE;
}
} else {
// We are passing by a frame element. If the selection starts
// somewhere in this element, we need to know about it to maintain
// bInSelection accurately
int ix;
for ( ix = i;
ix >= 0;
ix = tw->w3doc->aElements[ix].next )
{
if (ix == tw->w3doc->selStart.elementIndex)
bInSelection = TRUE;
/* Note that if the selection starts and ends on the same
element, both of these ifs may succeed. */
if (ix == tw->w3doc->selEnd.elementIndex)
bInSelection = FALSE;
// Check to see if this was the last element in the frame
if ( ix == pel->pFrame->elementTail )
break;
}
}
}
if (IntersectRect(&rSect, &rEntireWnd, &pel->r))
{
if (tw->w3doc->iFirstVisibleElement == -1)
{
tw->w3doc->iFirstVisibleElement = i;
#ifdef FEATURE_IMG_THREADS
tw->w3doc->iFirstVisibleDelta = pel->r.top - off_top;
#endif
}
if (IntersectRect(&rSect, rWnd, &pel->r))
{
/*
set the tw->hdc for the style of the element
*/
#ifdef FEATURE_INTL
unsigned char fontbits=pel->fontBits;
if (pel->lFlags & ELEFLAG_ANCHOR)
fontbits |= pel->fontBits|gPrefs.cAnchorFontBits;
if ( (fontbits & FONTBIT_UNDERLINE) && !wg.bDBCSEnabled &&
(IsFECodePage(GETMIMECP(tw->w3doc)) || aMimeCharSet[tw->w3doc->iMimeCharSet].AltCP) )
{
// This is to get around US GDIs behavior against those
// T2 fonts in FE character set.
fontbits &= (~FONTBIT_UNDERLINE);
bYankedUL = TRUE;
}
#endif
if (pel->lFlags & ELEFLAG_ANCHOR)
{
#ifdef FEATURE_INTL
pFont = STY_GetCPFont(GETMIMECP(tw->w3doc), tw->w3doc->pStyles, pel->iStyle, fontbits, pel->fontSize, pel->fontFace, TRUE );
#else
pFont = STY_GetFont(tw->w3doc->pStyles, pel->iStyle, pel->fontBits | gPrefs.cAnchorFontBits, pel->fontSize, pel->fontFace, TRUE );
#endif
}
else
{
#ifdef FEATURE_INTL
pFont = STY_GetCPFont(GETMIMECP(tw->w3doc), tw->w3doc->pStyles, pel->iStyle, pel->fontBits, pel->fontSize, pel->fontFace, TRUE );
#else
pFont = STY_GetFont(tw->w3doc->pStyles, pel->iStyle, pel->fontBits, pel->fontSize, pel->fontFace, TRUE );
#endif
}
if (pFont)
{
hFontElement = pFont->hFont;
if (hFontElement)
{
SelectObject(tw->hdc, hFontElement);
}
}
switch (pel->type)
{
case ELE_TEXT:
if (!bPrinting && !tw->bNoDrawSelection && bSelStateChanging)
{
SIZE siz, one_char_siz;
int iFrontCharOffset;
int iFrontPixelOffset;
/* There may be "normal" text beginning this element */
if (tw->w3doc->selStart.elementIndex == i && tw->w3doc->selStart.offset)
{
/*
ASSERT: the beginning part of the text in this element
is NOT selected
*/
bChangedTextColor = SetCorrectTextColor( tw, pel, anchor_color_beenthere, anchor_color );
#ifdef FEATURE_INTL
TextOutWithMIME(tw->w3doc->iMimeCharSet, tw->hdc, pel->r.left - off_left, pel->r.top - off_top,
&(tw->w3doc->pool[pel->textOffset]),
tw->w3doc->selStart.offset);
#else
TextOut(tw->hdc, pel->r.left - off_left, pel->r.top - off_top,
&(tw->w3doc->pool[pel->textOffset]),
tw->w3doc->selStart.offset);
#endif
if ( bChangedTextColor )
SetTextColor(tw->hdc, the_text_color);
// Measure non-selected text that is the start of the string, plus the
// first selected character
#ifdef FEATURE_INTL
if (IsFECodePage(GETMIMECP(tw->w3doc)))
{
bDBCS = IsDBCSLeadByteEx(GETMIMECP(tw->w3doc),*(tw->w3doc->pool + tw->w3doc->aElements[i].textOffset + tw->w3doc->selStart.offset));
}
else
{
bDBCS=FALSE;
}
myGetTextExtentPointWithMIME(tw->w3doc->iMimeCharSet,
tw->hdc,
tw->w3doc->pool + tw->w3doc->aElements[i].textOffset,
tw->w3doc->selStart.offset + 1 + ((bDBCS)?1:0), &siz);
myGetTextExtentPointWithMIME(tw->w3doc->iMimeCharSet, tw->hdc,
tw->w3doc->pool + tw->w3doc->aElements[i].textOffset + tw->w3doc->selStart.offset,
1 + ((bDBCS)?1:0), &one_char_siz);
#else // !FEATURE_INTL
myGetTextExtentPoint(tw->hdc,
tw->w3doc->pool + tw->w3doc->aElements[i].textOffset,
tw->w3doc->selStart.offset + 1, &siz);
// Measure the first selected character by itself
myGetTextExtentPoint(tw->hdc,
tw->w3doc->pool + tw->w3doc->aElements[i].textOffset + tw->w3doc->selStart.offset,
1, &one_char_siz);
#endif // FEATURE_INTL
// By subtracting the above two measurements, we'll end up with the
// measurement of the non-selected text, including any kerning that might
// have been done between the last non-selected character and the first
// selected character.
iFrontPixelOffset = siz.cx - one_char_siz.cx;
iFrontCharOffset = tw->w3doc->selStart.offset;
}
else
{
/*
ASSERT: the first part of the text in this element
is selected
*/
iFrontPixelOffset = 0;
iFrontCharOffset = 0;
}
if (tw->w3doc->selEnd.elementIndex == i)
{
/*
ASSERT: the last part of the text in this element
might not be selected
*/
COLORREF prevTextColor;
COLORREF prevBkColor;
int prevBkMode;
prevTextColor = SetTextColor(tw->hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
prevBkColor = SetBkColor(tw->hdc, GetSysColor(COLOR_HIGHLIGHT));
prevBkMode = SetBkMode(tw->hdc, OPAQUE);
#ifdef FEATURE_INTL
TextOutWithMIME(tw->w3doc->iMimeCharSet, tw->hdc, pel->r.left - off_left + iFrontPixelOffset, pel->r.top - off_top,
tw->w3doc->pool + pel->textOffset + iFrontCharOffset,
tw->w3doc->selEnd.offset - iFrontCharOffset);
#else
TextOut(tw->hdc, pel->r.left - off_left + iFrontPixelOffset, pel->r.top - off_top,
tw->w3doc->pool + pel->textOffset + iFrontCharOffset,
tw->w3doc->selEnd.offset - iFrontCharOffset);
#endif
(void)SetTextColor(tw->hdc, prevTextColor);
(void)SetBkColor(tw->hdc, prevBkColor);
(void)SetBkMode(tw->hdc, prevBkMode);
if (tw->w3doc->selEnd.offset < pel->textLen)
{
/*
ASSERT: the last part of the text in this element
is NOT selected
*/
// Measure selected text that is the start of the string, plus the
// first non-selected character
#ifdef FEATURE_INTL
if (IsFECodePage(GETMIMECP(tw->w3doc)))
{
bDBCS=IsDBCSLeadByteEx(GETMIMECP(tw->w3doc), *(tw->w3doc->pool + tw->w3doc->aElements[i].textOffset + tw->w3doc->selEnd.offset));
}
else
bDBCS=FALSE;
myGetTextExtentPointWithMIME(tw->w3doc->iMimeCharSet,
tw->hdc,
tw->w3doc->pool + tw->w3doc->aElements[i].textOffset,
tw->w3doc->selEnd.offset + 1 + ((bDBCS)?1:0), &siz);
// Measure the first non-selected character by itself
myGetTextExtentPointWithMIME(tw->w3doc->iMimeCharSet,
tw->hdc,
tw->w3doc->pool + tw->w3doc->aElements[i].textOffset + tw->w3doc->selEnd.offset,
1 + ((bDBCS)?1:0), &one_char_siz);
#else // !FEATURE_INTL
myGetTextExtentPoint(tw->hdc,
tw->w3doc->pool + tw->w3doc->aElements[i].textOffset,
tw->w3doc->selEnd.offset + 1, &siz);
// Measure the first non-selected character by itself
myGetTextExtentPoint(tw->hdc,
tw->w3doc->pool + tw->w3doc->aElements[i].textOffset + tw->w3doc->selEnd.offset,
1, &one_char_siz);
#endif // FEATURE_INTL
// By subtracting the above two measurements, we'll end up with the
// measurement of the selected text, including any kerning that might
// have been done between the last selected character and the first
// non-selected character.
iFrontPixelOffset = siz.cx - one_char_siz.cx;
bChangedTextColor = SetCorrectTextColor( tw, pel, anchor_color_beenthere, anchor_color );
#ifdef FEATURE_INTL
TextOutWithMIME(tw->w3doc->iMimeCharSet, tw->hdc, pel->r.left - off_left + iFrontPixelOffset, pel->r.top - off_top,
tw->w3doc->pool + pel->textOffset + tw->w3doc->selEnd.offset,
pel->textLen - tw->w3doc->selEnd.offset);
#else
TextOut(tw->hdc, pel->r.left - off_left + iFrontPixelOffset, pel->r.top - off_top,
tw->w3doc->pool + pel->textOffset + tw->w3doc->selEnd.offset,
pel->textLen - tw->w3doc->selEnd.offset);
#endif
if ( bChangedTextColor )
SetTextColor(tw->hdc, the_text_color);
}
}
else
{
/*
ASSERT: the last part of the text in this element
is selected.
*/
COLORREF prevTextColor;
COLORREF prevBkColor;
int prevBkMode;
prevTextColor = SetTextColor(tw->hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
prevBkColor = SetBkColor(tw->hdc, GetSysColor(COLOR_HIGHLIGHT));
prevBkMode = SetBkMode(tw->hdc, OPAQUE);
#ifdef FEATURE_INTL
TextOutWithMIME(tw->w3doc->iMimeCharSet, tw->hdc, pel->r.left - off_left + iFrontPixelOffset, pel->r.top - off_top,
tw->w3doc->pool + pel->textOffset + iFrontCharOffset,
pel->textLen - iFrontCharOffset);
#else
TextOut(tw->hdc, pel->r.left - off_left + iFrontPixelOffset, pel->r.top - off_top,
tw->w3doc->pool + pel->textOffset + iFrontCharOffset,
pel->textLen - iFrontCharOffset);
#endif
(void)SetTextColor(tw->hdc, prevTextColor);
(void)SetBkColor(tw->hdc, prevBkColor);
(void)SetBkMode(tw->hdc, prevBkMode);
}
}
else if (!bPrinting && !tw->bNoDrawSelection && bInSelection)
{
COLORREF prevTextColor;
COLORREF prevBkColor;
int prevBkMode;
prevTextColor = SetTextColor(tw->hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
prevBkColor = SetBkColor(tw->hdc, GetSysColor(COLOR_HIGHLIGHT));
prevBkMode = SetBkMode(tw->hdc, OPAQUE);
#ifdef FEATURE_INTL
TextOutWithMIME(tw->w3doc->iMimeCharSet, tw->hdc, pel->r.left - off_left, pel->r.top - off_top,
&(tw->w3doc->pool[pel->textOffset]),
pel->textLen);
#else
TextOut(tw->hdc, pel->r.left - off_left, pel->r.top - off_top,
&(tw->w3doc->pool[pel->textOffset]),
pel->textLen);
#endif
(void)SetTextColor(tw->hdc, prevTextColor);
(void)SetBkColor(tw->hdc, prevBkColor);
(void)SetBkMode(tw->hdc, prevBkMode);
}
else
{
bChangedTextColor = SetCorrectTextColor( tw, pel, anchor_color_beenthere, anchor_color );
#ifdef FEATURE_INTL
TextOutWithMIME(tw->w3doc->iMimeCharSet, tw->hdc, pel->r.left - off_left, pel->r.top - off_top,
&(tw->w3doc->pool[pel->textOffset]),
pel->textLen);
#else
TextOut(tw->hdc, pel->r.left - off_left, pel->r.top - off_top,
&(tw->w3doc->pool[pel->textOffset]),
pel->textLen);
#endif
if ( bChangedTextColor )
SetTextColor(tw->hdc, the_text_color);
}
#ifdef FEATURE_INTL
if (bYankedUL){
// Note we never have bYanedUL turned on unless we get into
// FarEast page
DrawYankedUnderLine(tw->hdc, pel, off_left, off_top, pFont, anchor_color, anchor_color_beenthere);
}
#endif
break;
case ELE_MARQUEE:
// BUGBUG Marquees don't print yet !!!
if ( bPrinting )
break;
pel->pMarquee->tw = tw;
pel->pMarquee->w3doc = tw->w3doc;
pel->pMarquee->iElement = i;
// if the textcolor = the background color we assume
// that we're just initalized and attempt to suck in
// the correct background color, otherwise the parse
// found a background color that needs to override the
// default background color
if ( pel->pMarquee->dwTColor == pel->pMarquee->dwBColor )
{
pel->pMarquee->dwBColor = the_background_color;
}
else
{
pel->pMarquee->dwBColor = GetBestColor(tw->hdc,
pel->pMarquee->dwBColor);
}
if ( pel->fontColor != (COLORREF) -1 )
pel->pMarquee->dwTColor =
GetBestColor( tw->hdc, pel->fontColor);
else
pel->pMarquee->dwTColor = the_text_color;
if (pel->lFlags & ELEFLAG_ANCHOR)
TW_DrawAnchorFrame(tw, off_left, off_top,
pel,anchor_color,anchor_color_beenthere);
MARQUEE_Draw(pel->pMarquee,tw->hdc, rWnd);
break;
case ELE_FRAME:
{
if ( pel->pFrame ) {
struct _position start, end;
RECT this_rWnd = org_rWnd;
int cellBorder =
(pel->pFrame->flags & ELE_FRAME_HAS_BORDER) ? 1 : 0;
// See if this cell or table has a background color
if ( pel->pFrame->bgColor != (COLORREF) -1 ) {
RECT r = pel->r;
HBRUSH hBrush =
CreateSolidBrush(
GetBestColor(tw->hdc, pel->pFrame->bgColor)
);
r.left -= off_left;
r.top -= off_top;
r.right -= off_left + cellBorder;
r.bottom -= off_top + cellBorder;
FillRect( tw->hdc, &r, hBrush );
DeleteObject( hBrush );
}
if ( (pel->pFrame->flags & ELE_FRAME_HAS_BORDER) &&
((pel->pFrame->flags & ELE_FRAME_IS_TABLE) ||
pel->pFrame->elementHead != pel->pFrame->elementTail)
)
{
RECT r = pel->r;
HPEN hDkGrayPen, hWhitePen;
HPEN oldPen;
BOOL inset = (pel->pFrame->flags & ELE_FRAME_IS_CELL);
COLORREF theBorderColorDark;
COLORREF theBorderColorLight;
r.left -= off_left;
r.top -= off_top;
r.right -= off_left + cellBorder;
r.bottom -= off_top + cellBorder;
if ( pel->pFrame->flags & ELE_FRAME_IS_TABLE ) {
if ( pel->pFrame->elementCaption != -1 ) {
struct _element *captionPel = NULL;
int captionHeight;
captionPel = &tw->w3doc->aElements[pel->pFrame->elementCaption];
captionHeight = captionPel->r.bottom - captionPel->r.top;
if ( captionPel->pFrame->valign == ALIGN_BOTTOM )
r.bottom -= captionHeight;
else
r.top += captionHeight;
}
}
if ( pel->pFrame->borderColorDark != (COLORREF) -1 )
theBorderColorDark = GetBestColor( tw->hdc, pel->pFrame->borderColorDark );
else
theBorderColorDark = GetSysColor(COLOR_BTNSHADOW);
if ( pel->pFrame->borderColorLight != (COLORREF) -1 )
theBorderColorLight = GetBestColor( tw->hdc, pel->pFrame->borderColorLight );
else
theBorderColorLight = GetSysColor(COLOR_BTNHIGHLIGHT);
hDkGrayPen = CreatePen(PS_SOLID, 0, theBorderColorDark);
hWhitePen = CreatePen(PS_SOLID, 0, theBorderColorLight);
oldPen = SelectObject(tw->hdc, inset ? hDkGrayPen : hWhitePen );
MoveToEx(tw->hdc, r.left, r.bottom, NULL);
LineTo(tw->hdc, r.left, r.top);
LineTo(tw->hdc, r.right, r.top );
SelectObject(tw->hdc, inset ? hWhitePen : hDkGrayPen );
MoveToEx(tw->hdc, r.right, r.top, NULL);
LineTo(tw->hdc, r.right, r.bottom);
LineTo(tw->hdc, r.left - 1, r.bottom);
SelectObject(tw->hdc, oldPen);
DeleteObject(hDkGrayPen);
DeleteObject(hWhitePen);
}
start.elementIndex = tw->w3doc->aElements[pel->pFrame->elementHead].next;
end.elementIndex = pel->pFrame->elementTail;
TW_Draw(tw, org_off_left + pel->r.left, org_off_top + pel->r.top,
pel->pFrame, &this_rWnd, bDrawFormControls,
&start, &end,
bTextOpaque, bPrinting);
}
}
break;
case ELE_FORMIMAGE:
case ELE_IMAGE:
if (MCI_IS_LOADED(pel->pmo)) {
if (pel->lFlags & ELEFLAG_ANCHOR) {
TW_DrawAnchorFrame(tw,off_left,off_top,pel,anchor_color,anchor_color_beenthere);
}
break;
}
#ifdef FEATURE_VRML
if (pel->lFlags & (ELEFLAG_BACKGROUND_IMAGE | ELEFLAG_HIDDEN))
#else
if (pel->lFlags & ELEFLAG_BACKGROUND_IMAGE)
#endif
return;
myImage = pel->myImage;
if ( pel->displayWidth == 0 ) {
displayWidth = myImage->width;
displayHeight = myImage->height;
} else {
displayWidth = pel->displayWidth;
displayHeight = pel->displayHeight;
}
if (!myImage)
{
XX_DMsg(DBG_IMAGE, ("myImage is NULL!!\n"));
}
else
{
int nPicW, nPicH;
#ifdef FEATURE_IMG_THREADS
PROGDRAWSTATUS cbProgDraw = DC_ProgNot;
#endif
dibenv.transparent = myImage->transparent;
dibenv.rectPaint = rSect;
OffsetRect(&dibenv.rectPaint, -off_left, -off_top);
/* Draw a placeholder in the case where either an image isn't loaded
or the space for it isn't the right size */
nPicW = pel->r.right - pel->r.left;
nPicH = pel->r.bottom - pel->r.top;
#ifdef FEATURE_CLIENT_IMAGEMAP
if (pel->lFlags & (ELEFLAG_ANCHOR | ELEFLAG_USEMAP))
#else
if (pel->lFlags & ELEFLAG_ANCHOR)
#endif
{
nPicW -= 2 * pel->border;
nPicH -= 2 * pel->border;
}
#ifdef FEATURE_IMG_THREADS
#ifdef FEATURE_DBG_PLACE
if (!(myImage->flags & IMG_WHKNOWN))
XX_DMsg(DBG_IMAGE, ("drawing w&h not known = %d,%d\n", pel->r.top, pel->r.bottom));
#endif
if ((myImage->flags & IMG_LOADING) &&
myImage->decoderObject &&
(!bPrinting))
cbProgDraw = cbDC_ProgDrawValid(myImage->decoderObject);
#endif
#ifdef FEATURE_IMG_THREADS
if (((myImage->flags & IMG_NOTLOADED) && cbProgDraw == DC_ProgNot) ||
(myImage->flags & (IMG_ERROR | IMG_MISSING)) ||
((!bPrinting) && ((nPicW != displayWidth) || (nPicH != displayHeight))
&& !(pel->lFlags & ELEFLAG_PERCENT_WIDTH)
&& !(pel->lFlags & ELEFLAG_PERCENT_HEIGHT) ))
#else
if ((myImage->flags & (IMG_ERROR | IMG_NOTLOADED | IMG_MISSING)) ||
((!bPrinting) && ((nPicW != displayWidth) || (nPicH != displayHeight))))
#endif
{
TW_DrawPlaceholder(tw, off_left, off_top, pel,TRUE);
#ifdef FEATURE_CLIENT_IMAGEMAP
if (pel->lFlags & (ELEFLAG_ANCHOR | ELEFLAG_USEMAP))
#else
if (pel->lFlags & ELEFLAG_ANCHOR)
#endif
TW_DrawAnchorFrame(tw,off_left,off_top,pel,anchor_color,anchor_color_beenthere);
}
else
{
int err;
BOOL sav_dibenv_bFancyBg = dibenv.bFancyBg;
BOOL sav_tw_bErase = tw->bErase;
BOOL bSetValues = FALSE;
// Check to see if we are in a table cell
if ( pel->frameIndex >= 0 ) {
FRAME_INFO *ptFrame = tw->w3doc->aElements[pel->frameIndex].pFrame;
int count = 0; // count iterations to avoid possible infinite loop
// Check to see if any enclosing frames have a background color set
while ( ptFrame ) {
if ( (ptFrame->pParentFrame && (ptFrame->bgColor != (COLORREF) -1)) || ++count > 20 ) {
// If we've found a background color, defeat double-buffer draw
dibenv.bFancyBg = TRUE;
tw->bErase = FALSE;
bSetValues = TRUE;
break;
}
ptFrame = ptFrame->pParentFrame;
}
}
#ifdef FEATURE_CLIENT_IMAGEMAP
if (pel->lFlags & (ELEFLAG_ANCHOR | ELEFLAG_USEMAP))
#else
if (pel->lFlags & ELEFLAG_ANCHOR)
#endif
{
#ifdef FEATURE_IMG_THREADS
if (cbProgDraw != DC_ProgNot)
{
if (cbProgDraw != DC_ProgTotal)
TW_DrawPlaceholder(tw, off_left, off_top, pel, FALSE);
err = cbDC_StretchDIBits(myImage->decoderObject,
tw->hdc,
pel->r.left - off_left + pel->border,
pel->r.top - off_top + pel->border,
pel->r.right - pel->r.left - (pel->border * 2), pel->r.bottom - pel->r.top - (pel->border * 2),
0, 0,
myImage->width, myImage->height,
(wg.eColorMode == 8 ? DIB_PAL_COLORS : DIB_RGB_COLORS), SRCCOPY, &dibenv);
XX_DMsg(DBG_PAL, ("After StretchDIBits, err=%d, GetLastError()=%d\n", err, GetLastError()));
}
else
#endif
if (myImage->data && myImage->pbmi)
{
if (bPrinting)
{
err = Printer_StretchDIBits(tw->hdc, pel->r.left - off_left + pel->border,
pel->r.top - off_top + pel->border,
pel->r.right - pel->r.left - (pel->border * 2), pel->r.bottom - pel->r.top - (pel->border * 2),
0, 0,
myImage->width, myImage->height, myImage);
XX_DMsg(DBG_PAL, ("After StretchDIBits, err=%d, GetLastError()=%d\n", err, GetLastError()));
}
else
{
err = MyStretchDIBits(tw->hdc, pel->r.left - off_left + pel->border,
pel->r.top - off_top + pel->border,
pel->r.right - pel->r.left - (pel->border * 2), pel->r.bottom - pel->r.top - (pel->border * 2),
0, 0,
myImage->width, myImage->height, myImage->data, myImage->pbmi,
(wg.eColorMode == 8 ? DIB_PAL_COLORS : DIB_RGB_COLORS), SRCCOPY, &dibenv);
XX_DMsg(DBG_PAL, ("After StretchDIBits, err=%d, GetLastError()=%d\n", err, GetLastError()));
}
}
TW_DrawAnchorFrame(tw,off_left,off_top,pel,anchor_color,anchor_color_beenthere);
}
else
{
#ifdef FEATURE_IMG_THREADS
if (cbProgDraw != DC_ProgNot)
{
if (cbProgDraw != DC_ProgTotal)
TW_DrawPlaceholder(tw, off_left, off_top, pel, FALSE);
err = cbDC_StretchDIBits(myImage->decoderObject,
tw->hdc,
pel->r.left - off_left, pel->r.top - off_top,
pel->r.right - pel->r.left, pel->r.bottom - pel->r.top,
0, 0,
myImage->width, myImage->height,
(wg.eColorMode == 8 ? DIB_PAL_COLORS : DIB_RGB_COLORS), SRCCOPY, &dibenv);
XX_DMsg(DBG_PAL, ("After StretchDIBits, err=%d, GetLastError()=%d\n", err, GetLastError()));
}
else
#endif
if (myImage->data && myImage->pbmi)
{
if (bPrinting)
{
err = Printer_StretchDIBits(tw->hdc, pel->r.left - off_left, pel->r.top - off_top,
pel->r.right - pel->r.left, pel->r.bottom - pel->r.top,
0, 0,
myImage->width, myImage->height, myImage);
XX_DMsg(DBG_PAL, ("After StretchDIBits, err=%d, GetLastError()=%d\n", err, GetLastError()));
}
else
{
err = MyStretchDIBits(tw->hdc,
pel->r.left - off_left, pel->r.top - off_top,
pel->r.right - pel->r.left, pel->r.bottom - pel->r.top,
0, 0,
myImage->width, myImage->height, myImage->data, myImage->pbmi,
(wg.eColorMode == 8 ? DIB_PAL_COLORS : DIB_RGB_COLORS), SRCCOPY, &dibenv);
XX_DMsg(DBG_PAL, ("After StretchDIBits, err=%d, GetLastError()=%d\n", err, GetLastError()));
}
}
}
if ( bSetValues ) {
dibenv.bFancyBg = sav_dibenv_bFancyBg;
tw->bErase = sav_tw_bErase;
}
}
}
break;
case ELE_HR:
{
RECT r = pel->r;
r.top += ((r.bottom - r.top) - pel->border) / 2;
r.bottom = r.top + pel->border - 1;
if ( pel->lFlags & ELEFLAG_HR_NOSHADE )
{
hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
r.left -= off_left;
r.top -= off_top;
r.right -= off_left - 1;
r.bottom -= off_top - 1;
FillRect(tw->hdc, &r, hBrush);
DeleteObject(hBrush);
} else {
HPEN hDkGrayPen, hWhitePen;
HPEN oldPen;
hDkGrayPen = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW));
hWhitePen = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNHIGHLIGHT));
oldPen = SelectObject(tw->hdc, hWhitePen);
if ( r.bottom <= r.top ) {
MoveToEx(tw->hdc, r.right - off_left, r.top - off_top, NULL);
} else {
MoveToEx(tw->hdc, r.left - off_left, r.bottom - off_top, NULL);
LineTo(tw->hdc, r.right - off_left, r.bottom - off_top);
LineTo(tw->hdc, r.right - off_left, r.top - off_top);
}
SelectObject(tw->hdc, hDkGrayPen);
LineTo(tw->hdc, r.left - off_left, r.top - off_top);
LineTo(tw->hdc, r.left - off_left, r.bottom - off_top);
SelectObject(tw->hdc, oldPen);
DeleteObject(hDkGrayPen);
DeleteObject(hWhitePen);
}
}
break;
default:
if (bDrawFormControls)
{
switch (pel->type)
{
case ELE_EDIT:
if (pel->form && pel->form->hWndControl)
{
int len;
char *s;
RECT r;
r = pel->r;
OffsetRect(&r, -off_left, -off_top);
len = GetWindowTextLength(pel->form->hWndControl);
s = (char *) GTR_MALLOC(len+2);
if (s)
{
GetWindowText(pel->form->hWndControl, s, len+1);
GDI_Rect(tw->hdc, &r);
r.left += (r.bottom - r.top) / 8;
if (pel->form->bWantReturn)
{
DrawText(tw->hdc, s, len, &r, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
}
else
{
DrawText(tw->hdc, s, len, &r, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK|DT_SINGLELINE|DT_VCENTER);
}
GTR_FREE(s);
}
}
break;
case ELE_PASSWORD:
if (pel->form && pel->form->hWndControl)
{
int len;
char *s;
RECT r;
r = pel->r;
OffsetRect(&r, -off_left, -off_top);
len = GetWindowTextLength(pel->form->hWndControl);
s = (char *) GTR_MALLOC(len+2);
if (s)
{
char *p;
GetWindowText(pel->form->hWndControl, s, len+1);
p = s;
while (*p)
{
*p++ = '*';
}
r.left += (r.bottom - r.top) / 8;
GDI_Rect(tw->hdc, &r);
DrawText(tw->hdc, s, len, &r, DT_LEFT|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER);
GTR_FREE(s);
}
}
break;
case ELE_CHECKBOX:
if (pel->form && pel->form->hWndControl)
{
RECT r;
r = pel->r;
OffsetRect(&r, -off_left, -off_top);
r.right = r.left + (r.bottom - r.top);
GDI_Rect(tw->hdc, &r);
if (SendMessage(pel->form->hWndControl, BM_GETCHECK, (WPARAM) 0, 0L))
{
MoveToEx(tw->hdc, r.left, r.top, NULL);
LineTo(tw->hdc, r.right, r.bottom);
MoveToEx(tw->hdc, r.right, r.top, NULL);
LineTo(tw->hdc, r.left, r.bottom);
}
}
break;
case ELE_RADIO:
if (pel->form && pel->form->hWndControl)
{
RECT r;
r = pel->r;
OffsetRect(&r, -off_left, -off_top);
r.right = r.left + (r.bottom - r.top);
Arc(tw->hdc, r.left, r.top, r.right, r.bottom,
r.right, r.top, r.right, r.top);
if (SendMessage(pel->form->hWndControl, BM_GETCHECK, (WPARAM) 0, 0L))
{
HBRUSH hOldBrush;
InflateRect(&r, -((r.right - r.left) / 5), -((r.bottom - r.top) / 5));
hOldBrush = SelectObject(tw->hdc, GetStockObject(BLACK_BRUSH));
Ellipse(tw->hdc, r.left, r.top, r.right, r.bottom);
(void) SelectObject(tw->hdc, hOldBrush);
}
}
break;
case ELE_SUBMIT:
if (pel->form && pel->form->hWndControl)
{
int len;
char *s;
RECT r;
len = GetWindowTextLength(pel->form->hWndControl);
s = (char *) GTR_MALLOC(len+2);
if (s)
{
r = pel->r;
OffsetRect(&r, -off_left, -off_top);
GetWindowText(pel->form->hWndControl, s, len+1);
RoundRect(tw->hdc, r.left, r.top, r.right, r.bottom,
(r.bottom - r.top) / 3, (r.bottom - r.top) / 3);
DrawText(tw->hdc, s, len, &r, DT_LEFT|DT_NOPREFIX|DT_CENTER|DT_SINGLELINE|DT_VCENTER);
GTR_FREE(s);
}
}
break;
case ELE_RESET:
if (pel->form && pel->form->hWndControl)
{
int len;
char *s;
RECT r;
len = GetWindowTextLength(pel->form->hWndControl);
s = (char *) GTR_MALLOC(len+2);
if (s)
{
r = pel->r;
OffsetRect(&r, -off_left, -off_top);
GetWindowText(pel->form->hWndControl, s, len+1);
RoundRect(tw->hdc, r.left, r.top, r.right, r.bottom,
(r.bottom - r.top) / 3, (r.bottom - r.top) / 3);
DrawText(tw->hdc, s, len, &r, DT_LEFT|DT_NOPREFIX|DT_CENTER|DT_SINGLELINE|DT_VCENTER);
GTR_FREE(s);
}
}
break;
case ELE_COMBO:
if (pel->form && pel->form->hWndControl)
{
int ndx;
int len;
char *s;
RECT r;
ndx = SendMessage(pel->form->hWndControl, CB_GETCURSEL, (WPARAM) 0, 0L);
if (ndx != CB_ERR)
{
len = SendMessage(pel->form->hWndControl, CB_GETLBTEXTLEN, (WPARAM) ndx, 0L);
s = (char *) GTR_MALLOC(len+1);
if (s)
{
(void) SendMessage(pel->form->hWndControl, CB_GETLBTEXT, (WPARAM) ndx, (LPARAM) s);
r = pel->r;
OffsetRect(&r, -off_left, -off_top);
GDI_Rect(tw->hdc, &r);
r.right -= (r.bottom - r.top);
GDI_Rect(tw->hdc, &r);
r.left += (r.bottom - r.top) / 8;
DrawText(tw->hdc, s, len, &r, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK|DT_SINGLELINE|DT_VCENTER);
GTR_FREE(s);
}
}
}
break;
case ELE_LIST:
case ELE_MULTILIST:
if (pel->form && pel->form->hWndControl)
{
int cVisible;
int iHeight;
int iHeightItem;
RECT r;
int i;
int ndx;
char *s;
int len;
UINT taOld;
COLORREF oldFore;
COLORREF oldBack;
/*
iHeight, iHeightItem and r are now in SCREEN coords
*/
GetWindowRect(pel->form->hWndControl, &r);
iHeight = r.bottom - r.top;
iHeightItem = SendMessage(pel->form->hWndControl, LB_GETITEMHEIGHT, (WPARAM) 0, 0L);
cVisible = iHeight / iHeightItem;
/*
iHeight, iHeightItem and r are now in PRINTER coords
*/
iHeight = pel->r.bottom - pel->r.top;
iHeightItem = iHeight / cVisible;
r = pel->r;
OffsetRect(&r, -off_left, -off_top);
r.bottom = r.top + (cVisible * iHeightItem);
GDI_Rect(tw->hdc, &r);
r.right -= iHeightItem;
GDI_Rect(tw->hdc, &r);
ndx = SendMessage(pel->form->hWndControl, LB_GETTOPINDEX, (WPARAM) 0, 0L);
for (i=0; i<cVisible; i++, ndx++)
{
r = pel->r;
OffsetRect(&r, -off_left, -off_top);
r.top += (i * iHeightItem);
r.bottom = r.top + iHeightItem;
r.right -= (r.bottom - r.top + 1);
r.left += 1;
len = SendMessage(pel->form->hWndControl, LB_GETTEXTLEN, (WPARAM) ndx, 0L);
if ( len == LB_ERR )
break; // if ndx isn't a valid index, break out of loop
s = (char *) GTR_MALLOC(len + 1);
if (s)
{
(void) SendMessage(pel->form->hWndControl, LB_GETTEXT, (WPARAM) ndx, (LPARAM) s);
taOld = SetTextAlign(tw->hdc, TA_LEFT|TA_BOTTOM);
if (SendMessage(pel->form->hWndControl, LB_GETSEL, (WPARAM) ndx, 0L))
{
oldFore = SetTextColor(tw->hdc, RGB(255,255,255));
oldBack = SetBkColor(tw->hdc, RGB(0,0,0));
#ifdef FEATURE_INTL
ExtTextOutWithMIME(tw->w3doc->iMimeCharSet, tw->hdc, r.left + (r.bottom - r.top) / 8, r.bottom - 1,
ETO_CLIPPED|ETO_OPAQUE, &r, s, len, NULL);
(void) SetBkColor(tw->hdc, oldBack);
(void) SetTextColor(tw->hdc, oldFore);
#else
ExtTextOut(tw->hdc, r.left + (r.bottom - r.top) / 8, r.bottom - 1,
ETO_CLIPPED|ETO_OPAQUE, &r, s, len, NULL);
(void) SetBkColor(tw->hdc, oldBack);
(void) SetTextColor(tw->hdc, oldFore);
#endif
}
else
{
#ifdef FEATURE_INTL
ExtTextOutWithMIME(tw->w3doc->iMimeCharSet, tw->hdc, r.left + (r.bottom - r.top) / 8, r.bottom - 1,
ETO_CLIPPED, &r, s, len, NULL);
#else
ExtTextOut(tw->hdc, r.left + (r.bottom - r.top) / 8, r.bottom - 1,
ETO_CLIPPED, &r, s, len, NULL);
#endif
}
(void) SetTextAlign(tw->hdc, taOld);
GTR_FREE(s);
}
}
}
break;
case ELE_TEXTAREA:
if (pel->form && pel->form->hWndControl)
{
int len;
char *s;
RECT r;
len = GetWindowTextLength(pel->form->hWndControl);
s = (char *) GTR_MALLOC(len+2);
if (s)
{
GetWindowText(pel->form->hWndControl, s, len+1);
r = pel->r;
OffsetRect(&r, -off_left, -off_top);
GDI_Rect(tw->hdc, &r);
DrawText(tw->hdc, s, len, &r, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
GTR_FREE(s);
}
}
break;
default:
break;
}
}
break;
}
}
}
if ((iEndingElement >= 0) && (i == iEndingElement))
{
break; /* out of the loop */
}
} // end of for loop
}
SetTextColor(tw->hdc, oldColor);
SetBkMode(tw->hdc, oldMode);
SetBkColor(tw->hdc, oldBkColor);
SetTextAlign(tw->hdc, oldTA);
return;
}
#ifdef FEATURE_INTL
// TextOutWithCP/ExtTextOutWithCP
//
BOOL TextOutWithMIME(int iMimeCharSet, HDC hDC, int nX, int nY, LPCTSTR lpStr, int cch)
{
MIMECSETTBL *pMime = aMimeCharSet + iMimeCharSet;
BYTE CharSet = GetTextCharsetInfo(hDC, NULL, 0);
WCHAR *szwBuf;
int cchW;
BOOL bret;
if (CharSet == ANSI_CHARSET || ((wg.bDBCSEnabled || !IsDBCSCharSet(CharSet)) && pMime->AltCP == 0))
{
return TextOut(hDC, nX, nY, lpStr, cch);
}
else if (pMime->AltCP) // _BUGBUG: If AltCP is DBCS, then we need to do more.
{
if (wg.bDBCSEnabled)
{
char *sz = GTR_MALLOC(sizeof(char)*cch);
cchW = MultiByteToWideChar(pMime->AltCP, MB_PRECOMPOSED, lpStr, cch, NULL, 0);
szwBuf = GTR_MALLOC(sizeof(WCHAR)*cchW);
if(sz && szwBuf)
{
cchW = MultiByteToWideChar(pMime->AltCP, MB_PRECOMPOSED, lpStr, cch, szwBuf, cchW);
cch = WideCharToMultiByte(pMime->CodePage, 0, szwBuf, cchW, sz, cch, NULL, NULL);
GTR_FREE(szwBuf);
bret = TextOut(hDC, nX, nY, sz, cch);
GTR_FREE(sz);
return bret;
}
}
else
{
cchW = MultiByteToWideChar(pMime->AltCP, MB_PRECOMPOSED, lpStr, cch, NULL, 0);
szwBuf = GTR_MALLOC(sizeof(WCHAR)*cchW);
if(szwBuf)
{
cch = MultiByteToWideChar(pMime->AltCP, MB_PRECOMPOSED, lpStr, cch, szwBuf, cchW);
bret = TextOutW(hDC, nX, nY, szwBuf, cch);
GTR_FREE(szwBuf);
return bret;
}
}
}
else
{
cchW = MultiByteToWideChar(pMime->CodePage, MB_PRECOMPOSED, lpStr, cch, NULL, 0);
szwBuf = GTR_MALLOC(sizeof(WCHAR)*cchW);
if(szwBuf)
{
cch = MultiByteToWideChar(pMime->CodePage, MB_PRECOMPOSED, lpStr, cch, szwBuf, cchW);
bret = TextOutW(hDC, nX, nY, szwBuf, cch);
GTR_FREE(szwBuf);
return bret;
}
}
return FALSE;
}
BOOL ExtTextOutWithMIME(int iMimeCharSet, HDC hDC, int nX, int nY, UINT fuOpt, CONST RECT *lprc, LPCTSTR lpStr, UINT cch, CONST int *lpDx)
{
MIMECSETTBL *pMime = aMimeCharSet + iMimeCharSet;
BYTE CharSet = GetTextCharsetInfo(hDC, NULL, 0);
WCHAR *szwBuf;
int cchW;
BOOL bret;
if (CharSet == ANSI_CHARSET || ((wg.bDBCSEnabled || !IsDBCSCharSet(CharSet)) && pMime->AltCP == 0))
{
return ExtTextOut(hDC, nX, nY, fuOpt, lprc, lpStr, cch, lpDx);
}
else if (pMime->AltCP) // _BUGBUG: If AltCP is DBCS, then we need to do more.
{
if (wg.bDBCSEnabled)
{
char *sz = GTR_MALLOC(sizeof(char)*cch);
cchW = MultiByteToWideChar(pMime->AltCP, MB_PRECOMPOSED, lpStr, cch, NULL, 0);
szwBuf = GTR_MALLOC(sizeof(WCHAR)*cchW);
if(sz && szwBuf)
{
cchW = MultiByteToWideChar(pMime->AltCP, MB_PRECOMPOSED, lpStr, cch, szwBuf, cchW);
cch = WideCharToMultiByte(pMime->CodePage, 0, szwBuf, cchW, sz, cch, NULL, NULL);
GTR_FREE(szwBuf);
bret = ExtTextOut(hDC, nX, nY, fuOpt, lprc, sz, cch, lpDx);
GTR_FREE(sz);
return bret;
}
}
else
{
cchW = MultiByteToWideChar(pMime->AltCP, MB_PRECOMPOSED, lpStr, cch, NULL, 0);
szwBuf = GTR_MALLOC(sizeof(WCHAR)*cchW);
if(szwBuf)
{
cch = MultiByteToWideChar(pMime->AltCP, MB_PRECOMPOSED, lpStr, cch, szwBuf, cchW);
bret = ExtTextOutW(hDC, nX, nY, fuOpt, lprc, szwBuf, cch, lpDx);
GTR_FREE(szwBuf);
return bret;
}
}
}
else
{
cchW = MultiByteToWideChar(pMime->CodePage, MB_PRECOMPOSED, lpStr, cch, NULL, 0);
szwBuf = GTR_MALLOC(sizeof(WCHAR)*cchW);
if (szwBuf)
{
cch = MultiByteToWideChar(pMime->CodePage, MB_PRECOMPOSED, lpStr, cch, szwBuf, cchW);
bret = ExtTextOutW(hDC, nX, nY, fuOpt, lprc, szwBuf, cch, lpDx);
GTR_FREE(szwBuf);
return bret;
}
}
return FALSE;
}
void DrawYankedUnderLine(HDC hdc, struct _element *pel, int off_left, int off_top, struct GTRFont *pFont, COLORREF anchor_color, COLORREF anchor_color_beenthere)
{
COLORREF clr;
HBRUSH hbr, hbrOld;
if (!pel || !pFont) return;
if (pel->lFlags & ELEFLAG_ANCHOR)
{
if (pel->lFlags & ELEFLAG_VISITED)
clr=anchor_color_beenthere;
else
clr=anchor_color;
}
else if ( pel->fontColor != (COLORREF) -1 )
{
clr=GetBestColor(hdc, pel->fontColor);
}
else
return;
hbr=CreateSolidBrush(clr);
hbrOld=SelectObject(hdc, hbr);
PatBlt(hdc, pel->r.left-off_left, pel->r.top-off_top+pFont->tmAscent+2, pel->r.right-pel->r.left, 1, PATCOPY);
SelectObject(hdc, hbrOld);
DeleteObject(hbr);
}
#endif