mirror of https://github.com/lianthony/NT4.0
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
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
|