mirror of
https://github.com/rizonesoft/Notepad3.git
synced 2026-06-14 21:09:05 +08:00
5507 lines
198 KiB
C
5507 lines
198 KiB
C
// encoding: UTF-8
|
|
/******************************************************************************
|
|
* *
|
|
* *
|
|
* Notepad3 *
|
|
* *
|
|
* Styles.c *
|
|
* Scintilla Style Management *
|
|
* Based on code from Notepad2, (c) Florian Balmer 1996-2011 *
|
|
* Mostly taken from SciTE, (c) Neil Hodgson *
|
|
* *
|
|
* (c) Rizonesoft 2008-2026 *
|
|
* http://www.rizonesoft.com *
|
|
* *
|
|
* *
|
|
*******************************************************************************/
|
|
#include "Helpers.h"
|
|
|
|
#include <assert.h>
|
|
#include <commctrl.h>
|
|
#include <commdlg.h>
|
|
#include <shlobj.h>
|
|
#include <shellapi.h>
|
|
#include <shlwapi.h>
|
|
#include <stdio.h>
|
|
|
|
#include "Lexilla.h"
|
|
#include "lexers_x/SciXLexer.h"
|
|
|
|
#include "uthash/utarray.h"
|
|
|
|
#include "PathLib.h"
|
|
#include "Edit.h"
|
|
#include "Dialogs.h"
|
|
#include "Encoding.h"
|
|
#include "MuiLanguage.h"
|
|
#include "Notepad3.h"
|
|
#include "Config/Config.h"
|
|
#include "DarkMode/DarkMode.h"
|
|
#include "tinyexpr/tinyexpr.h"
|
|
|
|
#include "SciCall.h"
|
|
|
|
#include "Styles.h"
|
|
|
|
extern COLORREF g_colorCustom[16];
|
|
|
|
// removed from project, not MUI language compatible with ChooseFont()
|
|
//~bool ChooseFontDirectWrite(HWND hwnd, const WCHAR* localeName, UINT dpi, LPCHOOSEFONT lpCF);
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// This array holds all the lexers...
|
|
// Don't forget to change the number of the lexer for HTML and XML
|
|
// in Notepad2.c ParseCommandLine() if you change this array!
|
|
static PEDITLEXER g_pLexArray[] = {
|
|
&lexStandard, // Default Text
|
|
&lexStandard2nd, // 2nd Default Text
|
|
&lexTEXT, // Pure Text Files (Constants.StdDefaultLexerID = 2)
|
|
&lexANSI, // ANSI Files (ASCII Art)
|
|
&lexCONF, // Apache Config Files
|
|
&lexASM, // Assembly Script
|
|
&lexAHK, // AutoHotkey Script
|
|
&lexAU3, // AutoIt3 Script
|
|
&lexAVS, // AviSynth Script
|
|
&lexAwk, // Awk Script
|
|
&lexBAT, // Batch Files
|
|
&lexCS, // C# Source Code
|
|
&lexCPP, // C/C++ Source Code
|
|
&lexCmake, // Cmake Script
|
|
&lexCOFFEESCRIPT, // Coffeescript
|
|
&lexPROPS, // Configuration Files
|
|
&lexCSS, // CSS Style Sheets
|
|
&lexCSV, // CSV Prism Color Lexer
|
|
&lexD, // D Source Code
|
|
&lexDart, // Dart Source Code
|
|
&lexDIFF, // Diff Files
|
|
&lexFortran, // Fortran F90+
|
|
//&lexF77, // Fortran F77
|
|
&lexGo, // Go Source Code
|
|
&lexINNO, // Inno Setup Script
|
|
&lexJAVA, // Java Source Code
|
|
&lexJS, // JavaScript
|
|
&lexJSON, // JSON
|
|
&lexJulia, // Julia
|
|
&lexKiX, // KiX
|
|
&lexKotlin, // Kotlin
|
|
&lexLATEX, // LaTeX Files
|
|
&lexLUA, // Lua Script
|
|
&lexMAK, // Makefiles
|
|
&lexMARKDOWN, // Markdown
|
|
&lexMATLAB, // MATLAB
|
|
&lexNim, // Nim(rod)
|
|
&lexNSIS, // NSIS Script
|
|
&lexPAS, // Pascal Source Code
|
|
&lexPL, // Perl Script
|
|
&lexPS, // PowerShell Script
|
|
&lexPY, // Python Script
|
|
&lexRegistry, // Registry Files
|
|
&lexRC, // Resource Script
|
|
&lexR, // R Statistics Code
|
|
&lexRUBY, // Ruby Script
|
|
&lexRust, // Rust Script
|
|
&lexBASH, // Shell Script
|
|
&lexSQL, // SQL Query
|
|
&lexSysVerilog, // SystemVerilog HDVL
|
|
&lexTCL, // Tcl Script
|
|
&lexTOML, // TOML Config Script
|
|
&lexVBS, // VBScript
|
|
&lexVerilog, // Verilog HDL
|
|
&lexVHDL, // VHDL
|
|
&lexVB, // Visual Basic
|
|
&lexHTML, // Web Source Code
|
|
&lexXML, // XML Document
|
|
&lexYAML, // YAML
|
|
};
|
|
|
|
int Style_NumOfLexers() {
|
|
return COUNTOF(g_pLexArray);
|
|
}
|
|
|
|
|
|
// Currently used lexer
|
|
static PEDITLEXER s_pLexCurrent = &lexStandard;
|
|
static int s_iDefaultLexer = 2; // (Constants.StdDefaultLexerID) Pure Text Files
|
|
|
|
|
|
const COLORREF s_colorLightDefault[16] = {
|
|
RGB(0x00, 0x00, 0x00),
|
|
RGB(0x0A, 0x24, 0x6A),
|
|
RGB(0x3A, 0x6E, 0xA5),
|
|
RGB(0x00, 0x3C, 0xE6),
|
|
RGB(0x00, 0x66, 0x33),
|
|
RGB(0x60, 0x80, 0x20),
|
|
RGB(0x64, 0x80, 0x00),
|
|
RGB(0xA4, 0x60, 0x00),
|
|
RGB(0xFF, 0xFF, 0xFF),
|
|
RGB(0xFF, 0xFF, 0xE2),
|
|
RGB(0xFF, 0xF1, 0xA8),
|
|
RGB(0xFF, 0xC0, 0x00),
|
|
RGB(0xFF, 0x40, 0x00),
|
|
RGB(0xC8, 0x00, 0x00),
|
|
RGB(0xB0, 0x00, 0xB0),
|
|
RGB(0xB2, 0x8B, 0x40)
|
|
};
|
|
|
|
const COLORREF s_colorDarkDefault[16] = {
|
|
RGB(0xDE, 0xDE, 0xDE),
|
|
RGB(0xB4, 0xE1, 0xF5),
|
|
RGB(0xA1, 0xC3, 0xD3),
|
|
RGB(0x89, 0xAB, 0xEC),
|
|
RGB(0x71, 0xF8, 0xAD),
|
|
RGB(0xB1, 0xD7, 0x65),
|
|
RGB(0xD8, 0xF7, 0x66),
|
|
RGB(0xF6, 0xB0, 0x5A),
|
|
RGB(0x14, 0x14, 0x14),
|
|
RGB(0x27, 0x27, 0x02),
|
|
RGB(0x54, 0x46, 0x04),
|
|
RGB(0xF2, 0xB5, 0x0D),
|
|
RGB(0xF2, 0x46, 0x0D),
|
|
RGB(0xF5, 0x3C, 0x3D),
|
|
RGB(0xF6, 0x51, 0xF6),
|
|
RGB(0xBE, 0x94, 0x4E)
|
|
};
|
|
|
|
|
|
static bool s_bAutoSelect = true;
|
|
|
|
#define STYLESELECTDLG_X 305
|
|
#define STYLESELECTDLG_Y 344
|
|
static int s_cxStyleSelectDlg = STYLESELECTDLG_X;
|
|
static int s_cyStyleSelectDlg = STYLESELECTDLG_Y;
|
|
|
|
//=============================================================================
|
|
|
|
// Font Weights
|
|
typedef struct _fntwght {
|
|
LPCWSTR const wname;
|
|
int const weight;
|
|
} FONTWEIGHT_T;
|
|
|
|
static const FONTWEIGHT_T FontWeights[21] = {
|
|
{ L"thin", FW_THIN }, // 0
|
|
{ L"semithin", 150 }, // 1
|
|
{ L"extralight", FW_EXTRALIGHT }, // 2
|
|
{ L"lighter", 250 }, // 3
|
|
{ L"light", FW_LIGHT }, // 4
|
|
{ L"book", 350 }, // 5
|
|
{ L"text", 375 }, // 6
|
|
{ L"regular", FW_REGULAR }, // 7
|
|
{ L"thick", 425 }, // 8
|
|
{ L"retina", 450 }, // 9
|
|
{ L"medium", FW_MEDIUM }, // 10
|
|
{ L"extramedium", 550 }, // 11
|
|
{ L"semibold", FW_SEMIBOLD }, // 12
|
|
{ L"dark", 650 }, // 13
|
|
{ L"bold", FW_BOLD }, // 14
|
|
{ L"bolder", 750 }, // 15
|
|
{ L"extrabold", FW_EXTRABOLD }, // 16
|
|
{ L"semiheavy", 850 }, // 17
|
|
{ L"heavy", FW_HEAVY }, // 18
|
|
{ L"extrablack", 950 }, // 19
|
|
{ L"ultradark", 1000 }, // 20
|
|
};
|
|
|
|
typedef enum {
|
|
FW_IDX_THIN = 0,
|
|
FW_IDX_SEMITHIN,
|
|
FW_IDX_EXTRALIGHT,
|
|
FW_IDX_LIGHTER,
|
|
FW_IDX_LIGHT,
|
|
FW_IDX_BOOK,
|
|
FW_IDX_TEXT,
|
|
FW_IDX_REGULAR,
|
|
FW_IDX_THICK,
|
|
FW_IDX_RETINA,
|
|
FW_IDX_MEDIUM,
|
|
FW_IDX_EXTRAMEDIUM,
|
|
FW_IDX_SEMIBOLD,
|
|
FW_IDX_DARK,
|
|
FW_IDX_BOLD,
|
|
FW_IDX_BOLDER,
|
|
FW_IDX_EXTRABOLD,
|
|
FW_IDX_SEMIHEAVY,
|
|
FW_IDX_HEAVY,
|
|
FW_IDX_EXTRABLACK,
|
|
FW_IDX_ULTRADARK
|
|
} FW_IDX;
|
|
|
|
// Font Stretch
|
|
typedef struct _fntstrtch {
|
|
LPCWSTR const wname;
|
|
int const stretch;
|
|
} FONTSTRETCH_T;
|
|
|
|
static const FONTSTRETCH_T FontStretches[9] = {
|
|
{ L"ultracondensed", SC_STRETCH_ULTRA_CONDENSED }, // 0
|
|
{ L"extracondensed", SC_STRETCH_EXTRA_CONDENSED }, // 1
|
|
{ L"condensed", SC_STRETCH_CONDENSED }, // 2
|
|
{ L"semicondensed", SC_STRETCH_SEMI_CONDENSED }, // 3
|
|
{ L"normal", SC_STRETCH_NORMAL }, // 4 (default)
|
|
{ L"semiexpanded", SC_STRETCH_SEMI_EXPANDED }, // 5
|
|
{ L"expanded", SC_STRETCH_EXPANDED }, // 6
|
|
{ L"extraexpanded", SC_STRETCH_EXTRA_EXPANDED }, // 7
|
|
{ L"ultraexpanded", SC_STRETCH_ULTRA_EXPANDED }, // 8
|
|
};
|
|
|
|
typedef enum {
|
|
FS_IDX_ULTRACONDENSED = 0,
|
|
FS_IDX_EXTRACONDENSED,
|
|
FS_IDX_CONDENSED,
|
|
FS_IDX_SEMICONDENSED,
|
|
FS_IDX_NORMAL,
|
|
FS_IDX_SEMIEXPANDED,
|
|
FS_IDX_EXPANDED,
|
|
FS_IDX_EXTRAEXPANDED,
|
|
FS_IDX_ULTRAEXPANDED,
|
|
} FONTSTRETCH_IDX;
|
|
|
|
//// font quality
|
|
//#define Style_StrHasAttrNone(lpszStyle) Style_StrHasAttribute((lpszStyle), L"none")
|
|
//#define Style_StrHasAttrStdType(lpszStyle) Style_StrHasAttribute((lpszStyle), L"standard")
|
|
//#define Style_StrHasAttrClearType(lpszStyle) Style_StrHasAttribute((lpszStyle), L"cleartype")
|
|
|
|
// font effects
|
|
static const WCHAR *const FontEffects[] = { L"italic", L"underline", L"strikeout", L"eolfilled" };
|
|
typedef enum { FE_ITALIC = 0, FE_UNDERLINE, FE_STRIKEOUT, FE_EOLFILLED } FE_IDX;
|
|
|
|
// caret style
|
|
static const WCHAR *const CaretStyle[] = { L"ovrblck", L"block", L"noblink", };
|
|
typedef enum { CS_OVRBLCK = 0, CS_BLOCK, CS_NOBLINK, } CS_IDX;
|
|
|
|
typedef struct _fntqual {
|
|
LPCWSTR const qname;
|
|
int const sci_value;
|
|
int const win_value;
|
|
} FONTQUALITY_T;
|
|
|
|
static const FONTQUALITY_T FontQuality[4] = {
|
|
{ L"standard", SC_EFF_QUALITY_DEFAULT, DEFAULT_QUALITY },
|
|
{ L"aliased", SC_EFF_QUALITY_NON_ANTIALIASED, NONANTIALIASED_QUALITY },
|
|
{ L"antialiased", SC_EFF_QUALITY_ANTIALIASED, ANTIALIASED_QUALITY },
|
|
{ L"cleartype", SC_EFF_QUALITY_LCD_OPTIMIZED, CLEARTYPE_QUALITY }
|
|
};
|
|
typedef enum { FQ_STANDARD = 0, FQ_ALIASED, FQ_ANTIALIASED, FQ_CLEARTYPE } FQ_IDX;
|
|
|
|
static inline int MapSciToWinFontQuality(const int sciFQ)
|
|
{
|
|
for (int i = 0; i < COUNTOF(FontQuality); ++i) {
|
|
if (FontQuality[i].sci_value == sciFQ) {
|
|
return FontQuality[i].win_value;
|
|
}
|
|
}
|
|
// default should be CLEARTYPE_QUALITY
|
|
return CLEARTYPE_QUALITY; //~DEFAULT_QUALITY;
|
|
}
|
|
|
|
#if 0
|
|
static inline int MapFQNameToSciFontQuality(LPCWSTR fqName) {
|
|
for (int i = 0; i < COUNTOF(FontQuality); ++i) {
|
|
if (StringCchCompareXI(fqName, FontQuality[i].qname) == 0) {
|
|
return FontQuality[i].sci_value;
|
|
}
|
|
}
|
|
// default should be SC_EFF_QUALITY_LCD_OPTIMIZED
|
|
return SC_EFF_QUALITY_LCD_OPTIMIZED; //~SC_EFF_QUALITY_DEFAULT;
|
|
}
|
|
#endif
|
|
|
|
//=============================================================================
|
|
|
|
// ensure to be consistent with
|
|
static WCHAR* IndicatorTypes[23] = {
|
|
L"indic_plain", // 0 INDIC_PLAIN
|
|
L"indic_squiggle", // 1 INDIC_SQUIGGLE
|
|
L"indic_tt", // 2 INDIC_TT
|
|
L"indic_diagonal", // 3 INDIC_DIAGONAL
|
|
L"indic_strike", // 4 INDIC_STRIKE
|
|
L"indic_hidden", // 5 INDIC_HIDDEN
|
|
L"indic_box", // 6 INDIC_BOX
|
|
L"indic_roundbox", // 7 INDIC_ROUNDBOX
|
|
L"indic_straightbox", // 8 INDIC_STRAIGHTBOX
|
|
L"indic_dash", // 9 INDIC_DASH
|
|
L"indic_dots", // 10 INDIC_DOTS
|
|
L"indic_squigglelow", // 11 INDIC_SQUIGGLELOW
|
|
L"indic_dotbox", // 12 INDIC_DOTBOX
|
|
L"indic_squigglepixmap", // 13 INDIC_SQUIGGLEPIXMAP
|
|
L"indic_compositionthick", // 14 INDIC_COMPOSITIONTHICK
|
|
L"indic_compositionthin", // 15 INDIC_COMPOSITIONTHIN
|
|
L"indic_fullbox", // 16 INDIC_FULLBOX
|
|
L"indic_textfore", // 17 INDIC_TEXTFORE
|
|
L"indic_point", // 18 INDIC_POINT
|
|
L"indic_pointcharacter", // 19 INDIC_POINTCHARACTER
|
|
L"indic_gradient", // 20 INDIC_GRADIENT
|
|
L"indic_gradientcentre", // 21 INDIC_GRADIENTCENTRE
|
|
L"indic_point_top" // 22 INDIC_POINT_TOP
|
|
};
|
|
|
|
static inline bool HasIndicStyleStrokeWidth(const int indicStyle) {
|
|
switch (indicStyle) {
|
|
case INDIC_PLAIN:
|
|
case INDIC_SQUIGGLE:
|
|
case INDIC_TT:
|
|
case INDIC_DIAGONAL:
|
|
case INDIC_STRIKE:
|
|
case INDIC_BOX:
|
|
case INDIC_ROUNDBOX:
|
|
case INDIC_STRAIGHTBOX:
|
|
case INDIC_DASH:
|
|
case INDIC_DOTS:
|
|
case INDIC_SQUIGGLELOW:
|
|
case INDIC_FULLBOX:
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static const int FoldMarkerID[] = {
|
|
SC_MARKNUM_FOLDEROPEN,
|
|
SC_MARKNUM_FOLDER,
|
|
SC_MARKNUM_FOLDERSUB,
|
|
SC_MARKNUM_FOLDERTAIL,
|
|
SC_MARKNUM_FOLDEREND,
|
|
SC_MARKNUM_FOLDEROPENMID,
|
|
SC_MARKNUM_FOLDERMIDTAIL
|
|
};
|
|
|
|
//=============================================================================
|
|
|
|
THEMEFILES Theme_Files[] = {
|
|
{ 0, L"Standard Config", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL },
|
|
{ 0, L"", NULL }
|
|
};
|
|
|
|
unsigned ThemeItems_CountOf()
|
|
{
|
|
return COUNTOF(Theme_Files);
|
|
}
|
|
|
|
void ThemesItems_Init()
|
|
{
|
|
for (unsigned i = 0; i < ThemeItems_CountOf(); ++i) {
|
|
Theme_Files[i].rid = 0;
|
|
Theme_Files[i].szName[0] = L'\0';
|
|
if (Theme_Files[i].hStyleFilePath == NULL) {
|
|
Theme_Files[i].hStyleFilePath = Path_Allocate(L"");
|
|
}
|
|
}
|
|
}
|
|
|
|
void ThemesItems_Release()
|
|
{
|
|
for (unsigned i = 0; i < ThemeItems_CountOf(); ++i) {
|
|
if (Theme_Files[i].hStyleFilePath != NULL) {
|
|
Path_Release(Theme_Files[i].hStyleFilePath);
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned ThemesItems_MaxIndex()
|
|
{
|
|
for (unsigned i = 1; i < ThemeItems_CountOf(); ++i) {
|
|
if (Theme_Files[i].rid == 0) {
|
|
return (i - 1);
|
|
}
|
|
}
|
|
return (ThemeItems_CountOf() - 1);
|
|
}
|
|
|
|
|
|
static void _FillThemesMenuTable()
|
|
{
|
|
HPATHL hThemesDir = Path_Copy(Paths.IniFile);
|
|
|
|
// NP3.ini settings
|
|
|
|
Theme_Files[0].rid = IDM_THEMES_STD_CFG;
|
|
GetLngString(IDM_THEMES_STD_CFG, Theme_Files[0].szName, COUNTOF(Theme_Files[0].szName));
|
|
if (Path_IsNotEmpty(hThemesDir)) {
|
|
Path_Reset(Theme_Files[0].hStyleFilePath, Path_Get(hThemesDir));
|
|
}
|
|
Globals.uCurrentThemeIndex = 0;
|
|
|
|
unsigned iTheme = 1; // other themes
|
|
|
|
if (Path_IsEmpty(hThemesDir)) {
|
|
Path_Reset(hThemesDir, Path_Get(Paths.IniFileDefault));
|
|
}
|
|
if (Path_IsNotEmpty(hThemesDir)) {
|
|
Path_RemoveFileSpec(hThemesDir);
|
|
Path_Append(hThemesDir, L"themes");
|
|
}
|
|
|
|
/// names are filled by Style_InsertThemesMenu()
|
|
|
|
if (Path_IsExistingDirectory(hThemesDir)) {
|
|
|
|
HPATHL hThemePath = Path_Copy(hThemesDir);
|
|
Path_Append(hThemePath, L"*.ini");
|
|
|
|
WIN32_FIND_DATA FindFileData;
|
|
ZeroMemory(&FindFileData, sizeof(WIN32_FIND_DATA));
|
|
HANDLE hFindFile = FindFirstFileW(Path_Get(hThemePath), &FindFileData);
|
|
|
|
// --- fill table by directory entries ---
|
|
|
|
if (IS_VALID_HANDLE(hFindFile)) {
|
|
|
|
WCHAR wchFileName[SMALL_BUFFER] = { L'\0' };
|
|
|
|
for (iTheme = 1; iTheme < ThemeItems_CountOf(); ++iTheme) {
|
|
|
|
Theme_Files[iTheme].rid = (iTheme + IDM_THEMES_STD_CFG);
|
|
|
|
StringCchCopy(wchFileName, COUNTOF(wchFileName), PathFindFileNameW(FindFileData.cFileName));
|
|
PathRemoveExtensionW(wchFileName);
|
|
StringCchCopy(Theme_Files[iTheme].szName, COUNTOF(Theme_Files[iTheme].szName), wchFileName);
|
|
|
|
if (StringCchCompareXI(Theme_Files[iTheme].szName, Settings.CurrentThemeName) == 0) {
|
|
Globals.uCurrentThemeIndex = iTheme;
|
|
}
|
|
|
|
Path_Reset(hThemePath, Path_Get(hThemesDir));
|
|
Path_Append(hThemePath, FindFileData.cFileName);
|
|
Path_Swap(Theme_Files[iTheme].hStyleFilePath, hThemePath);
|
|
|
|
if (!FindNextFileW(hFindFile, &FindFileData)) {
|
|
break;
|
|
}
|
|
}
|
|
FindClose(hFindFile);
|
|
}
|
|
Path_Release(hThemePath);
|
|
}
|
|
|
|
Path_Release(hThemesDir);
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
static inline void AppendStyle(LPWSTR lpszStyleDest, size_t cchSizeDest, LPCWSTR lpszStyleSrc) {
|
|
StringCchCat(lpszStyleDest, cchSizeDest, L"; ");
|
|
StringCchCat(lpszStyleDest, cchSizeDest, lpszStyleSrc);
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
void Style_InitFileExtensions()
|
|
{
|
|
for (int iLexer = 0; iLexer < COUNTOF(g_pLexArray); iLexer++) {
|
|
if (StrIsEmpty(g_pLexArray[iLexer]->szExtensions)) {
|
|
StringCchCopy(g_pLexArray[iLexer]->szExtensions, COUNTOF(g_pLexArray[iLexer]->szExtensions), g_pLexArray[iLexer]->pszDefExt);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_InsertThemesMenu()
|
|
//
|
|
static HMENU s_hmenuThemes = NULL;
|
|
|
|
bool Style_InsertThemesMenu(HMENU hMenuBar)
|
|
{
|
|
if (s_hmenuThemes) {
|
|
DestroyMenu(s_hmenuThemes);
|
|
}
|
|
s_hmenuThemes = CreatePopupMenu();
|
|
//int const pos = GetMenuItemCount(hMenuBar) - 2;
|
|
|
|
WCHAR tchThemeName[SMALL_BUFFER] = { L'\0' };
|
|
GetLngString(IDM_THEMES_FACTORY_RESET, tchThemeName, COUNTOF(tchThemeName));
|
|
GetLngString(IDM_THEMES_STD_CFG, Theme_Files[0].szName, COUNTOF(Theme_Files[0].szName));
|
|
AppendMenu(s_hmenuThemes, MF_ENABLED | MF_STRING, IDM_THEMES_FACTORY_RESET, tchThemeName);
|
|
AppendMenu(s_hmenuThemes, MF_SEPARATOR, 0, 0);
|
|
|
|
UINT iMaxRID = 0;
|
|
for (unsigned i = 0; i < ThemeItems_CountOf(); ++i) {
|
|
if (Theme_Files[i].rid > 0) {
|
|
iMaxRID = Theme_Files[i].rid;
|
|
AppendMenu(s_hmenuThemes, MF_ENABLED | MF_STRING, iMaxRID, Theme_Files[i].szName);
|
|
} else {
|
|
break; // done
|
|
}
|
|
}
|
|
|
|
// --- insert ---
|
|
WCHAR wchMenuItemStrg[128] = { L'\0' };
|
|
GetLngString(IDS_MUI_MENU_THEMES, wchMenuItemStrg, COUNTOF(wchMenuItemStrg));
|
|
|
|
//bool const res = InsertMenu(hMenuBar, pos, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR)s_hmenuThemes, wchMenuItemStrg);
|
|
bool const res = InsertMenu(hMenuBar, IDM_VIEW_SCHEMECONFIG, MF_BYCOMMAND | MF_POPUP | MF_STRING, (UINT_PTR)s_hmenuThemes, wchMenuItemStrg);
|
|
|
|
unsigned const iTheme = Globals.uCurrentThemeIndex;
|
|
|
|
CheckMenuRadioItem(hMenuBar, IDM_THEMES_STD_CFG, iMaxRID, IDM_THEMES_STD_CFG + iTheme, MF_BYCOMMAND);
|
|
|
|
if (Path_IsEmpty(Theme_Files[iTheme].hStyleFilePath)) {
|
|
EnableCmd(hMenuBar, Theme_Files[iTheme].rid, false);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_DynamicThemesMenuCmd() - Handles IDS_MUI_MENU_THEMES messages
|
|
//
|
|
//
|
|
bool Style_DynamicThemesMenuCmd(int cmd)
|
|
{
|
|
int const iThemeIdx = clampi(cmd - IDM_THEMES_STD_CFG, -1, ThemeItems_CountOf() - 1); // consecutive IDs, -1 for factory reset
|
|
|
|
if (iThemeIdx == (int)Globals.uCurrentThemeIndex) {
|
|
return true;
|
|
}
|
|
|
|
if (Settings.SaveSettings) {
|
|
if (Globals.uCurrentThemeIndex == 0) {
|
|
if (!Flags.bSettingsFileSoftLocked) {
|
|
Globals.bCanSaveIniFile = CreateIniFile(Paths.IniFile, NULL);
|
|
if (Globals.bCanSaveIniFile) {
|
|
Style_ExportToFile(Paths.IniFile, false);
|
|
}
|
|
}
|
|
} else if (Path_IsExistingFile(Theme_Files[Globals.uCurrentThemeIndex].hStyleFilePath)) {
|
|
Style_ExportToFile(Theme_Files[Globals.uCurrentThemeIndex].hStyleFilePath, true);
|
|
}
|
|
}
|
|
|
|
ResetIniFileCache();
|
|
bool const result = Style_ImportTheme(iThemeIdx); // -1: factory reset
|
|
|
|
if (result) {
|
|
|
|
Globals.uCurrentThemeIndex = clampi(iThemeIdx, 0, (int)ThemeItems_CountOf() - 1);
|
|
StringCchCopy(Settings.CurrentThemeName, COUNTOF(Settings.CurrentThemeName), Theme_Files[Globals.uCurrentThemeIndex].szName);
|
|
|
|
CheckMenuRadioItem(Globals.hMainMenu, IDM_THEMES_STD_CFG, Theme_Files[ThemesItems_MaxIndex()].rid,
|
|
IDM_THEMES_STD_CFG + Globals.uCurrentThemeIndex, MF_BYCOMMAND);
|
|
|
|
if (IsWindow(Globals.hwndDlgCustomizeSchemes)) {
|
|
SendMessage(Globals.hwndDlgCustomizeSchemes, WM_THEMECHANGED, 0, 0);
|
|
} else {
|
|
Style_ResetCurrentLexer(Globals.hwndEdit);
|
|
}
|
|
UpdateMargins(true);
|
|
UpdateUI(Globals.hwndMain);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// IsLexerStandard()
|
|
//
|
|
|
|
inline bool IsLexerStandard(PEDITLEXER pLexer)
|
|
{
|
|
return (pLexer && ((pLexer == &lexStandard) || (pLexer == &lexStandard2nd)));
|
|
}
|
|
|
|
inline PEDITLEXER GetCurrentStdLexer()
|
|
{
|
|
return (Style_GetUse2ndDefault() ? &lexStandard2nd : &lexStandard);
|
|
}
|
|
|
|
inline bool IsStyleStandardDefault(PEDITSTYLE pStyle)
|
|
{
|
|
return (pStyle && ((pStyle->rid == IDS_LEX_STD_STYLE) || (pStyle->rid == IDS_LEX_2ND_STYLE)));
|
|
}
|
|
|
|
inline bool IsStyleSchemeDefault(PEDITSTYLE pStyle)
|
|
{
|
|
return (pStyle && (pStyle->rid == IDS_LEX_STR_Default));
|
|
}
|
|
|
|
inline PEDITLEXER GetDefaultLexer()
|
|
{
|
|
return g_pLexArray[s_iDefaultLexer];
|
|
}
|
|
|
|
inline PEDITLEXER GetLargeFileLexer()
|
|
{
|
|
return &lexTEXT;
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// IsLexerStandard()
|
|
//
|
|
bool Style_IsCurLexerStandard()
|
|
{
|
|
return IsLexerStandard(s_pLexCurrent);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_GetBaseFontSize()
|
|
//
|
|
float Style_GetBaseFontSize()
|
|
{
|
|
LPCWSTR const lpszStyle = GetCurrentStdLexer()->Styles[STY_DEFAULT].szValue;
|
|
float fFontSize = GLOBAL_INITIAL_FONTSIZE;
|
|
Style_StrGetSizeFloatEx(lpszStyle, &fFontSize);
|
|
return max_f(0.5f, fFontSize);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_GetBaseFontSize()
|
|
//
|
|
float Style_GetCurrentLexerFontSize()
|
|
{
|
|
float fFontSize = Style_GetBaseFontSize();
|
|
if (!IsLexerStandard(Style_GetCurrentLexerPtr())) {
|
|
LPCWSTR const lpszStyle = Style_GetCurrentLexerPtr()->Styles[STY_DEFAULT].szValue;
|
|
Style_StrGetSizeFloatEx(lpszStyle, &fFontSize);
|
|
}
|
|
return max_f(0.5f, fFontSize);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_RgbAlpha() - Simulate Translucency
|
|
//
|
|
int Style_RgbAlpha(int rgbFore, int rgbBack, int alpha)
|
|
{
|
|
alpha = clampi(alpha, SC_ALPHA_TRANSPARENT, SC_ALPHA_OPAQUE);
|
|
return (int)RGB(
|
|
(0xFF - alpha) * (int)GetRValue(rgbBack) / 0xFF + alpha * (int)GetRValue(rgbFore) / 0xFF,
|
|
(0xFF - alpha) * (int)GetGValue(rgbBack) / 0xFF + alpha * (int)GetGValue(rgbFore) / 0xFF,
|
|
(0xFF - alpha) * (int)GetBValue(rgbBack) / 0xFF + alpha * (int)GetBValue(rgbFore) / 0xFF);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_Import()
|
|
//
|
|
bool Style_Import(HWND hwnd)
|
|
{
|
|
HPATHL hfile_pth = Path_Allocate(NULL);
|
|
|
|
HSTRINGW hflt_str = StrgCreate(NULL);
|
|
wchar_t* const flt_buf = StrgWriteAccessBuf(hflt_str, EXTENTIONS_FILTER_BUFFER);
|
|
|
|
GetLngString(IDS_MUI_FILTER_INI, flt_buf, (int)StrgGetAllocLength(hflt_str));
|
|
StrgSanitize(hflt_str);
|
|
|
|
PrepareFilterStr(flt_buf);
|
|
|
|
bool result = false;
|
|
|
|
if (FileOpenDlg(hwnd, hfile_pth, NULL, StrgGet(hflt_str), L"ini",
|
|
FOS_FILEMUSTEXIST | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR |
|
|
FOS_DONTADDTORECENT | FOS_SHAREAWARE)) {
|
|
Path_Sanitize(hfile_pth);
|
|
result = Style_ImportFromFile(hfile_pth);
|
|
}
|
|
|
|
StrgDestroy(hflt_str);
|
|
Path_Release(hfile_pth);
|
|
return result;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// _LoadLexerFileExtensions()
|
|
//
|
|
static void _LoadLexerFileExtensions()
|
|
{
|
|
if (OpenSettingsFile(__func__)) {
|
|
|
|
for (int iLexer = 0; iLexer < COUNTOF(g_pLexArray); iLexer++) {
|
|
|
|
LPCWSTR Lexer_Section = g_pLexArray[iLexer]->pszName;
|
|
|
|
if ((Globals.iCfgVersionRead < CFG_VER_0004) && (iLexer < 2)) {
|
|
Lexer_Section = (iLexer == 0) ? L"Default Text" : L"2nd Default Text";
|
|
}
|
|
|
|
IniSectionGetString(Lexer_Section, L"FileNameExtensions", g_pLexArray[iLexer]->pszDefExt,
|
|
g_pLexArray[iLexer]->szExtensions, COUNTOF(g_pLexArray[iLexer]->szExtensions));
|
|
|
|
// don't allow empty extensions settings => use default ext
|
|
if (StrIsEmpty(g_pLexArray[iLexer]->szExtensions)) {
|
|
StringCchCopy(g_pLexArray[iLexer]->szExtensions, COUNTOF(g_pLexArray[iLexer]->szExtensions), g_pLexArray[iLexer]->pszDefExt);
|
|
}
|
|
|
|
if (Globals.iCfgVersionRead < CFG_VER_0004) {
|
|
// handling "Text Files" lexer
|
|
if (StringCchCompareXI(L"Text Files", g_pLexArray[iLexer]->pszName) == 0) {
|
|
if (StrIsNotEmpty(g_pLexArray[0]->szExtensions)) {
|
|
StringCchCopy(g_pLexArray[iLexer]->szExtensions, COUNTOF(g_pLexArray[iLexer]->szExtensions), g_pLexArray[0]->szExtensions);
|
|
StrTrim(g_pLexArray[iLexer]->szExtensions, L"; ");
|
|
}
|
|
lexStandard.szExtensions[0] = L'\0';
|
|
lexStandard2nd.szExtensions[0] = L'\0';
|
|
// copy default style
|
|
StringCchCopy(g_pLexArray[iLexer]->Styles[0].szValue, COUNTOF(g_pLexArray[iLexer]->Styles[0].szValue), g_pLexArray[0]->Styles[0].szValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
CloseSettingsFile(__func__, false); // read only
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_Prerequisites()
|
|
//
|
|
void Style_Prerequisites() {
|
|
|
|
//_SetBaseFontSize(GLOBAL_INITIAL_FONTSIZE);
|
|
//_SetCurrentFontSize(GLOBAL_INITIAL_FONTSIZE);
|
|
|
|
for (int i = 0; i < 16; ++i) {
|
|
g_colorCustom[i] = (UseDarkMode() ? s_colorDarkDefault[i] : s_colorLightDefault[i]);
|
|
}
|
|
|
|
_FillThemesMenuTable();
|
|
_LoadLexerFileExtensions();
|
|
|
|
///~ Style_ImportFromFile(Paths.IniFile); ~ done later
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// _DefaultsToTmpCache()
|
|
//
|
|
static void _DefaultsToTmpCache() {
|
|
|
|
ResetTmpCache();
|
|
|
|
if (UseDarkMode()) {
|
|
|
|
WCHAR wchDefaultStyle[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
|
|
CopyToTmpCache(Globals.pStdDarkModeIniStyles);
|
|
|
|
// in case of "pStdDarkModeIniStyles" is incomplete (new Lexer, etc.)
|
|
for (int iLexer = 0; iLexer < COUNTOF(g_pLexArray); ++iLexer) {
|
|
LPCWSTR const Lexer_Section = g_pLexArray[iLexer]->pszName;
|
|
unsigned i = 0;
|
|
while (g_pLexArray[iLexer]->Styles[i].iStyle != -1) {
|
|
LPCWSTR const pszKeyName = g_pLexArray[iLexer]->Styles[i].pszName;
|
|
LPCWSTR const pszDefault = g_pLexArray[iLexer]->Styles[i].pszDefault;
|
|
wchDefaultStyle[0] = L'\0'; // empty
|
|
TmpCacheGetString(Lexer_Section, pszKeyName, L"", wchDefaultStyle, COUNTOF(wchDefaultStyle));
|
|
StrTrim(wchDefaultStyle, L" ;");
|
|
if (StrIsEmpty(wchDefaultStyle) && StrIsNotEmpty(pszDefault)) {
|
|
TmpCacheSetString(Lexer_Section, pszKeyName, pszDefault);
|
|
}
|
|
++i;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
for (int iLexer = 0; iLexer < COUNTOF(g_pLexArray); ++iLexer) {
|
|
LPCWSTR const Lexer_Section = g_pLexArray[iLexer]->pszName;
|
|
unsigned i = 0;
|
|
while (g_pLexArray[iLexer]->Styles[i].iStyle != -1) {
|
|
LPCWSTR const pszKeyName = g_pLexArray[iLexer]->Styles[i].pszName;
|
|
LPCWSTR const pszDefault = g_pLexArray[iLexer]->Styles[i].pszDefault;
|
|
TmpCacheSetString(Lexer_Section, pszKeyName, pszDefault);
|
|
++i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool _CopyTmpCacheToIniFileCache() {
|
|
|
|
WCHAR wchStyle[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
|
|
for (int iLexer = 0; iLexer < COUNTOF(g_pLexArray); ++iLexer) {
|
|
LPCWSTR const Lexer_Section = g_pLexArray[iLexer]->pszName;
|
|
unsigned i = 0;
|
|
while (g_pLexArray[iLexer]->Styles[i].iStyle != -1) {
|
|
LPCWSTR const pszKeyName = g_pLexArray[iLexer]->Styles[i].pszName;
|
|
wchStyle[0] = L'\0';
|
|
TmpCacheGetString(Lexer_Section, pszKeyName, L"", wchStyle, COUNTOF(wchStyle));
|
|
IniSectionSetString(Lexer_Section, pszKeyName, wchStyle);
|
|
++i;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// _ReadFromIniCache()
|
|
//
|
|
static void _ReadFromIniCache() {
|
|
|
|
for (int i = 0; i < 16; i++) {
|
|
g_colorCustom[i] = (UseDarkMode() ? s_colorDarkDefault[i] : s_colorLightDefault[i]); // reset
|
|
}
|
|
const WCHAR *const CustomColors_Section = L"Custom Colors";
|
|
WCHAR tch[32] = { L'\0' };
|
|
for (int i = 0; i < 16; i++) {
|
|
WCHAR wch[32] = { L'\0' };
|
|
StringCchPrintf(tch, COUNTOF(tch), L"%02i", i + 1);
|
|
int itok = 0;
|
|
if (IniSectionGetString(CustomColors_Section, tch, L"", wch, COUNTOF(wch))) {
|
|
if (wch[0] == L'#') {
|
|
unsigned int irgb;
|
|
itok = swscanf_s(CharNext(wch), L"%x", &irgb);
|
|
if (itok == 1) {
|
|
g_colorCustom[i] = RGB((irgb & 0xFF0000) >> 16, (irgb & 0xFF00) >> 8, irgb & 0xFF);
|
|
}
|
|
}
|
|
}
|
|
if (itok != 1) {
|
|
g_colorCustom[i] = (UseDarkMode() ? s_colorDarkDefault[i] : s_colorLightDefault[i]);
|
|
}
|
|
}
|
|
|
|
// Styles
|
|
const WCHAR *const IniSecStyles = Constants.Styles_Section;
|
|
|
|
// 2nd default
|
|
Style_SetUse2ndDefault(IniSectionGetBool(IniSecStyles, L"Use2ndDefaultStyle", false));
|
|
|
|
// default scheme
|
|
s_iDefaultLexer = clampi(IniSectionGetInt(IniSecStyles, L"DefaultScheme", Constants.StdDefaultLexerID), 0, COUNTOF(g_pLexArray) - 1);
|
|
|
|
// auto select
|
|
s_bAutoSelect = IniSectionGetBool(IniSecStyles, L"AutoSelect", true);
|
|
|
|
// scheme select dlg dimensions
|
|
s_cxStyleSelectDlg = clampi(IniSectionGetInt(IniSecStyles, L"SelectDlgSizeX", STYLESELECTDLG_X), 0, 8192);
|
|
s_cyStyleSelectDlg = clampi(IniSectionGetInt(IniSecStyles, L"SelectDlgSizeY", STYLESELECTDLG_Y), 0, 8192);
|
|
|
|
// Lexer
|
|
WCHAR wchDefaultStyle[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
|
|
_DefaultsToTmpCache();
|
|
|
|
for (int iLexer = 0; iLexer < COUNTOF(g_pLexArray); iLexer++) {
|
|
|
|
LPCWSTR Lexer_Section = g_pLexArray[iLexer]->pszName;
|
|
|
|
if ((Globals.iCfgVersionRead < CFG_VER_0004) && (iLexer < 2)) {
|
|
Lexer_Section = (iLexer == 0) ? L"Default Text" : L"2nd Default Text";
|
|
}
|
|
|
|
unsigned i = 0;
|
|
while (g_pLexArray[iLexer]->Styles[i].iStyle != -1) {
|
|
|
|
LPCWSTR const pszKeyName = g_pLexArray[iLexer]->Styles[i].pszName;
|
|
|
|
wchDefaultStyle[0] = L'\0';
|
|
TmpCacheGetString(Lexer_Section, pszKeyName, L"", wchDefaultStyle, COUNTOF(wchDefaultStyle));
|
|
IniSectionGetString(Lexer_Section, pszKeyName, wchDefaultStyle,
|
|
g_pLexArray[iLexer]->Styles[i].szValue,
|
|
COUNTOF(g_pLexArray[iLexer]->Styles[i].szValue));
|
|
++i;
|
|
}
|
|
}
|
|
|
|
ResetTmpCache();
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_ImportFromFile()
|
|
//
|
|
bool Style_ImportFromFile(const HPATHL hpath)
|
|
{
|
|
bool const bHaveFileResource = Path_IsNotEmpty(hpath);
|
|
bool const bIsStdIniFile = bHaveFileResource ? (Path_StrgComparePath(hpath, Paths.IniFile, Paths.ModuleDirectory, true) == 0) : false;
|
|
|
|
bool result = bIsStdIniFile ? OpenSettingsFile(__func__) : (bHaveFileResource ? LoadIniFileCache(hpath) : true);
|
|
if (result) {
|
|
_ReadFromIniCache();
|
|
result = bIsStdIniFile ? !CloseSettingsFile(__func__, false) /* (!)import only */ : (bHaveFileResource ? ResetIniFileCache() : true);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_ImportTheme()
|
|
//
|
|
bool Style_ImportTheme(const int iThemeIdx) {
|
|
|
|
switch (iThemeIdx) {
|
|
case -1:
|
|
return Style_ImportFromFile(NULL);
|
|
default:
|
|
if ((iThemeIdx >= 0) && (iThemeIdx < (int)ThemeItems_CountOf()) && Path_IsExistingFile(Theme_Files[iThemeIdx].hStyleFilePath)) {
|
|
return Style_ImportFromFile(Theme_Files[iThemeIdx].hStyleFilePath);
|
|
}
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SaveSettings()
|
|
//
|
|
void Style_SaveSettings(bool bForceSaveSettings)
|
|
{
|
|
if (Settings.SaveSettings || bForceSaveSettings) {
|
|
Style_ExportToFile(Theme_Files[Globals.uCurrentThemeIndex].hStyleFilePath, false);
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_Export()
|
|
//
|
|
bool Style_Export(HWND hwnd)
|
|
{
|
|
HPATHL hfile_pth = Path_Allocate(NULL);
|
|
|
|
HSTRINGW hflt_str = StrgCreate(NULL);
|
|
wchar_t* const flt_buf = StrgWriteAccessBuf(hflt_str, EXTENTIONS_FILTER_BUFFER);
|
|
|
|
GetLngString(IDS_MUI_FILTER_INI, flt_buf, (int)StrgGetAllocLength(hflt_str));
|
|
StrgSanitize(hflt_str);
|
|
|
|
PrepareFilterStr(flt_buf);
|
|
|
|
bool result = false;
|
|
|
|
if (FileSaveDlg(hwnd, hfile_pth, NULL, StrgGet(hflt_str), L"ini",
|
|
FOS_OVERWRITEPROMPT | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR |
|
|
FOS_DONTADDTORECENT | FOS_SHAREAWARE)) {
|
|
Path_Sanitize(hfile_pth);
|
|
result = Style_ExportToFile(hfile_pth, true);
|
|
if (!result) {
|
|
InfoBoxLng(MB_ICONERROR, NULL, IDS_MUI_EXPORT_FAIL, Path_FindFileName(hfile_pth));
|
|
}
|
|
}
|
|
|
|
StrgDestroy(hflt_str);
|
|
Path_Release(hfile_pth);
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_FileExtToIniSection()
|
|
//
|
|
void Style_FileExtToIniSection(bool bForceAll)
|
|
{
|
|
for (int iLexer = 0; iLexer < COUNTOF(g_pLexArray); ++iLexer) {
|
|
|
|
LPCWSTR const Lexer_Section = g_pLexArray[iLexer]->pszName;
|
|
|
|
if (bForceAll || (StringCchCompareXI(g_pLexArray[iLexer]->szExtensions, g_pLexArray[iLexer]->pszDefExt) != 0)) {
|
|
IniSectionSetString(Lexer_Section, L"FileNameExtensions", g_pLexArray[iLexer]->szExtensions);
|
|
} else {
|
|
IniSectionDelete(Lexer_Section, L"FileNameExtensions", false);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_CanonicalSectionToIniCache()
|
|
// create canonical order of lexer sections
|
|
//
|
|
void Style_CanonicalSectionToIniCache() {
|
|
for (int iLexer = 0; iLexer < COUNTOF(g_pLexArray); iLexer++) {
|
|
IniSectionClear(g_pLexArray[iLexer]->pszName, true);
|
|
}
|
|
for (int iLexer = 0; iLexer < COUNTOF(g_pLexArray); iLexer++) {
|
|
IniSectionSetString(g_pLexArray[iLexer]->pszName, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_ToIniSection()
|
|
//
|
|
|
|
#define SAVE_STYLE_IF_NOT_EQ_DEFAULT(TYPE, VARNAME, VALUE, DEFAULT) \
|
|
if ((VALUE) != (DEFAULT)) { \
|
|
IniSectionSet##TYPE(IniSecStyles, _W(_STRG(VARNAME)), (VALUE)); \
|
|
} else { \
|
|
IniSectionDelete(IniSecStyles, _W(_STRG(VARNAME)), false); \
|
|
}
|
|
|
|
bool Style_ToIniSection(bool bForceAll)
|
|
{
|
|
// Custom colors
|
|
const WCHAR* const CustomColors_Section = L"Custom Colors";
|
|
|
|
for (int i = 0; i < 16; i++) {
|
|
WCHAR tch[32] = { L'\0' };
|
|
StringCchPrintf(tch, COUNTOF(tch), L"%02i", i + 1);
|
|
if ((g_colorCustom[i] != (UseDarkMode() ? s_colorDarkDefault[i] : s_colorLightDefault[i])) || bForceAll) {
|
|
WCHAR wch[32] = { L'\0' };
|
|
ColorToHtmlCode(g_colorCustom[i], wch, COUNTOF(wch));
|
|
IniSectionSetString(CustomColors_Section, tch, wch);
|
|
} else {
|
|
IniSectionDelete(CustomColors_Section, tch, false);
|
|
}
|
|
}
|
|
|
|
const WCHAR* const IniSecStyles = Constants.Styles_Section;
|
|
|
|
// auto select
|
|
SAVE_STYLE_IF_NOT_EQ_DEFAULT(Bool, Use2ndDefaultStyle, Style_GetUse2ndDefault(), false);
|
|
|
|
// default scheme
|
|
SAVE_STYLE_IF_NOT_EQ_DEFAULT(Int, DefaultScheme, s_iDefaultLexer, Constants.StdDefaultLexerID);
|
|
|
|
// auto select
|
|
SAVE_STYLE_IF_NOT_EQ_DEFAULT(Bool, AutoSelect, s_bAutoSelect, true);
|
|
|
|
// scheme select dlg dimensions
|
|
SAVE_STYLE_IF_NOT_EQ_DEFAULT(Int, SelectDlgSizeX, s_cxStyleSelectDlg, STYLESELECTDLG_X);
|
|
SAVE_STYLE_IF_NOT_EQ_DEFAULT(Int, SelectDlgSizeY, s_cyStyleSelectDlg, STYLESELECTDLG_Y);
|
|
|
|
if (bForceAll || Globals.bIniFileFromScratch) {
|
|
Style_CanonicalSectionToIniCache();
|
|
}
|
|
|
|
WCHAR wchCurrentStyle[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
WCHAR wchDefaultStyle[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
|
|
// prepare tmp cache with defaults
|
|
_DefaultsToTmpCache();
|
|
|
|
for (int iLexer = 0; iLexer < COUNTOF(g_pLexArray); ++iLexer) {
|
|
|
|
LPCWSTR const Lexer_Section = g_pLexArray[iLexer]->pszName;
|
|
|
|
unsigned idx = 0;
|
|
while (g_pLexArray[iLexer]->Styles[idx].iStyle != -1) {
|
|
|
|
LPCWSTR const pszKeyName = g_pLexArray[iLexer]->Styles[idx].pszName;
|
|
|
|
// normalize values for comparison
|
|
wchCurrentStyle[0] = L'\0';
|
|
TmpCacheGetString(Lexer_Section, pszKeyName, L"", wchCurrentStyle, COUNTOF(wchCurrentStyle));
|
|
wchDefaultStyle[0] = L'\0';
|
|
Style_CopyStyles_IfNotDefined(wchCurrentStyle, wchDefaultStyle, COUNTOF(wchDefaultStyle));
|
|
|
|
wchCurrentStyle[0] = L'\0';
|
|
LPCWSTR const pszValue = g_pLexArray[iLexer]->Styles[idx].szValue;
|
|
Style_CopyStyles_IfNotDefined(pszValue, wchCurrentStyle, COUNTOF(wchCurrentStyle));
|
|
|
|
if (bForceAll || (StringCchCompareX(wchCurrentStyle, wchDefaultStyle) != 0)) {
|
|
if (StrIsNotEmpty(wchCurrentStyle)) {
|
|
IniSectionSetString(Lexer_Section, pszKeyName, wchCurrentStyle);
|
|
} else {
|
|
IniSectionDelete(Lexer_Section, pszKeyName, false);
|
|
}
|
|
} else {
|
|
IniSectionDelete(Lexer_Section, pszKeyName, false);
|
|
}
|
|
++idx;
|
|
}
|
|
}
|
|
|
|
ResetTmpCache();
|
|
|
|
// cleanup old (< v4) stuff
|
|
IniSectionDelete(L"Default Text", NULL, true);
|
|
IniSectionDelete(L"2nd Default Text", NULL, true);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_ExportToFile()
|
|
//
|
|
bool Style_ExportToFile(const HPATHL hpath, bool bForceAll)
|
|
{
|
|
if (Path_IsEmpty(hpath)) {
|
|
if (Globals.uCurrentThemeIndex != 0) {
|
|
InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SETTINGSNOTSAVED);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool const bIsStdIniFile = (Path_StrgComparePath(hpath, Paths.IniFile, Paths.ModuleDirectory, true) == 0);
|
|
|
|
// special handling of standard .ini-file
|
|
bool ok = false;
|
|
if (bIsStdIniFile) {
|
|
if (OpenSettingsFile(__func__)) {
|
|
Style_ToIniSection(bForceAll);
|
|
Style_FileExtToIniSection(bForceAll);
|
|
ok = CloseSettingsFile(__func__, true);
|
|
}
|
|
} else {
|
|
HPATHL hpth_tmp = Path_Copy(hpath);
|
|
Path_NormalizeEx(hpth_tmp, Paths.WorkingDirectory, true, false);
|
|
if (Path_IsNotEmpty(hpth_tmp)) {
|
|
if (!Path_IsExistingFile(hpth_tmp)) {
|
|
HANDLE hFile = CreateFile(Path_Get(hpth_tmp),
|
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
|
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (IS_VALID_HANDLE(hFile)) {
|
|
CloseHandle(hFile); // done
|
|
}
|
|
}
|
|
ResetIniFileCache();
|
|
if (LoadIniFileCache(hpth_tmp)) {
|
|
Style_ToIniSection(bForceAll);
|
|
Style_FileExtToIniSection(bForceAll);
|
|
ok = SaveIniFileCache(hpth_tmp);
|
|
ResetIniFileCache();
|
|
}
|
|
}
|
|
Path_Release(hpth_tmp);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_StrHasAttribute()
|
|
//
|
|
// zufuliu: parse a style attribute separated by ';'
|
|
// e.g.: 'bold', ' bold;', '; bold ' and '; bold;'
|
|
//
|
|
static bool Style_StrHasAttributeEx(LPCWSTR lpszStyle, LPCWSTR key, const size_t keyLen)
|
|
{
|
|
LPCWSTR p = StrStrI(lpszStyle, key);
|
|
while (p) {
|
|
WCHAR chPrev = (p == lpszStyle) ? L';' : p[-1];
|
|
if (chPrev == L' ') {
|
|
LPCWSTR t = p - 2;
|
|
while ((t > lpszStyle) && (*t == L' ')) {
|
|
--t;
|
|
}
|
|
chPrev = (t <= lpszStyle) ? L';' : *t;
|
|
}
|
|
p += keyLen;
|
|
if (chPrev == L';') {
|
|
while (*p == L' ') {
|
|
++p;
|
|
}
|
|
if (*p == L'\0' || *p == L';') {
|
|
return true;
|
|
}
|
|
}
|
|
p = StrStrI(p, key);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static __forceinline bool Style_StrHasAttribute(LPCWSTR lpszStyle, LPCWSTR name) {
|
|
return Style_StrHasAttributeEx(lpszStyle, name, StringCchLen(name, 0));
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetLexer()
|
|
//
|
|
void Style_SetLexer(HWND hwnd, PEDITLEXER pLexNew)
|
|
{
|
|
// Select standard if NULL is specified
|
|
if (!pLexNew) {
|
|
pLexNew = Flags.bHugeFileLoadState ? GetLargeFileLexer() : GetDefaultLexer();
|
|
if (IsLexerStandard(pLexNew)) {
|
|
pLexNew = GetCurrentStdLexer();
|
|
}
|
|
}
|
|
bool const bFocusedView = FocusedView.HideNonMatchedLines;
|
|
if (bFocusedView) {
|
|
EditToggleView(Globals.hwndEdit);
|
|
}
|
|
|
|
//~ ! dont check for (pLexNew == s_pLexCurrent) <= "reapply current lexer"
|
|
//~ assert(pLexNew != s_pLexCurrent);
|
|
|
|
BeginWaitCursorUID(Flags.bHugeFileLoadState, IDS_MUI_SB_LEXER_STYLING);
|
|
|
|
int const idleStylingMode = SciCall_GetIdleStyling();
|
|
SciCall_SetIdleStyling(SC_IDLESTYLING_ALL);
|
|
|
|
// first set standard lexer's default values
|
|
const PEDITLEXER pCurrentStandard = (IsLexerStandard(pLexNew)) ? pLexNew : GetCurrentStdLexer();
|
|
|
|
// Set Lexer
|
|
SciCall_SetILexer(CreateLexer(pLexNew->lexerName));
|
|
|
|
#ifdef _DEBUG
|
|
int const iNewLexer = SciCall_GetLexer();
|
|
if ((pLexNew->lexerID > SCLEX_NULL) && (iNewLexer != pLexNew->lexerID)) {
|
|
WCHAR msg[256] = { L'\0' };
|
|
StringCchPrintf(msg, COUNTOF(msg), L"Failed to set desired Lexer (#%i), got Lexer #%i!", pLexNew->lexerID, iNewLexer);
|
|
InfoBoxLastError(msg, ERROR_DLL_INIT_FAILED);
|
|
}
|
|
#endif
|
|
|
|
// Lexer very specific styles
|
|
Lexer_SetLexerSpecificProperties(pLexNew->lexerID);
|
|
|
|
// Code folding
|
|
Lexer_SetFoldingAvailability(pLexNew);
|
|
Lexer_SetFoldingProperties(FocusedView.CodeFoldingAvailable);
|
|
|
|
// Add KeyWord Lists
|
|
for (int i = 0; i <= KEYWORDSET_MAX; ++i) {
|
|
const char* pKeyWordList = pLexNew->pKeyWords->pszKeyWords[i];
|
|
SciCall_SetKeywords(i, (pKeyWordList ? pKeyWordList : ""));
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// Clear
|
|
SciCall_ClearDocumentStyle();
|
|
|
|
// Default Values are always set
|
|
SciCall_StyleResetDefault();
|
|
|
|
// Constants
|
|
SciCall_StyleSetVisible(STYLE_DEFAULT, true);
|
|
|
|
//~Style_SetACPfromCharSet(hwnd);
|
|
|
|
// --- apply/init default style ---
|
|
|
|
// --- apply current scheme specific settings to default style ---
|
|
WCHAR wchStylesBuffer[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
// set common defaults
|
|
StringCchCopy(wchStylesBuffer, COUNTOF(wchStylesBuffer), pLexNew->Styles[STY_DEFAULT].szValue);
|
|
// merge lexer default styles
|
|
Style_CopyStyles_IfNotDefined(pCurrentStandard->Styles[STY_DEFAULT].szValue, wchStylesBuffer, COUNTOF(wchStylesBuffer));
|
|
|
|
// apply default settings
|
|
float fBaseFontSize = IsLexerStandard(pLexNew) ? GLOBAL_INITIAL_FONTSIZE : Style_GetBaseFontSize();
|
|
Style_SetStyles(hwnd, STYLE_DEFAULT, wchStylesBuffer, fBaseFontSize);
|
|
Style_StrGetSizeFloatEx(wchStylesBuffer, &fBaseFontSize); // get scheme base font size
|
|
|
|
// Broadcast STYLE_DEFAULT as base style to all other styles
|
|
SciCall_StyleClearAll();
|
|
|
|
if (IsLexerStandard(pLexNew)) {
|
|
EnableCmd(GetMenu(Globals.hwndMain), IDM_VIEW_CURRENTSCHEME, true);
|
|
}
|
|
else {
|
|
EnableCmd(GetMenu(Globals.hwndMain), IDM_VIEW_CURRENTSCHEME, !IsWindow(Globals.hwndDlgCustomizeSchemes));
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
bool bFlag;
|
|
int iValue;
|
|
COLORREF dColor;
|
|
WCHAR wch[64] = { L'\0' };
|
|
wchStylesBuffer[0] = L'\0';
|
|
|
|
// margin (line number, bookmarks, folding) style
|
|
Style_SetMargin(hwnd, pCurrentStandard->Styles[STY_MARGIN].szValue);
|
|
|
|
if (Settings2.UseOldStyleBraceMatching) {
|
|
Style_SetStyles(hwnd, pCurrentStandard->Styles[STY_BRACE_OK].iStyle,
|
|
pCurrentStandard->Styles[STY_BRACE_OK].szValue, fBaseFontSize); // brace light
|
|
}
|
|
else {
|
|
if (Style_StrGetColor(pCurrentStandard->Styles[STY_BRACE_OK].szValue, FOREGROUND_LAYER, &dColor, NULL, false)) {
|
|
SciCall_IndicSetFore(INDIC_NP3_MATCH_BRACE, dColor);
|
|
}
|
|
if (Style_StrGetAlpha(pCurrentStandard->Styles[STY_BRACE_OK].szValue, &iValue, SC_ALPHA_OPAQUE, true)) {
|
|
SciCall_IndicSetAlpha(INDIC_NP3_MATCH_BRACE, iValue);
|
|
}
|
|
if (Style_StrGetAlpha(pCurrentStandard->Styles[STY_BRACE_OK].szValue, &iValue, SC_ALPHA_OPAQUE, false)) {
|
|
SciCall_IndicSetOutlineAlpha(INDIC_NP3_MATCH_BRACE, iValue);
|
|
}
|
|
|
|
iValue = -1; // need for retrieval
|
|
if (!Style_GetIndicatorType(pCurrentStandard->Styles[STY_BRACE_OK].szValue, 0, &iValue)) {
|
|
// got default, get string
|
|
StringCchCatW(pCurrentStandard->Styles[STY_BRACE_OK].szValue, COUNTOF(pCurrentStandard->Styles[0].szValue), L"; ");
|
|
Style_GetIndicatorType(wchStylesBuffer, COUNTOF(wchStylesBuffer), &iValue);
|
|
StringCchCatW(pCurrentStandard->Styles[STY_BRACE_OK].szValue, COUNTOF(pCurrentStandard->Styles[0].szValue), wchStylesBuffer);
|
|
}
|
|
|
|
SciCall_IndicSetStyle(INDIC_NP3_MATCH_BRACE, iValue);
|
|
|
|
if (Style_StrGetStrokeWidth(hwnd, INDIC_NP3_MATCH_BRACE, pCurrentStandard->Styles[STY_BRACE_OK].szValue, &iValue)) {
|
|
SciCall_IndicSetStrokeWidth(INDIC_NP3_MATCH_BRACE, iValue);
|
|
}
|
|
|
|
// Indentation Guide
|
|
SciCall_StyleSetBack(STYLE_BRACELIGHT, dColor);
|
|
}
|
|
|
|
if (Settings2.UseOldStyleBraceMatching) {
|
|
Style_SetStyles(hwnd, pCurrentStandard->Styles[STY_BRACE_BAD].iStyle,
|
|
pCurrentStandard->Styles[STY_BRACE_BAD].szValue, fBaseFontSize); // brace bad
|
|
}
|
|
else {
|
|
if (Style_StrGetColor(pCurrentStandard->Styles[STY_BRACE_BAD].szValue, FOREGROUND_LAYER, &dColor, NULL, false)) {
|
|
SciCall_IndicSetFore(INDIC_NP3_BAD_BRACE, dColor);
|
|
}
|
|
if (Style_StrGetAlpha(pCurrentStandard->Styles[STY_BRACE_BAD].szValue, &iValue, SC_ALPHA_OPAQUE, true)) {
|
|
SciCall_IndicSetAlpha(INDIC_NP3_BAD_BRACE, iValue);
|
|
}
|
|
if (Style_StrGetAlpha(pCurrentStandard->Styles[STY_BRACE_BAD].szValue, &iValue, SC_ALPHA_OPAQUE, false)) {
|
|
SciCall_IndicSetOutlineAlpha(INDIC_NP3_BAD_BRACE, iValue);
|
|
}
|
|
|
|
iValue = -1; // need for retrieval
|
|
if (!Style_GetIndicatorType(pCurrentStandard->Styles[STY_BRACE_BAD].szValue, 0, &iValue)) {
|
|
// got default, get string
|
|
StringCchCatW(pCurrentStandard->Styles[STY_BRACE_BAD].szValue, COUNTOF(pCurrentStandard->Styles[0].szValue), L"; ");
|
|
Style_GetIndicatorType(wchStylesBuffer, COUNTOF(wchStylesBuffer), &iValue);
|
|
StringCchCatW(pCurrentStandard->Styles[STY_BRACE_BAD].szValue, COUNTOF(pCurrentStandard->Styles[0].szValue), wchStylesBuffer);
|
|
}
|
|
|
|
SciCall_IndicSetStyle(INDIC_NP3_BAD_BRACE, iValue);
|
|
|
|
if (Style_StrGetStrokeWidth(hwnd, INDIC_NP3_BAD_BRACE, pCurrentStandard->Styles[STY_BRACE_BAD].szValue, &iValue)) {
|
|
SciCall_IndicSetStrokeWidth(INDIC_NP3_BAD_BRACE, iValue);
|
|
}
|
|
}
|
|
|
|
// Occurrences Marker
|
|
if (!Style_StrGetColor(pCurrentStandard->Styles[STY_MARK_OCC].szValue, FOREGROUND_LAYER, &dColor, NULL, false)) {
|
|
dColor = GetSysColor(COLOR_HIGHLIGHT);
|
|
WCHAR sty[32] = { L'\0' };
|
|
Style_PrintfCchColor(sty, COUNTOF(sty), L"; ", FOREGROUND_LAYER, dColor);
|
|
StringCchCat(pCurrentStandard->Styles[STY_MARK_OCC].szValue, COUNTOF(pCurrentStandard->Styles[0].szValue), sty);
|
|
}
|
|
SciCall_IndicSetFore(INDIC_NP3_MARK_OCCURANCE, dColor);
|
|
|
|
if (!Style_StrGetAlpha(pCurrentStandard->Styles[STY_MARK_OCC].szValue, &iValue, SC_ALPHA_OPAQUE, true)) {
|
|
iValue = 60; // force
|
|
StringCchCat(pCurrentStandard->Styles[STY_MARK_OCC].szValue, COUNTOF(pCurrentStandard->Styles[0].szValue), L"; alpha:60");
|
|
}
|
|
SciCall_IndicSetAlpha(INDIC_NP3_MARK_OCCURANCE, iValue);
|
|
|
|
if (!Style_StrGetAlpha(pCurrentStandard->Styles[STY_MARK_OCC].szValue, &iValue, SC_ALPHA_OPAQUE, false)) {
|
|
iValue = 60; // force
|
|
StringCchCat(pCurrentStandard->Styles[STY_MARK_OCC].szValue, COUNTOF(pCurrentStandard->Styles[0].szValue), L"; alpha2:60");
|
|
}
|
|
SciCall_IndicSetOutlineAlpha(INDIC_NP3_MARK_OCCURANCE, iValue);
|
|
|
|
iValue = -1; // need for retrieval
|
|
if (!Style_GetIndicatorType(pCurrentStandard->Styles[STY_MARK_OCC].szValue, 0, &iValue)) {
|
|
// got default, get string
|
|
StringCchCat(pCurrentStandard->Styles[STY_MARK_OCC].szValue, COUNTOF(pCurrentStandard->Styles[0].szValue), L"; ");
|
|
Style_GetIndicatorType(wchStylesBuffer, COUNTOF(wchStylesBuffer), &iValue);
|
|
StringCchCat(pCurrentStandard->Styles[STY_MARK_OCC].szValue, COUNTOF(pCurrentStandard->Styles[0].szValue), wchStylesBuffer);
|
|
}
|
|
|
|
SciCall_IndicSetStyle(INDIC_NP3_MARK_OCCURANCE, iValue);
|
|
|
|
if (Style_StrGetStrokeWidth(hwnd, INDIC_NP3_MARK_OCCURANCE, pCurrentStandard->Styles[STY_MARK_OCC].szValue, &iValue)) {
|
|
SciCall_IndicSetStrokeWidth(INDIC_NP3_MARK_OCCURANCE, iValue);
|
|
}
|
|
|
|
// --------------------------------------------------------------
|
|
// COLOR definitions (INDIC_NP3_COLOR_DEF) are not configurable
|
|
// --------------------------------------------------------------
|
|
|
|
// Unicode-Point Indicator (Hover)
|
|
//SciCall_IndicSetFore(INDIC_NP3_UNICODE_POINT, RGB(0x00, 0x00, 0xF0));
|
|
SciCall_IndicSetStyle(INDIC_NP3_UNICODE_POINT, INDIC_COMPOSITIONTHIN); // simple underline
|
|
|
|
if (Style_StrGetStrokeWidth(hwnd, INDIC_NP3_UNICODE_POINT, pCurrentStandard->Styles[STY_UNICODE_HOTSPOT].szValue, &iValue)) {
|
|
SciCall_IndicSetStrokeWidth(INDIC_NP3_UNICODE_POINT, iValue);
|
|
}
|
|
|
|
if (Style_StrGetColor(pCurrentStandard->Styles[STY_UNICODE_HOTSPOT].szValue, FOREGROUND_LAYER, &dColor, NULL, false)) {
|
|
SciCall_IndicSetHoverFore(INDIC_NP3_UNICODE_POINT, dColor);
|
|
}
|
|
if (Style_StrGetAlpha(pCurrentStandard->Styles[STY_UNICODE_HOTSPOT].szValue, &iValue, SC_ALPHA_OPAQUE, true)) {
|
|
SciCall_IndicSetAlpha(INDIC_NP3_UNICODE_POINT, iValue);
|
|
}
|
|
if (Style_StrGetAlpha(pCurrentStandard->Styles[STY_UNICODE_HOTSPOT].szValue, &iValue, SC_ALPHA_OPAQUE, false)) {
|
|
SciCall_IndicSetOutlineAlpha(INDIC_NP3_UNICODE_POINT, iValue);
|
|
}
|
|
|
|
iValue = -1; // need for retrieval
|
|
if (!Style_GetIndicatorType(pCurrentStandard->Styles[STY_UNICODE_HOTSPOT].szValue, 0, &iValue)) {
|
|
// got default, get string
|
|
StringCchCatW(pCurrentStandard->Styles[STY_UNICODE_HOTSPOT].szValue, COUNTOF(pCurrentStandard->Styles[0].szValue), L"; ");
|
|
Style_GetIndicatorType(wchStylesBuffer, COUNTOF(wchStylesBuffer), &iValue);
|
|
StringCchCatW(pCurrentStandard->Styles[STY_UNICODE_HOTSPOT].szValue, COUNTOF(pCurrentStandard->Styles[0].szValue), wchStylesBuffer);
|
|
}
|
|
SciCall_IndicSetHoverStyle(INDIC_NP3_UNICODE_POINT, iValue);
|
|
|
|
// Multi Edit Indicator
|
|
if (Style_StrGetColor(pCurrentStandard->Styles[STY_MULTI_EDIT].szValue, FOREGROUND_LAYER, &dColor, NULL, false)) {
|
|
SciCall_IndicSetFore(INDIC_NP3_MULTI_EDIT, dColor);
|
|
}
|
|
if (Style_StrGetAlpha(pCurrentStandard->Styles[STY_MULTI_EDIT].szValue, &iValue, SC_ALPHA_OPAQUE, true)) {
|
|
SciCall_IndicSetAlpha(INDIC_NP3_MULTI_EDIT, iValue);
|
|
}
|
|
if (Style_StrGetAlpha(pCurrentStandard->Styles[STY_MULTI_EDIT].szValue, &iValue, SC_ALPHA_OPAQUE, false)) {
|
|
SciCall_IndicSetOutlineAlpha(INDIC_NP3_MULTI_EDIT, iValue);
|
|
}
|
|
|
|
iValue = -1; // need for retrieval
|
|
if (!Style_GetIndicatorType(pCurrentStandard->Styles[STY_MULTI_EDIT].szValue, 0, &iValue)) {
|
|
// got default, get string
|
|
StringCchCatW(pCurrentStandard->Styles[STY_MULTI_EDIT].szValue, COUNTOF(pCurrentStandard->Styles[0].szValue), L"; ");
|
|
Style_GetIndicatorType(wchStylesBuffer, COUNTOF(wchStylesBuffer), &iValue);
|
|
StringCchCatW(pCurrentStandard->Styles[STY_MULTI_EDIT].szValue, COUNTOF(pCurrentStandard->Styles[0].szValue), wchStylesBuffer);
|
|
}
|
|
|
|
SciCall_IndicSetStyle(INDIC_NP3_MULTI_EDIT, iValue);
|
|
|
|
if (Style_StrGetStrokeWidth(hwnd, INDIC_NP3_MULTI_EDIT, pCurrentStandard->Styles[STY_MULTI_EDIT].szValue, &iValue)) {
|
|
SciCall_IndicSetStrokeWidth(INDIC_NP3_MULTI_EDIT, iValue);
|
|
}
|
|
|
|
// Inline-IME Color
|
|
#define _SC_INDIC_IME_INPUT (INDIC_IME + 0)
|
|
#define _SC_INDIC_IME_TARGET (INDIC_IME + 1)
|
|
#define _SC_INDIC_IME_CONVERTED (INDIC_IME + 2)
|
|
#define _SC_INDIC_IME_UNKNOWN INDIC_IME_MAX
|
|
|
|
COLORREF rgb = RGB(0xFF, 0xA0, 0x00);
|
|
COLORREF rgbWrt = RGB(0xFF, 0xA0, 0x00);
|
|
Style_StrGetColor(pCurrentStandard->Styles[STY_IME_COLOR].szValue, FOREGROUND_LAYER, &rgb, NULL, true); // IME foregr
|
|
SciCall_IndicSetFore(_SC_INDIC_IME_INPUT, rgb);
|
|
SciCall_IndicSetFore(_SC_INDIC_IME_TARGET, rgb);
|
|
SciCall_IndicSetFore(_SC_INDIC_IME_CONVERTED, rgb);
|
|
SciCall_IndicSetFore(_SC_INDIC_IME_UNKNOWN, rgb);
|
|
|
|
if (pLexNew != &lexANSI) {
|
|
Style_SetStyles(hwnd, pCurrentStandard->Styles[STY_CTRL_CHR].iStyle, pCurrentStandard->Styles[STY_CTRL_CHR].szValue, fBaseFontSize); // control char
|
|
}
|
|
Style_SetStyles(hwnd, pCurrentStandard->Styles[STY_INDENT_GUIDE].iStyle, pCurrentStandard->Styles[STY_INDENT_GUIDE].szValue, fBaseFontSize); // indent guide
|
|
|
|
if (Style_StrGetColor(pCurrentStandard->Styles[STY_SEL_TXT].szValue, FOREGROUND_LAYER, &rgb, NULL, false)) { // selection fore
|
|
COLORALPHAREF const argb = RGB2RGBAREF(rgb); // opaque
|
|
SciCall_SetElementColour(SC_ELEMENT_SELECTION_TEXT, argb);
|
|
SciCall_SetElementColour(SC_ELEMENT_SELECTION_SECONDARY_TEXT, argb);
|
|
SciCall_SetElementColour(SC_ELEMENT_SELECTION_INACTIVE_TEXT, argb);
|
|
SciCall_SetElementColour(SC_ELEMENT_SELECTION_ADDITIONAL_TEXT, argb);
|
|
}
|
|
else {
|
|
SciCall_ResetElementColour(SC_ELEMENT_SELECTION_TEXT);
|
|
SciCall_ResetElementColour(SC_ELEMENT_SELECTION_SECONDARY_TEXT);
|
|
SciCall_ResetElementColour(SC_ELEMENT_SELECTION_INACTIVE_TEXT);
|
|
SciCall_ResetElementColour(SC_ELEMENT_SELECTION_ADDITIONAL_TEXT);
|
|
}
|
|
|
|
rgb = RGB(0xC0, 0xC0, 0xC0);
|
|
SciCall_SetSelectionLayer(SC_LAYER_UNDER_TEXT); // selection back
|
|
if (Style_StrGetColor(pCurrentStandard->Styles[STY_SEL_TXT].szValue, BACKGROUND_LAYER, &rgb, NULL, true)) {
|
|
Style_StrGetAlpha(pCurrentStandard->Styles[STY_SEL_TXT].szValue, &iValue, SC_ALPHA_OPAQUE * 2 / 3, true);
|
|
COLORALPHAREF const argb = AxRGB(iValue, rgb);
|
|
SciCall_SetElementColour(SC_ELEMENT_SELECTION_BACK, argb);
|
|
SciCall_SetElementColour(SC_ELEMENT_SELECTION_SECONDARY_BACK, argb);
|
|
SciCall_SetElementColour(SC_ELEMENT_SELECTION_INACTIVE_BACK, argb);
|
|
SciCall_SetElementColour(SC_ELEMENT_SELECTION_ADDITIONAL_BACK, argb);
|
|
}
|
|
else {
|
|
SciCall_ResetElementColour(SC_ELEMENT_SELECTION_BACK);
|
|
SciCall_ResetElementColour(SC_ELEMENT_SELECTION_SECONDARY_BACK);
|
|
SciCall_ResetElementColour(SC_ELEMENT_SELECTION_INACTIVE_BACK);
|
|
SciCall_ResetElementColour(SC_ELEMENT_SELECTION_ADDITIONAL_BACK);
|
|
}
|
|
|
|
// AutoCompletion List
|
|
SciCall_SetElementColour(SC_ELEMENT_LIST, RGB2RGBAREF(GetModeTextColor(UseDarkMode())));
|
|
SciCall_SetElementColour(SC_ELEMENT_LIST_BACK, RGB2RGBAREF(GetModeBkColor(UseDarkMode())));
|
|
//SciCall_SetElementColour(SC_ELEMENT_LIST_SELECTED, SciCall_GetElementBaseColour(SC_ELEMENT_LIST_SELECTED));
|
|
//SciCall_SetElementColour(SC_ELEMENT_LIST_SELECTED_BACK, SciCall_GetElementBaseColour(SC_ELEMENT_LIST_SELECTED_BACK));
|
|
|
|
|
|
// selection eol filled
|
|
bFlag = Style_StrHasAttribute(pCurrentStandard->Styles[STY_SEL_TXT].szValue, FontEffects[FE_EOLFILLED]);
|
|
SciCall_SetSelEOLFilled(bFlag);
|
|
|
|
|
|
// Nonprinting characters
|
|
if (SciCall_GetTechnology() == SC_TECHNOLOGY_DEFAULT) {
|
|
SciCall_ClearAllRepresentations();
|
|
}
|
|
else {
|
|
SciCall_SetRepresentation("\r", "\xE2\x86\x90");
|
|
SciCall_SetRepresentationAppearance("\r", SC_REPRESENTATION_COLOUR);
|
|
SciCall_SetRepresentation("\n", "\xE2\x86\x93");
|
|
SciCall_SetRepresentationAppearance("\n", SC_REPRESENTATION_COLOUR);
|
|
SciCall_SetRepresentation("\r\n", "\xE2\x86\xB2"); // "\xE2\xAE\x92"
|
|
SciCall_SetRepresentationAppearance("\r\n", SC_REPRESENTATION_COLOUR);
|
|
}
|
|
|
|
// whitespace dot size
|
|
wchStylesBuffer[0] = L'\0'; // empty
|
|
|
|
iValue = 2; // default whitespace size
|
|
if (Style_StrGetSizeInt(pCurrentStandard->Styles[STY_WHITESPACE].szValue, &iValue)) {
|
|
iValue = clampi(iValue, 1, 12);
|
|
StringCchPrintf(wchStylesBuffer, COUNTOF(wchStylesBuffer), L"size:%i", iValue);
|
|
}
|
|
Globals.iWhiteSpaceSize = iValue;
|
|
//SciCall_SetWhiteSpaceSize(iValue);
|
|
SciCall_SetWhiteSpaceSize(MulDiv(Globals.iWhiteSpaceSize, NP3_GetZoomPercent(), 100)); // needs update on zoom
|
|
|
|
// whitespace colors
|
|
rgb = RGB(0, 0, 0);
|
|
rgbWrt = rgb;
|
|
if (Style_StrGetColor(pCurrentStandard->Styles[STY_WHITESPACE].szValue, FOREGROUND_LAYER, &rgb, &rgbWrt, false)) {
|
|
Style_PrintfCchColor(wch, COUNTOF(wch), L"; ", FOREGROUND_LAYER, rgbWrt);
|
|
StringCchCat(wchStylesBuffer, COUNTOF(wchStylesBuffer), wch);
|
|
if (Style_StrGetAlpha(pCurrentStandard->Styles[STY_WHITESPACE].szValue, &iValue, SC_ALPHA_OPAQUE, true)) {
|
|
StringCchPrintf(wch, COUNTOF(wch), L"; alpha:%i", iValue);
|
|
StringCchCat(wchStylesBuffer, COUNTOF(wchStylesBuffer), wch);
|
|
}
|
|
SciCall_SetElementColour(SC_ELEMENT_WHITE_SPACE, AxRGB(iValue, rgb));
|
|
SciCall_SetRepresentationColour("\r", AxRGB(iValue, rgb));
|
|
SciCall_SetRepresentationColour("\n", AxRGB(iValue, rgb));
|
|
SciCall_SetRepresentationColour("\r\n", AxRGB(iValue, rgb));
|
|
}
|
|
else {
|
|
SciCall_ResetElementColour(SC_ELEMENT_WHITE_SPACE);
|
|
SciCall_SetRepresentationColour("\r", SciCall_GetElementColour(SC_ELEMENT_WHITE_SPACE));
|
|
SciCall_SetRepresentationColour("\n", SciCall_GetElementColour(SC_ELEMENT_WHITE_SPACE));
|
|
SciCall_SetRepresentationColour("\r\n", SciCall_GetElementColour(SC_ELEMENT_WHITE_SPACE));
|
|
}
|
|
|
|
rgb = RGB(0, 0, 0);
|
|
rgbWrt = rgb;
|
|
if (Style_StrGetColor(pCurrentStandard->Styles[STY_WHITESPACE].szValue, BACKGROUND_LAYER, &rgb, &rgbWrt, true)) {
|
|
Style_PrintfCchColor(wch, COUNTOF(wch), L"; ", FOREGROUND_LAYER, rgbWrt);
|
|
StringCchCat(wchStylesBuffer, COUNTOF(wchStylesBuffer), wch);
|
|
|
|
//~ always opaque, no translucency possible in Win32
|
|
//~if (Style_StrGetAlpha(pCurrentStandard->Styles[STY_WHITESPACE].szValue, &iValue, SC_ALPHA_OPAQUE, false)) {
|
|
//~ StringCchPrintf(wch, COUNTOF(wch), L"; alpha2:%i", iValue);
|
|
//~ StringCchCat(wchStylesBuffer, COUNTOF(wchStylesBuffer), wch);
|
|
//~}
|
|
SciCall_SetElementColour(SC_ELEMENT_WHITE_SPACE_BACK, RGB2RGBAREF(rgb));
|
|
}
|
|
else {
|
|
SciCall_ResetElementColour(SC_ELEMENT_WHITE_SPACE_BACK);
|
|
}
|
|
|
|
StrTrim(wchStylesBuffer, L" ;");
|
|
StringCchCopy(pCurrentStandard->Styles[STY_WHITESPACE].szValue,
|
|
COUNTOF(pCurrentStandard->Styles[STY_WHITESPACE].szValue), wchStylesBuffer);
|
|
|
|
|
|
// current line background
|
|
Style_HighlightCurrentLine(hwnd, Settings.HighlightCurrentLine);
|
|
|
|
// Hyperlink (URL) indicators
|
|
Style_SetUrlHotSpot(hwnd);
|
|
|
|
// caret style and width
|
|
wchStylesBuffer[0] = L'\0';
|
|
int const ovrstrk_mode = (StrStr(pCurrentStandard->Styles[STY_CARET].szValue, L"ovrblck")) ? CARETSTYLE_OVERSTRIKE_BLOCK : CARETSTYLE_OVERSTRIKE_BAR;
|
|
|
|
if (StrStr(pCurrentStandard->Styles[STY_CARET].szValue, L"block")) {
|
|
StringCchCat(wchStylesBuffer, COUNTOF(wchStylesBuffer), L"; block");
|
|
SciCall_SetCaretStyle(CARETSTYLE_BLOCK | ovrstrk_mode);
|
|
} else {
|
|
SciCall_SetCaretStyle(CARETSTYLE_LINE | ovrstrk_mode);
|
|
|
|
iValue = 1; // don't allow invisible 0
|
|
if (Style_StrGetSizeInt(pCurrentStandard->Styles[STY_CARET].szValue, &iValue)) {
|
|
iValue = clampi(iValue, 1, 20);
|
|
if (iValue != 1) {
|
|
StringCchPrintf(wch, COUNTOF(wch), L"; size:%i", iValue);
|
|
StringCchCat(wchStylesBuffer, COUNTOF(wchStylesBuffer), wch);
|
|
}
|
|
}
|
|
SciCall_SetCaretWidth(iValue);
|
|
}
|
|
|
|
if (CARETSTYLE_OVERSTRIKE_BLOCK == ovrstrk_mode) {
|
|
StringCchCat(wchStylesBuffer, COUNTOF(wchStylesBuffer), L"; ovrblck");
|
|
}
|
|
|
|
if (StrStr(pCurrentStandard->Styles[STY_CARET].szValue,L"noblink")) {
|
|
SciCall_SetCaretPeriod(0);
|
|
SciCall_SetAdditionalCaretsBlink(false);
|
|
StringCchCat(wchStylesBuffer,COUNTOF(wchStylesBuffer),L"; noblink");
|
|
} else {
|
|
const UINT uCaretBlinkTime = GetCaretBlinkTime();
|
|
SciCall_SetCaretPeriod(uCaretBlinkTime);
|
|
SciCall_SetAdditionalCaretsBlink(uCaretBlinkTime != 0);
|
|
}
|
|
// caret fore
|
|
rgb = GetModeTextColor(UseDarkMode());
|
|
rgbWrt = rgb;
|
|
if (Style_StrGetColor(pCurrentStandard->Styles[STY_CARET].szValue, FOREGROUND_LAYER, &rgb, &rgbWrt, false)) {
|
|
Style_PrintfCchColor(wch, COUNTOF(wch), L"; ", FOREGROUND_LAYER, rgbWrt);
|
|
StringCchCat(wchStylesBuffer,COUNTOF(wchStylesBuffer),wch);
|
|
}
|
|
if (!VerifyContrast(rgb, SciCall_StyleGetBack(0))) {
|
|
rgb = SciCall_StyleGetFore(0);
|
|
}
|
|
|
|
if (Style_StrGetAlpha(pCurrentStandard->Styles[STY_CARET].szValue, &iValue, SC_ALPHA_OPAQUE, true)) {
|
|
iValue = clampi(iValue, 20, SC_ALPHA_OPAQUE); // no full transparency
|
|
StringCchPrintf(wch, COUNTOF(wch), L"; alpha:%i", iValue);
|
|
StringCchCat(wchStylesBuffer, COUNTOF(wchStylesBuffer), wch);
|
|
}
|
|
SciCall_SetElementColour(SC_ELEMENT_CARET, AxRGB(iValue, rgb));
|
|
SciCall_SetElementColour(SC_ELEMENT_CARET_ADDITIONAL, AxRGB(iValue, RGB(220, 0, 0)));
|
|
|
|
StrTrim(wchStylesBuffer, L" ;");
|
|
StringCchCopy(pCurrentStandard->Styles[STY_CARET].szValue,
|
|
COUNTOF(pCurrentStandard->Styles[STY_CARET].szValue),wchStylesBuffer);
|
|
|
|
int edgeColumns[EDGELINE_NUM_LIMIT] = { 0 };
|
|
size_t const cnt = ReadVectorFromString(Globals.fvCurFile.wchMultiEdgeLines, edgeColumns, COUNTOF(edgeColumns), 0, LONG_LINES_MARKER_LIMIT, 0, true);
|
|
Style_SetMultiEdgeLine(edgeColumns, cnt);
|
|
|
|
|
|
int iLnSpc = 0;
|
|
if (Style_StrGetSizeIntEx(pCurrentStandard->Styles[STY_X_LN_SPACE].szValue, &iLnSpc)) {
|
|
Style_SetExtraLineSpace(iLnSpc);
|
|
}
|
|
else {
|
|
Style_SetExtraLineSpace(0);
|
|
}
|
|
|
|
if (SciCall_GetIndentationGuides() != SC_IV_NONE) {
|
|
Style_SetIndentGuides(hwnd, true);
|
|
}
|
|
|
|
// (!) here: global define current lexer (used in subsequent calls)
|
|
// --------------------------------------------------------------------
|
|
s_pLexCurrent = pLexNew;
|
|
// --------------------------------------------------------------------
|
|
|
|
if (s_pLexCurrent == &lexANSI) { // special ANSI-Art style
|
|
|
|
// margin (line number, bookmarks, folding) style
|
|
StringCchCopy(wchStylesBuffer, COUNTOF(wchStylesBuffer), s_pLexCurrent->Styles[STY_MARGIN].szValue);
|
|
Style_CopyStyles_IfNotDefined(pCurrentStandard->Styles[STY_MARGIN].szValue, wchStylesBuffer, COUNTOF(wchStylesBuffer));
|
|
Style_SetMargin(hwnd, wchStylesBuffer);
|
|
|
|
if (Settings2.UseOldStyleBraceMatching) {
|
|
Style_SetStyles(hwnd, pCurrentStandard->Styles[STY_BRACE_OK].iStyle,
|
|
pCurrentStandard->Styles[STY_BRACE_OK].szValue, fBaseFontSize);
|
|
|
|
Style_SetStyles(hwnd, pCurrentStandard->Styles[STY_BRACE_BAD].iStyle,
|
|
pCurrentStandard->Styles[STY_BRACE_BAD].szValue, fBaseFontSize);
|
|
}
|
|
|
|
iLnSpc = 0; // do not inherit from base
|
|
if (Style_StrGetSizeIntEx(s_pLexCurrent->Styles[4].szValue, &iLnSpc)) {
|
|
Style_SetExtraLineSpace(iLnSpc);
|
|
}
|
|
}
|
|
else if (s_pLexCurrent == &lexTEXT) {
|
|
|
|
// margin (line number, bookmarks, folding) style
|
|
StringCchCopy(wchStylesBuffer, COUNTOF(wchStylesBuffer), s_pLexCurrent->Styles[STY_MARGIN].szValue);
|
|
Style_CopyStyles_IfNotDefined(pCurrentStandard->Styles[STY_MARGIN].szValue, wchStylesBuffer, COUNTOF(wchStylesBuffer));
|
|
Style_SetMargin(hwnd, wchStylesBuffer);
|
|
|
|
iLnSpc = (SciCall_GetExtraAscent() + SciCall_GetExtraDescent()) >> 1; // inherit from base
|
|
if (Style_StrGetSizeIntEx(s_pLexCurrent->Styles[2].szValue, &iLnSpc)) {
|
|
Style_SetExtraLineSpace(iLnSpc);
|
|
}
|
|
|
|
} else if (s_pLexCurrent->lexerID != SCLEX_NULL) {
|
|
|
|
Style_FillRelatedStyles(hwnd, s_pLexCurrent);
|
|
}
|
|
|
|
// Lexer reserved indicator styles
|
|
switch (s_pLexCurrent->lexerID) {
|
|
case SCLEX_PYTHON:
|
|
SciCall_IndicSetStyle(1, INDIC_BOX);
|
|
SciCall_IndicSetFore(1, RGB(0xBF, 0, 0)); // (light red)
|
|
//SciCall_IndicSetAlpha(1, 40);
|
|
//SciCall_IndicSetOutlineAlpha(1, 100);
|
|
break;
|
|
|
|
default:
|
|
//SciCall_IndicSetStyle(0, INDIC_SQUIGGLE);
|
|
//SciCall_IndicSetStyle(1, INDIC_TT);
|
|
//SciCall_IndicSetStyle(2, INDIC_PLAIN);
|
|
//SciCall_IndicSetFore(0, RGB(0, 0x7F, 0)); // (dark green)
|
|
//SciCall_IndicSetFore(1, RGB(0, 0, 0xFF)); // (light blue)
|
|
//SciCall_IndicSetFore(2, RGB(0xBF, 0, 0)); // (light red)
|
|
//for (int sty = 3; sty < INDIC_CONTAINER; ++sty) {
|
|
// SciCall_IndicSetStyle(sty, INDIC_ROUNDBOX);
|
|
//}
|
|
break;
|
|
}
|
|
|
|
Style_SetInvisible(hwnd, false); // set fixed invisible style
|
|
|
|
// EditLoadFile() sets SC_CACHE_DOCUMENT for small files (<=2MB) — don't override that
|
|
if (Flags.bHugeFileLoadState) {
|
|
SciCall_SetLayoutCache(SC_CACHE_PAGE);
|
|
}
|
|
SciCall_SetPositionCache(SciCall_GetPositionCache()); // clear - default=1024
|
|
|
|
Sci_SetWrapModeEx(GET_WRAP_MODE());
|
|
|
|
SciCall_StartStyling(0);
|
|
//~SciCall_Colourise(0, -1);
|
|
|
|
// apply lexer styles
|
|
if (Flags.bHugeFileLoadState) {
|
|
EditUpdateVisibleIndicators();
|
|
} else {
|
|
EditUpdateIndicators(0, -1, false);
|
|
}
|
|
|
|
Style_UpdateAllMargins(hwnd, true);
|
|
|
|
if (Flags.bHugeFileLoadState) {
|
|
SciCall_SetIdleStyling(SC_IDLESTYLING_TOVISIBLE);
|
|
} else if (SciCall_GetTextLength() > (2 * 1024 * 1024)) {
|
|
SciCall_SetIdleStyling(SC_IDLESTYLING_AFTERVISIBLE);
|
|
} else {
|
|
SciCall_SetIdleStyling(idleStylingMode);
|
|
}
|
|
|
|
if (bFocusedView) {
|
|
EditToggleView(hwnd);
|
|
}
|
|
|
|
Sci_ScrollSelectionToView();
|
|
|
|
EndWaitCursor();
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_FillRelatedStyles()
|
|
//
|
|
void Style_FillRelatedStyles(HWND hwnd, const PEDITLEXER pLexer) {
|
|
|
|
//bool const bIsLexerStd = IsLexerStandard(pLexer);
|
|
|
|
float fBaseFontSize = IsLexerStandard(pLexer) ? GLOBAL_INITIAL_FONTSIZE : Style_GetBaseFontSize();
|
|
Style_StrGetSizeFloatEx(pLexer->Styles[STY_DEFAULT].szValue, &fBaseFontSize);
|
|
|
|
// -----------------------------------------------
|
|
int i = 1; // don't re-apply lexer's default style
|
|
// -----------------------------------------------
|
|
while (pLexer->Styles[i].iStyle != -1) {
|
|
|
|
// apply MULTI_STYLE() MACRO
|
|
for (int j = 0; j < 4 && (pLexer->Styles[i].iStyle8[j] != 0 || j == 0); ++j) {
|
|
Style_SetStyles(hwnd, pLexer->Styles[i].iStyle8[j], pLexer->Styles[i].szValue, fBaseFontSize);
|
|
}
|
|
|
|
if (pLexer->lexerID == SCLEX_HTML && pLexer->Styles[i].iStyle8[0] == SCE_HPHP_DEFAULT) {
|
|
int iRelated[] = { SCE_HPHP_COMMENT, SCE_HPHP_COMMENTLINE, SCE_HPHP_WORD, SCE_HPHP_HSTRING, SCE_HPHP_SIMPLESTRING, SCE_HPHP_NUMBER,
|
|
SCE_HPHP_OPERATOR, SCE_HPHP_VARIABLE, SCE_HPHP_HSTRING_VARIABLE, SCE_HPHP_COMPLEX_VARIABLE };
|
|
for (int j = 0; j < COUNTOF(iRelated); j++) {
|
|
Style_SetStyles(hwnd, iRelated[j], pLexer->Styles[i].szValue, fBaseFontSize);
|
|
}
|
|
}
|
|
|
|
if (pLexer->lexerID == SCLEX_HTML && pLexer->Styles[i].iStyle8[0] == SCE_HJ_DEFAULT) {
|
|
int iRelated[] = { SCE_HJ_COMMENT, SCE_HJ_COMMENTLINE, SCE_HJ_COMMENTDOC, SCE_HJ_KEYWORD, SCE_HJ_WORD, SCE_HJ_DOUBLESTRING,
|
|
SCE_HJ_SINGLESTRING, SCE_HJ_STRINGEOL, SCE_HJ_REGEX, SCE_HJ_NUMBER, SCE_HJ_SYMBOLS };
|
|
for (int j = 0; j < COUNTOF(iRelated); j++) {
|
|
Style_SetStyles(hwnd, iRelated[j], pLexer->Styles[i].szValue, fBaseFontSize);
|
|
}
|
|
}
|
|
|
|
if (pLexer->lexerID == SCLEX_HTML && pLexer->Styles[i].iStyle8[0] == SCE_HJA_DEFAULT) {
|
|
int iRelated[] = { SCE_HJA_COMMENT, SCE_HJA_COMMENTLINE, SCE_HJA_COMMENTDOC, SCE_HJA_KEYWORD, SCE_HJA_WORD, SCE_HJA_DOUBLESTRING,
|
|
SCE_HJA_SINGLESTRING, SCE_HJA_STRINGEOL, SCE_HJA_REGEX, SCE_HJA_NUMBER, SCE_HJA_SYMBOLS };
|
|
for (int j = 0; j < COUNTOF(iRelated); j++) {
|
|
Style_SetStyles(hwnd, iRelated[j], pLexer->Styles[i].szValue, fBaseFontSize);
|
|
}
|
|
}
|
|
|
|
if (pLexer->lexerID == SCLEX_HTML && pLexer->Styles[i].iStyle8[0] == SCE_HB_DEFAULT) {
|
|
int iRelated[] = { SCE_HB_COMMENTLINE, SCE_HB_WORD, SCE_HB_IDENTIFIER, SCE_HB_STRING, SCE_HB_STRINGEOL, SCE_HB_NUMBER };
|
|
for (int j = 0; j < COUNTOF(iRelated); j++) {
|
|
Style_SetStyles(hwnd, iRelated[j], pLexer->Styles[i].szValue, fBaseFontSize);
|
|
}
|
|
}
|
|
|
|
if (pLexer->lexerID == SCLEX_HTML && pLexer->Styles[i].iStyle8[0] == SCE_HBA_DEFAULT) {
|
|
int iRelated[] = { SCE_HBA_COMMENTLINE, SCE_HBA_WORD, SCE_HBA_IDENTIFIER, SCE_HBA_STRING, SCE_HBA_STRINGEOL, SCE_HBA_NUMBER };
|
|
for (int j = 0; j < COUNTOF(iRelated); j++) {
|
|
Style_SetStyles(hwnd, iRelated[j], pLexer->Styles[i].szValue, fBaseFontSize);
|
|
}
|
|
}
|
|
|
|
if ((pLexer->lexerID == SCLEX_HTML || pLexer->lexerID == SCLEX_XML) && pLexer->Styles[i].iStyle8[0] == SCE_H_SGML_DEFAULT) {
|
|
int iRelated[] = { SCE_H_SGML_COMMAND, SCE_H_SGML_1ST_PARAM, SCE_H_SGML_DOUBLESTRING, SCE_H_SGML_SIMPLESTRING, SCE_H_SGML_ERROR,
|
|
SCE_H_SGML_SPECIAL, SCE_H_SGML_ENTITY, SCE_H_SGML_COMMENT, SCE_H_SGML_1ST_PARAM_COMMENT, SCE_H_SGML_BLOCK_DEFAULT };
|
|
for (int j = 0; j < COUNTOF(iRelated); j++) {
|
|
Style_SetStyles(hwnd, iRelated[j], pLexer->Styles[i].szValue, fBaseFontSize);
|
|
}
|
|
}
|
|
|
|
if ((pLexer->lexerID == SCLEX_HTML || pLexer->lexerID == SCLEX_XML) && pLexer->Styles[i].iStyle8[0] == SCE_H_CDATA) {
|
|
int iRelated[] = { SCE_HP_START, SCE_HP_DEFAULT, SCE_HP_COMMENTLINE, SCE_HP_NUMBER, SCE_HP_STRING,
|
|
SCE_HP_CHARACTER, SCE_HP_WORD, SCE_HP_TRIPLE, SCE_HP_TRIPLEDOUBLE, SCE_HP_CLASSNAME,
|
|
SCE_HP_DEFNAME, SCE_HP_OPERATOR, SCE_HP_IDENTIFIER, SCE_HPA_START, SCE_HPA_DEFAULT,
|
|
SCE_HPA_COMMENTLINE, SCE_HPA_NUMBER, SCE_HPA_STRING, SCE_HPA_CHARACTER, SCE_HPA_WORD,
|
|
SCE_HPA_TRIPLE, SCE_HPA_TRIPLEDOUBLE, SCE_HPA_CLASSNAME, SCE_HPA_DEFNAME, SCE_HPA_OPERATOR,
|
|
SCE_HPA_IDENTIFIER };
|
|
for (int j = 0; j < COUNTOF(iRelated); j++) {
|
|
Style_SetStyles(hwnd, iRelated[j], pLexer->Styles[i].szValue, fBaseFontSize);
|
|
}
|
|
}
|
|
|
|
if (pLexer->lexerID == SCLEX_XML && pLexer->Styles[i].iStyle8[0] == SCE_H_CDATA) {
|
|
int iRelated[] = { SCE_H_SCRIPT, SCE_H_ASP, SCE_H_ASPAT, SCE_H_QUESTION,
|
|
SCE_HPHP_DEFAULT, SCE_HPHP_COMMENT, SCE_HPHP_COMMENTLINE, SCE_HPHP_WORD, SCE_HPHP_HSTRING,
|
|
SCE_HPHP_SIMPLESTRING, SCE_HPHP_NUMBER, SCE_HPHP_OPERATOR, SCE_HPHP_VARIABLE,
|
|
SCE_HPHP_HSTRING_VARIABLE, SCE_HPHP_COMPLEX_VARIABLE, SCE_HJ_START, SCE_HJ_DEFAULT,
|
|
SCE_HJ_COMMENT, SCE_HJ_COMMENTLINE, SCE_HJ_COMMENTDOC, SCE_HJ_KEYWORD, SCE_HJ_WORD,
|
|
SCE_HJ_DOUBLESTRING, SCE_HJ_SINGLESTRING, SCE_HJ_STRINGEOL, SCE_HJ_REGEX, SCE_HJ_NUMBER,
|
|
SCE_HJ_SYMBOLS, SCE_HJA_START, SCE_HJA_DEFAULT, SCE_HJA_COMMENT, SCE_HJA_COMMENTLINE,
|
|
SCE_HJA_COMMENTDOC, SCE_HJA_KEYWORD, SCE_HJA_WORD, SCE_HJA_DOUBLESTRING, SCE_HJA_SINGLESTRING,
|
|
SCE_HJA_STRINGEOL, SCE_HJA_REGEX, SCE_HJA_NUMBER, SCE_HJA_SYMBOLS, SCE_HB_START, SCE_HB_DEFAULT,
|
|
SCE_HB_COMMENTLINE, SCE_HB_WORD, SCE_HB_IDENTIFIER, SCE_HB_STRING, SCE_HB_STRINGEOL,
|
|
SCE_HB_NUMBER, SCE_HBA_START, SCE_HBA_DEFAULT, SCE_HBA_COMMENTLINE, SCE_HBA_WORD,
|
|
SCE_HBA_IDENTIFIER, SCE_HBA_STRING, SCE_HBA_STRINGEOL, SCE_HBA_NUMBER, SCE_HP_START,
|
|
SCE_HP_DEFAULT, SCE_HP_COMMENTLINE, SCE_HP_NUMBER, SCE_HP_STRING, SCE_HP_CHARACTER, SCE_HP_WORD,
|
|
SCE_HP_TRIPLE, SCE_HP_TRIPLEDOUBLE, SCE_HP_CLASSNAME, SCE_HP_DEFNAME, SCE_HP_OPERATOR,
|
|
SCE_HP_IDENTIFIER, SCE_HPA_START, SCE_HPA_DEFAULT, SCE_HPA_COMMENTLINE, SCE_HPA_NUMBER,
|
|
SCE_HPA_STRING, SCE_HPA_CHARACTER, SCE_HPA_WORD, SCE_HPA_TRIPLE, SCE_HPA_TRIPLEDOUBLE,
|
|
SCE_HPA_CLASSNAME, SCE_HPA_DEFNAME, SCE_HPA_OPERATOR, SCE_HPA_IDENTIFIER };
|
|
|
|
for (int j = 0; j < COUNTOF(iRelated); j++) {
|
|
Style_SetStyles(hwnd, iRelated[j], pLexer->Styles[i].szValue, fBaseFontSize);
|
|
}
|
|
}
|
|
|
|
if (pLexer->lexerID == SCLEX_CPP && pLexer->Styles[i].iStyle8[0] == SCE_C_STRING) {
|
|
int iRelated[] = { SCE_C_CHARACTER, SCE_C_STRINGEOL, SCE_C_VERBATIM, SCE_C_STRINGRAW, SCE_C_HASHQUOTEDSTRING };
|
|
for (int j = 0; j < COUNTOF(iRelated); j++) {
|
|
Style_SetStyles(hwnd, iRelated[j], pLexer->Styles[i].szValue, fBaseFontSize);
|
|
}
|
|
}
|
|
|
|
if (pLexer->lexerID == SCLEX_SQL && pLexer->Styles[i].iStyle8[0] == SCE_SQL_COMMENT) {
|
|
int iRelated[] = { SCE_SQL_COMMENTLINE, SCE_SQL_COMMENTDOC, SCE_SQL_COMMENTLINEDOC, SCE_SQL_COMMENTDOCKEYWORD, SCE_SQL_COMMENTDOCKEYWORDERROR };
|
|
for (int j = 0; j < COUNTOF(iRelated); j++) {
|
|
Style_SetStyles(hwnd, iRelated[j], pLexer->Styles[i].szValue, fBaseFontSize);
|
|
}
|
|
}
|
|
++i;
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetUrlHotSpot()
|
|
//
|
|
void Style_SetUrlHotSpot(HWND hwnd)
|
|
{
|
|
UNREFERENCED_PARAMETER(hwnd);
|
|
|
|
WCHAR* lpszStyleHotSpot = GetCurrentStdLexer()->Styles[STY_URL_HOTSPOT].szValue;
|
|
int const cCount = COUNTOF(GetCurrentStdLexer()->Styles[STY_URL_HOTSPOT].szValue);
|
|
|
|
int indicHoverStyle = -1; // need for retrieval
|
|
if (!Style_GetIndicatorType(lpszStyleHotSpot, cCount, &indicHoverStyle)) {
|
|
// got default, get string
|
|
WCHAR wchSpecificStyle[80] = { L'\0' };
|
|
StringCchCatW(lpszStyleHotSpot, cCount, L"; ");
|
|
Style_GetIndicatorType(wchSpecificStyle, COUNTOF(wchSpecificStyle), &indicHoverStyle);
|
|
StringCchCatW(lpszStyleHotSpot, cCount, wchSpecificStyle);
|
|
}
|
|
|
|
COLORREF activeFG = RGB(0x00, 0x00, 0xE0);
|
|
Style_StrGetColor(lpszStyleHotSpot, FOREGROUND_LAYER, &activeFG, NULL, false);
|
|
|
|
COLORREF inactiveFG = RGB(0x00, 0x60, 0xB0);
|
|
Style_StrGetColor(lpszStyleHotSpot, BACKGROUND_LAYER, &inactiveFG, NULL, false);
|
|
|
|
int iValue;
|
|
Style_StrGetAlpha(lpszStyleHotSpot, &iValue, SC_ALPHA_OPAQUE, true);
|
|
SciCall_IndicSetAlpha(INDIC_NP3_HYPERLINK_U, iValue);
|
|
|
|
Style_StrGetAlpha(lpszStyleHotSpot, &iValue, SC_ALPHA_OPAQUE, false); // alpha2:
|
|
SciCall_IndicSetOutlineAlpha(INDIC_NP3_HYPERLINK_U, iValue);
|
|
|
|
// normal (fix)
|
|
SciCall_IndicSetStyle(INDIC_NP3_HYPERLINK, INDIC_TEXTFORE);
|
|
SciCall_IndicSetFore(INDIC_NP3_HYPERLINK, inactiveFG);
|
|
SciCall_IndicSetStyle(INDIC_NP3_HYPERLINK_U, INDIC_PLAIN);
|
|
SciCall_IndicSetFore(INDIC_NP3_HYPERLINK_U, inactiveFG);
|
|
// hover (stylish)
|
|
SciCall_IndicSetHoverStyle(INDIC_NP3_HYPERLINK, INDIC_TEXTFORE);
|
|
SciCall_IndicSetHoverFore(INDIC_NP3_HYPERLINK, activeFG);
|
|
SciCall_IndicSetHoverStyle(INDIC_NP3_HYPERLINK_U, indicHoverStyle);
|
|
SciCall_IndicSetHoverFore(INDIC_NP3_HYPERLINK_U, activeFG);
|
|
|
|
// style for hotspot
|
|
//~SciCall_StyleSetHotspot(_STYLE_GETSTYLEID(STY_URL_HOTSPOT), true);
|
|
//~SciCall_SetHotspotActiveUnderline(false);
|
|
//~SciCall_SetHotspotSingleLine(true);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetInvisible()
|
|
//
|
|
void Style_SetInvisible(HWND hwnd, bool bInvisible)
|
|
{
|
|
UNREFERENCED_PARAMETER(hwnd);
|
|
//SendMessage(hwnd, SCI_FOLDDISPLAYTEXTSETSTYLE, (WPARAM)SC_FOLDDISPLAYTEXT_BOXED, 0);
|
|
//SciCall_MarkerDefine(MARKER_NP3_OCCUR_LINE, SC_MARK_EMPTY); // occurrences marker
|
|
if (bInvisible) {
|
|
SciCall_StyleSetVisible(Style_GetInvisibleStyleID(), !bInvisible);
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
//=============================================================================
|
|
//
|
|
// Style_SetReadonly()
|
|
//
|
|
void Style_SetReadonly(HWND hwnd, bool bReadonly)
|
|
{
|
|
UNREFERENCED_PARAMETER(hwnd);
|
|
SciCall_StyleSetChangeable(Style_GetReadonlyStyleID(), !bReadonly);
|
|
}
|
|
#endif
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetMultiEdgeLine()
|
|
//
|
|
void Style_SetMultiEdgeLine(const int colVec[], const size_t count)
|
|
{
|
|
COLORREF rgb;
|
|
|
|
int const iLongLineLimit = (count > 0) ? colVec[count - 1] : Settings.LongLinesLimit;
|
|
int const mLongLineMode = (count > 1) ? EDGE_MULTILINE : Settings.LongLineMode;
|
|
|
|
Settings.LongLinesLimit = iLongLineLimit; // normalize
|
|
Globals.iWrapCol = iLongLineLimit; // long line limit should be explicit wrap column too
|
|
|
|
if (mLongLineMode == EDGE_BACKGROUND) {
|
|
if (!Style_StrGetColor(GetCurrentStdLexer()->Styles[STY_LONG_LN_MRK].szValue, BACKGROUND_LAYER, &rgb, NULL, false)) { // edge back
|
|
rgb = GetSysColor(COLOR_3DSHADOW);
|
|
}
|
|
} else {
|
|
if (!Style_StrGetColor(GetCurrentStdLexer()->Styles[STY_LONG_LN_MRK].szValue, FOREGROUND_LAYER, &rgb, NULL, false)) { // edge fore
|
|
rgb = GetSysColor(COLOR_3DLIGHT);
|
|
}
|
|
}
|
|
if (Settings.MarkLongLines) {
|
|
switch (mLongLineMode) {
|
|
case EDGE_LINE:
|
|
case EDGE_BACKGROUND:
|
|
SciCall_SetEdgeMode(mLongLineMode);
|
|
SciCall_SetEdgeColour(rgb);
|
|
SciCall_SetEdgeColumn(iLongLineLimit);
|
|
break;
|
|
case EDGE_MULTILINE:
|
|
SciCall_SetEdgeMode(mLongLineMode);
|
|
SciCall_MultiEdgeClearAll();
|
|
for (size_t i = 0; i < count; ++i) {
|
|
SciCall_MultiEdgeAddLine(colVec[i], rgb);
|
|
}
|
|
break;
|
|
default:
|
|
SciCall_SetEdgeMode(EDGE_NONE);
|
|
break;
|
|
}
|
|
} else {
|
|
SciCall_SetEdgeMode(EDGE_NONE);
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_HighlightCurrentLine()
|
|
//
|
|
void Style_HighlightCurrentLine(HWND hwnd, int iHiLitCurLn)
|
|
{
|
|
bool const bHiLitAsBckgr = (iHiLitCurLn == 1);
|
|
bool const bHiLitAsFrame = (iHiLitCurLn == 2);
|
|
|
|
if (!(bHiLitAsBckgr || bHiLitAsFrame)) {
|
|
// clear all
|
|
SciCall_SetCaretLineFrame(0);
|
|
SciCall_SetCaretLineLayer(SC_LAYER_UNDER_TEXT);
|
|
SciCall_SetElementColour(SC_ELEMENT_CARET_LINE_BACK, AxRGB(SC_ALPHA_TRANSPARENT, RGB(0x00, 0x00, 0x00)));
|
|
//~SciCall_SetCaretLineHighlightSubline(false);
|
|
return;
|
|
}
|
|
|
|
LPCWSTR szValue = GetCurrentStdLexer()->Styles[STY_CUR_LN].szValue;
|
|
|
|
int alpha = SC_ALPHA_NOALPHA;
|
|
Style_StrGetAlpha(szValue, &alpha, 50, true);
|
|
|
|
int alpha2 = SC_ALPHA_NOALPHA;
|
|
Style_StrGetAlpha(szValue, &alpha2, 50, false);
|
|
|
|
COLORREF const rgbDefault = (bHiLitAsBckgr ? RGB(0xFF, 0xFF, 0x00) : RGB(0xA0, 0xA0, 0xA0));
|
|
|
|
COLORREF foreRGB = rgbDefault;
|
|
bool const hasFGDef = Style_StrGetColor(szValue, FOREGROUND_LAYER, &foreRGB, NULL, false);
|
|
|
|
COLORREF backgrRGB = rgbDefault;
|
|
Style_StrGetColor(szValue, BACKGROUND_LAYER, &backgrRGB, NULL, false);
|
|
|
|
if (hasFGDef && (alpha != SC_ALPHA_TRANSPARENT)) { // visible foreground layer
|
|
SciCall_SetCaretLineLayer(SC_LAYER_OVER_TEXT);
|
|
SciCall_SetElementColour(SC_ELEMENT_CARET_LINE_BACK, AxRGB(alpha, foreRGB));
|
|
}
|
|
else {
|
|
SciCall_SetCaretLineLayer(SC_LAYER_UNDER_TEXT);
|
|
SciCall_SetElementColour(SC_ELEMENT_CARET_LINE_BACK, AxRGB(alpha2, backgrRGB));
|
|
}
|
|
|
|
if (bHiLitAsFrame) {
|
|
int iFrameSize = 0;
|
|
if (!Style_StrGetSizeInt(szValue, &iFrameSize)) {
|
|
iFrameSize = 2;
|
|
}
|
|
iFrameSize = max_i(1, ScaleIntToDPI(hwnd, iFrameSize));
|
|
Globals.iCaretOutLineFrameSize = iFrameSize;
|
|
// SciCall_SetCaretLineFrame(iFrameSize);
|
|
SciCall_SetCaretLineFrame(MulDiv(Globals.iCaretOutLineFrameSize, NP3_GetZoomPercent(), 100)); // needs update on zoom
|
|
}
|
|
else {
|
|
SciCall_SetCaretLineFrame(0);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_UpdateLineNumberMargin()
|
|
//
|
|
void Style_UpdateLineNumberMargin(const bool bForce)
|
|
{
|
|
static bool bShowLnNums = false;
|
|
static DocLn prevLineCount = -1LL;
|
|
|
|
DocLn const currLineCount = SciCall_GetLineCount();
|
|
|
|
if (!bForce && (currLineCount == prevLineCount) && (bShowLnNums == Settings.ShowLineNumbers)) {
|
|
return;
|
|
}
|
|
|
|
if (Settings.ShowLineNumbers) {
|
|
static char chLines[32] = { '\0' };
|
|
StringCchPrintfA(chLines, COUNTOF(chLines), "_%td", (size_t)currLineCount);
|
|
int const iLineMarginWidthFit = SciCall_TextWidth(STYLE_LINENUMBER, chLines);
|
|
int const iLineMarginWidthNow = SciCall_GetMarginWidthN(MARGIN_SCI_LINENUM);
|
|
if (iLineMarginWidthNow != iLineMarginWidthFit) {
|
|
SciCall_SetMarginWidthN(MARGIN_SCI_LINENUM, iLineMarginWidthFit);
|
|
}
|
|
}
|
|
else {
|
|
SciCall_SetMarginWidthN(MARGIN_SCI_LINENUM, 0);
|
|
}
|
|
|
|
bShowLnNums = Settings.ShowLineNumbers;
|
|
prevLineCount = currLineCount;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// _GetMarkerMarginWidth()
|
|
//
|
|
static int _GetMarkerMarginWidth(HWND hwnd, LPCWSTR styleStrg, const float fScale)
|
|
{
|
|
UNREFERENCED_PARAMETER(hwnd);
|
|
float fSize = (float)SciCall_TextWidth(STYLE_LINENUMBER, "__"); // 2x underscore
|
|
Style_StrGetSizeFloatEx(styleStrg, &fSize);
|
|
return lroundf(fSize * fScale);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_UpdateBookmarkMargin()
|
|
//
|
|
void Style_UpdateBookmarkMargin(HWND hwnd)
|
|
{
|
|
int const size = _GetMarkerMarginWidth(hwnd, GetCurrentStdLexer()->Styles[STY_BOOK_MARK].szValue, 1.0f);
|
|
SciCall_SetMarginWidthN(MARGIN_SCI_BOOKMRK, (Settings.ShowBookmarkMargin ? size : 0));
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_UpdateChangeHistoryMargin()
|
|
//
|
|
void Style_UpdateChangeHistoryMargin(HWND hwnd)
|
|
{
|
|
int const size = _GetMarkerMarginWidth(hwnd, GetCurrentStdLexer()->Styles[STY_BOOK_MARK].szValue, 1.0f);
|
|
bool const bShowMargin = (Settings.ChangeHistoryMode & SC_CHANGE_HISTORY_MARKERS);
|
|
SciCall_SetMarginWidthN(MARGIN_SCI_CHGHIST, (bShowMargin ? size : 0));
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_UpdateFoldingMargin()
|
|
//
|
|
void Style_UpdateFoldingMargin(HWND hwnd, bool bShowMargin)
|
|
{
|
|
int const size = _GetMarkerMarginWidth(hwnd, GetCurrentStdLexer()->Styles[STY_BOOK_MARK].szValue, 0.8f);
|
|
SciCall_SetMarginWidthN(MARGIN_SCI_FOLDING, (bShowMargin ? size : 0));
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// UpdateMargins()
|
|
//
|
|
//
|
|
void Style_UpdateAllMargins(HWND hwnd, const bool bForce)
|
|
{
|
|
Style_UpdateLineNumberMargin(bForce);
|
|
if (bForce) {
|
|
Style_UpdateBookmarkMargin(hwnd);
|
|
Style_UpdateChangeHistoryMargin(hwnd);
|
|
Style_UpdateFoldingMargin(hwnd, (FocusedView.CodeFoldingAvailable && FocusedView.ShowCodeFolding));
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetMargin()
|
|
//
|
|
void Style_SetMargin(HWND hwnd, LPCWSTR lpszStyle) /// iStyle == STYLE_LINENUMBER
|
|
{
|
|
Style_SetStyles(hwnd, STYLE_LINENUMBER, lpszStyle, Style_GetBaseFontSize()); // line numbers
|
|
|
|
int alpha;
|
|
COLORREF colorRead;
|
|
|
|
// background
|
|
if (!Style_StrGetColor(lpszStyle, BACKGROUND_LAYER, &colorRead, NULL, false)) {
|
|
colorRead = GetModeBtnfaceColor(UseDarkMode());
|
|
}
|
|
COLORREF const clrMarginBack = colorRead; // (=clrLineNumBack)
|
|
|
|
// foreground
|
|
if (!Style_StrGetColor(lpszStyle, FOREGROUND_LAYER, &colorRead, NULL, false)) {
|
|
colorRead = GetModeTextColor(UseDarkMode());
|
|
}
|
|
Style_StrGetAlpha(lpszStyle, &alpha, SC_ALPHA_OPAQUE, true);
|
|
COLORREF const clrLineNumFore = Style_RgbAlpha(colorRead, clrMarginBack, alpha);
|
|
|
|
// --- Line Numbers ---
|
|
SciCall_StyleSetFore(STYLE_LINENUMBER, clrLineNumFore);
|
|
SciCall_StyleSetBack(STYLE_LINENUMBER, clrMarginBack);
|
|
SciCall_SetMarginBackN(MARGIN_SCI_LINENUM, clrMarginBack);
|
|
SciCall_SetMarginSensitiveN(MARGIN_SCI_LINENUM, false); /// (!) false: allow selection drag
|
|
|
|
|
|
// --- CallTips ---
|
|
//~SciCall_CallTipSetBack(clrMarginBack);
|
|
//~SciCall_CallTipSetFore(CalcContrastColor(clrMarginBack, 0)); // clrLineNumFore
|
|
char fontFaceName[LF_FACESIZE] = { '\0' };
|
|
GetSystemMessageFontA(fontFaceName, false); // "Segoe UI"
|
|
SciCall_StyleSetItalic(STYLE_CALLTIP, false);
|
|
SciCall_StyleSetBold(STYLE_CALLTIP, false);
|
|
SciCall_StyleSetBack(STYLE_CALLTIP, clrMarginBack);
|
|
SciCall_StyleSetFore(STYLE_CALLTIP, CalcContrastColor(clrMarginBack, 0)); // clrLineNumFore
|
|
SciCall_CallTipUseStyle(24); // tabsize
|
|
SciCall_CallTipSetForeHlt(clrLineNumFore);
|
|
|
|
// --- Bookmarks ---
|
|
LPCWSTR const wchBookMarkStyleStrg = GetCurrentStdLexer()->Styles[STY_BOOK_MARK].szValue;
|
|
|
|
colorRead = clrLineNumFore; // bookmark
|
|
Style_StrGetColor(wchBookMarkStyleStrg, FOREGROUND_LAYER, &colorRead, NULL, false);
|
|
COLORREF const clrBookMarkFore = colorRead;
|
|
|
|
Style_StrGetAlpha(wchBookMarkStyleStrg, &alpha, SC_ALPHA_OPAQUE, true);
|
|
int const bookmarkAlpha = alpha;
|
|
|
|
colorRead = clrMarginBack; // folding signs
|
|
// document background as default:
|
|
Style_StrGetColor(GetCurrentStdLexer()->Styles[STY_DEFAULT].szValue, BACKGROUND_LAYER, &colorRead, NULL, true);
|
|
// if defined, use bookmark background color
|
|
Style_StrGetColor(wchBookMarkStyleStrg, BACKGROUND_LAYER, &colorRead, NULL, false);
|
|
COLORREF const clrFoldMarginBack = colorRead;
|
|
|
|
int strokeWidth = FW_THIN;
|
|
if (!Style_StrGetWeightValue(lpszStyle, &strokeWidth)) {
|
|
strokeWidth = FontWeights[FW_IDX_REGULAR].weight;
|
|
}
|
|
strokeWidth = max_i(FW_THIN, strokeWidth >> 2); // 1/4
|
|
|
|
// standard bookmark
|
|
SciCall_MarkerDefine(MARKER_NP3_BOOKMARK, SC_MARK_VERTICALBOOKMARK); // SC_MARK_BOOKMARK/SC_MARK_SHORTARROW
|
|
SciCall_MarkerSetAlpha(MARKER_NP3_BOOKMARK, bookmarkAlpha);
|
|
SciCall_MarkerSetForeTranslucent(MARKER_NP3_BOOKMARK, AxRGB(bookmarkAlpha, clrLineNumFore)); //~clrBookMarkFore
|
|
//~SciCall_MarkerSetBack(MARKER_NP3_BOOKMARK, Style_RgbAlpha(clrBookMarkFore, clrMarginBack, bookmarkAlpha));
|
|
SciCall_MarkerSetBackTranslucent(MARKER_NP3_BOOKMARK, AxRGB(bookmarkAlpha, clrBookMarkFore));
|
|
SciCall_MarkerSetStrokeWidth(MARKER_NP3_BOOKMARK, strokeWidth);
|
|
|
|
// occurrence bookmarker
|
|
bool const visible = Settings.MarkOccurrencesBookmark;
|
|
//SciCall_MarkerDefine(MARKER_NP3_OCCURRENCE, visible ? SC_MARK_ARROWS : SC_MARK_BACKGROUND);
|
|
SciCall_MarkerDefine(MARKER_NP3_OCCURRENCE, visible ? SC_MARK_ARROWS : SC_MARK_EMPTY);
|
|
SciCall_MarkerSetForeTranslucent(MARKER_NP3_OCCURRENCE, RGB2RGBAREF(CalcContrastColor(clrMarginBack, 100)));
|
|
SciCall_MarkerSetBackTranslucent(MARKER_NP3_OCCURRENCE, AxRGB(SC_ALPHA_TRANSPARENT, clrMarginBack));
|
|
//~SciCall_MarkerSetForeSelected(MARKER_NP3_OCCURRENCE, RGB(0,0,220));
|
|
SciCall_MarkerSetStrokeWidth(MARKER_NP3_OCCURRENCE, strokeWidth);
|
|
|
|
// --- WordBookMarks ---
|
|
COLORREF color;
|
|
for (int m = MARKER_NP3_1; m < MARKER_NP3_BOOKMARK; ++m) {
|
|
SciCall_MarkerDefine(m, (Settings.FocusViewMarkerMode & FVMM_LN_BACKGR) ? SC_MARK_BACKGROUND : SC_MARK_BOOKMARK);
|
|
Style_StrGetColor(WordBookMarks[m], BACKGROUND_LAYER, &color, NULL, true);
|
|
SciCall_MarkerSetAlpha(m, bookmarkAlpha); // if drawn in content area
|
|
SciCall_MarkerSetForeTranslucent(m, RGB2RGBAREF(color));
|
|
SciCall_MarkerSetBackTranslucent(m, AxRGB(bookmarkAlpha, color)); // 'alpha' no meaning for SC_MARK_BACKGROUND
|
|
}
|
|
|
|
SciCall_SetMarginBackN(MARGIN_SCI_BOOKMRK, clrMarginBack);
|
|
SciCall_SetMarginSensitiveN(MARGIN_SCI_BOOKMRK, true);
|
|
SciCall_SetMarginCursorN(MARGIN_SCI_BOOKMRK, SC_NP3_CURSORHAND);
|
|
|
|
// --- Change History ---
|
|
|
|
SciCall_SetMarginBackN(MARGIN_SCI_CHGHIST, clrMarginBack);
|
|
SciCall_SetMarginSensitiveN(MARGIN_SCI_CHGHIST, true);
|
|
|
|
const WCHAR* const wchChgHistMrkModifiedStyleStrg = GetCurrentStdLexer()->Styles[STY_CHGHIST_MODIFIED].szValue;
|
|
colorRead = clrLineNumFore;
|
|
if (Style_StrGetColor(wchChgHistMrkModifiedStyleStrg, FOREGROUND_LAYER, &colorRead, NULL, false)) {
|
|
SciCall_MarkerSetFore(SC_MARKNUM_HISTORY_MODIFIED, colorRead);
|
|
}
|
|
colorRead = clrMarginBack;
|
|
Style_StrGetColor(wchChgHistMrkModifiedStyleStrg, BACKGROUND_LAYER, &colorRead, NULL, false);
|
|
// also if not defined, use margin backgr
|
|
SciCall_MarkerSetBack(SC_MARKNUM_HISTORY_MODIFIED, colorRead);
|
|
|
|
// TODO: alpha/translucent/layer in print mode ?
|
|
//Style_StrGetAlpha(wchChgHistMrkModifiedStyleStrg, &alpha, SC_ALPHA_OPAQUE, true);
|
|
//SciCall_MarkerSetAlpha(SC_MARKNUM_HISTORY_MODIFIED, alpha);
|
|
// COLORREF const rgbAlpha = Style_RgbAlpha(colorRead, clrMarginBack, alpha);
|
|
|
|
const WCHAR* const wchChgHistMrkSavedStyleStrg = GetCurrentStdLexer()->Styles[STY_CHGHIST_SAVED].szValue;
|
|
colorRead = clrLineNumFore;
|
|
if (Style_StrGetColor(wchChgHistMrkSavedStyleStrg, FOREGROUND_LAYER, &colorRead, NULL, false)) {
|
|
SciCall_MarkerSetFore(SC_MARKNUM_HISTORY_SAVED, colorRead);
|
|
}
|
|
colorRead = clrMarginBack;
|
|
if (Style_StrGetColor(wchChgHistMrkSavedStyleStrg, BACKGROUND_LAYER, &colorRead, NULL, false)) {
|
|
SciCall_MarkerSetBack(SC_MARKNUM_HISTORY_SAVED, colorRead);
|
|
}
|
|
//SciCall_MarkerSetStrokeWidth(SC_MARKNUM_HISTORY_SAVED, strokeWidth);
|
|
|
|
const WCHAR* const wchChgHistMrkRev2OrgStyleStrg = GetCurrentStdLexer()->Styles[STY_CHGHIST_REV_TO_ORG].szValue;
|
|
colorRead = clrLineNumFore;
|
|
if (Style_StrGetColor(wchChgHistMrkRev2OrgStyleStrg, FOREGROUND_LAYER, &colorRead, NULL, false)) {
|
|
SciCall_MarkerSetFore(SC_MARKNUM_HISTORY_REVERTED_TO_ORIGIN, colorRead);
|
|
}
|
|
colorRead = clrMarginBack;
|
|
if (Style_StrGetColor(wchChgHistMrkRev2OrgStyleStrg, BACKGROUND_LAYER, &colorRead, NULL, false)) {
|
|
SciCall_MarkerSetBack(SC_MARKNUM_HISTORY_REVERTED_TO_ORIGIN, colorRead);
|
|
}
|
|
//SciCall_MarkerSetStrokeWidth(SC_MARKNUM_HISTORY_REVERTED_TO_ORIGIN, strokeWidth);
|
|
|
|
const WCHAR* const wchChgHistMrkRev2ModStyleStrg = GetCurrentStdLexer()->Styles[STY_CHGHIST_REV_TO_MOD].szValue;
|
|
colorRead = clrLineNumFore;
|
|
if (Style_StrGetColor(wchChgHistMrkRev2ModStyleStrg, FOREGROUND_LAYER, &colorRead, NULL, false)) {
|
|
SciCall_MarkerSetFore(SC_MARKNUM_HISTORY_REVERTED_TO_MODIFIED, colorRead);
|
|
}
|
|
colorRead = clrMarginBack;
|
|
if (Style_StrGetColor(wchChgHistMrkRev2ModStyleStrg, BACKGROUND_LAYER, &colorRead, NULL, false)) {
|
|
SciCall_MarkerSetBack(SC_MARKNUM_HISTORY_REVERTED_TO_MODIFIED, colorRead);
|
|
}
|
|
//SciCall_MarkerSetStrokeWidth(SC_MARKNUM_HISTORY_REVERTED_TO_MODIFIED, strokeWidth);
|
|
|
|
// --- Code folding ---
|
|
|
|
SciCall_SetMarginSensitiveN(MARGIN_SCI_FOLDING, true);
|
|
|
|
int fldStyleMrk = SC_CASE_LOWER;
|
|
Style_StrGetCase(wchBookMarkStyleStrg, &fldStyleMrk);
|
|
if (fldStyleMrk == SC_CASE_UPPER) { // circle style
|
|
SciCall_MarkerDefine(SC_MARKNUM_FOLDEROPEN, SC_MARK_CIRCLEMINUS);
|
|
SciCall_MarkerDefine(SC_MARKNUM_FOLDER, SC_MARK_CIRCLEPLUS);
|
|
SciCall_MarkerDefine(SC_MARKNUM_FOLDERSUB, SC_MARK_VLINE);
|
|
SciCall_MarkerDefine(SC_MARKNUM_FOLDERTAIL, SC_MARK_LCORNERCURVE);
|
|
SciCall_MarkerDefine(SC_MARKNUM_FOLDEREND, SC_MARK_CIRCLEPLUSCONNECTED);
|
|
SciCall_MarkerDefine(SC_MARKNUM_FOLDEROPENMID, SC_MARK_CIRCLEMINUSCONNECTED);
|
|
SciCall_MarkerDefine(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNERCURVE);
|
|
} else { // box style
|
|
SciCall_MarkerDefine(SC_MARKNUM_FOLDEROPEN, SC_MARK_BOXMINUS);
|
|
SciCall_MarkerDefine(SC_MARKNUM_FOLDER, SC_MARK_BOXPLUS);
|
|
SciCall_MarkerDefine(SC_MARKNUM_FOLDERSUB, SC_MARK_VLINE);
|
|
SciCall_MarkerDefine(SC_MARKNUM_FOLDERTAIL, SC_MARK_LCORNER);
|
|
SciCall_MarkerDefine(SC_MARKNUM_FOLDEREND, SC_MARK_BOXPLUSCONNECTED);
|
|
SciCall_MarkerDefine(SC_MARKNUM_FOLDEROPENMID, SC_MARK_BOXMINUSCONNECTED);
|
|
SciCall_MarkerDefine(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNER);
|
|
}
|
|
|
|
colorRead = clrLineNumFore;
|
|
const WCHAR* wchHighlightStyleStrg = GetCurrentStdLexer()->Styles[STY_SEL_TXT].szValue;
|
|
Style_StrGetColor(wchHighlightStyleStrg, FOREGROUND_LAYER, &colorRead, NULL, true);
|
|
COLORREF const fldHiLight = colorRead;
|
|
|
|
for (int i = 0; i < COUNTOF(FoldMarkerID); ++i) {
|
|
SciCall_MarkerSetForeTranslucent(FoldMarkerID[i], RGB2RGBAREF(clrFoldMarginBack)); // (!)
|
|
SciCall_MarkerSetBackTranslucent(FoldMarkerID[i], RGB2RGBAREF(clrLineNumFore)); // (!) //~clrBookMarkForeAlpha
|
|
SciCall_MarkerSetBackSelected(FoldMarkerID[i], fldHiLight);
|
|
SciCall_MarkerSetStrokeWidth(FoldMarkerID[i], strokeWidth<<1);
|
|
}
|
|
SciCall_SetElementColour(SC_ELEMENT_FOLD_LINE, AxRGB(255, clrLineNumFore));
|
|
|
|
SciCall_MarkerEnableHighlight(true); // highlight folding block
|
|
|
|
// background
|
|
//~SciCall_SetMarginBackN(MARGIN_SCI_FOLDING, clrMarginBack); // no effect
|
|
SciCall_SetFoldMarginColour(true, clrFoldMarginBack); // background
|
|
SciCall_SetFoldMarginHiColour(true, clrFoldMarginBack); // (!)
|
|
|
|
|
|
int const _debug_flags = 0;
|
|
//int const _debug_flags = (SC_FOLDFLAG_LEVELNUMBERS | SC_FOLDFLAG_LINESTATE); // !extend margin width
|
|
|
|
int fldStyleLn = 0;
|
|
Style_StrGetCharSet(wchBookMarkStyleStrg, &fldStyleLn);
|
|
switch (fldStyleLn) {
|
|
case 1:
|
|
SciCall_SetFoldFlags(SC_FOLDFLAG_LINEBEFORE_CONTRACTED | _debug_flags);
|
|
break;
|
|
case 2:
|
|
SciCall_SetFoldFlags(SC_FOLDFLAG_LINEBEFORE_CONTRACTED | SC_FOLDFLAG_LINEAFTER_CONTRACTED | _debug_flags);
|
|
break;
|
|
case 3:
|
|
SciCall_SetFoldFlags(SC_FOLDFLAG_NONE | _debug_flags);
|
|
SciCall_SetDefaultFoldDisplayText(" \xE2\x80\xA6 ");
|
|
SciCall_FoldDisplayTextSetStyle(SC_FOLDDISPLAYTEXT_BOXED);
|
|
break;
|
|
default:
|
|
SciCall_SetFoldFlags(SC_FOLDFLAG_LINEAFTER_CONTRACTED | _debug_flags);
|
|
break;
|
|
}
|
|
|
|
// set width
|
|
Style_UpdateAllMargins(hwnd, true);
|
|
}
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SniffShebang()
|
|
//
|
|
PEDITLEXER Style_SniffShebang(char* pchText)
|
|
{
|
|
if (StrCmpNA(pchText,"#!",2) == 0) {
|
|
char *pch = pchText + 2;
|
|
while (*pch == ' ' || *pch == '\t') {
|
|
pch++;
|
|
}
|
|
while (*pch && *pch != ' ' && *pch != '\t' && *pch != '\r' && *pch != '\n') {
|
|
pch++;
|
|
}
|
|
if ((pch - pchText) >= 3 && StrCmpNA(pch-3,"env",3) == 0) {
|
|
while (*pch == ' ') {
|
|
pch++;
|
|
}
|
|
while (*pch && *pch != ' ' && *pch != '\t' && *pch != '\r' && *pch != '\n') {
|
|
pch++;
|
|
}
|
|
}
|
|
if ((pch - pchText) >= 3 && StrCmpNIA(pch - 3, "php", 3) == 0) {
|
|
return(&lexHTML);
|
|
}
|
|
if ((pch - pchText) >= 4 && StrCmpNIA(pch - 4, "perl", 4) == 0) {
|
|
return(&lexPL);
|
|
}
|
|
if ((pch - pchText) >= 6 && StrCmpNIA(pch - 6, "python", 6) == 0) {
|
|
return(&lexPY);
|
|
}
|
|
if ((pch - pchText) >= 3 && StrCmpNA(pch - 3, "tcl", 3) == 0) {
|
|
return(&lexTCL);
|
|
}
|
|
if ((pch - pchText) >= 4 && StrCmpNA(pch - 4, "wish", 4) == 0) {
|
|
return(&lexTCL);
|
|
}
|
|
if ((pch - pchText) >= 5 && StrCmpNA(pch - 5, "tclsh", 5) == 0) {
|
|
return(&lexTCL);
|
|
}
|
|
if ((pch - pchText) >= 2 && StrCmpNA(pch - 2, "sh", 2) == 0) {
|
|
return(&lexBASH);
|
|
}
|
|
if ((pch - pchText) >= 4 && StrCmpNA(pch - 4, "ruby", 4) == 0) {
|
|
return(&lexRUBY);
|
|
}
|
|
if ((pch - pchText) >= 4 && StrCmpNA(pch - 4, "node", 4) == 0) {
|
|
return(&lexJS);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_MatchLexer()
|
|
//
|
|
PEDITLEXER Style_MatchLexer(LPCWSTR lpszMatch, bool bCheckNames)
|
|
{
|
|
if (bCheckNames) {
|
|
int const cch = (int)StringCchLen(lpszMatch, 0);
|
|
if (cch >= 3) {
|
|
for (int iLex = 0; iLex < COUNTOF(g_pLexArray); ++iLex) {
|
|
if (StrCmpNI(g_pLexArray[iLex]->pszName, lpszMatch, cch) == 0) {
|
|
return (g_pLexArray[iLex]);
|
|
}
|
|
}
|
|
}
|
|
} else if (StrIsNotEmpty(lpszMatch)) {
|
|
for (int iLex = 0; iLex < COUNTOF(g_pLexArray); ++iLex) {
|
|
if (Style_StrHasAttribute(g_pLexArray[iLex]->szExtensions, lpszMatch)) {
|
|
return g_pLexArray[iLex];
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_RegExMatchLexer()
|
|
//
|
|
PEDITLEXER Style_RegExMatchLexer(LPCWSTR lpszFileName)
|
|
{
|
|
if (StrIsNotEmpty(lpszFileName)) {
|
|
|
|
char chFilePath[XHUGE_BUFFER] = { '\0' };
|
|
WideCharToMultiByteEx(CP_UTF8, 0, lpszFileName, -1, chFilePath, COUNTOF(chFilePath), NULL, NULL);
|
|
|
|
for (int iLex = 0; iLex < COUNTOF(g_pLexArray); ++iLex) {
|
|
const WCHAR *p = g_pLexArray[iLex]->szExtensions;
|
|
do {
|
|
const WCHAR* f = StrChr(p, L'\\');
|
|
const WCHAR* e = f;
|
|
if (f) {
|
|
e = StrChr(f, L';');
|
|
if (!e) {
|
|
e = f + StringCchLen(f, 0);
|
|
}
|
|
++f; // exclude '\'
|
|
char regexpat[HUGE_BUFFER] = { '\0' };
|
|
WideCharToMultiByte(CP_UTF8, 0, f, (int)(e-f), regexpat, (int)COUNTOF(regexpat), NULL, NULL);
|
|
|
|
if (RegExFind(regexpat, chFilePath, false, NULL) >= 0) {
|
|
return g_pLexArray[iLex];
|
|
}
|
|
}
|
|
p = e;
|
|
} while (p != NULL);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_HasLexerForExt()
|
|
//
|
|
bool Style_HasLexerForExt(const HPATHL hpath)
|
|
{
|
|
bool bFound = false;
|
|
LPCWSTR lpszExt = Path_FindExtension(hpath);
|
|
if (StrIsNotEmpty(lpszExt)) {
|
|
if (*lpszExt == L'.') {
|
|
++lpszExt;
|
|
}
|
|
if (lpszExt && Style_MatchLexer(lpszExt, false)) {
|
|
bFound = true;
|
|
}
|
|
}
|
|
if (!bFound && Path_IsNotEmpty(hpath)) {
|
|
bFound = Style_RegExMatchLexer(Path_FindFileName(hpath));
|
|
}
|
|
return bFound;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetLexerFromFile()
|
|
//
|
|
bool Style_SetLexerFromFile(HWND hwnd, const HPATHL hpath)
|
|
{
|
|
if (Flags.bHugeFileLoadState) {
|
|
Style_SetDefaultLexer(hwnd);
|
|
return true;
|
|
}
|
|
|
|
LPCWSTR lpszExt = Path_FindExtension(hpath);
|
|
bool bFound = false;
|
|
PEDITLEXER pLexNew = NULL;
|
|
PEDITLEXER pLexSniffed = NULL;
|
|
|
|
if ((Globals.fvCurFile.mask & FV_MODE) && Globals.fvCurFile.chMode[0]) {
|
|
PEDITLEXER pLexMode;
|
|
WCHAR wchMode[MICRO_BUFFER] = { L'\0' };
|
|
MultiByteToWideCharEx(Encoding_SciCP, 0, Globals.fvCurFile.chMode, -1, wchMode, MICRO_BUFFER);
|
|
|
|
if (!Flags.NoCGIGuess && (StrCmpIW(wchMode, L"cgi") == 0 || StrCmpIW(wchMode, L"fcgi") == 0)) {
|
|
char tchText[256] = { '\0' };
|
|
SciCall_GetText(COUNTOF(tchText) - 1, tchText);
|
|
StrTrimA(tchText," \t\n\r");
|
|
pLexSniffed = Style_SniffShebang(tchText);
|
|
if (pLexSniffed) {
|
|
if ((Encoding_GetCurrent() != Globals.DOSEncoding) || !IsLexerStandard(pLexSniffed) || (
|
|
(StringCchCompareXI(lpszExt,L"nfo") == 0) && (StringCchCompareXI(lpszExt,L"diz") == 0))) {
|
|
// Although .nfo and .diz were removed from the default lexer's
|
|
// default extensions list, they may still presist in the user's INI
|
|
pLexNew = pLexSniffed;
|
|
bFound = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!bFound) {
|
|
pLexMode = Style_MatchLexer(wchMode, false);
|
|
if (pLexMode) {
|
|
pLexNew = pLexMode;
|
|
bFound = true;
|
|
} else {
|
|
pLexMode = Style_MatchLexer(wchMode, true);
|
|
if (pLexMode) {
|
|
pLexNew = pLexMode;
|
|
bFound = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LPCWSTR lpszFileName = Path_FindFileName(hpath);
|
|
|
|
// check for filename regex match
|
|
if (!bFound && s_bAutoSelect && Path_IsNotEmpty(hpath)) {
|
|
pLexSniffed = Style_RegExMatchLexer(lpszFileName);
|
|
if (pLexSniffed) {
|
|
pLexNew = pLexSniffed;
|
|
bFound = true;
|
|
}
|
|
}
|
|
|
|
if (!bFound && s_bAutoSelect && (Path_IsNotEmpty(hpath) && *lpszExt)) {
|
|
if (*lpszExt == L'.') {
|
|
++lpszExt;
|
|
}
|
|
|
|
if (!Flags.NoCGIGuess && (StringCchCompareXI(lpszExt,L"cgi") == 0 || StringCchCompareXI(lpszExt,L"fcgi") == 0)) {
|
|
char tchText[256] = { '\0' };
|
|
SciCall_GetText(COUNTOF(tchText) - 1, tchText);
|
|
StrTrimA(tchText," \t\n\r");
|
|
pLexSniffed = Style_SniffShebang(tchText);
|
|
if (pLexSniffed) {
|
|
pLexNew = pLexSniffed;
|
|
bFound = true;
|
|
}
|
|
}
|
|
|
|
// check associated extensions
|
|
if (!bFound) {
|
|
pLexSniffed = Style_MatchLexer(lpszExt, false);
|
|
if (pLexSniffed) {
|
|
pLexNew = pLexSniffed;
|
|
bFound = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!bFound && s_bAutoSelect && (!Flags.NoHTMLGuess || !Flags.NoCGIGuess)) {
|
|
char tchText[512] = { '\0' };
|
|
SciCall_GetText(COUNTOF(tchText) - 1, tchText);
|
|
StrTrimA(tchText," \t\n\r");
|
|
if (!Flags.NoCGIGuess) {
|
|
if (tchText[0] == '<') {
|
|
if (StrStrIA(tchText, "<html")) {
|
|
pLexNew = &lexHTML;
|
|
} else {
|
|
pLexNew = &lexXML;
|
|
}
|
|
bFound = true;
|
|
} else {
|
|
pLexSniffed = Style_SniffShebang(tchText);
|
|
if (pLexSniffed) {
|
|
pLexNew = pLexSniffed;
|
|
bFound = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!bFound && (Encoding_GetCurrent() == Globals.DOSEncoding)) {
|
|
pLexNew = &lexANSI;
|
|
}
|
|
|
|
// Apply the new lexer
|
|
if (IsLexerStandard(pLexNew)) {
|
|
Style_SetDefaultLexer(hwnd);
|
|
} else {
|
|
Style_SetLexer(hwnd, pLexNew);
|
|
}
|
|
|
|
return bFound;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_MaybeBinaryFile()
|
|
//
|
|
bool Style_MaybeBinaryFile(HWND hwnd, const HPATHL hpath)
|
|
{
|
|
UNREFERENCED_PARAMETER(hwnd);
|
|
#if 0
|
|
UNREFERENCED_PARAMETER(lpszFile);
|
|
#else
|
|
unsigned char buf[5] = { '\0' }; // magic
|
|
SciCall_GetText(COUNTOF(buf) - 1, (char*)buf);
|
|
UINT const magic2 = (buf[0] << 8) | buf[1];
|
|
if (magic2 == 0x4D5AU || // PE: MZ
|
|
magic2 == 0x504BU || // ZIP: PK
|
|
magic2 == 0x377AU || // 7z: 7z
|
|
magic2 == 0x424DU || // BMP: BM
|
|
magic2 == 0xFFD8U // JPEG
|
|
) {
|
|
return true;
|
|
}
|
|
UINT const magic = (magic2 << 16) | (buf[2] << 8) | buf[3];
|
|
if (magic == 0x0000FEFFU || // UTF32-BE
|
|
magic == 0xFFFE0000U || // UTF32-LE
|
|
magic == 0x89504E47U || // PNG: 0x89+PNG
|
|
magic == 0x47494638U || // GIF: GIF89a
|
|
magic == 0x25504446U || // PDF: %PDF-{version}
|
|
magic == 0x52617221U || // RAR: Rar!
|
|
magic == 0x7F454C46U || // ELF: 0x7F+ELF
|
|
magic == 0x213C6172U || // .lib, .a: !<arch>\n
|
|
magic == 0xFD377A58U || // xz: 0xFD+7zXZ
|
|
magic == 0xCAFEBABEU // Java class
|
|
) {
|
|
return true;
|
|
}
|
|
const WCHAR* const binaryExt = L"|bin|exe|cur|ico|iso|img|lib|mdb|obj|pak|pdb|pyc|pyd|tar|"; // keep '|' at end
|
|
size_t const _min = 5ULL;
|
|
size_t const _max = 6ULL;
|
|
|
|
WCHAR lpszExt[32] = { L'\0' };
|
|
StringCchCopyW(lpszExt, COUNTOF(lpszExt), L"|");
|
|
StringCchCopyW(lpszExt, COUNTOF(lpszExt), Path_FindExtension(hpath));
|
|
StringCchCat(lpszExt, COUNTOF(lpszExt), L"|");
|
|
|
|
size_t const len = StringCchLen(lpszExt, COUNTOF(lpszExt));
|
|
if (len < _min || len > _max) {
|
|
if (StrStrIW(binaryExt, lpszExt)) {
|
|
return true;
|
|
}
|
|
}
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetLexerFromName()
|
|
//
|
|
void Style_SetLexerFromName(HWND hwnd, const HPATHL hpath, LPCWSTR lpszName)
|
|
{
|
|
PEDITLEXER pLexNew = Style_MatchLexer(lpszName, false);
|
|
if (pLexNew) {
|
|
Style_SetLexer(hwnd, pLexNew);
|
|
} else {
|
|
pLexNew = Style_MatchLexer(lpszName, true);
|
|
if (pLexNew) {
|
|
Style_SetLexer(hwnd, pLexNew);
|
|
} else {
|
|
Style_SetLexerFromFile(hwnd, hpath);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_ResetCurrentLexer()
|
|
//
|
|
void Style_ResetCurrentLexer(HWND hwnd)
|
|
{
|
|
Style_SetLexer(hwnd, s_pLexCurrent);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetDefaultLexer()
|
|
//
|
|
void Style_SetDefaultLexer(HWND hwnd)
|
|
{
|
|
Style_SetLexer(hwnd, NULL);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetHTMLLexer()
|
|
//
|
|
void Style_SetHTMLLexer(HWND hwnd)
|
|
{
|
|
Style_SetLexer(hwnd,&lexHTML);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetXMLLexer()
|
|
//
|
|
void Style_SetXMLLexer(HWND hwnd)
|
|
{
|
|
Style_SetLexer(hwnd,&lexXML);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetLexerFromID()
|
|
//
|
|
void Style_SetLexerFromID(HWND hwnd,int id)
|
|
{
|
|
if (id >= 0 && id < COUNTOF(g_pLexArray)) {
|
|
Style_SetLexer(hwnd, g_pLexArray[id]);
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_ToggleUse2ndDefault()
|
|
//
|
|
void Style_ToggleUse2ndDefault(HWND hwnd)
|
|
{
|
|
bool const use2ndDefStyle = Style_GetUse2ndDefault();
|
|
Style_SetUse2ndDefault(!use2ndDefStyle); // swap
|
|
if (IsLexerStandard(s_pLexCurrent)) {
|
|
s_pLexCurrent = GetCurrentStdLexer(); // sync
|
|
}
|
|
Style_ResetCurrentLexer(Globals.hwndEdit);
|
|
UNREFERENCED_PARAMETER(hwnd);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetDefaultFont()
|
|
//
|
|
void Style_SetDefaultFont(HWND hwnd, bool bGlobalDefault)
|
|
{
|
|
WCHAR newStyle[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
WCHAR lexerName[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
WCHAR styleName[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
|
|
PEDITLEXER const pLexer = bGlobalDefault ? GetCurrentStdLexer() : s_pLexCurrent;
|
|
PEDITSTYLE const pLexerDefStyle = &(pLexer->Styles[STY_DEFAULT]);
|
|
|
|
StringCchCopyW(newStyle, COUNTOF(newStyle), pLexer->Styles[STY_DEFAULT].szValue);
|
|
|
|
GetLngString(pLexer->resID, lexerName, COUNTOF(lexerName));
|
|
GetLngString(pLexer->Styles[STY_DEFAULT].rid, styleName, COUNTOF(styleName));
|
|
|
|
DEFAULT_FONT_STYLES const defaultFontStyle = bGlobalDefault ? DFS_GLOBAL : DFS_CURR_LEXER;
|
|
if (Style_SelectFont(hwnd, newStyle, COUNTOF(newStyle), lexerName, styleName, defaultFontStyle)) {
|
|
// set new styles to current lexer's default text
|
|
StringCchCopyW(pLexerDefStyle->szValue, COUNTOF(pLexerDefStyle->szValue), newStyle);
|
|
Style_ResetCurrentLexer(Globals.hwndEdit);
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetUse2ndDefault(), Style_GetUse2ndDefault()
|
|
//
|
|
static bool s_bUse2ndDefaultStyle = false;
|
|
|
|
void Style_SetUse2ndDefault(bool use2nd)
|
|
{
|
|
s_bUse2ndDefaultStyle = use2nd;
|
|
}
|
|
|
|
bool Style_GetUse2ndDefault()
|
|
{
|
|
return s_bUse2ndDefaultStyle;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetIndentGuides()
|
|
//
|
|
void Style_SetIndentGuides(HWND hwnd,bool bShow)
|
|
{
|
|
UNREFERENCED_PARAMETER(hwnd);
|
|
int iIndentView = SC_IV_NONE;
|
|
if (bShow) {
|
|
if (!Flags.SimpleIndentGuides) {
|
|
switch (SciCall_GetLexer()) {
|
|
case SCLEX_PYTHON:
|
|
case SCLEX_NIM:
|
|
iIndentView = SC_IV_LOOKFORWARD;
|
|
break;
|
|
default:
|
|
iIndentView = SC_IV_LOOKBOTH;
|
|
break;
|
|
}
|
|
} else {
|
|
iIndentView = SC_IV_REAL;
|
|
}
|
|
}
|
|
SciCall_SetIndentationGuides(iIndentView);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetExtraLineSpace()
|
|
//
|
|
void Style_SetExtraLineSpace(int iValue)
|
|
{
|
|
int iAscent = 0, iDescent = 0;
|
|
if ((iValue % 2) != 0) {
|
|
iAscent++;
|
|
iValue--;
|
|
}
|
|
iAscent += (iValue >> 1);
|
|
iDescent += (iValue >> 1);
|
|
SciCall_SetExtraAscent(iAscent);
|
|
SciCall_SetExtraDescent(iDescent);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_GetFileFilterStr()
|
|
//
|
|
bool Style_GetFileFilterStr(LPWSTR lpszFilter, int cchFilter, LPWSTR lpszDefExt, int cchExt, bool bSaveAs)
|
|
{
|
|
ZeroMemory(lpszFilter, cchFilter * sizeof(WCHAR));
|
|
|
|
LPCWSTR curExt = Path_FindExtension(Paths.CurrentFile);
|
|
if (StrIsNotEmpty(curExt)) {
|
|
curExt += 1;
|
|
}
|
|
|
|
WCHAR filterAll[80] = { L'\0' };
|
|
GetLngString(IDS_MUI_FILTER_ALL, filterAll, COUNTOF(filterAll));
|
|
|
|
WCHAR filterDef[EXTENTIONS_FILTER_BUFFER] = { L'\0' };
|
|
WCHAR ext[64] = { L'\0' };
|
|
WCHAR append[80] = { L'\0' };
|
|
bool bCurExtIncl = false;
|
|
LPWSTR p = Style_GetCurrentLexerPtr()->szExtensions;
|
|
while (p) {
|
|
LPWSTR q = StrChrW(p, L';');
|
|
if (q) {
|
|
StringCchCopyN(ext, COUNTOF(ext), p, (q - p));
|
|
p = q + 1;
|
|
} else {
|
|
StringCchCopy(ext, COUNTOF(ext), p);
|
|
p = q;
|
|
}
|
|
if (StrIsNotEmpty(ext)) {
|
|
if (StringCchCompareXI(ext, curExt) == 0) {
|
|
bCurExtIncl = true;
|
|
}
|
|
if (StrIsNotEmpty(append)) {
|
|
StringCchCat(filterDef, COUNTOF(filterDef), L";");
|
|
} else {
|
|
StringCchCopy(lpszDefExt, cchExt, ext); // first bIsDefined ext is default
|
|
}
|
|
StringCchPrintf(append, COUNTOF(append), L"*.%s", ext);
|
|
StringCchCat(filterDef, COUNTOF(filterDef), append);
|
|
}
|
|
}
|
|
if (!bCurExtIncl && StrIsNotEmpty(curExt)) {
|
|
StringCchPrintf(append, COUNTOF(append), L";*.%s", curExt);
|
|
StringCchCat(filterDef, COUNTOF(filterDef), append);
|
|
}
|
|
|
|
if (!bSaveAs) {
|
|
StringCchCat(lpszFilter, cchFilter, filterAll); // 1st for open dlg
|
|
}
|
|
|
|
if (StrIsNotEmpty(filterDef)) {
|
|
WCHAR lexerNameLng[80];
|
|
GetLngString(Style_GetCurrentLexerPtr()->resID, lexerNameLng, COUNTOF(lexerNameLng));
|
|
StringCchCat(lpszFilter, cchFilter, lexerNameLng);
|
|
StringCchCat(lpszFilter, cchFilter, L" (");
|
|
StringCchCat(lpszFilter, cchFilter, filterDef);
|
|
StringCchCat(lpszFilter, cchFilter, L")|");
|
|
StringCchCat(lpszFilter, cchFilter, filterDef);
|
|
StringCchCat(lpszFilter, cchFilter, L"|");
|
|
}
|
|
|
|
if (StrgIsNotEmpty(Settings2.FileDlgFilters)) {
|
|
StringCchCat(lpszFilter, cchFilter, StrgGet(Settings2.FileDlgFilters));
|
|
StringCchCat(lpszFilter, cchFilter, L"|");
|
|
}
|
|
|
|
if (bSaveAs) {
|
|
StringCchCat(lpszFilter, cchFilter, filterAll); // last if save as dlg
|
|
}
|
|
|
|
PrepareFilterStr(lpszFilter);
|
|
return true;
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
static inline void GetDefaultCodeFont(LPWSTR pwchFontName, int cchFont, int iStartIdx)
|
|
{
|
|
pwchFontName[0] = L'\0';
|
|
|
|
for (unsigned i = iStartIdx; i < COUNTOF(Settings2.CodeFontPrefPrioList); ++i) {
|
|
LPCWSTR const fontName = Settings2.CodeFontPrefPrioList[i];
|
|
if (IsFontAvailable(fontName)) {
|
|
StringCchCopy(pwchFontName, cchFont, fontName);
|
|
break;
|
|
}
|
|
}
|
|
if (StrIsEmpty(pwchFontName)) {
|
|
// use internal list
|
|
for (unsigned i = iStartIdx; i < COUNTOF(g_CodeFontPrioList); ++i) {
|
|
LPCWSTR const fontName = g_CodeFontPrioList[i];
|
|
if (IsFontAvailable(fontName)) {
|
|
StringCchCopy(pwchFontName, cchFont, fontName);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (StrIsEmpty(pwchFontName)) {
|
|
StringCchCopy(pwchFontName, cchFont, L"Courier New"); // fallback
|
|
}
|
|
}
|
|
|
|
|
|
static inline void GetDefaultTextFont(LPWSTR pwchFontName, int cchFont, int iStartIdx)
|
|
{
|
|
pwchFontName[0] = L'\0';
|
|
|
|
for (unsigned i = iStartIdx; i < COUNTOF(Settings2.TextFontPrefPrioList); ++i) {
|
|
LPCWSTR const fontName = Settings2.TextFontPrefPrioList[i];
|
|
if (IsFontAvailable(fontName)) {
|
|
StringCchCopy(pwchFontName, cchFont, fontName);
|
|
break;
|
|
}
|
|
}
|
|
if (StrIsEmpty(pwchFontName)) {
|
|
// use internal list
|
|
for (unsigned i = iStartIdx; i < COUNTOF(g_TextFontPrioList); ++i) {
|
|
LPCWSTR const fontName = g_TextFontPrioList[i];
|
|
if (IsFontAvailable(fontName)) {
|
|
StringCchCopy(pwchFontName, cchFont, fontName);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (StrIsEmpty(pwchFontName)) {
|
|
WORD _wDTFSize = 9;
|
|
GetThemedDialogFont(pwchFontName, &_wDTFSize);
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_StrGetFontName()
|
|
//
|
|
bool Style_StrGetFontName(LPCWSTR lpszStyle, LPWSTR lpszFont, int cchFont)
|
|
{
|
|
WCHAR *p = StrStr(lpszStyle, L"font:");
|
|
if (p) {
|
|
p += CONSTSTRGLEN(L"font:");
|
|
while (*p == L' ') {
|
|
++p;
|
|
}
|
|
StringCchCopy(lpszFont, cchFont, p);
|
|
if ((p = StrChr(lpszFont, L';')) != NULL) {
|
|
*p = L'\0';
|
|
}
|
|
TrimSpcW(lpszFont);
|
|
|
|
if (StringCchCompareXI(lpszFont, L"Default") == 0) {
|
|
|
|
GetDefaultCodeFont(lpszFont, cchFont, 0);
|
|
|
|
}
|
|
else if (StringCchStartsWithI(lpszFont, L"$Code")) {
|
|
|
|
int idx = 0;
|
|
Str2Int(&lpszFont[CONSTSTRGLEN(L"$Code")], &idx);
|
|
GetDefaultCodeFont(lpszFont, cchFont, idx);
|
|
|
|
}
|
|
else if (StringCchStartsWithI(lpszFont, L"$Text")) {
|
|
|
|
int idx = 0;
|
|
Str2Int(&lpszFont[CONSTSTRGLEN(L"$Text")], &idx);
|
|
GetDefaultTextFont(lpszFont, cchFont, idx);
|
|
|
|
} else if (!IsFontAvailable(lpszFont)) {
|
|
|
|
GetDefaultCodeFont(lpszFont, cchFont, 0);
|
|
|
|
}
|
|
return true; // font: defined
|
|
}
|
|
return false; // font: not defined
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_StrGetFontQuality()
|
|
//
|
|
bool Style_StrGetFontQuality(LPCWSTR lpszStyle, LPWSTR lpszQuality, int cchQuality, int* iSciQuality_out)
|
|
{
|
|
WCHAR szFontQuality[64] = { L'\0' };
|
|
|
|
WCHAR *p = StrStr(lpszStyle, L"smoothing:");
|
|
if (p) {
|
|
p += CONSTSTRGLEN(L"smoothing:");
|
|
while (*p == L' ') {
|
|
++p;
|
|
}
|
|
StringCchCopy(szFontQuality, COUNTOF(szFontQuality), p);
|
|
if ((p = StrChr(szFontQuality, L';')) != NULL) {
|
|
*p = L'\0';
|
|
}
|
|
TrimSpcW(szFontQuality);
|
|
|
|
for (int i = 0; i < COUNTOF(FontQuality); ++i) {
|
|
if (StringCchCompareX(szFontQuality, FontQuality[i].qname) == 0) {
|
|
if (lpszQuality) {
|
|
StringCchCopy(lpszQuality, cchQuality, FontQuality[i].qname);
|
|
}
|
|
if (iSciQuality_out) {
|
|
*iSciQuality_out = FontQuality[i].sci_value;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_StrGetCharSet()
|
|
//
|
|
bool Style_StrGetCharSet(LPCWSTR lpszStyle, int* i)
|
|
{
|
|
WCHAR *p = StrStr(lpszStyle, L"charset:");
|
|
if (p) {
|
|
p += CONSTSTRGLEN(L"charset:");
|
|
int iValue = 0;
|
|
if (Str2Int(p, &iValue)) {
|
|
*i = (int)max_l(SC_CHARSET_ANSI, iValue);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_StrGetSizeInt()
|
|
//
|
|
bool Style_StrGetSizeInt(LPCWSTR lpszStyle, int* i)
|
|
{
|
|
if (i) {
|
|
WCHAR* p = StrStr(lpszStyle, L"size:");
|
|
if (p) {
|
|
p += CONSTSTRGLEN(L"size:");
|
|
return Str2Int(p, i);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_StrGetSizeIntEx()
|
|
//
|
|
bool Style_StrGetSizeIntEx(LPCWSTR lpszStyle, int* i)
|
|
{
|
|
if (i) {
|
|
WCHAR* p = StrStr(lpszStyle, L"size:");
|
|
if (p) {
|
|
int iSign = 0;
|
|
WCHAR tch[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
StringCchCopy(tch, COUNTOF(tch), p + CONSTSTRGLEN(L"size:"));
|
|
if (tch[0] == L'+') {
|
|
iSign = 1;
|
|
tch[0] = L' ';
|
|
}
|
|
else if (tch[0] == L'-') {
|
|
iSign = -1;
|
|
tch[0] = L' ';
|
|
}
|
|
p = StrChr(tch, L';');
|
|
if (p) {
|
|
*p = L'\0';
|
|
}
|
|
TrimSpcW(tch);
|
|
|
|
int iValue = 0;
|
|
if (Str2Int(tch, &iValue)) {
|
|
if (iSign == 0) {
|
|
*i = iValue;
|
|
}
|
|
else { // iSign: relative value
|
|
iValue = (iSign * iValue); // can be negative
|
|
*i += iValue;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_StrGetSizeFloat()
|
|
//
|
|
bool Style_StrGetSizeFloat(LPCWSTR lpszStyle, float* f)
|
|
{
|
|
WCHAR *p = StrStr(lpszStyle, L"size:");
|
|
if (p) {
|
|
p += CONSTSTRGLEN(L"size:");
|
|
return Str2Float(p, f);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_StrGetSizeFloatEx()
|
|
// Adds parsed value to given one if relative (+/-)
|
|
//
|
|
bool Style_StrGetSizeFloatEx(LPCWSTR lpszStyle, float* f)
|
|
{
|
|
WCHAR *p = StrStr(lpszStyle, L"size:");
|
|
if (p) {
|
|
int fSign = 0;
|
|
WCHAR tch[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
StringCchCopy(tch,COUNTOF(tch),p + CONSTSTRGLEN(L"size:"));
|
|
if (tch[0] == L'+') {
|
|
fSign = 1;
|
|
tch[0] = L' ';
|
|
} else if (tch[0] == L'-') {
|
|
fSign = -1;
|
|
tch[0] = L' ';
|
|
}
|
|
p = StrChr(tch, L';');
|
|
if (p) {
|
|
*p = L'\0';
|
|
}
|
|
TrimSpcW(tch);
|
|
|
|
float fValue = 0.0;
|
|
if (StrToFloatEx(tch, &fValue)) {
|
|
if (fSign == 0) {
|
|
*f = Round10th(fValue);
|
|
}
|
|
else { // fSign: relative value
|
|
fValue = (fSign * fValue); // can be negative
|
|
*f += Round10th(fValue);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_StrGetSizeStr()
|
|
//
|
|
bool Style_StrGetSizeStr(LPCWSTR lpszStyle, LPWSTR lpszSize, int cchSize)
|
|
{
|
|
WCHAR *p = StrStr(lpszStyle, L"size:");
|
|
if (p) {
|
|
WCHAR tch[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
StringCchCopy(tch, COUNTOF(tch), (p + CONSTSTRGLEN(L"size:")));
|
|
p = StrChr(tch, L';');
|
|
if (p) {
|
|
*p = L'\0';
|
|
}
|
|
TrimSpcW(tch);
|
|
// --- normalize ---
|
|
float fValue = 0.0f;
|
|
if (StrToFloatEx(tch, &fValue)) {
|
|
WCHAR wchFloatVal[64];
|
|
fValue = (float)fabs(fValue);
|
|
bool const isZero = (fValue == 0.0f);
|
|
FloatToStr(fValue, wchFloatVal, COUNTOF(wchFloatVal));
|
|
|
|
if (tch[0] == L'+') {
|
|
if (!isZero) {
|
|
StringCchPrintf(lpszSize, cchSize, L"+%s", wchFloatVal);
|
|
} else {
|
|
return false;
|
|
}
|
|
} else if (tch[0] == L'-') {
|
|
if (!isZero) {
|
|
StringCchPrintf(lpszSize, cchSize, L"-%s", wchFloatVal);
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
StringCchPrintf(lpszSize, cchSize, L"%s", wchFloatVal);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_AppendSizeAttribute()
|
|
//
|
|
void Style_AppendSizeAttribute(LPWSTR lpszSize, int cchSize, const float fFontSize, const float fBaseFontSize)
|
|
{
|
|
WCHAR tch[32] = { L'\0' };
|
|
WCHAR newSize[64] = { L'\0' };
|
|
|
|
if (fBaseFontSize > 0.0f) {
|
|
|
|
float const fRelSize = (fFontSize - fBaseFontSize);
|
|
|
|
if (fRelSize >= 0.0f) {
|
|
FloatToStr(fRelSize, tch, COUNTOF(tch));
|
|
StringCchPrintf(newSize, COUNTOF(newSize), L"; size:+%s", tch);
|
|
} else {
|
|
FloatToStr((0.0f - fRelSize), tch, COUNTOF(tch));
|
|
StringCchPrintf(newSize, COUNTOF(newSize), L"; size:-%s", tch);
|
|
}
|
|
|
|
} else { // absolute size
|
|
|
|
FloatToStr(fFontSize, tch, COUNTOF(tch));
|
|
StringCchPrintf(newSize, COUNTOF(newSize), L"; size:%s", tch);
|
|
}
|
|
|
|
if (StrIsNotEmpty(newSize)) {
|
|
AppendStyle(lpszSize, cchSize, newSize);
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_StrGetWeightValue()
|
|
//
|
|
bool Style_StrGetWeightValue(LPCWSTR lpszWeight, int* weight)
|
|
{
|
|
int fontWeight = FW_DONTCARE;
|
|
for (int i = FW_IDX_THIN; i <= FW_IDX_ULTRADARK; ++i) {
|
|
if (Style_StrHasAttribute(lpszWeight, FontWeights[i].wname)) {
|
|
fontWeight = FontWeights[i].weight;
|
|
break;
|
|
}
|
|
}
|
|
bool const bFoundFW = (fontWeight > FW_DONTCARE);
|
|
if (bFoundFW) {
|
|
*weight = fontWeight;
|
|
}
|
|
return bFoundFW;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_AppendWeightAttribute()
|
|
//
|
|
void Style_AppendWeightAttribute(LPWSTR lpszWeight, int cchSize, int fontWeight)
|
|
{
|
|
const WCHAR * pFontWeight = NULL;
|
|
int i;
|
|
for (i = FW_IDX_THIN; i <= FW_IDX_ULTRADARK; ++i) {
|
|
if (fontWeight <= FontWeights[i].weight) {
|
|
pFontWeight = FontWeights[i].wname;
|
|
break;
|
|
}
|
|
}
|
|
if (pFontWeight && (i != FW_IDX_REGULAR)) {
|
|
AppendStyle(lpszWeight, cchSize, pFontWeight);
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_StrGetStretchValue()
|
|
//
|
|
bool Style_StrGetStretchValue(LPCWSTR lpszStyle, int* stretch)
|
|
{
|
|
int fontStretch = SC_STRETCH_NORMAL;
|
|
bool bFound = false;
|
|
for (int i = FS_IDX_ULTRACONDENSED; i <= FS_IDX_ULTRAEXPANDED; ++i) {
|
|
if (Style_StrHasAttribute(lpszStyle, FontStretches[i].wname)) {
|
|
fontStretch = FontStretches[i].stretch;
|
|
bFound = true;
|
|
break;
|
|
}
|
|
}
|
|
if (bFound) {
|
|
*stretch = fontStretch;
|
|
}
|
|
return bFound;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_AppendStretchAttribute()
|
|
//
|
|
void Style_AppendStretchAttribute(LPWSTR lpszStyle, int cchSize, int fontStretch)
|
|
{
|
|
if (fontStretch == SC_STRETCH_NORMAL) {
|
|
return; // normal is default, no need to append
|
|
}
|
|
const WCHAR *pFontStretch = NULL;
|
|
for (int i = FS_IDX_ULTRACONDENSED; i <= FS_IDX_ULTRAEXPANDED; ++i) {
|
|
if (fontStretch == FontStretches[i].stretch) {
|
|
pFontStretch = FontStretches[i].wname;
|
|
break;
|
|
}
|
|
}
|
|
if (pFontStretch) {
|
|
AppendStyle(lpszStyle, cchSize, pFontStretch);
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_StrGetColor()
|
|
//
|
|
bool Style_StrGetColor(LPCWSTR lpszStyle, COLOR_LAYER layer, COLORALPHAREF* rgba, COLORALPHAREF* rgbaOrig, bool useDefault)
|
|
{
|
|
bool const bFGLayer = (layer == FOREGROUND_LAYER);
|
|
//~COLORREF const colorDefault = bFGLayer ? GetModeTextColor(UseDarkMode()) : GetModeBkColor(UseDarkMode());
|
|
COLORALPHAREF const colorDefault = bFGLayer ? RGB2RGBAREF(SciCall_StyleGetFore(STYLE_DEFAULT)) :
|
|
RGB2RGBAREF(SciCall_StyleGetBack(STYLE_DEFAULT)); //~ SCI maybe not initialized
|
|
COLORALPHAREF color = rgbaOrig ? *rgbaOrig : (rgba ? *rgba : colorDefault);
|
|
bool bIsDefined = false;
|
|
const WCHAR* const pItem = bFGLayer ? L"fore:" : L"back:";
|
|
WCHAR* p = StrStr(lpszStyle, pItem);
|
|
if (p) {
|
|
WCHAR tch[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
StringCchCopy(tch, COUNTOF(tch), p + StringCchLen(pItem, 0));
|
|
if (tch[0] == L'#') {
|
|
tch[0] = L' ';
|
|
}
|
|
p = StrChr(tch, L';');
|
|
if (p) {
|
|
*p = L'\0';
|
|
}
|
|
TrimSpcW(tch);
|
|
|
|
unsigned __int32 iValue = 0;
|
|
if (swscanf_s(tch, L"%x", &iValue) == 1) {
|
|
color = ARGB((iValue & 0xFF000000) >> 24, (iValue & 0xFF0000) >> 16, (iValue & 0xFF00) >> 8, iValue & 0xFF);
|
|
if (GetAValue(color) == 0) {
|
|
color = RGB2RGBAREF(color); // alpha not defined: assuming opaque
|
|
}
|
|
bIsDefined = true;
|
|
}
|
|
}
|
|
|
|
if (!bIsDefined && useDefault) {
|
|
color = colorDefault;
|
|
//~ don't: bIsDefined = true;
|
|
}
|
|
|
|
if (rgbaOrig) {
|
|
*rgbaOrig = color;
|
|
}
|
|
if (bFGLayer && UseDarkMode()) {
|
|
color = AxRGB(GetAValue(color), ContrastColor(ARGB_TO_COLREF(color), ((float)Settings.DarkModeHiglightContrast / 100.0f)));
|
|
}
|
|
if (rgba) {
|
|
*rgba = color;
|
|
}
|
|
|
|
return bIsDefined;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_StrGetAlpha()
|
|
//
|
|
bool Style_StrGetAlpha(LPCWSTR lpszStyle, int* iOutValue, const int defAlpha, const bool bAlpha1st)
|
|
{
|
|
const WCHAR* strAlpha = bAlpha1st ? L"alpha:" : L"alpha2:";
|
|
|
|
WCHAR* p = StrStr(lpszStyle, strAlpha);
|
|
if (p) {
|
|
WCHAR tch[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
StringCchCopy(tch, COUNTOF(tch), p + StringCchLen(strAlpha,0));
|
|
p = StrChr(tch, L';');
|
|
if (p) {
|
|
*p = L'\0';
|
|
}
|
|
TrimSpcW(tch);
|
|
int iValue = 0;
|
|
if (StrToIntEx(tch, STIF_DEFAULT, &iValue)) {
|
|
*iOutValue = Sci_ClampAlpha(iValue);
|
|
return true;
|
|
}
|
|
}
|
|
if (defAlpha >= 0) {
|
|
*iOutValue = Sci_ClampAlpha(defAlpha);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_StrGetStrokeWidth()
|
|
//
|
|
bool Style_StrGetStrokeWidth(HWND hwnd, int indicID, LPCWSTR lpszStyle, int *piStrokeWidth)
|
|
{
|
|
if (HasIndicStyleStrokeWidth(SciCall_IndicGetStyle(indicID))) {
|
|
int iStrkWdth = 1;
|
|
if (Style_StrGetSizeInt(lpszStyle, &iStrkWdth)) {
|
|
iStrkWdth = ScaleIntToDPI(hwnd, iStrkWdth * 100);
|
|
*piStrokeWidth = clampi(iStrkWdth, 100, 64000);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
////=============================================================================
|
|
////
|
|
//// Style_StrGetPropertyValue()
|
|
////
|
|
//bool Style_StrGetPropertyValue(LPCWSTR lpszStyle, LPCWSTR lpszProperty, int* val)
|
|
//{
|
|
// WCHAR tch[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
// WCHAR *p = StrStr(lpszStyle, lpszProperty);
|
|
// if (p) {
|
|
// StringCchCopy(tch, COUNTOF(tch), (p + StringCchLen(lpszProperty,0)));
|
|
// p = StrChr(tch, L';');
|
|
// if (p)
|
|
// *p = L'\0';
|
|
// TrimStringW(tch);
|
|
// //if (1 == swscanf_s(tch, L"%i", val)) { return true; }
|
|
// if (StrToIntEx(tch, STIF_DEFAULT, val)) { return true; }
|
|
// }
|
|
// return false;
|
|
//}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_StrGetCase()
|
|
//
|
|
bool Style_StrGetCase(LPCWSTR lpszStyle, int* i)
|
|
{
|
|
WCHAR *p = StrStr(lpszStyle, L"case:");
|
|
if (p) {
|
|
p += CONSTSTRGLEN(L"case:");
|
|
p += StrSpn(p, L" ");
|
|
switch (*p) {
|
|
case L'u':
|
|
case L'U':
|
|
*i = SC_CASE_UPPER;
|
|
return true;
|
|
case L'l':
|
|
case L'L':
|
|
*i = SC_CASE_LOWER;
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_GetIndicatorType()
|
|
//
|
|
bool Style_GetIndicatorType(LPWSTR lpszStyle, int cchSize, int* idx)
|
|
{
|
|
if (*idx < 0) { // retrieve indicator style from string
|
|
for (int i = COUNTOF(IndicatorTypes) - 1; 0 <= i; --i) {
|
|
if (Style_StrHasAttribute(lpszStyle, IndicatorTypes[i])) {
|
|
*idx = i;
|
|
return true;
|
|
}
|
|
}
|
|
*idx = INDIC_ROUNDBOX; // default
|
|
} else { // get indicator string from index
|
|
if (*idx < COUNTOF(IndicatorTypes)) {
|
|
StringCchCopy(lpszStyle, cchSize, IndicatorTypes[*idx]);
|
|
return true;
|
|
}
|
|
StringCchCopy(lpszStyle, cchSize, IndicatorTypes[INDIC_ROUNDBOX]); // default
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_CopyStyles_IfNotDefined()
|
|
//
|
|
void Style_CopyStyles_IfNotDefined(LPCWSTR lpszStyleSrc, LPWSTR lpszStyleDest, int cchSizeDest)
|
|
{
|
|
int iValue;
|
|
COLORREF dColor;
|
|
WCHAR tch[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
WCHAR szTmpStyle[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
|
|
// --------- Font settings ---------
|
|
|
|
bool bIsFontDefInDestination = false;
|
|
|
|
if (Style_StrGetFontName(lpszStyleDest, tch, COUNTOF(tch))) {
|
|
bIsFontDefInDestination = true;
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), L"font:");
|
|
StringCchCat(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
} else if (Style_StrGetFontName(lpszStyleSrc, tch, COUNTOF(tch))) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), L"font:");
|
|
StringCchCat(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
}
|
|
|
|
// --------- Font Style ---------
|
|
|
|
const WCHAR *pFontWeight = NULL;
|
|
for (int idx = FW_IDX_THIN; idx <= FW_IDX_ULTRADARK; ++idx) {
|
|
if (Style_StrHasAttribute(lpszStyleDest, FontWeights[idx].wname)) {
|
|
pFontWeight = FontWeights[idx].wname;
|
|
break;
|
|
}
|
|
}
|
|
if (!bIsFontDefInDestination && !pFontWeight) {
|
|
for (int idx = FW_IDX_THIN; idx <= FW_IDX_ULTRADARK; ++idx) {
|
|
if (Style_StrHasAttribute(lpszStyleSrc, FontWeights[idx].wname)) {
|
|
pFontWeight = FontWeights[idx].wname;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (pFontWeight) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), pFontWeight);
|
|
}
|
|
|
|
// Font Stretch
|
|
const WCHAR *pFontStretch = NULL;
|
|
for (int idx = FS_IDX_ULTRACONDENSED; idx <= FS_IDX_ULTRAEXPANDED; ++idx) {
|
|
if (Style_StrHasAttribute(lpszStyleDest, FontStretches[idx].wname)) {
|
|
pFontStretch = FontStretches[idx].wname;
|
|
break;
|
|
}
|
|
}
|
|
if (!bIsFontDefInDestination && !pFontStretch) {
|
|
for (int idx = FS_IDX_ULTRACONDENSED; idx <= FS_IDX_ULTRAEXPANDED; ++idx) {
|
|
if (Style_StrHasAttribute(lpszStyleSrc, FontStretches[idx].wname)) {
|
|
pFontStretch = FontStretches[idx].wname;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (pFontStretch) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), pFontStretch);
|
|
}
|
|
|
|
if (Style_StrHasAttribute(lpszStyleDest, FontEffects[FE_ITALIC])) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), FontEffects[FE_ITALIC]);
|
|
} else if (!bIsFontDefInDestination && Style_StrHasAttribute(lpszStyleSrc, FontEffects[FE_ITALIC])) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), FontEffects[FE_ITALIC]);
|
|
}
|
|
|
|
// --------- Size ---------
|
|
|
|
if (Style_StrGetSizeStr(lpszStyleDest, tch, COUNTOF(tch))) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), L"size:");
|
|
StringCchCat(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
} else if (!bIsFontDefInDestination && Style_StrGetSizeStr(lpszStyleSrc, tch, COUNTOF(tch))) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), L"size:");
|
|
StringCchCat(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
}
|
|
|
|
if (Style_StrHasAttribute(lpszStyleDest, FontEffects[FE_UNDERLINE])) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), FontEffects[FE_UNDERLINE]);
|
|
} else if (!bIsFontDefInDestination && Style_StrHasAttribute(lpszStyleSrc, FontEffects[FE_UNDERLINE])) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), FontEffects[FE_UNDERLINE]);
|
|
}
|
|
|
|
if (Style_StrHasAttribute(lpszStyleDest, FontEffects[FE_STRIKEOUT])) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), FontEffects[FE_STRIKEOUT]);
|
|
} else if (!bIsFontDefInDestination && Style_StrHasAttribute(lpszStyleSrc, FontEffects[FE_STRIKEOUT])) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), FontEffects[FE_STRIKEOUT]);
|
|
}
|
|
|
|
if (Style_StrGetCharSet(lpszStyleDest, &iValue)) {
|
|
StringCchPrintf(tch, COUNTOF(tch), L"charset:%i", iValue);
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
} else if (!bIsFontDefInDestination && Style_StrGetCharSet(lpszStyleSrc, &iValue)) {
|
|
StringCchPrintf(tch, COUNTOF(tch), L"charset:%i", iValue);
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
}
|
|
|
|
// foreground color
|
|
if (Style_StrGetColor(lpszStyleDest, FOREGROUND_LAYER, NULL, &dColor, false)) {
|
|
Style_PrintfCchColor(tch, COUNTOF(tch), L"; ", FOREGROUND_LAYER, dColor);
|
|
StringCchCat(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
}
|
|
else if (Style_StrGetColor(lpszStyleSrc, FOREGROUND_LAYER, NULL, &dColor, false)) {
|
|
Style_PrintfCchColor(tch, COUNTOF(tch), L"; ", FOREGROUND_LAYER, dColor);
|
|
StringCchCat(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
}
|
|
|
|
// ######## attributes not defined by Font Selection Dialog ########
|
|
|
|
// background color
|
|
if (Style_StrGetColor(lpszStyleDest, BACKGROUND_LAYER, NULL, &dColor, false)) {
|
|
Style_PrintfCchColor(tch, COUNTOF(tch), L"; ", BACKGROUND_LAYER, dColor);
|
|
StringCchCat(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
}
|
|
else if (Style_StrGetColor(lpszStyleSrc, BACKGROUND_LAYER, NULL, &dColor, false)) {
|
|
Style_PrintfCchColor(tch, COUNTOF(tch), L"; ", BACKGROUND_LAYER, dColor);
|
|
StringCchCat(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
}
|
|
|
|
int iFontQuality = Settings2.SciFontQuality;
|
|
if (Style_StrGetFontQuality(lpszStyleDest, tch, COUNTOF(tch), &iFontQuality)) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), L"smoothing:");
|
|
StringCchCat(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
} else if (!bIsFontDefInDestination && Style_StrGetFontQuality(lpszStyleSrc, tch, COUNTOF(tch), &iFontQuality)) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), L"smoothing:");
|
|
StringCchCat(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
}
|
|
|
|
// --------- Special Styles ---------
|
|
|
|
if (Style_StrHasAttribute(lpszStyleDest, FontEffects[FE_EOLFILLED])) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), FontEffects[FE_EOLFILLED]);
|
|
} else if (Style_StrHasAttribute(lpszStyleSrc, FontEffects[FE_EOLFILLED])) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), FontEffects[FE_EOLFILLED]);
|
|
}
|
|
|
|
if (Style_StrGetCase(lpszStyleDest, &iValue)) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), L"case:");
|
|
StringCchCat(szTmpStyle, COUNTOF(szTmpStyle), (iValue == SC_CASE_UPPER) ? L"U" : L"L");
|
|
} else if (Style_StrGetCase(lpszStyleSrc, &iValue)) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), L"case:");
|
|
StringCchCat(szTmpStyle, COUNTOF(szTmpStyle), (iValue == SC_CASE_UPPER) ? L"U" : L"L");
|
|
}
|
|
|
|
if (Style_StrGetAlpha(lpszStyleDest, &iValue, SC_ALPHA_OPAQUE, true)) {
|
|
StringCchPrintf(tch, COUNTOF(tch), L"alpha:%i", iValue);
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
}
|
|
else if (Style_StrGetAlpha(lpszStyleSrc, &iValue, SC_ALPHA_OPAQUE, true)) {
|
|
StringCchPrintf(tch, COUNTOF(tch), L"alpha:%i", iValue);
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
}
|
|
|
|
if (Style_StrGetAlpha(lpszStyleDest, &iValue, SC_ALPHA_OPAQUE, false)) {
|
|
StringCchPrintf(tch, COUNTOF(tch), L"alpha2:%i", iValue);
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
}
|
|
else if (Style_StrGetAlpha(lpszStyleSrc, &iValue, SC_ALPHA_OPAQUE, false)) {
|
|
StringCchPrintf(tch, COUNTOF(tch), L"alpha2:%i", iValue);
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
}
|
|
|
|
// -------- Indicator Type --------
|
|
|
|
bool indic_found = false;
|
|
iValue = -1; // find SCI index
|
|
StringCchCopy(tch, COUNTOF(tch), lpszStyleDest);
|
|
if (Style_GetIndicatorType(tch, 0, &iValue)) {
|
|
Style_GetIndicatorType(tch, COUNTOF(tch), &iValue);
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
indic_found = true;
|
|
}
|
|
if (!indic_found) {
|
|
iValue = -1; // find SCI index
|
|
StringCchCopy(tch, COUNTOF(tch), lpszStyleSrc);
|
|
if (Style_GetIndicatorType(tch, 0, &iValue)) {
|
|
Style_GetIndicatorType(tch, COUNTOF(tch), &iValue);
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), tch);
|
|
}
|
|
}
|
|
|
|
// -------- other style settings --------
|
|
if (Style_StrHasAttribute(lpszStyleDest, CaretStyle[CS_OVRBLCK])) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), CaretStyle[CS_OVRBLCK]);
|
|
} else if (Style_StrHasAttribute(lpszStyleSrc, CaretStyle[CS_OVRBLCK])) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), CaretStyle[CS_OVRBLCK]);
|
|
}
|
|
|
|
if (Style_StrHasAttribute(lpszStyleDest, CaretStyle[CS_BLOCK])) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), CaretStyle[CS_BLOCK]);
|
|
} else if (Style_StrHasAttribute(lpszStyleSrc, CaretStyle[CS_BLOCK])) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), CaretStyle[CS_BLOCK]);
|
|
}
|
|
|
|
if (Style_StrHasAttribute(lpszStyleDest, CaretStyle[CS_NOBLINK])) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), CaretStyle[CS_NOBLINK]);
|
|
} else if (Style_StrHasAttribute(lpszStyleSrc, CaretStyle[CS_NOBLINK])) {
|
|
AppendStyle(szTmpStyle, COUNTOF(szTmpStyle), CaretStyle[CS_NOBLINK]);
|
|
}
|
|
|
|
// cleanup
|
|
StrTrim(szTmpStyle, L" ;");
|
|
|
|
// replace destination by normalized string
|
|
StringCchCopy(lpszStyleDest, cchSizeDest, szTmpStyle);
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SelectFont()
|
|
//
|
|
bool Style_SelectFont(HWND hwnd, LPWSTR lpszStyle, int cchStyle, LPCWSTR sLexerName,
|
|
LPCWSTR sStyleName, DEFAULT_FONT_STYLES styleType)
|
|
{
|
|
|
|
// Map lpszStyle to LOGFONT
|
|
WCHAR wchDefaultFontName[LF_FACESIZE] = { L'\0' };
|
|
GetDefaultCodeFont(wchDefaultFontName, COUNTOF(wchDefaultFontName), 0);
|
|
|
|
// current base style
|
|
const WCHAR *const lpszBaseStyleDefinition = GetCurrentStdLexer()->Styles[STY_DEFAULT].szValue;
|
|
|
|
// current common default font name setting
|
|
WCHAR wchCurrCommonFontName[LF_FACESIZE] = { L'\0' };
|
|
if (!Style_StrGetFontName(lpszBaseStyleDefinition, wchCurrCommonFontName, COUNTOF(wchCurrCommonFontName))) {
|
|
StringCchCopy(wchCurrCommonFontName, COUNTOF(wchCurrCommonFontName), wchDefaultFontName);
|
|
}
|
|
|
|
// specified font name
|
|
WCHAR wchFontName[LF_FACESIZE] = { L'\0' };
|
|
if (!Style_StrGetFontName(lpszStyle, wchFontName, COUNTOF(wchFontName))) {
|
|
StringCchCopy(wchFontName, COUNTOF(wchFontName), wchCurrCommonFontName);
|
|
}
|
|
|
|
// font style
|
|
// NOTE: To globalists your application, you should specify the style by using
|
|
// the lfWeight and lfItalic members of the LOGFONT structure pointed to by lpLogFont.
|
|
// The style name may change depending on the system user interface language.
|
|
DWORD const flagUseStyle = 0; // = CF_USESTYLE; ~ don't use
|
|
|
|
// Font Weight
|
|
int iBaseFontWeight = FontWeights[FW_IDX_REGULAR].weight;
|
|
Style_StrGetWeightValue(lpszBaseStyleDefinition, &iBaseFontWeight);
|
|
|
|
int iFontWeight = iBaseFontWeight;
|
|
Style_StrGetWeightValue(lpszStyle, &iFontWeight);
|
|
|
|
// Italic / Oblique
|
|
bool const bIsItalic = Style_StrHasAttribute(lpszStyle, FontEffects[FE_ITALIC]);
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
int iCharSet = SC_CHARSET_DEFAULT;
|
|
Style_StrGetCharSet(lpszStyle, &iCharSet);
|
|
|
|
// is "size:" definition relative ?
|
|
bool const bRelFontSize = (StrStr(lpszStyle, L"size:+") || StrStr(lpszStyle, L"size:-"));
|
|
|
|
// Font Height
|
|
float fFontSize = GLOBAL_INITIAL_FONTSIZE;
|
|
switch (styleType) {
|
|
case DFS_GLOBAL:
|
|
fFontSize = Style_GetBaseFontSize();
|
|
break;
|
|
case DFS_CURR_LEXER:
|
|
fFontSize = Style_GetCurrentLexerFontSize();
|
|
break;
|
|
case DFS_GENERIC_USE:
|
|
default:
|
|
Style_StrGetSizeFloatEx(lpszStyle, &fFontSize);
|
|
break;
|
|
}
|
|
|
|
HDC const hdc = GetDC(hwnd);
|
|
int const iFontHeight = PointSizeToFontHeight(fFontSize, hdc);
|
|
ReleaseDC(hwnd, hdc);
|
|
|
|
int iFontStretch = SC_STRETCH_NORMAL;
|
|
Style_StrGetStretchValue(lpszStyle, &iFontStretch);
|
|
bool const bIsUnderline = Style_StrHasAttribute(lpszStyle, FontEffects[FE_UNDERLINE]);
|
|
bool const bIsStrikeout = Style_StrHasAttribute(lpszStyle, FontEffects[FE_STRIKEOUT]);
|
|
|
|
COLORREF fgColor = 0L;
|
|
Style_StrGetColor(lpszStyle, FOREGROUND_LAYER, &fgColor, NULL, true);
|
|
|
|
// Font Quality
|
|
WCHAR wchFontQuality[80] = { L'\0' };
|
|
int iFontQuality = Settings2.SciFontQuality;
|
|
Style_StrGetFontQuality(lpszStyle, wchFontQuality, COUNTOF(wchFontQuality), &iFontQuality);
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
LOGFONT lf = { 0 };
|
|
lf.lfCharSet = (BYTE)iCharSet;
|
|
lf.lfHeight = iFontHeight;
|
|
lf.lfWidth = 0; // let system calculate character width
|
|
lf.lfWeight = iFontWeight;
|
|
lf.lfItalic = (BYTE)(BOOL)bIsItalic;
|
|
lf.lfUnderline = (BYTE)(BOOL)bIsUnderline;
|
|
lf.lfStrikeOut = (BYTE)(BOOL)bIsStrikeout;
|
|
lf.lfQuality = (BYTE)MapSciToWinFontQuality(iFontQuality);
|
|
//~lf.lfClipPrecision = (BYTE)CLIP_DEFAULT_PRECIS;
|
|
//~lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
|
|
|
|
StringCchCopy(lf.lfFaceName, LF_FACESIZE, wchFontName); // (!) not LF_FULLFACESIZE
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// Init cf
|
|
CHOOSEFONT cf = { sizeof(CHOOSEFONT) }; // cf.lStructSize = sizeof(CHOOSEFONT);
|
|
cf.hwndOwner = hwnd;
|
|
cf.hInstance = Globals.hLngResContainer; // Globals.hInstance;
|
|
|
|
cf.iPointSize = (INT)f2int(fFontSize * 10.0f);
|
|
cf.rgbColors = fgColor;
|
|
|
|
// --- FLAGS ---
|
|
cf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_FORCEFONTEXIST; // | CF_NOSCRIPTSEL
|
|
|
|
// use logfont struct
|
|
cf.Flags |= CF_INITTOLOGFONTSTRUCT;
|
|
cf.lpLogFont = (LPLOGFONT)&lf;
|
|
|
|
cf.Flags |= (SciCall_GetTechnology() != SC_TECHNOLOGY_DEFAULT) ? CF_SCALABLEONLY : 0;
|
|
cf.Flags |= IsKeyDown(VK_SHIFT) ? CF_FIXEDPITCHONLY : 0;
|
|
|
|
// font style (
|
|
cf.Flags |= flagUseStyle; //~ CF_USESTYLE
|
|
cf.lpszStyle = NULL; //~flagUseStyle ? szStyleStrg : NULL;
|
|
|
|
// Font size limits
|
|
cf.Flags |= CF_LIMITSIZE;
|
|
cf.nSizeMin = 4;
|
|
cf.nSizeMax = 128;
|
|
|
|
// custom hook for title bar
|
|
cf.Flags |= CF_ENABLEHOOK;
|
|
cf.lpfnHook = (LPCFHOOKPROC)FontDialogHookProc; // Register the callback
|
|
cf.lCustData = (LPARAM)FontSelTitle;
|
|
|
|
// Font.dlg resource template
|
|
cf.Flags |= CF_ENABLETEMPLATE;
|
|
cf.lpTemplateName = MAKEINTRESOURCEW(IDD_MUI_SYSFONT_WITHLINK);
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
switch (styleType) {
|
|
case DFS_GLOBAL:
|
|
FormatLngStringW(FontSelTitle, COUNTOF(FontSelTitle), bRelFontSize ? IDS_MUI_TITLE_RELBASE : IDS_MUI_TITLE_FIXBASE, sStyleName);
|
|
break;
|
|
case DFS_CURR_LEXER:
|
|
FormatLngStringW(FontSelTitle, COUNTOF(FontSelTitle), bRelFontSize ? IDS_MUI_TITLE_RELCUR : IDS_MUI_TITLE_FIXCUR, sLexerName, sStyleName);
|
|
break;
|
|
case DFS_GENERIC_USE:
|
|
default:
|
|
FormatLngStringW(FontSelTitle, COUNTOF(FontSelTitle), bRelFontSize ? IDS_MUI_TITLE_RELARB : IDS_MUI_TITLE_FIXARB, sStyleName, sLexerName);
|
|
break;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
#if TRUE
|
|
|
|
// --- open systems Font Selection dialog ---
|
|
if (!ChooseFont(&cf) || StrIsEmpty(lf.lfFaceName)) {
|
|
return false;
|
|
}
|
|
|
|
#else
|
|
|
|
if (Settings.RenderingTechnology > 0) {
|
|
UINT const dpi = Scintilla_GetWindowDPI(hwnd);
|
|
const WCHAR *const localName = Settings2.PreferredLanguageLocaleName;
|
|
if (!ChooseFontDirectWrite(Globals.hwndMain, localName, dpi, &cf) || StrIsEmpty(lf.lfFaceName)) {
|
|
return false;
|
|
}
|
|
// HACK: to get the full font name instead of font family name
|
|
// [see: Style_FontDialogHook() WM_INITDIALOG]
|
|
cf.lCustData = (LPARAM)NULL;
|
|
ChooseFont(&cf);
|
|
} else {
|
|
if (!ChooseFont(&cf) || StrIsEmpty(lf.lfFaceName)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
// --- map back to lpszStyle ---
|
|
|
|
WCHAR szNewStyle[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
|
|
if (StringCchCompareX(lf.lfFaceName, wchDefaultFontName) == 0) {
|
|
StringCchCopy(szNewStyle, COUNTOF(szNewStyle), L"font:$Code0");
|
|
} else {
|
|
StringCchPrintf(szNewStyle, COUNTOF(szNewStyle), L"font:%s", lf.lfFaceName);
|
|
}
|
|
|
|
if (lf.lfWeight != FontWeights[FW_IDX_REGULAR].weight) {
|
|
Style_AppendWeightAttribute(szNewStyle, COUNTOF(szNewStyle), lf.lfWeight);
|
|
}
|
|
|
|
// persist stretch (ChooseFont dialog doesn't modify it, so round-trip the original)
|
|
if (iFontStretch != SC_STRETCH_NORMAL) {
|
|
Style_AppendStretchAttribute(szNewStyle, COUNTOF(szNewStyle), iFontStretch);
|
|
}
|
|
|
|
if (lf.lfItalic) {
|
|
AppendStyle(szNewStyle, COUNTOF(szNewStyle), FontEffects[FE_ITALIC]);
|
|
}
|
|
|
|
float const fNewFontSize = ((float)(cf.iPointSize < 10 ? 10 : cf.iPointSize)) / 10.0f;
|
|
|
|
switch (styleType) {
|
|
case DFS_GLOBAL:
|
|
Style_AppendSizeAttribute(szNewStyle, COUNTOF(szNewStyle), fNewFontSize, bRelFontSize ? GLOBAL_INITIAL_FONTSIZE : 0.0f);
|
|
break;
|
|
case DFS_CURR_LEXER:
|
|
Style_AppendSizeAttribute(szNewStyle, COUNTOF(szNewStyle), fNewFontSize, bRelFontSize ? Style_GetBaseFontSize() : 0.0f);
|
|
break;
|
|
case DFS_GENERIC_USE:
|
|
default:
|
|
Style_AppendSizeAttribute(szNewStyle, COUNTOF(szNewStyle), fNewFontSize, bRelFontSize ? Style_GetCurrentLexerFontSize() : 0.0f);
|
|
break;
|
|
}
|
|
|
|
if ((lf.lfCharSet != DEFAULT_CHARSET) && (lf.lfCharSet != ANSI_CHARSET)) {
|
|
WCHAR chset[32] = { L'\0' };
|
|
StringCchPrintf(chset, COUNTOF(chset), L"charset:%i", GdiCharsetToSci(lf.lfCharSet));
|
|
AppendStyle(szNewStyle, COUNTOF(szNewStyle), chset);
|
|
}
|
|
|
|
if (lf.lfUnderline) {
|
|
AppendStyle(szNewStyle, COUNTOF(szNewStyle), FontEffects[FE_UNDERLINE]);
|
|
}
|
|
|
|
if (lf.lfStrikeOut) {
|
|
AppendStyle(szNewStyle, COUNTOF(szNewStyle), FontEffects[FE_STRIKEOUT]);
|
|
}
|
|
|
|
COLORREF fgColorDefault = 0L;
|
|
Style_StrGetColor(L"", FOREGROUND_LAYER, &fgColorDefault, NULL, true);
|
|
if (cf.rgbColors != fgColorDefault) {
|
|
WCHAR fgColorStr[32] = { L'\0' };
|
|
Style_PrintfCchColor(fgColorStr, COUNTOF(fgColorStr), L"; ", FOREGROUND_LAYER, cf.rgbColors);
|
|
StringCchCat(szNewStyle, COUNTOF(szNewStyle), fgColorStr);
|
|
}
|
|
|
|
// Font Quality
|
|
if (StrIsNotEmpty(wchFontQuality)) {
|
|
AppendStyle(szNewStyle, COUNTOF(szNewStyle), L"smoothing:");
|
|
StringCchCat(szNewStyle, COUNTOF(szNewStyle), wchFontQuality);
|
|
}
|
|
|
|
// copy all other styles (incl. background color)
|
|
Style_CopyStyles_IfNotDefined(lpszStyle, szNewStyle, COUNTOF(szNewStyle));
|
|
|
|
StrTrim(szNewStyle, L" ;");
|
|
StringCchCopy(lpszStyle, cchStyle, szNewStyle);
|
|
return true;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SelectColor()
|
|
//
|
|
bool Style_SelectColor(HWND hwnd,bool bForeGround,LPWSTR lpszStyle,int cchStyle, bool bPreserveStyles)
|
|
{
|
|
WCHAR szNewStyle[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
COLORREF dColor;
|
|
WCHAR tch[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
|
|
COLOR_LAYER const layer = (bForeGround ? FOREGROUND_LAYER : BACKGROUND_LAYER);
|
|
COLORREF dRGBResult;
|
|
Style_StrGetColor(lpszStyle, layer, &dRGBResult, NULL, true);
|
|
|
|
CHOOSECOLOR cc = { sizeof(CHOOSECOLOR) };
|
|
cc.hwndOwner = hwnd;
|
|
cc.hInstance = (HWND)Globals.hLngResContainer; // Globals.hInstance;
|
|
cc.rgbResult = dRGBResult;
|
|
cc.lpCustColors = &g_colorCustom[0];
|
|
cc.Flags = CC_FULLOPEN | CC_RGBINIT | CC_SOLIDCOLOR;
|
|
|
|
// custom hook
|
|
cc.Flags |= CC_ENABLEHOOK;
|
|
cc.lpfnHook = (LPCCHOOKPROC)ColorDialogHookProc;
|
|
cc.lCustData = (LPARAM)NULL;
|
|
|
|
// Color.dlg resource template
|
|
cc.Flags |= CC_ENABLETEMPLATE | CC_ENABLETEMPLATEHANDLE;
|
|
cc.lpTemplateName = MAKEINTRESOURCEW(IDD_MUI_SYSCOLOR_DLG);
|
|
|
|
if (!ChooseColor(&cc)) {
|
|
return false;
|
|
}
|
|
dRGBResult = cc.rgbResult;
|
|
|
|
// Rebuild style string
|
|
szNewStyle[0] = L'\0'; // clear
|
|
|
|
if (bForeGround) {
|
|
|
|
Style_PrintfCchColor(tch, COUNTOF(tch), L"; ", FOREGROUND_LAYER, dRGBResult);
|
|
StringCchCat(szNewStyle,COUNTOF(szNewStyle),tch);
|
|
|
|
if (Style_StrGetColor(lpszStyle, BACKGROUND_LAYER, &dColor, NULL, false)) {
|
|
Style_PrintfCchColor(tch, COUNTOF(tch), L"; ", BACKGROUND_LAYER, dColor);
|
|
StringCchCat(szNewStyle,COUNTOF(szNewStyle),tch);
|
|
}
|
|
|
|
} else { // set background
|
|
|
|
if (Style_StrGetColor(lpszStyle, FOREGROUND_LAYER, &dColor, NULL, false)) {
|
|
Style_PrintfCchColor(tch, COUNTOF(tch), L"; ", FOREGROUND_LAYER, dColor);
|
|
StringCchCat(szNewStyle,COUNTOF(szNewStyle),tch);
|
|
}
|
|
Style_PrintfCchColor(tch, COUNTOF(tch), L"; ", BACKGROUND_LAYER, dRGBResult);
|
|
StringCchCat(szNewStyle,COUNTOF(szNewStyle),tch);
|
|
}
|
|
|
|
if (bPreserveStyles) {
|
|
// copy all other styles
|
|
Style_CopyStyles_IfNotDefined(lpszStyle, szNewStyle, COUNTOF(szNewStyle));
|
|
}
|
|
|
|
StrTrim(szNewStyle, L" ;");
|
|
StringCchCopy(lpszStyle, cchStyle, szNewStyle);
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SetStyles()
|
|
//
|
|
void Style_SetStyles(HWND hwnd, const int iStyle, LPCWSTR lpszStyle, const float fBaseFontSize)
|
|
{
|
|
bool const bIsDefaultStyle = (iStyle == STYLE_DEFAULT);
|
|
|
|
if (!bIsDefaultStyle && StrIsEmpty(lpszStyle)) {
|
|
return;
|
|
}
|
|
|
|
int iValue = 0;
|
|
WCHAR tch[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
|
|
// reset horizontal scrollbar width
|
|
SciCall_SetScrollWidth(1);
|
|
|
|
// === FONT ===
|
|
|
|
// Font Face Name
|
|
WCHAR wchFontName[LF_FACESIZE] = { L'\0' };
|
|
if (!Style_StrGetFontName(lpszStyle, wchFontName, COUNTOF(wchFontName))) {
|
|
if (bIsDefaultStyle) {
|
|
//?Style_StrGetFontName(GetCurrentStdLexer()->Styles[STY_DEFAULT].szValue, wchFontName, COUNTOF(wchFontName));
|
|
GetDefaultCodeFont(wchFontName, COUNTOF(wchFontName), 0);
|
|
}
|
|
}
|
|
if (StrIsNotEmpty(wchFontName)) {
|
|
char chSetFontName[LF_FACESIZE<<2] = { '\0' };
|
|
WideCharToMultiByte(CP_UTF8, 0, wchFontName, -1, chSetFontName, (int)COUNTOF(chSetFontName), NULL, NULL);
|
|
SciCall_StyleSetFont(iStyle, chSetFontName);
|
|
}
|
|
|
|
// Font Weight
|
|
if (Style_StrGetWeightValue(lpszStyle, &iValue)) {
|
|
SciCall_StyleSetWeight(iStyle, iValue);
|
|
} else if (bIsDefaultStyle) {
|
|
SciCall_StyleSetWeight(iStyle, SC_WEIGHT_NORMAL);
|
|
}
|
|
|
|
// Font Stretch
|
|
if (Style_StrGetStretchValue(lpszStyle, &iValue)) {
|
|
SciCall_StyleSetStretch(iStyle, iValue);
|
|
} else if (bIsDefaultStyle) {
|
|
SciCall_StyleSetStretch(iStyle, SC_STRETCH_NORMAL);
|
|
}
|
|
|
|
// Italic
|
|
SciCall_StyleSetItalic(iStyle, Style_StrHasAttribute(lpszStyle, FontEffects[FE_ITALIC]));
|
|
|
|
// Font Quality
|
|
int iFontQuality = Settings2.SciFontQuality;
|
|
if (bIsDefaultStyle) {
|
|
if (Style_StrGetFontQuality(lpszStyle, tch, COUNTOF(tch), &iFontQuality)) {
|
|
SciCall_SetFontQuality(iFontQuality);
|
|
} else {
|
|
SciCall_SetFontQuality(Settings2.SciFontQuality);
|
|
}
|
|
}
|
|
|
|
// Size values are relative to BaseFontSize/CurrentFontSize
|
|
if (iStyle != STYLE_INDENTGUIDE) {
|
|
float fFontSize = fBaseFontSize;
|
|
Style_StrGetSizeFloatEx(lpszStyle, &fFontSize);
|
|
SendMessage(hwnd, SCI_STYLESETSIZEFRACTIONAL, iStyle, f2int(fFontSize * SC_FONT_SIZE_MULTIPLIER));
|
|
}
|
|
else {
|
|
float fWidth = 1.0;
|
|
Style_StrGetSizeFloatEx(lpszStyle, &fWidth);
|
|
int const width = clampi(f2int(fWidth), 0, f2int(fBaseFontSize));
|
|
SciCall_SetMarginLeft(width); // dead margin
|
|
}
|
|
|
|
char localeNameA[LOCALE_NAME_MAX_LENGTH] = "en-us\0";
|
|
#if defined(HAVE_DYN_LOAD_LIBS_MUI_LNGS)
|
|
WideCharToMultiByte(CP_UTF8, 0, Settings2.PreferredLanguageLocaleName, -1, localeNameA, COUNTOF(localeNameA), NULL, NULL);
|
|
#else
|
|
WideCharToMultiByte(CP_UTF8, 0, MUI_BASE_LNG_ID, -1, localeNameA, COUNTOF(localeNameA), NULL, NULL);
|
|
#endif
|
|
SciCall_SetFontLocale(localeNameA);
|
|
|
|
// Character Set
|
|
if (Style_StrGetCharSet(lpszStyle, &iValue)) {
|
|
SendMessage(hwnd, SCI_STYLESETCHARACTERSET, iStyle, (LPARAM)iValue);
|
|
} else if (bIsDefaultStyle) {
|
|
SendMessage(hwnd, SCI_STYLESETCHARACTERSET, iStyle, (LPARAM)SC_CHARSET_DEFAULT);
|
|
}
|
|
|
|
COLORREF dColor = 0L;
|
|
// Foregr
|
|
if (Style_StrGetColor(lpszStyle, FOREGROUND_LAYER, &dColor, NULL, false)) {
|
|
SciCall_StyleSetFore(iStyle, dColor);
|
|
} else if (bIsDefaultStyle) {
|
|
SciCall_StyleSetFore(iStyle, GetModeTextColor(UseDarkMode()));
|
|
} else { // fallback: SCI default
|
|
Style_StrGetColor(lpszStyle, FOREGROUND_LAYER, &dColor, NULL, true);
|
|
SciCall_StyleSetFore(iStyle, dColor);
|
|
}
|
|
|
|
// Backgr
|
|
if (Style_StrGetColor(lpszStyle, BACKGROUND_LAYER, &dColor, NULL, false)) {
|
|
SciCall_StyleSetBack(iStyle, dColor);
|
|
} else if (bIsDefaultStyle) {
|
|
SciCall_StyleSetBack(iStyle, GetModeBkColor(UseDarkMode()));
|
|
} else { // fallback: SCI default
|
|
Style_StrGetColor(lpszStyle, BACKGROUND_LAYER, &dColor, NULL, true);
|
|
SciCall_StyleSetBack(iStyle, dColor);
|
|
}
|
|
|
|
// Underline
|
|
if (Style_StrHasAttribute(lpszStyle, FontEffects[FE_UNDERLINE])) {
|
|
SendMessage(hwnd, SCI_STYLESETUNDERLINE, iStyle, (LPARAM)true);
|
|
} else if (bIsDefaultStyle) {
|
|
SendMessage(hwnd, SCI_STYLESETUNDERLINE, iStyle, (LPARAM)false);
|
|
}
|
|
// StrikeOut
|
|
if (Style_StrHasAttribute(lpszStyle, FontEffects[FE_STRIKEOUT])) {
|
|
SendMessage(hwnd, SCI_STYLESETSTRIKE, iStyle, (LPARAM)true);
|
|
} else if (bIsDefaultStyle) {
|
|
SendMessage(hwnd, SCI_STYLESETSTRIKE, iStyle, (LPARAM)false);
|
|
}
|
|
// EOL Filled
|
|
if (Style_StrHasAttribute(lpszStyle, FontEffects[FE_EOLFILLED])) {
|
|
SendMessage(hwnd, SCI_STYLESETEOLFILLED, iStyle, (LPARAM)true);
|
|
} else if (bIsDefaultStyle) {
|
|
SendMessage(hwnd, SCI_STYLESETEOLFILLED, iStyle, (LPARAM)false);
|
|
}
|
|
// Case
|
|
if (Style_StrGetCase(lpszStyle, &iValue)) {
|
|
SendMessage(hwnd, SCI_STYLESETCASE, iStyle, (LPARAM)iValue);
|
|
} else if (bIsDefaultStyle) {
|
|
SendMessage(hwnd, SCI_STYLESETCASE, iStyle, (LPARAM)SC_CASE_MIXED);
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_GetCurrentLexerPtr()
|
|
//
|
|
PEDITLEXER Style_GetCurrentLexerPtr()
|
|
{
|
|
return s_pLexCurrent;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_GetCurrentLexerRID()
|
|
//
|
|
int Style_GetCurrentLexerRID()
|
|
{
|
|
return s_pLexCurrent->resID;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_GetLexerDisplayName()
|
|
//
|
|
void Style_GetLexerDisplayName(PEDITLEXER pLexer, LPWSTR lpszName, int cchName)
|
|
{
|
|
if (!pLexer) {
|
|
pLexer = &lexStandard; // don't distinguish between STD/2ND
|
|
}
|
|
if (!GetLngString(pLexer->resID, lpszName, cchName)) {
|
|
StringCchCopyW(lpszName, cchName, pLexer->pszName);
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_GetStyleDisplayName()
|
|
//
|
|
void Style_GetStyleDisplayName(PEDITSTYLE pStyle, LPWSTR lpszName, int cchName)
|
|
{
|
|
if (pStyle) {
|
|
if (!GetLngString(pStyle->rid, lpszName, cchName)) {
|
|
StringCchCopyW(lpszName, cchName, pStyle->pszName);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_GetLexerIconId()
|
|
//
|
|
int Style_GetLexerIconId(PEDITLEXER plex)
|
|
{
|
|
WCHAR pszFile[STYLE_EXTENTIONS_BUFFER << 1];
|
|
|
|
LPCWSTR pszExtensions = StrIsNotEmpty(plex->szExtensions) ? plex->szExtensions : plex->pszDefExt;
|
|
StringCchCopy(pszFile, COUNTOF(pszFile), L"*.");
|
|
StringCchCat(pszFile, COUNTOF(pszFile), pszExtensions);
|
|
|
|
WCHAR *p = StrChrW(pszFile, L';');
|
|
if (p) {
|
|
*p = L'\0';
|
|
}
|
|
|
|
// check for ; at beginning
|
|
if (StringCchLen(pszFile, COUNTOF(pszFile)) < 3) {
|
|
StringCchCat(pszFile, COUNTOF(pszFile), L"txt");
|
|
}
|
|
SHFILEINFO shfi = { 0 };
|
|
SHGetFileInfo(pszFile,FILE_ATTRIBUTE_NORMAL,&shfi,sizeof(SHFILEINFO),
|
|
SHGFI_SMALLICON | SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES);
|
|
|
|
return (shfi.iIcon);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_AddLexerToTreeView()
|
|
//
|
|
HTREEITEM Style_AddLexerToTreeView(HWND hwnd,PEDITLEXER plex)
|
|
{
|
|
WCHAR tch[MIDSZ_BUFFER] = { L'\0' };
|
|
|
|
HTREEITEM hTreeNode;
|
|
|
|
TVINSERTSTRUCT tvis = { 0 };
|
|
tvis.hInsertAfter = TVI_LAST;
|
|
tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
|
|
|
|
if (GetLngString(plex->resID,tch,COUNTOF(tch))) {
|
|
tvis.item.pszText = tch;
|
|
} else {
|
|
tvis.item.pszText = (LPWSTR)plex->pszName;
|
|
}
|
|
|
|
tvis.item.iImage = Style_GetLexerIconId(plex);
|
|
tvis.item.iSelectedImage = tvis.item.iImage;
|
|
tvis.item.lParam = (LPARAM)plex;
|
|
|
|
hTreeNode = TreeView_InsertItem(hwnd,&tvis);
|
|
|
|
tvis.hParent = hTreeNode;
|
|
|
|
tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
|
|
//tvis.item.iImage = -1;
|
|
//tvis.item.iSelectedImage = -1;
|
|
|
|
int i = 1; // default style is handled separately
|
|
while (plex->Styles[i].iStyle != -1) {
|
|
|
|
if (GetLngString(plex->Styles[i].rid,tch,COUNTOF(tch))) {
|
|
tvis.item.pszText = tch;
|
|
} else {
|
|
tvis.item.pszText = (LPWSTR)plex->Styles[i].pszName;
|
|
}
|
|
tvis.item.lParam = (LPARAM)(&plex->Styles[i]);
|
|
TreeView_InsertItem(hwnd,&tvis);
|
|
i++;
|
|
}
|
|
|
|
return hTreeNode;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_AddLexerToListView()
|
|
//
|
|
void Style_AddLexerToListView(HWND hwnd,PEDITLEXER plex)
|
|
{
|
|
WCHAR tch[MIDSZ_BUFFER] = { L'\0' };
|
|
LVITEM lvi = { 0 };
|
|
lvi.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT;
|
|
lvi.iItem = ListView_GetItemCount(hwnd);
|
|
if (GetLngString(plex->resID,tch,COUNTOF(tch))) {
|
|
lvi.pszText = tch;
|
|
} else {
|
|
lvi.pszText = (LPWSTR)plex->pszName;
|
|
}
|
|
lvi.iImage = Style_GetLexerIconId(plex);
|
|
lvi.lParam = (LPARAM)plex;
|
|
|
|
ListView_InsertItem(hwnd,&lvi);
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_CustomizeSchemesDlgProc()
|
|
//
|
|
|
|
static bool _ApplyDialogItemText(HWND hwnd, PEDITLEXER pDlgLexer, PEDITSTYLE pDlgStyle, int iDlgStyleIdx, bool bIsStyleSelected)
|
|
{
|
|
UNREFERENCED_PARAMETER(iDlgStyleIdx);
|
|
|
|
bool bChgNfy = false;
|
|
bool bForce = false;
|
|
|
|
WCHAR szBuf[max(BUFSIZE_STYLE_VALUE, STYLE_EXTENTIONS_BUFFER)] = { L'\0' };
|
|
GetDlgItemText(hwnd, IDC_STYLEEDIT, szBuf, COUNTOF(szBuf));
|
|
// normalize
|
|
WCHAR szBufNorm[max(BUFSIZE_STYLE_VALUE, STYLE_EXTENTIONS_BUFFER)] = { L'\0' };
|
|
Style_CopyStyles_IfNotDefined(szBuf, szBufNorm, COUNTOF(szBufNorm));
|
|
|
|
if (StringCchCompareXI(szBufNorm, pDlgStyle->szValue) != 0) {
|
|
StringCchCopy(pDlgStyle->szValue, COUNTOF(pDlgStyle->szValue), szBufNorm);
|
|
bChgNfy = true;
|
|
}
|
|
if (!bIsStyleSelected) { // must be file extensions
|
|
if (!GetDlgItemText(hwnd, IDC_STYLEEDIT_ROOT, szBuf, COUNTOF(szBuf))) {
|
|
StringCchCopy(szBuf, COUNTOF(szBuf), pDlgLexer->pszDefExt);
|
|
}
|
|
if (StringCchCompareXI(szBuf, pDlgLexer->szExtensions) != 0) {
|
|
StringCchCopy(pDlgLexer->szExtensions, COUNTOF(pDlgLexer->szExtensions), szBuf);
|
|
bChgNfy = true;
|
|
}
|
|
}
|
|
|
|
char chDMHlContrast[96];
|
|
GetDlgItemTextA(hwnd, IDC_DARK_MODE_CONTRAST, chDMHlContrast, COUNTOF(chDMHlContrast));
|
|
te_int_t iExprError = 0;
|
|
int iDmHlCntrst = clampi((int)round(te_interp(chDMHlContrast, &iExprError)), 0, 6000);
|
|
if (iExprError > 1) {
|
|
chDMHlContrast[iExprError - 1] = '\0';
|
|
iDmHlCntrst = clampi((int)round(te_interp(chDMHlContrast, &iExprError)), 0, 6000);
|
|
}
|
|
if ((iExprError == 0) && (iDmHlCntrst != Settings.DarkModeHiglightContrast)) {
|
|
Settings.DarkModeHiglightContrast = iDmHlCntrst;
|
|
bForce = true;
|
|
}
|
|
SetDlgItemInt(hwnd, IDC_DARK_MODE_CONTRAST, Settings.DarkModeHiglightContrast, false);
|
|
|
|
if (bForce || (bChgNfy && (IsLexerStandard(pDlgLexer) || (pDlgLexer == s_pLexCurrent)))) {
|
|
Style_ResetCurrentLexer(Globals.hwndEdit);
|
|
}
|
|
return bChgNfy;
|
|
}
|
|
|
|
|
|
static WCHAR s_OrigTitle[64] = { L'\0' };
|
|
static WCHAR s_TitleTxt[128] = { L'\0' };
|
|
|
|
static void _UpdateTitleText(HWND hwnd)
|
|
{
|
|
if (StrIsEmpty(s_OrigTitle)) {
|
|
GetWindowText(hwnd, s_OrigTitle, COUNTOF(s_OrigTitle));
|
|
}
|
|
WCHAR scheme[96] = { L'\0' };
|
|
StringCchCopy(scheme, COUNTOF(scheme), Theme_Files[Globals.uCurrentThemeIndex].szName);
|
|
StrDelChr(scheme, L"&"); // rm hotkey mark
|
|
PWCHAR const e = StrChr(scheme, L' ');
|
|
if (e) {
|
|
*e = L'\0'; // until 1st space
|
|
}
|
|
StringCchPrintf(s_TitleTxt, COUNTOF(s_TitleTxt), L"%s - %s", s_OrigTitle, scheme);
|
|
SetWindowText(hwnd, s_TitleTxt);
|
|
}
|
|
|
|
|
|
static void _style_copy(void* _dst, const void* _src) {
|
|
LPCWSTR const * src = (LPWSTR const *)_src;
|
|
LPCWSTR * dst = (LPWSTR *)_dst;
|
|
*dst = *src ? StrDup(*src) : NULL;
|
|
}
|
|
|
|
static void _style_dtor(void *_elt) {
|
|
LPWSTR * const elt = (LPWSTR *)_elt;
|
|
if (*elt) { LocalFree(*elt); }
|
|
}
|
|
|
|
static UT_icd _style_icd = { sizeof(LPWSTR), NULL, _style_copy, _style_dtor };
|
|
|
|
INT_PTR CALLBACK Style_CustomizeSchemesDlgProc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static HWND hwndTV;
|
|
static HFONT hFontTitle = NULL;
|
|
static bool fDragging;
|
|
static PEDITLEXER pCurrentLexer = NULL;
|
|
static PEDITSTYLE pCurrentStyle = NULL;
|
|
static int iCurStyleIdx = -1;
|
|
static HBRUSH hbrFore = { 0 };
|
|
static HBRUSH hbrBack = { 0 };
|
|
static bool bIsStyleSelected = false;
|
|
static bool bWarnedNoIniFile = false;
|
|
static int iDMHighliteContrast = 75;
|
|
|
|
static WCHAR tchTmpBuffer[max(BUFSIZE_STYLE_VALUE, STYLE_EXTENTIONS_BUFFER)] = {L'\0'};
|
|
static UT_array *pStylesBackup = NULL;
|
|
|
|
switch (umsg) {
|
|
case WM_INITDIALOG: {
|
|
SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)lParam);
|
|
|
|
SetDialogIconNP3(hwnd);
|
|
InitWindowCommon(hwnd, true);
|
|
|
|
_UpdateTitleText(hwnd);
|
|
|
|
if (pStylesBackup) {
|
|
utarray_free(pStylesBackup);
|
|
pStylesBackup = NULL;
|
|
}
|
|
utarray_new(pStylesBackup, &_style_icd);
|
|
|
|
#ifdef D_NP3_WIN10_DARK_MODE
|
|
if (UseDarkMode()) {
|
|
SetExplorerTheme(GetDlgItem(hwnd, IDOK));
|
|
SetExplorerTheme(GetDlgItem(hwnd, IDCANCEL));
|
|
SetExplorerTheme(GetDlgItem(hwnd, IDC_STYLEFORE));
|
|
SetExplorerTheme(GetDlgItem(hwnd, IDC_STYLEBACK));
|
|
SetExplorerTheme(GetDlgItem(hwnd, IDC_STYLEFONT));
|
|
SetExplorerTheme(GetDlgItem(hwnd, IDC_PREVIEW));
|
|
SetExplorerTheme(GetDlgItem(hwnd, IDC_STYLEDEFAULT));
|
|
SetExplorerTheme(GetDlgItem(hwnd, IDC_PREVSTYLE));
|
|
SetExplorerTheme(GetDlgItem(hwnd, IDC_NEXTSTYLE));
|
|
SetExplorerTheme(GetDlgItem(hwnd, IDC_DARK_MODE_CONTRAST));
|
|
SetExplorerTheme(GetDlgItem(hwnd, IDC_IMPORT));
|
|
SetExplorerTheme(GetDlgItem(hwnd, IDC_EXPORT));
|
|
//SetExplorerTheme(GetDlgItem(hwnd, IDC_RESIZEGRIP));
|
|
// remove themes to colorize static controls correctly
|
|
SetWindowTheme(GetDlgItem(hwnd, IDC_STATIC), L"", L"");
|
|
SetWindowTheme(GetDlgItem(hwnd, IDC_INFO_GROUPBOX), L"", L"");
|
|
}
|
|
#endif
|
|
UINT const dpi = Scintilla_GetWindowDPI(hwnd);
|
|
|
|
GetLngString(IDS_MUI_STYLEEDIT_HELP, tchTmpBuffer, COUNTOF(tchTmpBuffer));
|
|
SetDlgItemText(hwnd, IDC_STYLEEDIT_HELP, tchTmpBuffer);
|
|
|
|
// Backup Styles
|
|
for (int iLexer = 0; iLexer < COUNTOF(g_pLexArray); ++iLexer) {
|
|
LPCWSTR const pExt = g_pLexArray[iLexer]->szExtensions;
|
|
utarray_push_back(pStylesBackup, &pExt);
|
|
int i = 0;
|
|
while (g_pLexArray[iLexer]->Styles[i].iStyle != -1) {
|
|
LPCWSTR const pVal = g_pLexArray[iLexer]->Styles[i++].szValue;
|
|
utarray_push_back(pStylesBackup, &pVal);
|
|
}
|
|
}
|
|
|
|
hwndTV = GetDlgItem(hwnd, IDC_STYLELIST);
|
|
fDragging = false;
|
|
|
|
SHFILEINFO shfi = { 0 };
|
|
|
|
InitWindowCommon(hwndTV, true);
|
|
InitTreeView(hwndTV);
|
|
|
|
TreeView_SetExtendedStyle(hwndTV, TVS_EX_DOUBLEBUFFER, TVS_EX_DOUBLEBUFFER);
|
|
|
|
UINT const flagIconSize = (dpi >= LargeIconDPI()) ? SHGFI_LARGEICON : SHGFI_SMALLICON;
|
|
TreeView_SetImageList(hwndTV,
|
|
(HIMAGELIST)SHGetFileInfoW(L"C:\\", FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(SHFILEINFO),
|
|
flagIconSize | SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES),
|
|
TVSIL_NORMAL);
|
|
|
|
// findlexer
|
|
int found = -1;
|
|
for (int i = 0; i < COUNTOF(g_pLexArray); ++i) {
|
|
if (g_pLexArray[i] == s_pLexCurrent) {
|
|
found = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Build lexer tree view
|
|
HTREEITEM hCurrentTVLex = NULL;
|
|
for (int i = 0; i < COUNTOF(g_pLexArray); i++) {
|
|
if (i == found) {
|
|
hCurrentTVLex = Style_AddLexerToTreeView(hwndTV, g_pLexArray[i]);
|
|
} else {
|
|
Style_AddLexerToTreeView(hwndTV, g_pLexArray[i]);
|
|
}
|
|
}
|
|
if (!hCurrentTVLex) {
|
|
hCurrentTVLex = TreeView_GetRoot(hwndTV);
|
|
if (Style_GetUse2ndDefault()) {
|
|
hCurrentTVLex = TreeView_GetNextSibling(hwndTV, hCurrentTVLex);
|
|
}
|
|
}
|
|
TreeView_Select(hwndTV, hCurrentTVLex, TVGN_CARET);
|
|
TreeView_Expand(hwndTV, hCurrentTVLex, TVE_EXPAND);
|
|
|
|
pCurrentLexer = (found >= 0) ? s_pLexCurrent : GetDefaultLexer();
|
|
pCurrentStyle = &(pCurrentLexer->Styles[STY_DEFAULT]);
|
|
iCurStyleIdx = STY_DEFAULT;
|
|
|
|
SendDlgItemMessage(hwnd, IDC_STYLEEDIT, EM_LIMITTEXT, max(BUFSIZE_STYLE_VALUE, STYLE_EXTENTIONS_BUFFER) - 1, 0);
|
|
|
|
MakeBitmapButton(hwnd, IDC_PREVSTYLE, IDB_PREV, -1, -1);
|
|
MakeBitmapButton(hwnd, IDC_NEXTSTYLE, IDB_NEXT, -1, -1);
|
|
|
|
COLORREF cr = COLORREF_MAX; // SciCall_StyleGetFore(STYLE_DEFAULT);
|
|
MakeColorPickButton(hwnd, IDC_STYLEFORE, Globals.hInstance, cr);
|
|
MakeColorPickButton(hwnd, IDC_STYLEBACK, Globals.hInstance, cr);
|
|
|
|
if (Settings.CustomSchemesDlgPosX == CW_USEDEFAULT || Settings.CustomSchemesDlgPosY == CW_USEDEFAULT) {
|
|
CenterDlgInParent(hwnd, false);
|
|
} else {
|
|
SetDlgPos(hwnd, Settings.CustomSchemesDlgPosX, Settings.CustomSchemesDlgPosY);
|
|
}
|
|
HMENU hmenu = GetSystemMenu(hwnd, false);
|
|
GetLngString(IDS_MUI_PREVIEW, tchTmpBuffer, COUNTOF(tchTmpBuffer));
|
|
InsertMenu(hmenu, 0, MF_BYPOSITION | MF_STRING | MF_ENABLED, IDS_MUI_PREVIEW, tchTmpBuffer);
|
|
InsertMenu(hmenu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
|
|
GetLngString(IDS_MUI_SAVEPOS, tchTmpBuffer, COUNTOF(tchTmpBuffer));
|
|
InsertMenu(hmenu, 2, MF_BYPOSITION | MF_STRING | MF_ENABLED, IDS_MUI_SAVEPOS, tchTmpBuffer);
|
|
GetLngString(IDS_MUI_RESETPOS, tchTmpBuffer, COUNTOF(tchTmpBuffer));
|
|
InsertMenu(hmenu, 3, MF_BYPOSITION | MF_STRING | MF_ENABLED, IDS_MUI_RESETPOS, tchTmpBuffer);
|
|
InsertMenu(hmenu, 4, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
|
|
|
|
bWarnedNoIniFile = false;
|
|
|
|
// Set title font
|
|
HFONT const hFont = (HFONT)SendDlgItemMessage(hwnd, IDC_STYLELABEL, WM_GETFONT, 0, 0);
|
|
if (hFont) {
|
|
LOGFONT lf = { 0 };
|
|
GetObject(hFont, sizeof(LOGFONT), &lf);
|
|
lf.lfHeight = MulDiv(lf.lfHeight, 3, 2);
|
|
lf.lfWeight = FW_BOLD;
|
|
//lf.lfUnderline = true;
|
|
if (hFontTitle) {
|
|
DeleteObject(hFontTitle);
|
|
}
|
|
hFontTitle = CreateFontIndirectW(&lf);
|
|
SendDlgItemMessageW(hwnd, IDC_TITLE, WM_SETFONT, (WPARAM)hFontTitle, true);
|
|
SendDlgItemMessageW(hwnd, IDC_TITLE, WM_SETTEXT, 0, (LPARAM)s_TitleTxt);
|
|
}
|
|
|
|
iDMHighliteContrast = Settings.DarkModeHiglightContrast;
|
|
SetDlgItemInt(hwnd, IDC_DARK_MODE_CONTRAST, iDMHighliteContrast, false);
|
|
SendDlgItemMessage(hwnd, IDC_DARK_MODE_CONTRAST, EM_LIMITTEXT, 80, 0);
|
|
EnableItem(hwnd, IDC_DARK_MODE_CONTRAST, UseDarkMode());
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_DPICHANGED: {
|
|
UINT const dpi = LOWORD(wParam);
|
|
|
|
SHFILEINFO shfi = { 0 };
|
|
UINT const flagIconSize = (dpi >= LargeIconDPI()) ? SHGFI_LARGEICON : SHGFI_SMALLICON;
|
|
TreeView_SetImageList(hwndTV,
|
|
(HIMAGELIST)SHGetFileInfoW(L"C:\\", FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(SHFILEINFO),
|
|
flagIconSize | SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES),
|
|
TVSIL_NORMAL);
|
|
|
|
// Set title font
|
|
HFONT const hFont = (HFONT)SendDlgItemMessage(hwnd, IDC_STYLELABEL, WM_GETFONT, 0, 0);
|
|
if (hFont) {
|
|
LOGFONT lf = { 0 };
|
|
GetObject(hFont, sizeof(LOGFONT), &lf);
|
|
lf.lfHeight = MulDiv(lf.lfHeight, 3, 2);
|
|
lf.lfWeight = FW_BOLD;
|
|
//lf.lfUnderline = true;
|
|
if (hFontTitle) {
|
|
DeleteObject(hFontTitle);
|
|
}
|
|
hFontTitle = CreateFontIndirectW(&lf);
|
|
SendDlgItemMessageW(hwnd, IDC_TITLE, WM_SETFONT, (WPARAM)hFontTitle, true);
|
|
SendDlgItemMessageW(hwnd, IDC_TITLE, WM_SETTEXT, 0, (LPARAM)s_TitleTxt);
|
|
}
|
|
|
|
MakeBitmapButton(hwnd, IDC_PREVSTYLE, IDB_PREV, -1, -1);
|
|
MakeBitmapButton(hwnd, IDC_NEXTSTYLE, IDB_NEXT, -1, -1);
|
|
|
|
UpdateWindowLayoutForDPI(hwnd, (RECT*)lParam, LOWORD(wParam));
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_PAINT: {
|
|
PAINTSTRUCT ps;
|
|
HDC const hdc = GetDC(hwnd); // ClientArea
|
|
if (hdc) {
|
|
BeginPaint(hwnd, &ps);
|
|
|
|
UINT const dpi = Scintilla_GetWindowDPI(hwnd);
|
|
|
|
int const iconSize = 64;
|
|
int const dpiSize = ScaleIntByDPI(iconSize, dpi);
|
|
HICON const hicon = (dpiSize > 128) ? Globals.hDlgIconPrefs256 : ((dpiSize > 64) ? Globals.hDlgIconPrefs128 : Globals.hDlgIconPrefs64);
|
|
if (hicon) {
|
|
RECT rc = {0};
|
|
MapWindowPoints(GetDlgItem(hwnd, IDC_INFO_GROUPBOX), hwnd, (LPPOINT)&rc, 2);
|
|
DrawIconEx(hdc, rc.left + ScaleIntByDPI(10, dpi), rc.top + ScaleIntByDPI(20, dpi), hicon, dpiSize, dpiSize, 0, NULL, DI_NORMAL);
|
|
}
|
|
|
|
ReleaseDC(hwnd, hdc);
|
|
EndPaint(hwnd, &ps);
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
#ifdef D_NP3_WIN10_DARK_MODE
|
|
|
|
CASE_WM_CTLCOLOR_SET:
|
|
return SetDarkModeCtlColors((HDC)wParam, UseDarkMode());
|
|
break;
|
|
|
|
case WM_SETTINGCHANGE:
|
|
if (IsDarkModeSupported() && IsColorSchemeChangeMessage(lParam)) {
|
|
SendMessage(hwnd, WM_THEMECHANGED, 0, 0);
|
|
}
|
|
break;
|
|
|
|
case WM_THEMECHANGED:
|
|
if (IsDarkModeSupported()) {
|
|
bool const darkModeEnabled = CheckDarkModeEnabled();
|
|
AllowDarkModeForWindowEx(hwnd, darkModeEnabled);
|
|
RefreshTitleBarThemeColor(hwnd);
|
|
int const buttons[] = { IDOK, IDCANCEL, IDC_STYLEFORE, IDC_STYLEBACK, IDC_STYLEFONT, IDC_PREVIEW,
|
|
IDC_STYLEDEFAULT, IDC_PREVSTYLE, IDC_NEXTSTYLE, IDC_IMPORT, IDC_EXPORT
|
|
};
|
|
for (int id = 0; id < COUNTOF(buttons); ++id) {
|
|
HWND const hBtn = GetDlgItem(hwnd, buttons[id]);
|
|
AllowDarkModeForWindowEx(hBtn, darkModeEnabled);
|
|
SendMessage(hBtn, WM_THEMECHANGED, 0, 0);
|
|
}
|
|
SendMessage(hwndTV, WM_THEMECHANGED, 0, 0);
|
|
_UpdateTitleText(hwnd);
|
|
SendDlgItemMessageW(hwnd, IDC_TITLE, WM_SETTEXT, 0, (LPARAM)s_TitleTxt); // scheme may have changed
|
|
SendWMCommandEx(hwnd, IDC_STYLEEDIT, EN_CHANGE); // button color inlay
|
|
UpdateWindowEx(hwnd);
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case WM_ENABLE:
|
|
// modal child dialog should disable main window too
|
|
EnableWindow(Globals.hwndMain, (BOOL)wParam);
|
|
return TRUE;
|
|
|
|
case WM_ACTIVATE:
|
|
DialogEnableControl(hwnd, IDC_PREVIEW, ((pCurrentLexer == s_pLexCurrent) || (pCurrentLexer == GetCurrentStdLexer())));
|
|
return TRUE;
|
|
|
|
case WM_DESTROY: {
|
|
DeleteBitmapButton(hwnd, IDC_STYLEFORE);
|
|
DeleteBitmapButton(hwnd, IDC_STYLEBACK);
|
|
DeleteBitmapButton(hwnd, IDC_PREVSTYLE);
|
|
DeleteBitmapButton(hwnd, IDC_NEXTSTYLE);
|
|
|
|
// free old backup
|
|
if (pStylesBackup) {
|
|
utarray_free(pStylesBackup);
|
|
pStylesBackup = NULL;
|
|
}
|
|
|
|
if (hFontTitle) {
|
|
DeleteObject(hFontTitle);
|
|
hFontTitle = NULL;
|
|
}
|
|
s_TitleTxt[0] = L'\0';
|
|
s_OrigTitle[0] = L'\0';
|
|
pCurrentLexer = NULL;
|
|
pCurrentStyle = NULL;
|
|
iCurStyleIdx = -1;
|
|
}
|
|
return FALSE;
|
|
|
|
case WM_SYSCOMMAND:
|
|
if (wParam == IDS_MUI_SAVEPOS) {
|
|
PostWMCommand(hwnd, IDACC_SAVEPOS);
|
|
return TRUE;
|
|
} else if (wParam == IDS_MUI_RESETPOS) {
|
|
PostWMCommand(hwnd, IDACC_RESETPOS);
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
|
|
case WM_NOTIFY:
|
|
|
|
if (((LPNMHDR)(lParam))->idFrom == IDC_STYLELIST) {
|
|
LPNMTREEVIEW lpnmtv = (LPNMTREEVIEW)lParam;
|
|
|
|
switch (lpnmtv->hdr.code) {
|
|
case TVN_SELCHANGED: {
|
|
if (pCurrentLexer && pCurrentStyle) {
|
|
_ApplyDialogItemText(hwnd, pCurrentLexer, pCurrentStyle, iCurStyleIdx, bIsStyleSelected);
|
|
}
|
|
|
|
WCHAR name[80] = { L'\0' };
|
|
WCHAR label[128] = { L'\0' };
|
|
WCHAR styleBuf[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
|
|
//DialogEnableWindow(hwnd, IDC_STYLEEDIT, true);
|
|
//DialogEnableWindow(hwnd, IDC_STYLEFONT, true);
|
|
//DialogEnableWindow(hwnd, IDC_STYLEFORE, true);
|
|
//DialogEnableWindow(hwnd, IDC_STYLEBACK, true);
|
|
//DialogEnableWindow(hwnd, IDC_STYLEDEFAULT, true);
|
|
|
|
// a lexer has been selected
|
|
if (!TreeView_GetParent(hwndTV, lpnmtv->itemNew.hItem)) {
|
|
pCurrentLexer = (PEDITLEXER)lpnmtv->itemNew.lParam;
|
|
|
|
if (pCurrentLexer) {
|
|
bIsStyleSelected = false;
|
|
GetLngString(IDS_MUI_ASSOCIATED_EXT, label, COUNTOF(label));
|
|
SetDlgItemText(hwnd, IDC_STYLELABEL_ROOT, label);
|
|
DialogEnableControl(hwnd, IDC_STYLEEDIT_ROOT, true);
|
|
SetDlgItemText(hwnd, IDC_STYLEEDIT_ROOT, pCurrentLexer->szExtensions);
|
|
DialogEnableControl(hwnd, IDC_STYLEEDIT_ROOT, true);
|
|
|
|
iCurStyleIdx = STY_DEFAULT;
|
|
pCurrentStyle = &(pCurrentLexer->Styles[iCurStyleIdx]);
|
|
|
|
StringCchCopy(styleBuf, COUNTOF(styleBuf), pCurrentStyle->szValue);
|
|
Style_CopyStyles_IfNotDefined(GetCurrentStdLexer()->Styles[STY_DEFAULT].szValue, styleBuf, COUNTOF(styleBuf));
|
|
|
|
if (IsLexerStandard(pCurrentLexer)) {
|
|
if (pCurrentStyle->rid == IDS_LEX_STD_STYLE) {
|
|
GetLngString(IDS_MUI_STY_BASESTD, label, COUNTOF(label));
|
|
} else {
|
|
GetLngString(IDS_MUI_STY_BASE2ND, label, COUNTOF(label));
|
|
DialogEnableControl(hwnd, IDC_STYLEEDIT_ROOT, false);
|
|
}
|
|
DialogEnableControl(hwnd, IDC_STYLEEDIT_ROOT, false);
|
|
} else {
|
|
GetLngString(pCurrentLexer->resID, name, COUNTOF(name));
|
|
FormatLngStringW(label, COUNTOF(label), IDS_MUI_STY_LEXDEF, name);
|
|
DialogEnableControl(hwnd, IDC_STYLEEDIT_ROOT, true);
|
|
}
|
|
SetDlgItemText(hwnd, IDC_STYLELABEL, label);
|
|
SetDlgItemText(hwnd, IDC_STYLEEDIT, styleBuf);
|
|
} else {
|
|
SetDlgItemText(hwnd, IDC_STYLELABEL_ROOT, L"");
|
|
DialogEnableControl(hwnd, IDC_STYLEEDIT_ROOT, false);
|
|
SetDlgItemText(hwnd, IDC_STYLELABEL, L"");
|
|
DialogEnableControl(hwnd, IDC_STYLEEDIT, false);
|
|
}
|
|
DialogEnableControl(hwnd, IDC_PREVIEW, ((pCurrentLexer == s_pLexCurrent) || (pCurrentLexer == GetCurrentStdLexer())));
|
|
}
|
|
// a style has been selected
|
|
else {
|
|
if (pCurrentLexer) {
|
|
if (IsLexerStandard(pCurrentLexer)) {
|
|
if (pCurrentLexer->Styles[STY_DEFAULT].rid == IDS_LEX_STD_STYLE) {
|
|
GetLngString(IDS_MUI_STY_BASESTD, label, COUNTOF(label));
|
|
} else {
|
|
GetLngString(IDS_MUI_STY_BASE2ND, label, COUNTOF(label));
|
|
}
|
|
} else {
|
|
GetLngString(pCurrentLexer->resID, name, COUNTOF(name));
|
|
FormatLngStringW(label, COUNTOF(label), IDS_MUI_STY_LEXDEF, name);
|
|
}
|
|
SetDlgItemText(hwnd, IDC_STYLELABEL_ROOT, label);
|
|
|
|
StringCchCopy(styleBuf, COUNTOF(styleBuf), pCurrentLexer->Styles[STY_DEFAULT].szValue);
|
|
Style_CopyStyles_IfNotDefined(GetCurrentStdLexer()->Styles[STY_DEFAULT].szValue, styleBuf, COUNTOF(styleBuf));
|
|
|
|
SetDlgItemText(hwnd, IDC_STYLEEDIT_ROOT, styleBuf);
|
|
DialogEnableControl(hwnd, IDC_STYLEEDIT_ROOT, false);
|
|
|
|
pCurrentStyle = (PEDITSTYLE)lpnmtv->itemNew.lParam;
|
|
iCurStyleIdx = -1;
|
|
int i = 0;
|
|
while (pCurrentLexer->Styles[i].iStyle != -1) {
|
|
if (pCurrentLexer->Styles[i].rid == pCurrentStyle->rid) {
|
|
iCurStyleIdx = i;
|
|
break;
|
|
}
|
|
++i;
|
|
}
|
|
//assert(iCurStyleIdx != -1);
|
|
}
|
|
if (pCurrentStyle) {
|
|
bIsStyleSelected = true;
|
|
GetLngString(pCurrentStyle->rid, name, COUNTOF(name));
|
|
FormatLngStringW(label, COUNTOF(label), IDS_MUI_STY_LEXSTYLE, name);
|
|
SetDlgItemText(hwnd, IDC_STYLELABEL, label);
|
|
SetDlgItemText(hwnd, IDC_STYLEEDIT, pCurrentStyle->szValue);
|
|
} else {
|
|
iCurStyleIdx = -1;
|
|
SetDlgItemText(hwnd, IDC_STYLELABEL, L"");
|
|
DialogEnableControl(hwnd, IDC_STYLEEDIT, false);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TVN_BEGINDRAG: {
|
|
TreeView_Select(hwndTV, lpnmtv->itemNew.hItem, TVGN_CARET);
|
|
|
|
if (bIsStyleSelected) {
|
|
DestroyCursor(SetCursor(LoadCursor(Globals.hInstance, MAKEINTRESOURCE(IDC_COPY))));
|
|
} else {
|
|
DestroyCursor(SetCursor(LoadCursor(NULL, IDC_NO)));
|
|
}
|
|
|
|
SetCapture(hwnd);
|
|
fDragging = true;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_MOUSEMOVE: {
|
|
HTREEITEM htiTarget = { 0 };
|
|
TVHITTESTINFO tvht = { 0 };
|
|
if (fDragging && bIsStyleSelected) {
|
|
LONG xCur = (LONG)(short)LOWORD(lParam);
|
|
LONG yCur = (LONG)(short)HIWORD(lParam);
|
|
|
|
//ImageList_DragMove(xCur,yCur);
|
|
//ImageList_DragShowNolock(false);
|
|
|
|
tvht.pt.x = xCur;
|
|
tvht.pt.y = yCur;
|
|
|
|
//ClientToScreen(hwnd,&tvht.pt);
|
|
//ScreenToClient(hwndTV,&tvht.pt);
|
|
MapWindowPoints(hwnd, hwndTV, &tvht.pt, 1);
|
|
|
|
if ((htiTarget = TreeView_HitTest(hwndTV, &tvht)) != NULL &&
|
|
TreeView_GetParent(hwndTV, htiTarget) != NULL) {
|
|
TreeView_SelectDropTarget(hwndTV, htiTarget);
|
|
//TreeView_Expand(hwndTV,htiTarget,TVE_EXPAND);
|
|
TreeView_EnsureVisible(hwndTV, htiTarget);
|
|
} else {
|
|
TreeView_SelectDropTarget(hwndTV, NULL);
|
|
}
|
|
|
|
//ImageList_DragShowNolock(true);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONUP: {
|
|
if (fDragging && bIsStyleSelected) {
|
|
//ImageList_EndDrag();
|
|
HTREEITEM htiTarget = TreeView_GetDropHilight(hwndTV);
|
|
if (htiTarget) {
|
|
WCHAR tchCopy[max(BUFSIZE_STYLE_VALUE, STYLE_EXTENTIONS_BUFFER)] = {L'\0'};
|
|
TreeView_SelectDropTarget(hwndTV, NULL);
|
|
GetDlgItemText(hwnd, IDC_STYLEEDIT, tchCopy, COUNTOF(tchCopy));
|
|
TreeView_Select(hwndTV, htiTarget, TVGN_CARET);
|
|
|
|
// after select, this is new current item
|
|
SetDlgItemText(hwnd, IDC_STYLEEDIT, tchCopy);
|
|
_ApplyDialogItemText(hwnd, pCurrentLexer, pCurrentStyle, iCurStyleIdx, bIsStyleSelected);
|
|
}
|
|
ReleaseCapture();
|
|
DestroyCursor(SetCursor(LoadCursor(NULL, IDC_ARROW)));
|
|
fDragging = false;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_CANCELMODE: {
|
|
if (fDragging) {
|
|
//ImageList_EndDrag();
|
|
TreeView_SelectDropTarget(hwndTV, NULL);
|
|
ReleaseCapture();
|
|
DestroyCursor(SetCursor(LoadCursor(NULL, IDC_ARROW)));
|
|
fDragging = false;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND: {
|
|
switch (LOWORD(wParam)) {
|
|
case IDC_SETCURLEXERTV: {
|
|
// find current lexer's tree entry
|
|
HTREEITEM hCurrentTVLex = TreeView_GetRoot(hwndTV);
|
|
for (int i = 0; i < COUNTOF(g_pLexArray); ++i) {
|
|
if (g_pLexArray[i] == s_pLexCurrent) {
|
|
break;
|
|
}
|
|
hCurrentTVLex = TreeView_GetNextSibling(hwndTV, hCurrentTVLex); // next
|
|
}
|
|
if (s_pLexCurrent == pCurrentLexer) {
|
|
break; // no change
|
|
}
|
|
|
|
// collaps current node
|
|
HTREEITEM hSel = TreeView_GetSelection(hwndTV);
|
|
if (hSel) {
|
|
HTREEITEM hPar = TreeView_GetParent(hwndTV, hSel);
|
|
TreeView_Expand(hwndTV, hSel, TVE_COLLAPSE);
|
|
if (hPar) {
|
|
TreeView_Expand(hwndTV, hPar, TVE_COLLAPSE);
|
|
}
|
|
}
|
|
|
|
// set new lexer
|
|
TreeView_Select(hwndTV, hCurrentTVLex, TVGN_CARET);
|
|
TreeView_Expand(hwndTV, hCurrentTVLex, TVE_EXPAND);
|
|
|
|
pCurrentLexer = s_pLexCurrent;
|
|
pCurrentStyle = &(pCurrentLexer->Styles[STY_DEFAULT]);
|
|
iCurStyleIdx = STY_DEFAULT;
|
|
|
|
PostMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)(GetDlgItem(hwnd, IDC_STYLEEDIT)), 1);
|
|
}
|
|
break;
|
|
|
|
case IDC_STYLEFORE:
|
|
if (pCurrentStyle) {
|
|
WCHAR tch[BUFSIZE_STYLE_VALUE] = {L'\0'};
|
|
GetDlgItemText(hwnd, IDC_STYLEEDIT, tch, COUNTOF(tch));
|
|
if (Style_SelectColor(hwnd, true, tch, COUNTOF(tch), true)) {
|
|
SetDlgItemText(hwnd, IDC_STYLEEDIT, tch);
|
|
}
|
|
}
|
|
PostMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)(GetDlgItem(hwnd, IDC_STYLEEDIT)), 1);
|
|
break;
|
|
|
|
case IDC_STYLEBACK:
|
|
if (pCurrentStyle) {
|
|
WCHAR tch[BUFSIZE_STYLE_VALUE] = {L'\0'};
|
|
GetDlgItemText(hwnd, IDC_STYLEEDIT, tch, COUNTOF(tch));
|
|
if (Style_SelectColor(hwnd, false, tch, COUNTOF(tch), true)) {
|
|
SetDlgItemText(hwnd, IDC_STYLEEDIT, tch);
|
|
}
|
|
}
|
|
PostMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)(GetDlgItem(hwnd, IDC_STYLEEDIT)), 1);
|
|
break;
|
|
|
|
case IDC_STYLEFONT:
|
|
if (pCurrentStyle) {
|
|
WCHAR lexerName[BUFSIZE_STYLE_VALUE] = {L'\0'};
|
|
WCHAR styleName[BUFSIZE_STYLE_VALUE] = {L'\0'};
|
|
GetDlgItemText(hwnd, IDC_STYLEEDIT, tchTmpBuffer, COUNTOF(tchTmpBuffer));
|
|
GetLngString(pCurrentLexer->resID, lexerName, COUNTOF(lexerName));
|
|
GetLngString(pCurrentStyle->rid, styleName, COUNTOF(styleName));
|
|
DEFAULT_FONT_STYLES const defaultFontStyle = IsStyleSchemeDefault(pCurrentStyle) ? DFS_CURR_LEXER :
|
|
(IsStyleStandardDefault(pCurrentStyle) ? DFS_GLOBAL : DFS_GENERIC_USE);
|
|
if (Style_SelectFont(hwnd, tchTmpBuffer, COUNTOF(tchTmpBuffer), lexerName, styleName, defaultFontStyle)) {
|
|
SetDlgItemText(hwnd, IDC_STYLEEDIT, tchTmpBuffer);
|
|
}
|
|
}
|
|
PostMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)(GetDlgItem(hwnd, IDC_STYLEEDIT)), 1);
|
|
break;
|
|
|
|
case IDC_STYLEDEFAULT: {
|
|
WCHAR wchDefaultStyle[BUFSIZE_STYLE_VALUE] = { L'\0' };
|
|
_DefaultsToTmpCache();
|
|
TmpCacheGetString(pCurrentLexer->pszName, pCurrentStyle->pszName, L"", wchDefaultStyle, COUNTOF(wchDefaultStyle));
|
|
SetDlgItemText(hwnd, IDC_STYLEEDIT, wchDefaultStyle);
|
|
if (!bIsStyleSelected) {
|
|
SetDlgItemText(hwnd, IDC_STYLEEDIT_ROOT, pCurrentLexer->pszDefExt);
|
|
}
|
|
_ApplyDialogItemText(hwnd, pCurrentLexer, pCurrentStyle, iCurStyleIdx, bIsStyleSelected);
|
|
PostMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)(GetDlgItem(hwnd, IDC_STYLEEDIT)), 1);
|
|
ResetTmpCache();
|
|
}
|
|
break;
|
|
|
|
case IDC_STYLEEDIT: {
|
|
if (HIWORD(wParam) == EN_CHANGE) {
|
|
WCHAR tch[max(BUFSIZE_STYLE_VALUE, STYLE_EXTENTIONS_BUFFER)] = {L'\0'};
|
|
|
|
GetDlgItemText(hwnd, IDC_STYLEEDIT, tch, COUNTOF(tch));
|
|
|
|
COLORREF cr = COLORREF_MAX; // SciCall_StyleGetFore(STYLE_DEFAULT);
|
|
Style_StrGetColor(tch, FOREGROUND_LAYER, &cr, NULL, false);
|
|
MakeColorPickButton(hwnd, IDC_STYLEFORE, Globals.hInstance, cr);
|
|
|
|
cr = COLORREF_MAX; // SciCall_StyleGetBack(STYLE_DEFAULT);
|
|
Style_StrGetColor(tch, BACKGROUND_LAYER, &cr, NULL, false);
|
|
MakeColorPickButton(hwnd, IDC_STYLEBACK, Globals.hInstance, cr);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_IMPORT: {
|
|
hwndTV = GetDlgItem(hwnd, IDC_STYLELIST);
|
|
|
|
if (Style_Import(hwnd)) {
|
|
SetDlgItemText(hwnd, IDC_STYLEEDIT, pCurrentStyle->szValue);
|
|
if (!bIsStyleSelected) {
|
|
SetDlgItemText(hwnd, IDC_STYLEEDIT_ROOT, pCurrentLexer->szExtensions);
|
|
}
|
|
TreeView_Select(hwndTV, TreeView_GetRoot(hwndTV), TVGN_CARET);
|
|
Style_ResetCurrentLexer(Globals.hwndEdit);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_EXPORT: {
|
|
_ApplyDialogItemText(hwnd, pCurrentLexer, pCurrentStyle, iCurStyleIdx, bIsStyleSelected);
|
|
Style_Export(hwnd);
|
|
}
|
|
break;
|
|
|
|
case IDC_PREVIEW: {
|
|
_ApplyDialogItemText(hwnd, pCurrentLexer, pCurrentStyle, iCurStyleIdx, bIsStyleSelected);
|
|
}
|
|
break;
|
|
|
|
case IDC_PREVSTYLE: {
|
|
_ApplyDialogItemText(hwnd, pCurrentLexer, pCurrentStyle, iCurStyleIdx, bIsStyleSelected);
|
|
HTREEITEM hSel = TreeView_GetSelection(hwndTV);
|
|
if (hSel) {
|
|
HTREEITEM hPrev = TreeView_GetPrevVisible(hwndTV, hSel);
|
|
if (hPrev) {
|
|
TreeView_Select(hwndTV, hPrev, TVGN_CARET);
|
|
}
|
|
}
|
|
PostMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)(GetDlgItem(hwnd, IDC_STYLEEDIT)), 1);
|
|
}
|
|
break;
|
|
|
|
case IDC_NEXTSTYLE: {
|
|
_ApplyDialogItemText(hwnd, pCurrentLexer, pCurrentStyle, iCurStyleIdx, bIsStyleSelected);
|
|
HTREEITEM hSel = TreeView_GetSelection(hwndTV);
|
|
if (hSel) {
|
|
HTREEITEM hNext = TreeView_GetNextVisible(hwndTV, hSel);
|
|
if (hNext) {
|
|
TreeView_Select(hwndTV, hNext, TVGN_CARET);
|
|
}
|
|
}
|
|
PostMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)(GetDlgItem(hwnd, IDC_STYLEEDIT)), 1);
|
|
}
|
|
break;
|
|
|
|
case IDOK: {
|
|
_ApplyDialogItemText(hwnd, pCurrentLexer, pCurrentStyle, iCurStyleIdx, bIsStyleSelected);
|
|
|
|
unsigned const iTheme = Globals.uCurrentThemeIndex;
|
|
if ((iTheme > 0) && (!bWarnedNoIniFile && Path_IsEmpty(Theme_Files[iTheme].hStyleFilePath))) {
|
|
InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SETTINGSNOTSAVED);
|
|
bWarnedNoIniFile = true;
|
|
}
|
|
//EndDialog(hwnd,IDOK);
|
|
DestroyWindow(hwnd);
|
|
}
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
if (fDragging) {
|
|
SendMessage(hwnd, WM_CANCELMODE, 0, 0);
|
|
} else {
|
|
Settings.DarkModeHiglightContrast = iDMHighliteContrast;
|
|
SetDlgItemInt(hwnd, IDC_DARK_MODE_CONTRAST, iDMHighliteContrast, false);
|
|
|
|
_ApplyDialogItemText(hwnd, pCurrentLexer, pCurrentStyle, iCurStyleIdx, bIsStyleSelected);
|
|
|
|
// Restore Styles from Backup
|
|
LPWSTR * pStyle = (LPWSTR*)utarray_front(pStylesBackup);
|
|
for (int iLexer = 0; iLexer < COUNTOF(g_pLexArray); ++iLexer) {
|
|
StringCchCopy(g_pLexArray[iLexer]->szExtensions, COUNTOF(g_pLexArray[iLexer]->szExtensions), *pStyle);
|
|
pStyle = (LPWSTR*)utarray_next(pStylesBackup, (void*)pStyle);
|
|
int i = 0;
|
|
while (pStyle && (g_pLexArray[iLexer]->Styles[i].iStyle != -1)) {
|
|
// normalize
|
|
tchTmpBuffer[0] = L'\0'; // clear
|
|
Style_CopyStyles_IfNotDefined(*pStyle, tchTmpBuffer, COUNTOF(tchTmpBuffer));
|
|
StringCchCopy(g_pLexArray[iLexer]->Styles[i].szValue, COUNTOF(g_pLexArray[iLexer]->Styles[i].szValue), tchTmpBuffer);
|
|
++i;
|
|
pStyle = (LPWSTR*)utarray_next(pStylesBackup, (void*)pStyle);
|
|
}
|
|
}
|
|
Style_ResetCurrentLexer(Globals.hwndEdit);
|
|
//EndDialog(hwnd,IDCANCEL);
|
|
DestroyWindow(hwnd);
|
|
}
|
|
break;
|
|
|
|
case IDACC_VIEWSCHEMECONFIG:
|
|
PostWMCommand(hwnd, IDC_SETCURLEXERTV);
|
|
break;
|
|
|
|
case IDACC_PREVIEW:
|
|
PostWMCommand(hwnd, IDC_PREVIEW);
|
|
break;
|
|
|
|
case IDACC_SAVEPOS:
|
|
GetDlgPos(hwnd, &Settings.CustomSchemesDlgPosX, &Settings.CustomSchemesDlgPosY);
|
|
break;
|
|
|
|
case IDACC_RESETPOS:
|
|
CenterDlgInParent(hwnd, false);
|
|
Settings.CustomSchemesDlgPosX = Settings.CustomSchemesDlgPosY = CW_USEDEFAULT;
|
|
break;
|
|
|
|
default:
|
|
// return false???
|
|
break;
|
|
|
|
} // switch()
|
|
} // WM_COMMAND
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_CustomizeSchemesDlg()
|
|
//
|
|
HWND Style_CustomizeSchemesDlg(HWND hwnd)
|
|
{
|
|
HWND hDlg = CreateThemedDialogParam(Globals.hLngResContainer,
|
|
MAKEINTRESOURCE(IDD_MUI_STYLECONFIG),
|
|
GetParent(hwnd),
|
|
Style_CustomizeSchemesDlgProc,
|
|
(LPARAM)hwnd);
|
|
if (IS_VALID_HANDLE(hDlg)) {
|
|
ShowWindow(hDlg, SW_SHOWDEFAULT);
|
|
}
|
|
return hDlg;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SelectLexerDlgProc()
|
|
//
|
|
|
|
INT_PTR CALLBACK Style_SelectLexerDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam)
|
|
{
|
|
static int cxClient = 0;
|
|
static int cyClient = 0;
|
|
|
|
static HWND hwndLV = NULL;
|
|
|
|
static int iInternalDefault = 0;
|
|
static PEDITLEXER* pSelectedLexer = NULL;
|
|
|
|
|
|
switch(umsg) {
|
|
case WM_INITDIALOG: {
|
|
|
|
pSelectedLexer = (PEDITLEXER*)lParam;
|
|
|
|
SetDialogIconNP3(hwnd);
|
|
InitWindowCommon(hwnd, true);
|
|
|
|
#ifdef D_NP3_WIN10_DARK_MODE
|
|
if (UseDarkMode()) {
|
|
SetExplorerTheme(GetDlgItem(hwnd, IDOK));
|
|
SetExplorerTheme(GetDlgItem(hwnd, IDCANCEL));
|
|
//SetExplorerTheme(GetDlgItem(hwnd, IDC_RESIZEGRIP));
|
|
int const ctl[] = { IDC_DEFAULTSCHEME, IDC_AUTOSELECT, IDC_STATIC };
|
|
for (int i = 0; i < COUNTOF(ctl); ++i) {
|
|
SetWindowTheme(GetDlgItem(hwnd, ctl[i]), L"", L""); // remove theme for BS_AUTORADIOBUTTON
|
|
}
|
|
}
|
|
#endif
|
|
|
|
UINT const dpi = Scintilla_GetWindowDPI(hwnd);
|
|
|
|
hwndLV = GetDlgItem(hwnd,IDC_STYLELIST);
|
|
InitWindowCommon(hwndLV, true);
|
|
InitListView(hwndLV);
|
|
|
|
SHFILEINFO shfi = { 0 };
|
|
|
|
UINT const flagIconSize = (dpi >= LargeIconDPI()) ? SHGFI_LARGEICON : SHGFI_SMALLICON;
|
|
ListView_SetImageList(hwndLV,
|
|
(HIMAGELIST)SHGetFileInfo(L"C:\\",FILE_ATTRIBUTE_DIRECTORY,
|
|
&shfi, sizeof(SHFILEINFO), flagIconSize | SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES),
|
|
LVSIL_SMALL);
|
|
|
|
ListView_SetImageList(hwndLV,
|
|
(HIMAGELIST)SHGetFileInfo(L"C:\\",FILE_ATTRIBUTE_DIRECTORY,
|
|
&shfi,sizeof(SHFILEINFO), SHGFI_LARGEICON | SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES),
|
|
LVSIL_NORMAL);
|
|
|
|
LVCOLUMN lvc = { LVCF_FMT | LVCF_TEXT, LVCFMT_LEFT, 0, L"", -1, 0, 0, 0 };
|
|
ListView_SetExtendedListViewStyle(hwndLV,/*LVS_EX_FULLROWSELECT|*/LVS_EX_DOUBLEBUFFER|LVS_EX_LABELTIP);
|
|
ListView_InsertColumn(hwndLV,0,&lvc);
|
|
|
|
// Add lexers
|
|
for (int i = 0; i < COUNTOF(g_pLexArray); i++) {
|
|
Style_AddLexerToListView(hwndLV, g_pLexArray[i]);
|
|
}
|
|
ListView_SetColumnWidth(hwndLV,0,LVSCW_AUTOSIZE_USEHEADER);
|
|
|
|
// Select current lexer
|
|
int lvItems = ListView_GetItemCount(hwndLV);
|
|
LVITEM lvi = { 0 };
|
|
lvi.mask = LVIF_PARAM;
|
|
for (int i = 0; i < lvItems; i++) {
|
|
lvi.iItem = i;
|
|
ListView_GetItem(hwndLV,&lvi);
|
|
|
|
if (((PEDITLEXER)lvi.lParam)->resID == (*pSelectedLexer)->resID) {
|
|
ListView_SetItemState(hwndLV,i,LVIS_FOCUSED|LVIS_SELECTED,LVIS_FOCUSED|LVIS_SELECTED);
|
|
ListView_EnsureVisible(hwndLV,i,false);
|
|
CheckDlgButton(hwnd, IDC_DEFAULTSCHEME, SetBtn(s_iDefaultLexer == i));
|
|
break;
|
|
}
|
|
}
|
|
|
|
iInternalDefault = s_iDefaultLexer;
|
|
CheckDlgButton(hwnd,IDC_AUTOSELECT, SetBtn(s_bAutoSelect));
|
|
|
|
CenterDlgInParent(hwnd, false);
|
|
}
|
|
return TRUE;
|
|
|
|
|
|
case WM_CLOSE:
|
|
EndDialog(hwnd, IDCLOSE);
|
|
break;
|
|
|
|
|
|
case WM_DESTROY:
|
|
return TRUE;
|
|
|
|
|
|
case WM_SIZE: {
|
|
ListView_SetColumnWidth(GetDlgItem(hwnd, IDC_STYLELIST), 0, LVSCW_AUTOSIZE_USEHEADER);
|
|
}
|
|
return TRUE;
|
|
|
|
|
|
case WM_DPICHANGED: {
|
|
UINT const dpi = LOWORD(wParam);
|
|
UpdateWindowLayoutForDPI(hwnd, (RECT*)lParam, dpi);
|
|
SHFILEINFO shfi = { 0 };
|
|
UINT const flagIconSize = (dpi >= LargeIconDPI()) ? SHGFI_LARGEICON : SHGFI_SMALLICON;
|
|
ListView_SetImageList(hwndLV,
|
|
(HIMAGELIST)SHGetFileInfo(L"C:\\", FILE_ATTRIBUTE_DIRECTORY,
|
|
&shfi, sizeof(SHFILEINFO), flagIconSize | SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES),
|
|
LVSIL_SMALL);
|
|
}
|
|
return TRUE;
|
|
|
|
|
|
case WM_GETMINMAXINFO:
|
|
return TRUE;
|
|
|
|
|
|
#ifdef D_NP3_WIN10_DARK_MODE
|
|
|
|
CASE_WM_CTLCOLOR_SET:
|
|
return SetDarkModeCtlColors((HDC)wParam, UseDarkMode());
|
|
break;
|
|
|
|
case WM_SETTINGCHANGE:
|
|
if (IsDarkModeSupported() && IsColorSchemeChangeMessage(lParam)) {
|
|
SendMessage(hwnd, WM_THEMECHANGED, 0, 0);
|
|
}
|
|
break;
|
|
|
|
case WM_THEMECHANGED:
|
|
if (IsDarkModeSupported()) {
|
|
bool const darkModeEnabled = CheckDarkModeEnabled();
|
|
AllowDarkModeForWindowEx(hwnd, darkModeEnabled);
|
|
RefreshTitleBarThemeColor(hwnd);
|
|
int const buttons[] = { IDOK, IDCANCEL };
|
|
for (int id = 0; id < COUNTOF(buttons); ++id) {
|
|
HWND const hBtn = GetDlgItem(hwnd, buttons[id]);
|
|
AllowDarkModeForWindowEx(hBtn, darkModeEnabled);
|
|
SendMessage(hBtn, WM_THEMECHANGED, 0, 0);
|
|
}
|
|
SendMessage(hwndLV, WM_THEMECHANGED, 0, 0);
|
|
UpdateWindowEx(hwnd);
|
|
}
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
|
case WM_NOTIFY: {
|
|
if (((LPNMHDR)(lParam))->idFrom == IDC_STYLELIST) {
|
|
|
|
switch (((LPNMHDR)(lParam))->code) {
|
|
|
|
case NM_DBLCLK:
|
|
SendWMCommand(hwnd, IDOK);
|
|
break;
|
|
|
|
case LVN_ITEMCHANGED:
|
|
case LVN_DELETEITEM: {
|
|
int i = ListView_GetNextItem(hwndLV, -1, LVNI_ALL | LVNI_SELECTED);
|
|
CheckDlgButton(hwnd, IDC_DEFAULTSCHEME, SetBtn(iInternalDefault == i));
|
|
DialogEnableControl(hwnd, IDC_DEFAULTSCHEME, i != -1);
|
|
DialogEnableControl(hwnd, IDOK, i != -1);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
|
|
|
|
case WM_COMMAND: {
|
|
switch (LOWORD(wParam)) {
|
|
case IDC_DEFAULTSCHEME:
|
|
if (IsButtonChecked(hwnd, IDC_DEFAULTSCHEME)) {
|
|
iInternalDefault = ListView_GetNextItem(hwndLV, -1, LVNI_ALL | LVNI_SELECTED);
|
|
} else {
|
|
iInternalDefault = 0;
|
|
}
|
|
break;
|
|
|
|
|
|
case IDOK: {
|
|
LVITEM lvi = {0};
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = ListView_GetNextItem(hwndLV, -1, LVNI_ALL | LVNI_SELECTED);
|
|
if (ListView_GetItem(hwndLV, &lvi)) {
|
|
*pSelectedLexer = (PEDITLEXER)lvi.lParam;
|
|
s_iDefaultLexer = iInternalDefault;
|
|
s_bAutoSelect = IsButtonChecked(hwnd, IDC_AUTOSELECT);
|
|
//@@@??? Flags.bHugeFileLoadState = false; // user choice
|
|
EndDialog(hwnd,IDOK);
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hwnd, IDCANCEL);
|
|
break;
|
|
|
|
} // switch()
|
|
} // WM_COMMAND
|
|
return TRUE;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// Style_SelectLexerDlg()
|
|
//
|
|
void Style_SelectLexerDlg(HWND hwnd)
|
|
{
|
|
PEDITLEXER selectedLexer = s_pLexCurrent;
|
|
|
|
if (IsYesOkay(ThemedDialogBoxParam(Globals.hLngResContainer,
|
|
MAKEINTRESOURCE(IDD_MUI_STYLESELECT),
|
|
GetParent(hwnd), Style_SelectLexerDlgProc, (LPARAM)&selectedLexer))) {
|
|
Style_SetLexer(Globals.hwndEdit, selectedLexer);
|
|
}
|
|
}
|
|
|
|
// End of Styles.c
|