?? platwin.cxx
字號(hào):
// Scintilla source code edit control
/** @file PlatWin.cxx
** Implementation of platform facilities on Windows.
**/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <time.h>
#define _WIN32_WINNT 0x0400
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include <windowsx.h>
#include "Platform.h"
#include "PlatformRes.h"
#include "UniConversion.h"
#include "XPM.h"
#ifndef IDC_HAND
#define IDC_HAND MAKEINTRESOURCE(32649)
#endif
// Take care of 32/64 bit pointers
#ifdef GetWindowLongPtr
static void *PointerFromWindow(HWND hWnd) {
return reinterpret_cast<void *>(::GetWindowLongPtr(hWnd, 0));
}
static void SetWindowPointer(HWND hWnd, void *ptr) {
::SetWindowLongPtr(hWnd, 0, reinterpret_cast<LONG_PTR>(ptr));
}
#else
static void *PointerFromWindow(HWND hWnd) {
return reinterpret_cast<void *>(::GetWindowLong(hWnd, 0));
}
static void SetWindowPointer(HWND hWnd, void *ptr) {
::SetWindowLong(hWnd, 0, reinterpret_cast<LONG>(ptr));
}
#ifndef GWLP_USERDATA
#define GWLP_USERDATA GWL_USERDATA
#endif
#ifndef GWLP_WNDPROC
#define GWLP_WNDPROC GWL_WNDPROC
#endif
#ifndef LONG_PTR
#define LONG_PTR LONG
#endif
static LONG_PTR SetWindowLongPtr(HWND hWnd, int nIndex, LONG_PTR dwNewLong) {
return ::SetWindowLong(hWnd, nIndex, dwNewLong);
}
static LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex) {
return ::GetWindowLong(hWnd, nIndex);
}
#endif
typedef BOOL (WINAPI *AlphaBlendSig)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION);
static CRITICAL_SECTION crPlatformLock;
static HINSTANCE hinstPlatformRes = 0;
static bool onNT = false;
static HMODULE hDLLImage = 0;
static AlphaBlendSig AlphaBlendFn = 0;
bool IsNT() {
return onNT;
}
Point Point::FromLong(long lpoint) {
return Point(static_cast<short>(LOWORD(lpoint)), static_cast<short>(HIWORD(lpoint)));
}
static RECT RectFromPRectangle(PRectangle prc) {
RECT rc = {prc.left, prc.top, prc.right, prc.bottom};
return rc;
}
Palette::Palette() {
used = 0;
allowRealization = false;
hpal = 0;
size = 100;
entries = new ColourPair[size];
}
Palette::~Palette() {
Release();
delete []entries;
entries = 0;
}
void Palette::Release() {
used = 0;
if (hpal)
::DeleteObject(hpal);
hpal = 0;
delete []entries;
size = 100;
entries = new ColourPair[size];
}
/**
* This method either adds a colour to the list of wanted colours (want==true)
* or retrieves the allocated colour back to the ColourPair.
* This is one method to make it easier to keep the code for wanting and retrieving in sync.
*/
void Palette::WantFind(ColourPair &cp, bool want) {
if (want) {
for (int i=0; i < used; i++) {
if (entries[i].desired == cp.desired)
return;
}
if (used >= size) {
int sizeNew = size * 2;
ColourPair *entriesNew = new ColourPair[sizeNew];
for (int j=0; j<size; j++) {
entriesNew[j] = entries[j];
}
delete []entries;
entries = entriesNew;
size = sizeNew;
}
entries[used].desired = cp.desired;
entries[used].allocated.Set(cp.desired.AsLong());
used++;
} else {
for (int i=0; i < used; i++) {
if (entries[i].desired == cp.desired) {
cp.allocated = entries[i].allocated;
return;
}
}
cp.allocated.Set(cp.desired.AsLong());
}
}
void Palette::Allocate(Window &) {
if (hpal)
::DeleteObject(hpal);
hpal = 0;
if (allowRealization) {
char *pal = new char[sizeof(LOGPALETTE) + (used-1) * sizeof(PALETTEENTRY)];
LOGPALETTE *logpal = reinterpret_cast<LOGPALETTE *>(pal);
logpal->palVersion = 0x300;
logpal->palNumEntries = static_cast<WORD>(used);
for (int iPal=0;iPal<used;iPal++) {
ColourDesired desired = entries[iPal].desired;
logpal->palPalEntry[iPal].peRed = static_cast<BYTE>(desired.GetRed());
logpal->palPalEntry[iPal].peGreen = static_cast<BYTE>(desired.GetGreen());
logpal->palPalEntry[iPal].peBlue = static_cast<BYTE>(desired.GetBlue());
entries[iPal].allocated.Set(
PALETTERGB(desired.GetRed(), desired.GetGreen(), desired.GetBlue()));
// PC_NOCOLLAPSE means exact colours allocated even when in background this means other windows
// are less likely to get their colours and also flashes more when switching windows
logpal->palPalEntry[iPal].peFlags = PC_NOCOLLAPSE;
// 0 allows approximate colours when in background, yielding moe colours to other windows
//logpal->palPalEntry[iPal].peFlags = 0;
}
hpal = ::CreatePalette(logpal);
delete []pal;
}
}
static void SetLogFont(LOGFONT &lf, const char *faceName, int characterSet, int size, bool bold, bool italic) {
memset(&lf, 0, sizeof(lf));
// The negative is to allow for leading
lf.lfHeight = -(abs(size));
lf.lfWeight = bold ? FW_BOLD : FW_NORMAL;
lf.lfItalic = static_cast<BYTE>(italic ? 1 : 0);
lf.lfCharSet = static_cast<BYTE>(characterSet);
strncpy(lf.lfFaceName, faceName, sizeof(lf.lfFaceName));
}
/**
* Create a hash from the parameters for a font to allow easy checking for identity.
* If one font is the same as another, its hash will be the same, but if the hash is the
* same then they may still be different.
*/
static int HashFont(const char *faceName, int characterSet, int size, bool bold, bool italic) {
return
size ^
(characterSet << 10) ^
(bold ? 0x10000000 : 0) ^
(italic ? 0x20000000 : 0) ^
faceName[0];
}
class FontCached : Font {
FontCached *next;
int usage;
LOGFONT lf;
int hash;
FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_);
~FontCached() {}
bool SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_);
virtual void Release();
static FontCached *first;
public:
static FontID FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_);
static void ReleaseId(FontID id_);
};
FontCached *FontCached::first = 0;
FontCached::FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) :
next(0), usage(0), hash(0) {
::SetLogFont(lf, faceName_, characterSet_, size_, bold_, italic_);
hash = HashFont(faceName_, characterSet_, size_, bold_, italic_);
id = ::CreateFontIndirect(&lf);
usage = 1;
}
bool FontCached::SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) {
return
(lf.lfHeight == -(abs(size_))) &&
(lf.lfWeight == (bold_ ? FW_BOLD : FW_NORMAL)) &&
(lf.lfItalic == static_cast<BYTE>(italic_ ? 1 : 0)) &&
(lf.lfCharSet == characterSet_) &&
0 == strcmp(lf.lfFaceName,faceName_);
}
void FontCached::Release() {
if (id)
::DeleteObject(id);
id = 0;
}
FontID FontCached::FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) {
FontID ret = 0;
::EnterCriticalSection(&crPlatformLock);
int hashFind = HashFont(faceName_, characterSet_, size_, bold_, italic_);
for (FontCached *cur=first; cur; cur=cur->next) {
if ((cur->hash == hashFind) &&
cur->SameAs(faceName_, characterSet_, size_, bold_, italic_)) {
cur->usage++;
ret = cur->id;
}
}
if (ret == 0) {
FontCached *fc = new FontCached(faceName_, characterSet_, size_, bold_, italic_);
if (fc) {
fc->next = first;
first = fc;
ret = fc->id;
}
}
::LeaveCriticalSection(&crPlatformLock);
return ret;
}
void FontCached::ReleaseId(FontID id_) {
::EnterCriticalSection(&crPlatformLock);
FontCached **pcur=&first;
for (FontCached *cur=first; cur; cur=cur->next) {
if (cur->id == id_) {
cur->usage--;
if (cur->usage == 0) {
*pcur = cur->next;
cur->Release();
cur->next = 0;
delete cur;
}
break;
}
pcur=&cur->next;
}
::LeaveCriticalSection(&crPlatformLock);
}
Font::Font() {
id = 0;
}
Font::~Font() {
}
#define FONTS_CACHED
void Font::Create(const char *faceName, int characterSet, int size,
bool bold, bool italic, bool) {
Release();
#ifndef FONTS_CACHED
LOGFONT lf;
::SetLogFont(lf, faceName, characterSet, size, bold, italic);
id = ::CreateFontIndirect(&lf);
#else
id = FontCached::FindOrCreate(faceName, characterSet, size, bold, italic);
#endif
}
void Font::Release() {
#ifndef FONTS_CACHED
if (id)
::DeleteObject(id);
#else
if (id)
FontCached::ReleaseId(id);
#endif
id = 0;
}
class SurfaceImpl : public Surface {
bool unicodeMode;
HDC hdc;
bool hdcOwned;
HPEN pen;
HPEN penOld;
HBRUSH brush;
HBRUSH brushOld;
HFONT font;
HFONT fontOld;
HBITMAP bitmap;
HBITMAP bitmapOld;
HPALETTE paletteOld;
int maxWidthMeasure;
int maxLenText;
int codePage;
// If 9x OS and current code page is same as ANSI code page.
bool win9xACPSame;
void BrushColor(ColourAllocated back);
void SetFont(Font &font_);
// Private so SurfaceImpl objects can not be copied
SurfaceImpl(const SurfaceImpl &) : Surface() {}
SurfaceImpl &operator=(const SurfaceImpl &) { return *this; }
public:
SurfaceImpl();
virtual ~SurfaceImpl();
void Init(WindowID wid);
void Init(SurfaceID sid, WindowID wid);
void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
void Release();
bool Initialised();
void PenColour(ColourAllocated fore);
int LogPixelsY();
int DeviceHeightFont(int points);
void MoveTo(int x_, int y_);
void LineTo(int x_, int y_);
void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
void FillRectangle(PRectangle rc, ColourAllocated back);
void FillRectangle(PRectangle rc, Surface &surfacePattern);
void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
ColourAllocated outline, int alphaOutline, int flags);
void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
void Copy(PRectangle rc, Point from, Surface &surfaceSource);
void DrawTextCommon(PRectangle rc, Font &font_, int ybase, const char *s, int len, UINT fuOptions);
void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
void MeasureWidths(Font &font_, const char *s, int len, int *positions);
int WidthText(Font &font_, const char *s, int len);
int WidthChar(Font &font_, char ch);
int Ascent(Font &font_);
int Descent(Font &font_);
int InternalLeading(Font &font_);
int ExternalLeading(Font &font_);
int Height(Font &font_);
int AverageCharWidth(Font &font_);
int SetPalette(Palette *pal, bool inBackGround);
void SetClip(PRectangle rc);
void FlushCachedState();
void SetUnicodeMode(bool unicodeMode_);
void SetDBCSMode(int codePage_);
};
SurfaceImpl::SurfaceImpl() :
unicodeMode(false),
hdc(0), hdcOwned(false),
pen(0), penOld(0),
brush(0), brushOld(0),
font(0), fontOld(0),
bitmap(0), bitmapOld(0),
paletteOld(0) {
// Windows 9x has only a 16 bit coordinate system so break after 30000 pixels
maxWidthMeasure = IsNT() ? 1000000 : 30000;
// There appears to be a 16 bit string length limit in GDI on NT and a limit of
// 8192 characters on Windows 95.
maxLenText = IsNT() ? 65535 : 8192;
codePage = 0;
win9xACPSame = false;
}
SurfaceImpl::~SurfaceImpl() {
Release();
}
void SurfaceImpl::Release() {
if (penOld) {
::SelectObject(reinterpret_cast<HDC>(hdc), penOld);
::DeleteObject(pen);
penOld = 0;
}
pen = 0;
if (brushOld) {
::SelectObject(reinterpret_cast<HDC>(hdc), brushOld);
::DeleteObject(brush);
brushOld = 0;
}
brush = 0;
if (fontOld) {
// Fonts are not deleted as they are owned by a Font object
::SelectObject(reinterpret_cast<HDC>(hdc), fontOld);
fontOld = 0;
}
font = 0;
if (bitmapOld) {
::SelectObject(reinterpret_cast<HDC>(hdc), bitmapOld);
::DeleteObject(bitmap);
bitmapOld = 0;
}
bitmap = 0;
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -