Compare commits

...

6 Commits

Author SHA1 Message Date
d7ccc4d81d patch 8.0.1343: MS-Windows: does not show colored emojis
Problem:    MS-Windows: does not show colored emojis.
Solution:   Implement colored emojis. Improve drawing speed. Make 'taamode'
            work. (Taro Muraoka, Yasuhiro Matsumoto, Ken Takata, close #2375)
2017-11-26 14:29:32 +01:00
fb1db0e355 patch 8.0.1342: cannot build with Motif and multi-byte
Problem:    Cannot build with Motif and multi-byte. (Mohamed Boughaba)
Solution:   Use the right input method status flag. (closes #2374)
2017-11-25 21:07:46 +01:00
be5d998d0e patch 8.0.1341: 'imactivatefunc' test fails on MS-Windows
Problem:    'imactivatefunc' test fails on MS-Windows.
Solution:   Skip the text.
2017-11-25 17:58:28 +01:00
281c93e714 patch 8.0.1340: MS-Windows: cannot build GUI without IME
Problem:    MS-Windows: cannot build GUI without IME.
Solution:   Define im_get_status() and im_set_active() when IME is not used.
2017-11-25 17:48:33 +01:00
83799a7b74 patch 8.0.1339: no test for what 8.0.1335 fixes
Problem:    No test for what 8.0.1335 fixes.
Solution:   Add a test. (Yasuhiro Matsumoto, closes #2373)
2017-11-25 17:24:09 +01:00
819edbe078 patch 8.0.1338: USE_IM_CONTROL is confusing and incomplete
Problem:    USE_IM_CONTROL is confusing and incomplete.
Solution:   Just use FEAT_MBYTE.  Call 'imactivatefunc' also without GUI.
2017-11-25 17:14:33 +01:00
21 changed files with 725 additions and 427 deletions

View File

@ -16,6 +16,7 @@ matrix:
before_build: before_build:
- '"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 /release' - '"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 /release'
- 'set INCLUDE=%INCLUDE%C:\Program Files (x86)\Windows Kits\8.1\Include\um'
build_script: build_script:
- src/appveyor.bat - src/appveyor.bat

View File

@ -4259,6 +4259,7 @@ A jump table for the options with a short description can be found at |Q_op|.
{only available when compiled with |+mbyte|} {only available when compiled with |+mbyte|}
This option specifies a function that will be called to This option specifies a function that will be called to
activate/inactivate Input Method. activate/inactivate Input Method.
Does not work in the MS-Windows GUI version.
Example: > Example: >
function ImActivateFunc(active) function ImActivateFunc(active)
@ -4374,6 +4375,7 @@ A jump table for the options with a short description can be found at |Q_op|.
{only available when compiled with |+mbyte|} {only available when compiled with |+mbyte|}
This option specifies a function that is called to obtain the status This option specifies a function that is called to obtain the status
of Input Method. It must return a positive number when IME is active. of Input Method. It must return a positive number when IME is active.
Does not work in the MS-Windows GUI version.
Example: > Example: >
function ImStatusFunc() function ImStatusFunc()
@ -6152,11 +6154,34 @@ A jump table for the options with a short description can be found at |Q_op|.
Example: > Example: >
set encoding=utf-8 set encoding=utf-8
set gfn=Ricty_Diminished:h12:cSHIFTJIS set gfn=Ricty_Diminished:h12
set rop=type:directx set rop=type:directx
< <
If select a raster font (Courier, Terminal or FixedSys) to If select a raster font (Courier, Terminal or FixedSys which
'guifont', it fallbacks to be drawn by GDI automatically. have ".fon" extension in file name) to 'guifont', it will be
drawn by GDI as a fallback. This fallback will cause
significant slow down on drawing.
NOTE: It is known that some fonts and options combination
causes trouble on drawing glyphs.
- 'rendmode:5' and 'renmode:6' will not work with some
special made fonts (True-Type fonts which includes only
bitmap glyphs).
- 'taamode:3' will not work with some vector fonts.
NOTE: With this option, you can display colored emoji
(emoticon) in Windows 8.1 or later. To display colored emoji,
there are some conditions which you should notice.
- If your font includes non-colored emoji already, it will
be used.
- If your font doesn't have emoji, the system chooses an
alternative symbol font. On Windows 10, "Segoe UI Emoji"
will be used.
- When this alternative font didn't have fixed width glyph,
emoji might be rendered beyond the bounding box of drawing
cell.
Other render types are currently not supported. Other render types are currently not supported.

View File

@ -516,7 +516,7 @@ edit(
*/ */
if (curbuf->b_p_iminsert == B_IMODE_LMAP) if (curbuf->b_p_iminsert == B_IMODE_LMAP)
State |= LANGMAP; State |= LANGMAP;
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
im_set_active(curbuf->b_p_iminsert == B_IMODE_IM); im_set_active(curbuf->b_p_iminsert == B_IMODE_IM);
#endif #endif
@ -8372,7 +8372,7 @@ ins_reg(void)
++no_u_sync; ++no_u_sync;
if (regname == '=') if (regname == '=')
{ {
# ifdef USE_IM_CONTROL # ifdef FEAT_MBYTE
int im_on = im_get_status(); int im_on = im_get_status();
# endif # endif
/* Sync undo when evaluating the expression calls setline() or /* Sync undo when evaluating the expression calls setline() or
@ -8380,7 +8380,7 @@ ins_reg(void)
u_sync_once = 2; u_sync_once = 2;
regname = get_expr_register(); regname = get_expr_register();
# ifdef USE_IM_CONTROL # ifdef FEAT_MBYTE
/* Restore the Input Method. */ /* Restore the Input Method. */
if (im_on) if (im_on)
im_set_active(TRUE); im_set_active(TRUE);
@ -8509,12 +8509,12 @@ ins_ctrl_hat(void)
{ {
curbuf->b_p_iminsert = B_IMODE_LMAP; curbuf->b_p_iminsert = B_IMODE_LMAP;
State |= LANGMAP; State |= LANGMAP;
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
im_set_active(FALSE); im_set_active(FALSE);
#endif #endif
} }
} }
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
else else
{ {
/* There are no ":lmap" mappings, toggle IM */ /* There are no ":lmap" mappings, toggle IM */
@ -8661,7 +8661,7 @@ ins_esc(
} }
} }
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
/* Disable IM to allow typing English directly for Normal mode commands. /* Disable IM to allow typing English directly for Normal mode commands.
* When ":lmap" is enabled don't change 'iminsert' (IM can be enabled as * When ":lmap" is enabled don't change 'iminsert' (IM can be enabled as
* well). */ * well). */

View File

@ -359,11 +359,11 @@ getcmdline(
b_im_ptr = &curbuf->b_p_imsearch; b_im_ptr = &curbuf->b_p_imsearch;
if (*b_im_ptr == B_IMODE_LMAP) if (*b_im_ptr == B_IMODE_LMAP)
State |= LANGMAP; State |= LANGMAP;
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
im_set_active(*b_im_ptr == B_IMODE_IM); im_set_active(*b_im_ptr == B_IMODE_IM);
#endif #endif
} }
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
else if (p_imcmdline) else if (p_imcmdline)
im_set_active(TRUE); im_set_active(TRUE);
#endif #endif
@ -1119,7 +1119,7 @@ getcmdline(
{ {
/* ":lmap" mappings exists, toggle use of mappings. */ /* ":lmap" mappings exists, toggle use of mappings. */
State ^= LANGMAP; State ^= LANGMAP;
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
im_set_active(FALSE); /* Disable input method */ im_set_active(FALSE); /* Disable input method */
#endif #endif
if (b_im_ptr != NULL) if (b_im_ptr != NULL)
@ -1130,7 +1130,7 @@ getcmdline(
*b_im_ptr = B_IMODE_NONE; *b_im_ptr = B_IMODE_NONE;
} }
} }
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
else else
{ {
/* There are no ":lmap" mappings, toggle IM. When /* There are no ":lmap" mappings, toggle IM. When
@ -2143,7 +2143,7 @@ returncmd:
#endif #endif
State = save_State; State = save_State;
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
if (b_im_ptr != NULL && *b_im_ptr != B_IMODE_LMAP) if (b_im_ptr != NULL && *b_im_ptr != B_IMODE_LMAP)
im_save_status(b_im_ptr); im_save_status(b_im_ptr);
im_set_active(FALSE); im_set_active(FALSE);

View File

@ -2890,7 +2890,7 @@ vgetorpeek(int advance)
+ typebuf.tb_len] != NUL) + typebuf.tb_len] != NUL)
typebuf.tb_noremap[typebuf.tb_off typebuf.tb_noremap[typebuf.tb_off
+ typebuf.tb_len++] = RM_YES; + typebuf.tb_len++] = RM_YES;
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
/* Get IM status right after getting keys, not after the /* Get IM status right after getting keys, not after the
* timeout for a mapping (focus may be lost by then). */ * timeout for a mapping (focus may be lost by then). */
vgetc_im_active = im_get_status(); vgetc_im_active = im_get_status();

View File

@ -1022,7 +1022,7 @@ EXTERN int stop_insert_mode; /* for ":stopinsert" and 'insertmode' */
EXTERN int KeyTyped; /* TRUE if user typed current char */ EXTERN int KeyTyped; /* TRUE if user typed current char */
EXTERN int KeyStuffed; /* TRUE if current char from stuffbuf */ EXTERN int KeyStuffed; /* TRUE if current char from stuffbuf */
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
EXTERN int vgetc_im_active; /* Input Method was active for last EXTERN int vgetc_im_active; /* Input Method was active for last
character obtained from vgetc() */ character obtained from vgetc() */
#endif #endif

View File

@ -1078,7 +1078,7 @@ gui_update_cursor(
gui_undraw_cursor(); gui_undraw_cursor();
if (gui.row < 0) if (gui.row < 0)
return; return;
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
if (gui.row != gui.cursor_row || gui.col != gui.cursor_col) if (gui.row != gui.cursor_row || gui.col != gui.cursor_col)
im_set_position(gui.row, gui.col); im_set_position(gui.row, gui.col);
#endif #endif
@ -1136,7 +1136,7 @@ gui_update_cursor(
if (id > 0) if (id > 0)
{ {
cattr = syn_id2colors(id, &cfg, &cbg); cattr = syn_id2colors(id, &cfg, &cbg);
#if defined(USE_IM_CONTROL) || defined(FEAT_HANGULIN) #if defined(FEAT_MBYTE) || defined(FEAT_HANGULIN)
{ {
static int iid; static int iid;
guicolor_T fg, bg; guicolor_T fg, bg;

View File

@ -4,6 +4,7 @@
* *
* Contributors: * Contributors:
* - Ken Takata * - Ken Takata
* - Yasuhiro Matsumoto
* *
* Copyright (C) 2013 MURAOKA Taro <koron.kaoriya@gmail.com> * Copyright (C) 2013 MURAOKA Taro <koron.kaoriya@gmail.com>
* THIS FILE IS DISTRIBUTED UNDER THE VIM LICENSE. * THIS FILE IS DISTRIBUTED UNDER THE VIM LICENSE.
@ -23,7 +24,21 @@
#include <math.h> #include <math.h>
#include <d2d1.h> #include <d2d1.h>
#include <d2d1helper.h> #include <d2d1helper.h>
#include <dwrite.h>
// Disable these macros to compile with old VC and newer SDK (V8.1 or later).
#if defined(_MSC_VER) && (_MSC_VER < 1700)
# define _COM_Outptr_ __out
# define _In_reads_(s)
# define _In_reads_opt_(s)
# define _Maybenull_
# define _Out_writes_(s)
# define _Out_writes_opt_(s)
# define _Out_writes_to_(x, y)
# define _Out_writes_to_opt_(x, y)
# define _Outptr_
#endif
#include <dwrite_2.h>
#include "gui_dwrite.h" #include "gui_dwrite.h"
@ -79,16 +94,6 @@ template <class T> inline void SafeRelease(T **ppT)
} }
} }
struct GdiTextRendererContext
{
// const fields.
COLORREF color;
FLOAT cellWidth;
// working fields.
FLOAT offsetX;
};
static DWRITE_PIXEL_GEOMETRY static DWRITE_PIXEL_GEOMETRY
ToPixelGeometry(int value) ToPixelGeometry(int value)
{ {
@ -184,17 +189,151 @@ ToInt(DWRITE_RENDERING_MODE value)
} }
} }
class FontCache {
public:
struct Item {
HFONT hFont;
IDWriteTextFormat* pTextFormat;
DWRITE_FONT_WEIGHT fontWeight;
DWRITE_FONT_STYLE fontStyle;
Item() : hFont(NULL), pTextFormat(NULL) {}
};
private:
int mSize;
Item *mItems;
public:
FontCache(int size = 2) :
mSize(size),
mItems(new Item[size])
{
}
~FontCache()
{
for (int i = 0; i < mSize; ++i)
SafeRelease(&mItems[i].pTextFormat);
delete[] mItems;
}
bool get(HFONT hFont, Item &item)
{
int n = find(hFont);
if (n < 0)
return false;
item = mItems[n];
slide(n);
return true;
}
void put(const Item& item)
{
int n = find(item.hFont);
if (n < 0)
n = mSize - 1;
if (mItems[n].pTextFormat != item.pTextFormat)
{
SafeRelease(&mItems[n].pTextFormat);
item.pTextFormat->AddRef();
}
mItems[n] = item;
slide(n);
}
private:
int find(HFONT hFont)
{
for (int i = 0; i < mSize; ++i)
{
if (mItems[i].hFont == hFont)
return i;
}
return -1;
}
void slide(int nextTop)
{
if (nextTop == 0)
return;
Item tmp = mItems[nextTop];
for (int i = nextTop - 1; i >= 0; --i)
mItems[i + 1] = mItems[i];
mItems[0] = tmp;
}
};
struct DWriteContext {
HDC mHDC;
bool mDrawing;
bool mFallbackDC;
ID2D1Factory *mD2D1Factory;
ID2D1DCRenderTarget *mRT;
ID2D1SolidColorBrush *mBrush;
IDWriteFactory *mDWriteFactory;
IDWriteFactory2 *mDWriteFactory2;
IDWriteGdiInterop *mGdiInterop;
IDWriteRenderingParams *mRenderingParams;
FontCache mFontCache;
IDWriteTextFormat *mTextFormat;
DWRITE_FONT_WEIGHT mFontWeight;
DWRITE_FONT_STYLE mFontStyle;
D2D1_TEXT_ANTIALIAS_MODE mTextAntialiasMode;
// METHODS
DWriteContext();
virtual ~DWriteContext();
HRESULT CreateTextFormatFromLOGFONT(const LOGFONTW &logFont,
IDWriteTextFormat **ppTextFormat);
HRESULT SetFontByLOGFONT(const LOGFONTW &logFont);
void SetFont(HFONT hFont);
void BindDC(HDC hdc, RECT *rect);
void AssureDrawing();
ID2D1Brush* SolidBrush(COLORREF color);
void DrawText(const WCHAR* text, int len,
int x, int y, int w, int h, int cellWidth, COLORREF color,
UINT fuOptions, CONST RECT *lprc, CONST INT * lpDx);
void FillRect(RECT *rc, COLORREF color);
void Flush();
void SetRenderingParams(
const DWriteRenderingParams *params);
DWriteRenderingParams *GetRenderingParams(
DWriteRenderingParams *params);
};
class AdjustedGlyphRun : public DWRITE_GLYPH_RUN class AdjustedGlyphRun : public DWRITE_GLYPH_RUN
{ {
private: private:
FLOAT &mAccum;
FLOAT mDelta; FLOAT mDelta;
FLOAT *mAdjustedAdvances; FLOAT *mAdjustedAdvances;
public: public:
AdjustedGlyphRun( AdjustedGlyphRun(
const DWRITE_GLYPH_RUN *glyphRun, const DWRITE_GLYPH_RUN *glyphRun,
FLOAT cellWidth) : FLOAT cellWidth,
FLOAT &accum) :
DWRITE_GLYPH_RUN(*glyphRun), DWRITE_GLYPH_RUN(*glyphRun),
mAccum(accum),
mDelta(0.0f), mDelta(0.0f),
mAdjustedAdvances(new FLOAT[glyphRun->glyphCount]) mAdjustedAdvances(new FLOAT[glyphRun->glyphCount])
{ {
@ -209,45 +348,44 @@ public:
glyphAdvances = mAdjustedAdvances; glyphAdvances = mAdjustedAdvances;
} }
~AdjustedGlyphRun(void) ~AdjustedGlyphRun()
{ {
mAccum += mDelta;
delete[] mAdjustedAdvances; delete[] mAdjustedAdvances;
} }
FLOAT getDelta(void) const
{
return mDelta;
}
static FLOAT adjustToCell(FLOAT value, FLOAT cellWidth) static FLOAT adjustToCell(FLOAT value, FLOAT cellWidth)
{ {
int cellCount = (int)floor(value / cellWidth + 0.5f); int cellCount = int(floor(value / cellWidth + 0.5f));
if (cellCount < 1) if (cellCount < 1)
cellCount = 1; cellCount = 1;
return cellCount * cellWidth; return cellCount * cellWidth;
} }
}; };
class GdiTextRenderer FINAL : public IDWriteTextRenderer struct TextRendererContext {
// const fields.
COLORREF color;
FLOAT cellWidth;
// working fields.
FLOAT offsetX;
};
class TextRenderer FINAL : public IDWriteTextRenderer
{ {
public: public:
GdiTextRenderer( TextRenderer(
IDWriteBitmapRenderTarget* bitmapRenderTarget, DWriteContext* pDWC) :
IDWriteRenderingParams* renderingParams) :
cRefCount_(0), cRefCount_(0),
pRenderTarget_(bitmapRenderTarget), pDWC_(pDWC)
pRenderingParams_(renderingParams)
{ {
pRenderTarget_->AddRef();
pRenderingParams_->AddRef();
AddRef(); AddRef();
} }
// add "virtual" to avoid a compiler warning // add "virtual" to avoid a compiler warning
virtual ~GdiTextRenderer() virtual ~TextRenderer()
{ {
SafeRelease(&pRenderTarget_);
SafeRelease(&pRenderingParams_);
} }
IFACEMETHOD(IsPixelSnappingDisabled)( IFACEMETHOD(IsPixelSnappingDisabled)(
@ -263,7 +401,8 @@ public:
__out DWRITE_MATRIX* transform) __out DWRITE_MATRIX* transform)
{ {
// forward the render target's transform // forward the render target's transform
pRenderTarget_->GetCurrentTransform(transform); pDWC_->mRT->GetTransform(
reinterpret_cast<D2D1_MATRIX_3X2_F*>(transform));
return S_OK; return S_OK;
} }
@ -271,43 +410,12 @@ public:
__maybenull void* clientDrawingContext, __maybenull void* clientDrawingContext,
__out FLOAT* pixelsPerDip) __out FLOAT* pixelsPerDip)
{ {
*pixelsPerDip = pRenderTarget_->GetPixelsPerDip(); float dpiX, unused;
pDWC_->mRT->GetDpi(&dpiX, &unused);
*pixelsPerDip = dpiX / 96.0f;
return S_OK; return S_OK;
} }
IFACEMETHOD(DrawGlyphRun)(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_MEASURING_MODE measuringMode,
__in DWRITE_GLYPH_RUN const* glyphRun,
__in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
IUnknown* clientDrawingEffect)
{
HRESULT hr = S_OK;
GdiTextRendererContext *context =
reinterpret_cast<GdiTextRendererContext*>(clientDrawingContext);
AdjustedGlyphRun adjustedGlyphRun(glyphRun, context->cellWidth);
// Pass on the drawing call to the render target to do the real work.
RECT dirtyRect = {0};
hr = pRenderTarget_->DrawGlyphRun(
baselineOriginX + context->offsetX,
baselineOriginY,
measuringMode,
&adjustedGlyphRun,
pRenderingParams_,
context->color,
&dirtyRect);
context->offsetX += adjustedGlyphRun.getDelta();
return hr;
}
IFACEMETHOD(DrawUnderline)( IFACEMETHOD(DrawUnderline)(
__maybenull void* clientDrawingContext, __maybenull void* clientDrawingContext,
FLOAT baselineOriginX, FLOAT baselineOriginX,
@ -340,6 +448,69 @@ public:
return E_NOTIMPL; return E_NOTIMPL;
} }
IFACEMETHOD(DrawGlyphRun)(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_MEASURING_MODE measuringMode,
__in DWRITE_GLYPH_RUN const* glyphRun,
__in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
IUnknown* clientDrawingEffect)
{
TextRendererContext *context =
reinterpret_cast<TextRendererContext*>(clientDrawingContext);
AdjustedGlyphRun adjustedGlyphRun(glyphRun, context->cellWidth,
context->offsetX);
if (pDWC_->mDWriteFactory2 != NULL)
{
IDWriteColorGlyphRunEnumerator *enumerator = NULL;
HRESULT hr = pDWC_->mDWriteFactory2->TranslateColorGlyphRun(
baselineOriginX + context->offsetX,
baselineOriginY,
&adjustedGlyphRun,
NULL,
DWRITE_MEASURING_MODE_GDI_NATURAL,
NULL,
0,
&enumerator);
if (SUCCEEDED(hr))
{
// Draw by IDWriteFactory2 for color emoji
BOOL hasRun = TRUE;
enumerator->MoveNext(&hasRun);
while (hasRun)
{
const DWRITE_COLOR_GLYPH_RUN* colorGlyphRun;
enumerator->GetCurrentRun(&colorGlyphRun);
pDWC_->mBrush->SetColor(colorGlyphRun->runColor);
pDWC_->mRT->DrawGlyphRun(
D2D1::Point2F(
colorGlyphRun->baselineOriginX,
colorGlyphRun->baselineOriginY),
&colorGlyphRun->glyphRun,
pDWC_->mBrush,
DWRITE_MEASURING_MODE_NATURAL);
enumerator->MoveNext(&hasRun);
}
SafeRelease(&enumerator);
return S_OK;
}
}
// Draw by IDWriteFactory (without color emoji)
pDWC_->mRT->DrawGlyphRun(
D2D1::Point2F(
baselineOriginX + context->offsetX,
baselineOriginY),
&adjustedGlyphRun,
pDWC_->SolidBrush(context->color),
DWRITE_MEASURING_MODE_NATURAL);
return S_OK;
}
public: public:
IFACEMETHOD_(unsigned long, AddRef) () IFACEMETHOD_(unsigned long, AddRef) ()
{ {
@ -385,80 +556,28 @@ public:
private: private:
long cRefCount_; long cRefCount_;
IDWriteBitmapRenderTarget* pRenderTarget_; DWriteContext* pDWC_;
IDWriteRenderingParams* pRenderingParams_;
};
struct DWriteContext {
FLOAT mDpiScaleX;
FLOAT mDpiScaleY;
bool mDrawing;
ID2D1Factory *mD2D1Factory;
ID2D1DCRenderTarget *mRT;
ID2D1SolidColorBrush *mBrush;
IDWriteFactory *mDWriteFactory;
IDWriteGdiInterop *mGdiInterop;
IDWriteRenderingParams *mRenderingParams;
IDWriteTextFormat *mTextFormat;
HFONT mLastHFont;
DWRITE_FONT_WEIGHT mFontWeight;
DWRITE_FONT_STYLE mFontStyle;
D2D1_TEXT_ANTIALIAS_MODE mTextAntialiasMode;
// METHODS
DWriteContext();
virtual ~DWriteContext();
HRESULT SetLOGFONT(const LOGFONTW &logFont, float fontSize);
void SetFont(HFONT hFont);
void SetFont(const LOGFONTW &logFont);
void DrawText(HDC hdc, const WCHAR* text, int len,
int x, int y, int w, int h, int cellWidth, COLORREF color);
float PixelsToDipsX(int x);
float PixelsToDipsY(int y);
void SetRenderingParams(
const DWriteRenderingParams *params);
DWriteRenderingParams *GetRenderingParams(
DWriteRenderingParams *params);
}; };
DWriteContext::DWriteContext() : DWriteContext::DWriteContext() :
mDpiScaleX(1.f), mHDC(NULL),
mDpiScaleY(1.f),
mDrawing(false), mDrawing(false),
mFallbackDC(false),
mD2D1Factory(NULL), mD2D1Factory(NULL),
mRT(NULL), mRT(NULL),
mBrush(NULL), mBrush(NULL),
mDWriteFactory(NULL), mDWriteFactory(NULL),
mDWriteFactory2(NULL),
mGdiInterop(NULL), mGdiInterop(NULL),
mRenderingParams(NULL), mRenderingParams(NULL),
mFontCache(8),
mTextFormat(NULL), mTextFormat(NULL),
mLastHFont(NULL),
mFontWeight(DWRITE_FONT_WEIGHT_NORMAL), mFontWeight(DWRITE_FONT_WEIGHT_NORMAL),
mFontStyle(DWRITE_FONT_STYLE_NORMAL), mFontStyle(DWRITE_FONT_STYLE_NORMAL),
mTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_DEFAULT) mTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_DEFAULT)
{ {
HRESULT hr; HRESULT hr;
HDC screen = ::GetDC(0);
mDpiScaleX = ::GetDeviceCaps(screen, LOGPIXELSX) / 96.0f;
mDpiScaleY = ::GetDeviceCaps(screen, LOGPIXELSY) / 96.0f;
::ReleaseDC(0, screen);
hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
__uuidof(ID2D1Factory), NULL, __uuidof(ID2D1Factory), NULL,
reinterpret_cast<void**>(&mD2D1Factory)); reinterpret_cast<void**>(&mD2D1Factory));
@ -495,6 +614,15 @@ DWriteContext::DWriteContext() :
mDWriteFactory); mDWriteFactory);
} }
if (SUCCEEDED(hr))
{
DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory2),
reinterpret_cast<IUnknown**>(&mDWriteFactory2));
_RPT1(_CRT_WARN, "IDWriteFactory2: %s\n", SUCCEEDED(hr) ? "available" : "not available");
}
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = mDWriteFactory->GetGdiInterop(&mGdiInterop); hr = mDWriteFactory->GetGdiInterop(&mGdiInterop);
@ -515,20 +643,24 @@ DWriteContext::~DWriteContext()
SafeRelease(&mRenderingParams); SafeRelease(&mRenderingParams);
SafeRelease(&mGdiInterop); SafeRelease(&mGdiInterop);
SafeRelease(&mDWriteFactory); SafeRelease(&mDWriteFactory);
SafeRelease(&mDWriteFactory2);
SafeRelease(&mBrush); SafeRelease(&mBrush);
SafeRelease(&mRT); SafeRelease(&mRT);
SafeRelease(&mD2D1Factory); SafeRelease(&mD2D1Factory);
} }
HRESULT HRESULT
DWriteContext::SetLOGFONT(const LOGFONTW &logFont, float fontSize) DWriteContext::CreateTextFormatFromLOGFONT(const LOGFONTW &logFont,
IDWriteTextFormat **ppTextFormat)
{ {
// Most of this function is copy from: http://msdn.microsoft.com/en-us/library/windows/desktop/dd941783(v=vs.85).aspx // Most of this function is copied from: https://github.com/Microsoft/Windows-classic-samples/blob/master/Samples/Win7Samples/multimedia/DirectWrite/RenderTest/TextHelpers.cpp
HRESULT hr = S_OK; HRESULT hr = S_OK;
IDWriteTextFormat *pTextFormat = NULL;
IDWriteFont *font = NULL; IDWriteFont *font = NULL;
IDWriteFontFamily *fontFamily = NULL; IDWriteFontFamily *fontFamily = NULL;
IDWriteLocalizedStrings *localizedFamilyNames = NULL; IDWriteLocalizedStrings *localizedFamilyNames = NULL;
float fontSize = 0;
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -561,33 +693,30 @@ DWriteContext::SetLOGFONT(const LOGFONTW &logFont, float fontSize)
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
// If no font size was passed in use the lfHeight of the LOGFONT. // Use lfHeight of the LOGFONT as font size.
if (fontSize == 0) fontSize = float(logFont.lfHeight);
if (fontSize < 0)
{ {
// Convert from pixels to DIPs. // Negative lfHeight represents the size of the em unit.
fontSize = PixelsToDipsY(logFont.lfHeight); fontSize = -fontSize;
if (fontSize < 0) }
{ else
// Negative lfHeight represents the size of the em unit. {
fontSize = -fontSize; // Positive lfHeight represents the cell height (ascent +
} // descent).
else DWRITE_FONT_METRICS fontMetrics;
{ font->GetMetrics(&fontMetrics);
// Positive lfHeight represents the cell height (ascent +
// descent).
DWRITE_FONT_METRICS fontMetrics;
font->GetMetrics(&fontMetrics);
// Convert the cell height (ascent + descent) from design units // Convert the cell height (ascent + descent) from design units
// to ems. // to ems.
float cellHeight = static_cast<float>( float cellHeight = static_cast<float>(
fontMetrics.ascent + fontMetrics.descent) fontMetrics.ascent + fontMetrics.descent)
/ fontMetrics.designUnitsPerEm; / fontMetrics.designUnitsPerEm;
// Divide the font size by the cell height to get the font em // Divide the font size by the cell height to get the font em
// size. // size.
fontSize /= cellHeight; fontSize /= cellHeight;
}
} }
} }
@ -612,123 +741,165 @@ DWriteContext::SetLOGFONT(const LOGFONTW &logFont, float fontSize)
font->GetStretch(), font->GetStretch(),
fontSize, fontSize,
localeName, localeName,
&mTextFormat); &pTextFormat);
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ hr = pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);
mFontWeight = static_cast<DWRITE_FONT_WEIGHT>(logFont.lfWeight);
mFontStyle = logFont.lfItalic ? DWRITE_FONT_STYLE_ITALIC if (SUCCEEDED(hr))
: DWRITE_FONT_STYLE_NORMAL; hr = pTextFormat->SetParagraphAlignment(
} DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
if (SUCCEEDED(hr))
hr = pTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
SafeRelease(&localizedFamilyNames); SafeRelease(&localizedFamilyNames);
SafeRelease(&fontFamily); SafeRelease(&fontFamily);
SafeRelease(&font); SafeRelease(&font);
if (SUCCEEDED(hr))
*ppTextFormat = pTextFormat;
else
SafeRelease(&pTextFormat);
return hr;
}
HRESULT
DWriteContext::SetFontByLOGFONT(const LOGFONTW &logFont)
{
HRESULT hr = S_OK;
IDWriteTextFormat *pTextFormat = NULL;
hr = CreateTextFormatFromLOGFONT(logFont, &pTextFormat);
if (SUCCEEDED(hr))
{
SafeRelease(&mTextFormat);
mTextFormat = pTextFormat;
mFontWeight = static_cast<DWRITE_FONT_WEIGHT>(logFont.lfWeight);
mFontStyle = logFont.lfItalic ? DWRITE_FONT_STYLE_ITALIC
: DWRITE_FONT_STYLE_NORMAL;
}
return hr; return hr;
} }
void void
DWriteContext::SetFont(HFONT hFont) DWriteContext::SetFont(HFONT hFont)
{ {
if (mLastHFont != hFont) FontCache::Item item;
if (mFontCache.get(hFont, item))
{ {
LOGFONTW lf; if (item.pTextFormat != NULL)
if (GetObjectW(hFont, sizeof(lf), &lf))
{ {
SetFont(lf); item.pTextFormat->AddRef();
mLastHFont = hFont; SafeRelease(&mTextFormat);
mTextFormat = item.pTextFormat;
mFontWeight = item.fontWeight;
mFontStyle = item.fontStyle;
mFallbackDC = false;
} }
else
mFallbackDC = true;
return;
} }
HRESULT hr = E_FAIL;
LOGFONTW lf;
if (GetObjectW(hFont, sizeof(lf), &lf))
hr = SetFontByLOGFONT(lf);
item.hFont = hFont;
if (SUCCEEDED(hr))
{
item.pTextFormat = mTextFormat;
item.fontWeight = mFontWeight;
item.fontStyle = mFontStyle;
}
mFontCache.put(item);
} }
void void
DWriteContext::SetFont(const LOGFONTW &logFont) DWriteContext::BindDC(HDC hdc, RECT *rect)
{ {
SafeRelease(&mTextFormat); Flush();
mLastHFont = NULL; mRT->BindDC(hdc, rect);
mRT->SetTransform(D2D1::IdentityMatrix());
HRESULT hr = SetLOGFONT(logFont, 0.f); mHDC = hdc;
if (SUCCEEDED(hr))
hr = mTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);
if (SUCCEEDED(hr))
hr = mTextFormat->SetParagraphAlignment(
DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
if (SUCCEEDED(hr))
hr = mTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
} }
void void
DWriteContext::DrawText(HDC hdc, const WCHAR* text, int len, DWriteContext::AssureDrawing()
int x, int y, int w, int h, int cellWidth, COLORREF color)
{ {
HRESULT hr = S_OK; if (mDrawing == false)
IDWriteBitmapRenderTarget *bmpRT = NULL; {
mRT->BeginDraw();
mDrawing = true;
}
}
// Skip when any fonts are not set. ID2D1Brush*
if (mTextFormat == NULL) DWriteContext::SolidBrush(COLORREF color)
{
mBrush->SetColor(D2D1::ColorF(UINT32(GetRValue(color)) << 16 |
UINT32(GetGValue(color)) << 8 | UINT32(GetBValue(color))));
return mBrush;
}
void
DWriteContext::DrawText(const WCHAR* text, int len,
int x, int y, int w, int h, int cellWidth, COLORREF color,
UINT fuOptions, CONST RECT *lprc, CONST INT * lpDx)
{
if (mFallbackDC)
{
Flush();
ExtTextOutW(mHDC, x, y, fuOptions, lprc, text, len, lpDx);
return; return;
}
// Check possibility of zero divided error. AssureDrawing();
if (cellWidth == 0 || mDpiScaleX == 0.0f || mDpiScaleY == 0.0f)
return;
if (SUCCEEDED(hr)) HRESULT hr;
hr = mGdiInterop->CreateBitmapRenderTarget(hdc, w, h, &bmpRT); IDWriteTextLayout *textLayout = NULL;
hr = mDWriteFactory->CreateTextLayout(text, len, mTextFormat,
FLOAT(w), FLOAT(h), &textLayout);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
IDWriteTextLayout *textLayout = NULL; DWRITE_TEXT_RANGE textRange = { 0, UINT32(len) };
textLayout->SetFontWeight(mFontWeight, textRange);
textLayout->SetFontStyle(mFontStyle, textRange);
HDC memdc = bmpRT->GetMemoryDC(); TextRenderer renderer(this);
BitBlt(memdc, 0, 0, w, h, hdc, x, y, SRCCOPY); TextRendererContext context = { color, FLOAT(cellWidth), 0.0f };
textLayout->Draw(&context, &renderer, FLOAT(x), FLOAT(y));
hr = mDWriteFactory->CreateGdiCompatibleTextLayout(
text, len, mTextFormat, PixelsToDipsX(w),
PixelsToDipsY(h), mDpiScaleX, NULL, TRUE, &textLayout);
if (SUCCEEDED(hr))
{
DWRITE_TEXT_RANGE textRange = { 0, (UINT32)len };
textLayout->SetFontWeight(mFontWeight, textRange);
textLayout->SetFontStyle(mFontStyle, textRange);
}
if (SUCCEEDED(hr))
{
GdiTextRenderer *renderer = new GdiTextRenderer(bmpRT,
mRenderingParams);
GdiTextRendererContext data = {
color,
PixelsToDipsX(cellWidth),
0.0f
};
textLayout->Draw(&data, renderer, 0, 0);
SafeRelease(&renderer);
}
BitBlt(hdc, x, y, w, h, memdc, 0, 0, SRCCOPY);
SafeRelease(&textLayout);
} }
SafeRelease(&bmpRT); SafeRelease(&textLayout);
} }
float void
DWriteContext::PixelsToDipsX(int x) DWriteContext::FillRect(RECT *rc, COLORREF color)
{ {
return x / mDpiScaleX; AssureDrawing();
mRT->FillRectangle(
D2D1::RectF(FLOAT(rc->left), FLOAT(rc->top),
FLOAT(rc->right), FLOAT(rc->bottom)),
SolidBrush(color));
} }
float void
DWriteContext::PixelsToDipsY(int y) DWriteContext::Flush()
{ {
return y / mDpiScaleY; if (mDrawing)
{
mRT->EndDraw();
mDrawing = false;
}
} }
void void
@ -757,6 +928,10 @@ DWriteContext::SetRenderingParams(
SafeRelease(&mRenderingParams); SafeRelease(&mRenderingParams);
mRenderingParams = renderingParams; mRenderingParams = renderingParams;
mTextAntialiasMode = textAntialiasMode; mTextAntialiasMode = textAntialiasMode;
Flush();
mRT->SetTextRenderingParams(mRenderingParams);
mRT->SetTextAntialiasMode(mTextAntialiasMode);
} }
} }
@ -824,40 +999,23 @@ DWriteContext_Open(void)
return new DWriteContext(); return new DWriteContext();
} }
void
DWriteContext_BeginDraw(DWriteContext *ctx)
{
if (ctx != NULL && ctx->mRT != NULL)
{
ctx->mRT->BeginDraw();
ctx->mRT->SetTransform(D2D1::IdentityMatrix());
ctx->mDrawing = true;
}
}
void void
DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect) DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect)
{ {
if (ctx != NULL && ctx->mRT != NULL) if (ctx != NULL)
{ ctx->BindDC(hdc, rect);
ctx->mRT->BindDC(hdc, rect);
ctx->mRT->SetTextAntialiasMode(ctx->mTextAntialiasMode);
}
} }
void void
DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont) DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont)
{ {
if (ctx != NULL) if (ctx != NULL)
{
ctx->SetFont(hFont); ctx->SetFont(hFont);
}
} }
void void
DWriteContext_DrawText( DWriteContext_DrawText(
DWriteContext *ctx, DWriteContext *ctx,
HDC hdc,
const WCHAR* text, const WCHAR* text,
int len, int len,
int x, int x,
@ -865,20 +1023,28 @@ DWriteContext_DrawText(
int w, int w,
int h, int h,
int cellWidth, int cellWidth,
COLORREF color) COLORREF color,
UINT fuOptions,
CONST RECT *lprc,
CONST INT * lpDx)
{ {
if (ctx != NULL) if (ctx != NULL)
ctx->DrawText(hdc, text, len, x, y, w, h, cellWidth, color); ctx->DrawText(text, len, x, y, w, h, cellWidth, color,
fuOptions, lprc, lpDx);
} }
void void
DWriteContext_EndDraw(DWriteContext *ctx) DWriteContext_FillRect(DWriteContext *ctx, RECT *rc, COLORREF color)
{ {
if (ctx != NULL && ctx->mRT != NULL) if (ctx != NULL)
{ ctx->FillRect(rc, color);
ctx->mRT->EndDraw(); }
ctx->mDrawing = false;
} void
DWriteContext_Flush(DWriteContext *ctx)
{
if (ctx != NULL)
ctx->Flush();
} }
void void

View File

@ -4,6 +4,7 @@
* *
* Contributors: * Contributors:
* - Ken Takata * - Ken Takata
* - Yasuhiro Matsumoto
* *
* Copyright (C) 2013 MURAOKA Taro <koron.kaoriya@gmail.com> * Copyright (C) 2013 MURAOKA Taro <koron.kaoriya@gmail.com>
* THIS FILE IS DISTRIBUTED UNDER THE VIM LICENSE. * THIS FILE IS DISTRIBUTED UNDER THE VIM LICENSE.
@ -54,12 +55,10 @@ void DWrite_Init(void);
void DWrite_Final(void); void DWrite_Final(void);
DWriteContext *DWriteContext_Open(void); DWriteContext *DWriteContext_Open(void);
void DWriteContext_BeginDraw(DWriteContext *ctx);
void DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect); void DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect);
void DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont); void DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont);
void DWriteContext_DrawText( void DWriteContext_DrawText(
DWriteContext *ctx, DWriteContext *ctx,
HDC hdc,
const WCHAR* text, const WCHAR* text,
int len, int len,
int x, int x,
@ -67,8 +66,12 @@ void DWriteContext_DrawText(
int w, int w,
int h, int h,
int cellWidth, int cellWidth,
COLORREF color); COLORREF color,
void DWriteContext_EndDraw(DWriteContext *ctx); UINT fuOptions,
CONST RECT *lprc,
CONST INT * lpDx);
void DWriteContext_FillRect(DWriteContext *ctx, RECT *rc, COLORREF color);
void DWriteContext_Flush(DWriteContext *ctx);
void DWriteContext_Close(DWriteContext *ctx); void DWriteContext_Close(DWriteContext *ctx);
void DWriteContext_SetRenderingParams( void DWriteContext_SetRenderingParams(

View File

@ -2024,15 +2024,15 @@ gui_mac_handle_window_activate(
switch (eventKind) switch (eventKind)
{ {
case kEventWindowActivated: case kEventWindowActivated:
#if defined(USE_IM_CONTROL) # if defined(FEAT_MBYTE)
im_on_window_switch(TRUE); im_on_window_switch(TRUE);
#endif # endif
return noErr; return noErr;
case kEventWindowDeactivated: case kEventWindowDeactivated:
#if defined(USE_IM_CONTROL) # if defined(FEAT_MBYTE)
im_on_window_switch(FALSE); im_on_window_switch(FALSE);
#endif # endif
return noErr; return noErr;
} }
} }
@ -6230,7 +6230,7 @@ char_u *FullPathFromFSSpec_save(FSSpec file)
#endif #endif
} }
#if (defined(USE_IM_CONTROL) || defined(PROTO)) && defined(USE_CARBONKEYHANDLER) #if (defined(FEAT_MBYTE) || defined(PROTO)) && defined(USE_CARBONKEYHANDLER)
/* /*
* Input Method Control functions. * Input Method Control functions.
*/ */
@ -6317,7 +6317,7 @@ im_set_active(int active)
ScriptLanguageRecord *slptr = NULL; ScriptLanguageRecord *slptr = NULL;
OSStatus err; OSStatus err;
if (! gui.in_use) if (!gui.in_use)
return; return;
if (im_initialized == 0) if (im_initialized == 0)
@ -6379,7 +6379,7 @@ im_get_status(void)
return im_is_active; return im_is_active;
} }
#endif /* defined(USE_IM_CONTROL) || defined(PROTO) */ #endif /* defined(FEAT_MBYTE) || defined(PROTO) */

View File

@ -34,28 +34,14 @@ static DWriteContext *s_dwc = NULL;
static int s_directx_enabled = 0; static int s_directx_enabled = 0;
static int s_directx_load_attempted = 0; static int s_directx_load_attempted = 0;
# define IS_ENABLE_DIRECTX() (s_directx_enabled && s_dwc != NULL) # define IS_ENABLE_DIRECTX() (s_directx_enabled && s_dwc != NULL)
static int directx_enabled(void);
static void directx_binddc(void);
#endif #endif
#ifdef FEAT_MENU #ifdef FEAT_MENU
static int gui_mswin_get_menu_height(int fix_window); static int gui_mswin_get_menu_height(int fix_window);
#endif #endif
#if defined(FEAT_DIRECTX) || defined(PROTO)
int
directx_enabled(void)
{
if (s_dwc != NULL)
return 1;
else if (s_directx_load_attempted)
return 0;
/* load DirectX */
DWrite_Init();
s_directx_load_attempted = 1;
s_dwc = DWriteContext_Open();
return s_dwc != NULL ? 1 : 0;
}
#endif
#if defined(FEAT_RENDER_OPTIONS) || defined(PROTO) #if defined(FEAT_RENDER_OPTIONS) || defined(PROTO)
int int
gui_mch_set_rendering_options(char_u *s) gui_mch_set_rendering_options(char_u *s)
@ -369,6 +355,34 @@ static int allow_scrollbar = FALSE;
# define MyTranslateMessage(x) TranslateMessage(x) # define MyTranslateMessage(x) TranslateMessage(x)
#endif #endif
#if defined(FEAT_DIRECTX)
static int
directx_enabled(void)
{
if (s_dwc != NULL)
return 1;
else if (s_directx_load_attempted)
return 0;
/* load DirectX */
DWrite_Init();
s_directx_load_attempted = 1;
s_dwc = DWriteContext_Open();
directx_binddc();
return s_dwc != NULL ? 1 : 0;
}
static void
directx_binddc(void)
{
if (s_textArea != NULL)
{
RECT rect;
GetClientRect(s_textArea, &rect);
DWriteContext_BindDC(s_dwc, s_hdc, &rect);
}
}
#endif
#if defined(FEAT_MBYTE) || defined(GLOBAL_IME) #if defined(FEAT_MBYTE) || defined(GLOBAL_IME)
/* use of WindowProc depends on wide_WindowProc */ /* use of WindowProc depends on wide_WindowProc */
# define MyWindowProc vim_WindowProc # define MyWindowProc vim_WindowProc
@ -485,12 +499,10 @@ static void TrackUserActivity(UINT uMsg);
* These LOGFONT used for IME. * These LOGFONT used for IME.
*/ */
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
# ifdef USE_IM_CONTROL
/* holds LOGFONT for 'guifontwide' if available, otherwise 'guifont' */ /* holds LOGFONT for 'guifontwide' if available, otherwise 'guifont' */
static LOGFONT norm_logfont; static LOGFONT norm_logfont;
/* holds LOGFONT for 'guifont' always. */ /* holds LOGFONT for 'guifont' always. */
static LOGFONT sub_logfont; static LOGFONT sub_logfont;
# endif
#endif #endif
#ifdef FEAT_MBYTE_IME #ifdef FEAT_MBYTE_IME
@ -591,6 +603,10 @@ _OnBlinkTimer(
blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime, blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime,
(TIMERPROC)_OnBlinkTimer); (TIMERPROC)_OnBlinkTimer);
} }
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif
} }
static void static void
@ -1002,6 +1018,19 @@ _OnMouseMoveOrRelease(
_OnMouseEvent(button, x, y, FALSE, keyFlags); _OnMouseEvent(button, x, y, FALSE, keyFlags);
} }
static void
_OnSizeTextArea(
HWND hwnd UNUSED,
UINT state UNUSED,
int cx UNUSED,
int cy UNUSED)
{
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
directx_binddc();
#endif
}
#ifdef FEAT_MENU #ifdef FEAT_MENU
/* /*
* Find the vimmenu_T with the given id * Find the vimmenu_T with the given id
@ -1236,6 +1265,7 @@ _TextAreaWndProc(
HANDLE_MSG(hwnd, WM_XBUTTONDBLCLK,_OnMouseButtonDown); HANDLE_MSG(hwnd, WM_XBUTTONDBLCLK,_OnMouseButtonDown);
HANDLE_MSG(hwnd, WM_XBUTTONDOWN,_OnMouseButtonDown); HANDLE_MSG(hwnd, WM_XBUTTONDOWN,_OnMouseButtonDown);
HANDLE_MSG(hwnd, WM_XBUTTONUP, _OnMouseMoveOrRelease); HANDLE_MSG(hwnd, WM_XBUTTONUP, _OnMouseMoveOrRelease);
HANDLE_MSG(hwnd, WM_SIZE, _OnSizeTextArea);
#ifdef FEAT_BEVAL_GUI #ifdef FEAT_BEVAL_GUI
case WM_NOTIFY: Handle_WM_Notify(hwnd, (LPNMHDR)lParam); case WM_NOTIFY: Handle_WM_Notify(hwnd, (LPNMHDR)lParam);
@ -1635,6 +1665,11 @@ gui_mch_invert_rectangle(
{ {
RECT rc; RECT rc;
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif
/* /*
* Note: InvertRect() excludes right and bottom of rectangle. * Note: InvertRect() excludes right and bottom of rectangle.
*/ */
@ -1663,6 +1698,11 @@ gui_mch_draw_hollow_cursor(guicolor_T color)
HBRUSH hbr; HBRUSH hbr;
RECT rc; RECT rc;
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif
/* /*
* Note: FrameRect() excludes right and bottom of rectangle. * Note: FrameRect() excludes right and bottom of rectangle.
*/ */
@ -1703,6 +1743,12 @@ gui_mch_draw_part_cursor(
rc.top = FILL_Y(gui.row) + gui.char_height - h; rc.top = FILL_Y(gui.row) + gui.char_height - h;
rc.right = rc.left + w; rc.right = rc.left + w;
rc.bottom = rc.top + h; rc.bottom = rc.top + h;
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif
hbr = CreateSolidBrush(color); hbr = CreateSolidBrush(color);
FillRect(s_hdc, &rc, hbr); FillRect(s_hdc, &rc, hbr);
DeleteBrush(hbr); DeleteBrush(hbr);
@ -2858,10 +2904,6 @@ _OnPaint(
out_flush(); /* make sure all output has been processed */ out_flush(); /* make sure all output has been processed */
(void)BeginPaint(hwnd, &ps); (void)BeginPaint(hwnd, &ps);
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_BeginDraw(s_dwc);
#endif
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
/* prevent multi-byte characters from misprinting on an invalid /* prevent multi-byte characters from misprinting on an invalid
@ -2878,19 +2920,11 @@ _OnPaint(
if (!IsRectEmpty(&ps.rcPaint)) if (!IsRectEmpty(&ps.rcPaint))
{ {
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_BindDC(s_dwc, s_hdc, &ps.rcPaint);
#endif
gui_redraw(ps.rcPaint.left, ps.rcPaint.top, gui_redraw(ps.rcPaint.left, ps.rcPaint.top,
ps.rcPaint.right - ps.rcPaint.left + 1, ps.rcPaint.right - ps.rcPaint.left + 1,
ps.rcPaint.bottom - ps.rcPaint.top + 1); ps.rcPaint.bottom - ps.rcPaint.top + 1);
} }
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_EndDraw(s_dwc);
#endif
EndPaint(hwnd, &ps); EndPaint(hwnd, &ps);
} }
} }
@ -3012,6 +3046,11 @@ gui_mch_flash(int msec)
{ {
RECT rc; RECT rc;
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif
/* /*
* Note: InvertRect() excludes right and bottom of rectangle. * Note: InvertRect() excludes right and bottom of rectangle.
*/ */
@ -3084,6 +3123,12 @@ gui_mch_delete_lines(
intel_gpu_workaround(); intel_gpu_workaround();
#if defined(FEAT_DIRECTX)
// Commit drawing queue before ScrollWindowEx.
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif
rc.left = FILL_X(gui.scroll_region_left); rc.left = FILL_X(gui.scroll_region_left);
rc.right = FILL_X(gui.scroll_region_right + 1); rc.right = FILL_X(gui.scroll_region_right + 1);
rc.top = FILL_Y(row); rc.top = FILL_Y(row);
@ -3117,6 +3162,12 @@ gui_mch_insert_lines(
intel_gpu_workaround(); intel_gpu_workaround();
#if defined(FEAT_DIRECTX)
// Commit drawing queue before ScrollWindowEx.
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif
rc.left = FILL_X(gui.scroll_region_left); rc.left = FILL_X(gui.scroll_region_left);
rc.right = FILL_X(gui.scroll_region_right + 1); rc.right = FILL_X(gui.scroll_region_right + 1);
rc.top = FILL_Y(row); rc.top = FILL_Y(row);
@ -6147,9 +6198,6 @@ gui_mch_draw_string(
#endif #endif
HPEN hpen, old_pen; HPEN hpen, old_pen;
int y; int y;
#ifdef FEAT_DIRECTX
int font_is_ttf_or_vector = 0;
#endif
/* /*
* Italic and bold text seems to have an extra row of pixels at the bottom * Italic and bold text seems to have an extra row of pixels at the bottom
@ -6210,6 +6258,11 @@ gui_mch_draw_string(
hbr = hbr_cache[brush_lru]; hbr = hbr_cache[brush_lru];
brush_lru = !brush_lru; brush_lru = !brush_lru;
} }
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_FillRect(s_dwc, &rc, gui.currBgColor);
#endif
FillRect(s_hdc, &rc, hbr); FillRect(s_hdc, &rc, hbr);
SetBkMode(s_hdc, TRANSPARENT); SetBkMode(s_hdc, TRANSPARENT);
@ -6229,16 +6282,7 @@ gui_mch_draw_string(
#ifdef FEAT_DIRECTX #ifdef FEAT_DIRECTX
if (IS_ENABLE_DIRECTX()) if (IS_ENABLE_DIRECTX())
{ DWriteContext_SetFont(s_dwc, (HFONT)gui.currFont);
TEXTMETRIC tm;
GetTextMetrics(s_hdc, &tm);
if (tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))
{
font_is_ttf_or_vector = 1;
DWriteContext_SetFont(s_dwc, (HFONT)gui.currFont);
}
}
#endif #endif
if (pad_size != Columns || padding == NULL || padding[0] != gui.char_width) if (pad_size != Columns || padding == NULL || padding[0] != gui.char_width)
@ -6349,12 +6393,13 @@ gui_mch_draw_string(
++clen; ++clen;
} }
#if defined(FEAT_DIRECTX) #if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX() && font_is_ttf_or_vector) if (IS_ENABLE_DIRECTX())
{ {
/* Add one to "cells" for italics. */ /* Add one to "cells" for italics. */
DWriteContext_DrawText(s_dwc, s_hdc, unicodebuf, wlen, DWriteContext_DrawText(s_dwc, unicodebuf, wlen,
TEXT_X(col), TEXT_Y(row), FILL_X(cells + 1), FILL_Y(1), TEXT_X(col), TEXT_Y(row), FILL_X(cells + 1), FILL_Y(1),
gui.char_width, gui.currFgColor); gui.char_width, gui.currFgColor,
foptions, pcliprect, unicodepdy);
} }
else else
#endif #endif
@ -6413,6 +6458,12 @@ gui_mch_draw_string(
foptions, pcliprect, (char *)text, len, padding); foptions, pcliprect, (char *)text, len, padding);
} }
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX() &&
(flags & (DRAW_UNDERL | DRAW_STRIKE | DRAW_UNDERC | DRAW_CURSOR)))
DWriteContext_Flush(s_dwc);
#endif
/* Underline */ /* Underline */
if (flags & DRAW_UNDERL) if (flags & DRAW_UNDERL)
{ {
@ -6475,6 +6526,11 @@ gui_mch_flush(void)
BOOL __stdcall GdiFlush(void); BOOL __stdcall GdiFlush(void);
# endif # endif
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif
GdiFlush(); GdiFlush();
} }
@ -6483,6 +6539,14 @@ clear_rect(RECT *rcp)
{ {
HBRUSH hbr; HBRUSH hbr;
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
{
DWriteContext_FillRect(s_dwc, rcp, gui.back_pixel);
return;
}
#endif
hbr = CreateSolidBrush(gui.back_pixel); hbr = CreateSolidBrush(gui.back_pixel);
FillRect(s_hdc, rcp, hbr); FillRect(s_hdc, rcp, hbr);
DeleteBrush(hbr); DeleteBrush(hbr);
@ -8388,6 +8452,11 @@ gui_mch_drawsign(int row, int col, int typenr)
if (!gui.in_use || (sign = (signicon_t *)sign_get_image(typenr)) == NULL) if (!gui.in_use || (sign = (signicon_t *)sign_get_image(typenr)) == NULL)
return; return;
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif
x = TEXT_X(col); x = TEXT_X(col);
y = TEXT_Y(row); y = TEXT_Y(row);
w = gui.char_width * 2; w = gui.char_width * 2;
@ -8867,6 +8936,11 @@ netbeans_draw_multisign_indicator(int row)
x = 0; x = 0;
y = TEXT_Y(row); y = TEXT_Y(row);
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif
for (i = 0; i < gui.char_height - 3; i++) for (i = 0; i < gui.char_height - 3; i++)
SetPixel(s_hdc, x+2, y++, gui.currFgColor); SetPixel(s_hdc, x+2, y++, gui.currFgColor);

View File

@ -4794,6 +4794,26 @@ call_imactivatefunc(int active)
argv[0] = (char_u *)"0"; argv[0] = (char_u *)"0";
(void)call_func_retnr(p_imaf, 1, argv, FALSE); (void)call_func_retnr(p_imaf, 1, argv, FALSE);
} }
static int
call_imstatusfunc(void)
{
int is_active;
/* FIXME: Don't execute user function in unsafe situation. */
if (exiting
# ifdef FEAT_AUTOCMD
|| is_autocmd_blocked()
# endif
)
return FALSE;
/* FIXME: :py print 'xxx' is shown duplicate result.
* Use silent to avoid it. */
++msg_silent;
is_active = call_func_retnr(p_imsf, 0, NULL, FALSE);
--msg_silent;
return (is_active > 0);
}
#endif #endif
#if defined(FEAT_XIM) || defined(PROTO) #if defined(FEAT_XIM) || defined(PROTO)
@ -4838,14 +4858,7 @@ im_set_active(int active)
im_is_active = (active && !p_imdisable); im_is_active = (active && !p_imdisable);
if (im_is_active != was_active) if (im_is_active != was_active)
{ xim_reset();
#ifdef FEAT_EVAL
if (p_imaf[0] != NUL)
call_imactivatefunc(im_is_active);
else
#endif
xim_reset();
}
} }
void void
@ -5675,6 +5688,11 @@ im_synthesize_keypress(unsigned int keyval, unsigned int state)
void void
xim_reset(void) xim_reset(void)
{ {
#ifdef FEAT_EVAL
if (p_imaf[0] != NUL)
call_imactivatefunc(im_is_active);
else
#endif
if (xic != NULL) if (xic != NULL)
{ {
gtk_im_context_reset(xic); gtk_im_context_reset(xic);
@ -5685,12 +5703,7 @@ xim_reset(void)
{ {
xim_set_focus(gui.in_focus); xim_set_focus(gui.in_focus);
# ifdef FEAT_EVAL if (im_activatekey_keyval != GDK_VoidSymbol)
if (p_imaf[0] != NUL)
call_imactivatefunc(im_is_active);
else
# endif
if (im_activatekey_keyval != GDK_VoidSymbol)
{ {
if (im_is_active) if (im_is_active)
{ {
@ -5856,23 +5869,7 @@ im_get_status(void)
{ {
# ifdef FEAT_EVAL # ifdef FEAT_EVAL
if (p_imsf[0] != NUL) if (p_imsf[0] != NUL)
{ return call_imstatusfunc();
int is_active;
/* FIXME: Don't execute user function in unsafe situation. */
if (exiting
# ifdef FEAT_AUTOCMD
|| is_autocmd_blocked()
# endif
)
return FALSE;
/* FIXME: :py print 'xxx' is shown duplicate result.
* Use silent to avoid it. */
++msg_silent;
is_active = call_func_retnr(p_imsf, 0, NULL, FALSE);
--msg_silent;
return (is_active > 0);
}
# endif # endif
return im_is_active; return im_is_active;
} }
@ -5894,30 +5891,45 @@ im_is_preediting(void)
static int xim_is_active = FALSE; /* XIM should be active in the current static int xim_is_active = FALSE; /* XIM should be active in the current
mode */ mode */
static int xim_has_focus = FALSE; /* XIM is really being used for Vim */ static int xim_has_focus = FALSE; /* XIM is really being used for Vim */
#ifdef FEAT_GUI_X11 # ifdef FEAT_GUI_X11
static XIMStyle input_style; static XIMStyle input_style;
static int status_area_enabled = TRUE; static int status_area_enabled = TRUE;
#endif # endif
/* /*
* Switch using XIM on/off. This is used by the code that changes "State". * Switch using XIM on/off. This is used by the code that changes "State".
* When 'imactivatefunc' is defined use that function instead.
*/ */
void void
im_set_active(int active) im_set_active(int active_arg)
{ {
if (xic == NULL) int active = active_arg;
return;
/* If 'imdisable' is set, XIM is never active. */ /* If 'imdisable' is set, XIM is never active. */
if (p_imdisable) if (p_imdisable)
active = FALSE; active = FALSE;
#if !defined(FEAT_GUI_GTK) # if !defined(FEAT_GUI_GTK)
else if (input_style & XIMPreeditPosition) else if (input_style & XIMPreeditPosition)
/* There is a problem in switching XIM off when preediting is used, /* There is a problem in switching XIM off when preediting is used,
* and it is not clear how this can be solved. For now, keep XIM on * and it is not clear how this can be solved. For now, keep XIM on
* all the time, like it was done in Vim 5.8. */ * all the time, like it was done in Vim 5.8. */
active = TRUE; active = TRUE;
#endif # endif
# if defined(FEAT_EVAL)
if (p_imaf[0] != NUL)
{
if (active != im_get_status())
{
call_imactivatefunc(active);
xim_has_focus = active;
}
return;
}
# endif
if (xic == NULL)
return;
/* Remember the active state, it is needed when Vim gets keyboard focus. */ /* Remember the active state, it is needed when Vim gets keyboard focus. */
xim_is_active = active; xim_is_active = active;
@ -6019,19 +6031,19 @@ xim_set_preedit(void)
} }
} }
#if defined(FEAT_GUI_X11) # if defined(FEAT_GUI_X11)
static char e_xim[] = N_("E285: Failed to create input context"); static char e_xim[] = N_("E285: Failed to create input context");
#endif # endif
#if defined(FEAT_GUI_X11) || defined(PROTO) # if defined(FEAT_GUI_X11) || defined(PROTO)
# if defined(XtSpecificationRelease) && XtSpecificationRelease >= 6 && !defined(SUN_SYSTEM) # if defined(XtSpecificationRelease) && XtSpecificationRelease >= 6 && !defined(SUN_SYSTEM)
# define USE_X11R6_XIM # define USE_X11R6_XIM
# endif # endif
static int xim_real_init(Window x11_window, Display *x11_display); static int xim_real_init(Window x11_window, Display *x11_display);
#ifdef USE_X11R6_XIM # ifdef USE_X11R6_XIM
static void xim_destroy_cb(XIM im, XPointer client_data, XPointer call_data); static void xim_destroy_cb(XIM im, XPointer client_data, XPointer call_data);
static void static void
@ -6043,9 +6055,9 @@ xim_instantiate_cb(
Window x11_window; Window x11_window;
Display *x11_display; Display *x11_display;
#ifdef XIM_DEBUG # ifdef XIM_DEBUG
xim_log("xim_instantiate_cb()\n"); xim_log("xim_instantiate_cb()\n");
#endif # endif
gui_get_x11_windis(&x11_window, &x11_display); gui_get_x11_windis(&x11_window, &x11_display);
if (display != x11_display) if (display != x11_display)
@ -6067,9 +6079,9 @@ xim_destroy_cb(
Window x11_window; Window x11_window;
Display *x11_display; Display *x11_display;
#ifdef XIM_DEBUG # ifdef XIM_DEBUG
xim_log("xim_destroy_cb()\n"); xim_log("xim_destroy_cb()\n");
#endif #endif
gui_get_x11_windis(&x11_window, &x11_display); gui_get_x11_windis(&x11_window, &x11_display);
xic = NULL; xic = NULL;
@ -6080,7 +6092,7 @@ xim_destroy_cb(
XRegisterIMInstantiateCallback(x11_display, NULL, NULL, NULL, XRegisterIMInstantiateCallback(x11_display, NULL, NULL, NULL,
xim_instantiate_cb, NULL); xim_instantiate_cb, NULL);
} }
#endif # endif
void void
xim_init(void) xim_init(void)
@ -6088,9 +6100,9 @@ xim_init(void)
Window x11_window; Window x11_window;
Display *x11_display; Display *x11_display;
#ifdef XIM_DEBUG # ifdef XIM_DEBUG
xim_log("xim_init()\n"); xim_log("xim_init()\n");
#endif # endif
gui_get_x11_windis(&x11_window, &x11_display); gui_get_x11_windis(&x11_window, &x11_display);
@ -6101,10 +6113,10 @@ xim_init(void)
gui_set_shellsize(FALSE, FALSE, RESIZE_BOTH); gui_set_shellsize(FALSE, FALSE, RESIZE_BOTH);
#ifdef USE_X11R6_XIM # ifdef USE_X11R6_XIM
XRegisterIMInstantiateCallback(x11_display, NULL, NULL, NULL, XRegisterIMInstantiateCallback(x11_display, NULL, NULL, NULL,
xim_instantiate_cb, NULL); xim_instantiate_cb, NULL);
#endif # endif
} }
static int static int
@ -6116,7 +6128,7 @@ xim_real_init(Window x11_window, Display *x11_display)
*ns, *ns,
*end, *end,
tmp[1024]; tmp[1024];
#define IMLEN_MAX 40 # define IMLEN_MAX 40
char buf[IMLEN_MAX + 7]; char buf[IMLEN_MAX + 7];
XIM xim = NULL; XIM xim = NULL;
XIMStyles *xim_styles; XIMStyles *xim_styles;
@ -6181,7 +6193,7 @@ xim_real_init(Window x11_window, Display *x11_display)
return FALSE; return FALSE;
} }
#ifdef USE_X11R6_XIM # ifdef USE_X11R6_XIM
{ {
XIMCallback destroy_cb; XIMCallback destroy_cb;
@ -6190,7 +6202,7 @@ xim_real_init(Window x11_window, Display *x11_display)
if (XSetIMValues(xim, XNDestroyCallback, &destroy_cb, NULL)) if (XSetIMValues(xim, XNDestroyCallback, &destroy_cb, NULL))
EMSG(_("E287: Warning: Could not set destroy callback to IM")); EMSG(_("E287: Warning: Could not set destroy callback to IM"));
} }
#endif # endif
if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL) || !xim_styles) if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL) || !xim_styles)
{ {
@ -6266,7 +6278,7 @@ xim_real_init(Window x11_window, Display *x11_display)
/* A crash was reported when trying to pass gui.norm_font as XNFontSet, /* A crash was reported when trying to pass gui.norm_font as XNFontSet,
* thus that has been removed. Hopefully the default works... */ * thus that has been removed. Hopefully the default works... */
#ifdef FEAT_XFONTSET # ifdef FEAT_XFONTSET
if (gui.fontset != NOFONTSET) if (gui.fontset != NOFONTSET)
{ {
preedit_list = XVaCreateNestedList(0, preedit_list = XVaCreateNestedList(0,
@ -6282,7 +6294,7 @@ xim_real_init(Window x11_window, Display *x11_display)
NULL); NULL);
} }
else else
#endif # endif
{ {
preedit_list = XVaCreateNestedList(0, preedit_list = XVaCreateNestedList(0,
XNSpotLocation, &over_spot, XNSpotLocation, &over_spot,
@ -6324,7 +6336,7 @@ xim_real_init(Window x11_window, Display *x11_display)
return TRUE; return TRUE;
} }
#endif /* FEAT_GUI_X11 */ # endif /* FEAT_GUI_X11 */
/* /*
* Get IM status. When IM is on, return TRUE. Else return FALSE. * Get IM status. When IM is on, return TRUE. Else return FALSE.
@ -6335,6 +6347,10 @@ xim_real_init(Window x11_window, Display *x11_display)
int int
im_get_status(void) im_get_status(void)
{ {
# ifdef FEAT_EVAL
if (p_imsf[0] != NUL)
return call_imstatusfunc();
# endif
return xim_has_focus; return xim_has_focus;
} }
@ -6457,41 +6473,39 @@ xim_get_status_area_height(void)
#else /* !defined(FEAT_XIM) */ #else /* !defined(FEAT_XIM) */
# ifndef FEAT_GUI_W32 # if !defined(FEAT_GUI_W32) || !(defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME))
static int im_was_set_active = FALSE;
int int
im_get_status() im_get_status()
{ {
# ifdef FEAT_EVAL # ifdef FEAT_EVAL
if (p_imsf[0] != NUL) if (p_imsf[0] != NUL)
{ return call_imstatusfunc();
int is_active;
/* FIXME: Don't execute user function in unsafe situation. */
if (exiting
# ifdef FEAT_AUTOCMD
|| is_autocmd_blocked()
# endif
)
return FALSE;
/* FIXME: :py print 'xxx' is shown duplicate result.
* Use silent to avoid it. */
++msg_silent;
is_active = call_func_retnr(p_imsf, 0, NULL, FALSE);
--msg_silent;
return (is_active > 0);
}
# endif # endif
return FALSE; return im_was_set_active;
} }
void void
im_set_active(int active) im_set_active(int active_arg)
{ {
# if defined(USE_IM_CONTROL) && defined(FEAT_EVAL) # if defined(FEAT_MBYTE) && defined(FEAT_EVAL)
if (p_imaf[0] != NUL) int active = !p_imdisable && active_arg;
call_imactivatefunc(p_imdisable ? FALSE : active);
if (p_imaf[0] != NUL && active != im_get_status())
{
call_imactivatefunc(active);
im_was_set_active = active;
}
# endif # endif
} }
# ifdef FEAT_GUI
void
im_set_position(int row, int col)
{
}
# endif
# endif # endif
#endif /* FEAT_XIM */ #endif /* FEAT_XIM */

View File

@ -892,7 +892,7 @@ getcount:
int lit = FALSE; /* get extra character literally */ int lit = FALSE; /* get extra character literally */
int langmap_active = FALSE; /* using :lmap mappings */ int langmap_active = FALSE; /* using :lmap mappings */
int lang; /* getting a text character */ int lang; /* getting a text character */
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
int save_smd; /* saved value of p_smd */ int save_smd; /* saved value of p_smd */
#endif #endif
@ -957,7 +957,7 @@ getcount:
State = LANGMAP; State = LANGMAP;
langmap_active = TRUE; langmap_active = TRUE;
} }
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
save_smd = p_smd; save_smd = p_smd;
p_smd = FALSE; /* Don't let the IM code show the mode here */ p_smd = FALSE; /* Don't let the IM code show the mode here */
if (lang && curbuf->b_p_iminsert == B_IMODE_IM) if (lang && curbuf->b_p_iminsert == B_IMODE_IM)
@ -973,7 +973,7 @@ getcount:
++allow_keys; ++allow_keys;
State = NORMAL_BUSY; State = NORMAL_BUSY;
} }
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
if (lang) if (lang)
{ {
if (curbuf->b_p_iminsert != B_IMODE_LMAP) if (curbuf->b_p_iminsert != B_IMODE_LMAP)

View File

@ -1539,7 +1539,7 @@ static struct vimoption options[] =
(char_u *)&p_ic, PV_NONE, (char_u *)&p_ic, PV_NONE,
{(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
{"imactivatefunc","imaf",P_STRING|P_VI_DEF|P_SECURE, {"imactivatefunc","imaf",P_STRING|P_VI_DEF|P_SECURE,
#if defined(FEAT_EVAL) && defined(USE_IM_CONTROL) #if defined(FEAT_EVAL) && defined(FEAT_MBYTE)
(char_u *)&p_imaf, PV_NONE, (char_u *)&p_imaf, PV_NONE,
{(char_u *)"", (char_u *)NULL} {(char_u *)"", (char_u *)NULL}
# else # else
@ -1555,14 +1555,14 @@ static struct vimoption options[] =
#endif #endif
{(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, {(char_u *)"", (char_u *)0L} SCRIPTID_INIT},
{"imcmdline", "imc", P_BOOL|P_VI_DEF, {"imcmdline", "imc", P_BOOL|P_VI_DEF,
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
(char_u *)&p_imcmdline, PV_NONE, (char_u *)&p_imcmdline, PV_NONE,
#else #else
(char_u *)NULL, PV_NONE, (char_u *)NULL, PV_NONE,
#endif #endif
{(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
{"imdisable", "imd", P_BOOL|P_VI_DEF, {"imdisable", "imd", P_BOOL|P_VI_DEF,
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
(char_u *)&p_imdisable, PV_NONE, (char_u *)&p_imdisable, PV_NONE,
#else #else
(char_u *)NULL, PV_NONE, (char_u *)NULL, PV_NONE,
@ -1582,7 +1582,7 @@ static struct vimoption options[] =
{(char_u *)B_IMODE_USE_INSERT, (char_u *)0L} {(char_u *)B_IMODE_USE_INSERT, (char_u *)0L}
SCRIPTID_INIT}, SCRIPTID_INIT},
{"imstatusfunc","imsf",P_STRING|P_VI_DEF|P_SECURE, {"imstatusfunc","imsf",P_STRING|P_VI_DEF|P_SECURE,
#if defined(FEAT_EVAL) && defined(USE_IM_CONTROL) #if defined(FEAT_EVAL) && defined(FEAT_MBYTE)
(char_u *)&p_imsf, PV_NONE, (char_u *)&p_imsf, PV_NONE,
{(char_u *)"", (char_u *)NULL} {(char_u *)"", (char_u *)NULL}
#else #else
@ -8469,7 +8469,7 @@ set_bool_option(
} }
#endif #endif
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
/* 'imdisable' */ /* 'imdisable' */
else if ((int *)varp == &p_imdisable) else if ((int *)varp == &p_imdisable)
{ {

View File

@ -585,11 +585,11 @@ EXTERN char_u *p_imak; /* 'imactivatekey' */
#define IM_OVER_THE_SPOT 1L #define IM_OVER_THE_SPOT 1L
EXTERN long p_imst; /* 'imstyle' */ EXTERN long p_imst; /* 'imstyle' */
#endif #endif
#if defined(FEAT_EVAL) && defined(USE_IM_CONTROL) #if defined(FEAT_EVAL) && defined(FEAT_MBYTE)
EXTERN char_u *p_imaf; /* 'imactivatefunc' */ EXTERN char_u *p_imaf; /* 'imactivatefunc' */
EXTERN char_u *p_imsf; /* 'imstatusfunc' */ EXTERN char_u *p_imsf; /* 'imstatusfunc' */
#endif #endif
#ifdef USE_IM_CONTROL #ifdef FEAT_MBYTE
EXTERN int p_imcmdline; /* 'imcmdline' */ EXTERN int p_imcmdline; /* 'imcmdline' */
EXTERN int p_imdisable; /* 'imdisable' */ EXTERN int p_imdisable; /* 'imdisable' */
#endif #endif

View File

@ -1,5 +1,4 @@
/* gui_w32.c */ /* gui_w32.c */
int directx_enabled(void);
int gui_mch_set_rendering_options(char_u *s); int gui_mch_set_rendering_options(char_u *s);
int gui_mch_is_blinking(void); int gui_mch_is_blinking(void);
int gui_mch_is_blink_off(void); int gui_mch_is_blink_off(void);

View File

@ -17,6 +17,9 @@ func IM_statusfunc()
endfunc endfunc
func Test_iminsert2() func Test_iminsert2()
if has('gui_win32')
return
endif
set imactivatefunc=IM_activatefunc set imactivatefunc=IM_activatefunc
set imstatusfunc=IM_statusfunc set imstatusfunc=IM_statusfunc
set iminsert=2 set iminsert=2

View File

@ -100,3 +100,11 @@ func Test_writefile_sync_arg()
call writefile(['two'], 'Xtest', 'S') call writefile(['two'], 'Xtest', 'S')
call delete('Xtest') call delete('Xtest')
endfunc endfunc
func Test_writefile_sync_dev_stdout()
if !has('unix')
return
endif
" Just check that this doesn't cause an error.
call writefile(['one'], '/dev/stdout')
endfunc

View File

@ -3307,7 +3307,7 @@ ui_focus_change(
} }
#endif #endif
#if defined(USE_IM_CONTROL) || defined(PROTO) #if defined(FEAT_MBYTE) || defined(PROTO)
/* /*
* Save current Input Method status to specified place. * Save current Input Method status to specified place.
*/ */

View File

@ -771,6 +771,18 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1343,
/**/
1342,
/**/
1341,
/**/
1340,
/**/
1339,
/**/
1338,
/**/ /**/
1337, 1337,
/**/ /**/

View File

@ -533,13 +533,6 @@ typedef unsigned long u8char_T; /* long should be 32 bits or more */
# endif # endif
#endif #endif
/*
* Check input method control.
*/
#if defined(FEAT_MBYTE)
# define USE_IM_CONTROL
#endif
/* /*
* For dynamically loaded gettext library. Currently, only for Win32. * For dynamically loaded gettext library. Currently, only for Win32.
*/ */