mirror of
https://github.com/vim/vim
synced 2025-07-20 03:02:30 +00:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
d7ccc4d81d | |||
fb1db0e355 | |||
be5d998d0e | |||
281c93e714 | |||
83799a7b74 | |||
819edbe078 |
@ -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
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
12
src/edit.c
12
src/edit.c
@ -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). */
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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(
|
||||||
|
@ -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) */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
166
src/gui_w32.c
166
src/gui_w32.c
@ -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);
|
||||||
|
|
||||||
|
180
src/mbyte.c
180
src/mbyte.c
@ -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 */
|
||||||
|
@ -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)
|
||||||
|
10
src/option.c
10
src/option.c
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
2
src/ui.c
2
src/ui.c
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user