Notepad3/src/Notepad3.c
2020-09-19 22:15:20 +02:00

11537 lines
371 KiB
C

// encoding: UTF-8
/******************************************************************************
* *
* *
* Notepad3 *
* *
* Notepad3.c *
* Main application window functionality *
* Based on code from Notepad2, (c) Florian Balmer 1996-2011 *
* *
* (c) Rizonesoft 2008-2020 *
* https://rizonesoft.com *
* *
* *
*******************************************************************************/
#include "Helpers.h"
#include <crtdbg.h>
#include <commctrl.h>
#include <uxtheme.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <shellapi.h>
#include <commdlg.h>
#include <stdio.h>
#include <string.h>
//#include <pathcch.h>
//#include <locale.h>
#include "Edit.h"
#include "Styles.h"
#include "Dialogs.h"
#include "resource.h"
#include "crypto/crypto.h"
#include "uthash/utarray.h"
#include "uthash/utlist.h"
#include "tinyexpr/tinyexpr.h"
#include "Encoding.h"
#include "VersionEx.h"
#include "MuiLanguage.h"
#include "Notepad3.h"
#include "Config/Config.h"
#include "DarkMode/DarkMode.h"
#include "SciLexer.h"
#include "lexers_x/SciXLexer.h"
// ============================================================================
//
// Local and global Variables for Notepad3.c
//
// ============================================================================
LPCWSTR WordBookMarks[MARKER_NP3_BOOKMARK] = {
/*0*/ L"back:#0000", // OCC MARKER
/*1*/ L"back:#FF0000",
/*2*/ L"back:#0000FF",
/*3*/ L"back:#00FF00",
/*4*/ L"back:#FFFF00",
/*5*/ L"back:#00E8E8",
/*6*/ L"back:#FF00FF",
/*7*/ L"back:#FF8F20",
/*8*/ L"back:#950095"};
#define RELAUNCH_ELEVATED_BUF_ARG L"tmpfbuf="
CONSTANTS_T const Constants = {
2 // StdDefaultLexerID
, L"minipath.exe" // FileBrowserMiniPath
, L"grepWinNP3.exe" // FileSearchGrepWin
, L"Settings" // Inifile Section "Settings"
, L"Settings2" // Inifile Section "Settings2"
, L"Window" // Inifile Section "Window"
, L"Styles" // Inifile Section "Styles"
, L"Suppressed Messages" // Inifile Section "SuppressedMessages"
};
FLAGS_T Flags;
FLAGS_T DefaultFlags;
GLOBALS_T Globals;
SETTINGS_T Settings;
SETTINGS_T Defaults;
SETTINGS2_T Settings2;
SETTINGS2_T Defaults2;
FOCUSEDVIEW_T FocusedView;
FILEWATCHING_T FileWatching;
WININFO g_IniWinInfo = INIT_WININFO;
WININFO g_DefWinInfo = INIT_WININFO;
COLORREF g_colorCustom[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
prefix_t g_mxSBPrefix[STATUS_SECTOR_COUNT];
prefix_t g_mxSBPostfix[STATUS_SECTOR_COUNT];
bool g_iStatusbarVisible[STATUS_SECTOR_COUNT] = SBS_INIT_ZERO;
int g_iStatusbarWidthSpec[STATUS_SECTOR_COUNT] = SBS_INIT_ZERO;
int g_vSBSOrder[STATUS_SECTOR_COUNT] = SBS_INIT_MINUS;
WCHAR g_tchToolbarBitmap[MAX_PATH] = { L'\0' };
WCHAR g_tchToolbarBitmapHot[MAX_PATH] = { L'\0' };
WCHAR g_tchToolbarBitmapDisabled[MAX_PATH] = { L'\0' };
int g_flagMatchText = 0;
// ------------------------------------
static bool s_bIsProcessElevated = false;
static bool s_bIsUserInAdminGroup = false;
static bool s_bIsRunAsAdmin = false;
static bool s_flagSaveOnRelaunch = false;
static bool s_IsThisAnElevatedRelaunch = false;
static WCHAR s_wchWndClass[64] = { L'\0' };
static HWND s_hwndEditFrame = NULL;
static HWND s_hwndNextCBChain = NULL;
static WCHAR s_wchTmpFilePath[MAX_PATH] = { L'\0' };
static WCHAR s_wchPrefixSelection[256] = { L'\0' };
static WCHAR s_wchAppendSelection[256] = { L'\0' };
static WCHAR s_wchPrefixLines[256] = { L'\0' };
static WCHAR s_wchAppendLines[256] = { L'\0' };
static int s_WinCurrentWidth = 0;
#define FILE_LIST_SIZE 32
static LPWSTR s_lpFileList[FILE_LIST_SIZE] = { NULL };
static int s_cFileList = 0;
static int s_cchiFileList = 0;
static WCHAR s_tchLastSaveCopyDir[MAX_PATH] = { L'\0' };
static bool s_bRunningWatch = false;
static bool s_bFileReadOnly = false;
static int s_iSortOptions = 0;
static int s_iAlignMode = 0;
static bool s_bIsAppThemed = true;
static UINT s_msgTaskbarCreated = 0;
static DWORD s_dwChangeNotifyTime = 0;
static HANDLE s_hChangeHandle = NULL;
static WCHAR s_wchTitleExcerpt[MIDSZ_BUFFER] = { L'\0' };
static UINT s_uidsAppTitle = IDS_MUI_APPTITLE;
static DWORD s_dwLastCopyTime = 0;
static bool s_bLastCopyFromMe = false;
static bool s_bInMultiEditMode = false;
static bool s_bCallTipEscDisabled = false;
static int s_iInitialLine;
static int s_iInitialColumn;
static int s_iInitialLexer;
static int s_cyReBar;
static int s_cyReBarFrame;
static int s_cxEditFrame;
static int s_cyEditFrame;
static bool s_bUndoRedoScroll = false;
static bool s_bPrevFullScreenFlag = false;
// for tiny expression calculation
static double s_dExpression = 0.0;
static te_xint_t s_iExprError = -1;
static WIN32_FIND_DATA s_fdCurFile;
//~static CONST WCHAR *const s_ToolbarWndClassName = L"NP3_TOOLBAR_CLASS";
static int const INISECTIONBUFCNT = 32; // .ini file load buffer in KB
static TBBUTTON s_tbbMainWnd[] = {
{ 0,IDT_FILE_NEW,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 1,IDT_FILE_OPEN,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 3,IDT_FILE_SAVE,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 2,IDT_FILE_BROWSE,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 27,IDT_FILE_RECENT,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 0,0,0,BTNS_SEP,{0},0,0 },
{ 4,IDT_EDIT_UNDO,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 5,IDT_EDIT_REDO,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 0,0,0,BTNS_SEP,{0},0,0 },
{ 6,IDT_EDIT_CUT,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 7,IDT_EDIT_COPY,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 8,IDT_EDIT_PASTE,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 0,0,0,BTNS_SEP,{0},0,0 },
{ 9,IDT_EDIT_FIND,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 10,IDT_EDIT_REPLACE,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 0,0,0,BTNS_SEP,{0},0,0 },
{ 29,IDT_GREP_WIN_TOOL,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 0,0,0,BTNS_SEP,{0},0,0 },
{ 11,IDT_VIEW_WORDWRAP,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 0,0,0,BTNS_SEP,{0},0,0 },
{ 23,IDT_VIEW_TOGGLEFOLDS,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 25,IDT_VIEW_TOGGLE_VIEW,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 0,0,0,BTNS_SEP,{0},0,0 },
{ 21,IDT_FILE_OPENFAV,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 22,IDT_FILE_ADDTOFAV,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 0,0,0,BTNS_SEP,{0},0,0 },
{ 12,IDT_VIEW_ZOOMIN,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 13,IDT_VIEW_ZOOMOUT,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 0,0,0,BTNS_SEP,{0},0,0 },
{ 14,IDT_VIEW_SCHEME,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 0,0,0,BTNS_SEP,{0},0,0 },
{ 24,IDT_FILE_LAUNCH,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 0,0,0,BTNS_SEP,{0},0,0 },
{ 28,IDT_VIEW_PIN_ON_TOP,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 0,0,0,BTNS_SEP,{0},0,0 },
{ 16,IDT_FILE_EXIT,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 0,0,0,BTNS_SEP,{0},0,0 },
{ 15,IDT_VIEW_SCHEMECONFIG,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 17,IDT_FILE_SAVEAS,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 18,IDT_FILE_SAVECOPY,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 19,IDT_EDIT_CLEAR,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 20,IDT_FILE_PRINT,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
{ 26,IDT_VIEW_CHASING_DOCTAIL,TBSTATE_ENABLED,BTNS_BUTTON,{0},0,0 },
};
static const int NUMTOOLBITMAPS = 30;
// ----------------------------------------------------------------------------
const char chr_currency[6] = { '$', 0x80, 0xA2, 0xA3, 0xA5, '\0' }; // "$€¢£¥"
// ----------------------------------------------------------------------------
const WCHAR *const TBBUTTON_DEFAULT_IDS_V1 = L"1 2 4 3 28 0 5 6 0 7 8 9 0 10 11 0 30 0 12 0 24 26 0 22 23 0 13 14 0 27 0 15 0 25 0 17";
const WCHAR* const TBBUTTON_DEFAULT_IDS_V2 = L"1 2 4 3 28 0 5 6 0 7 8 9 0 10 11 0 30 0 12 0 24 26 0 22 23 0 13 14 0 15 0 25 0 29 0 17";
//=============================================================================
// static method declarations
// undo / redo selections
static UT_icd UndoRedoSelElement_icd = { sizeof(DocPos), NULL, NULL, NULL };
static void InitUndoRedoSelection(void* elt)
{
UndoRedoSelection_t* selection = (UndoRedoSelection_t*)elt;
if (selection != NULL) {
selection->selMode_undo = SC_SEL_STREAM;
selection->anchorPos_undo = NULL;
selection->curPos_undo = NULL;
selection->anchorVS_undo = NULL;
selection->curVS_undo = NULL;
selection->selMode_redo = SC_SEL_STREAM;
selection->anchorPos_redo = NULL;
selection->curPos_redo = NULL;
selection->anchorVS_redo = NULL;
selection->curVS_redo = NULL;
}
}
static void DelUndoRedoSelection(void* elt)
{
UndoRedoSelection_t* selection = (UndoRedoSelection_t*)elt;
if (selection != NULL) {
if (selection->anchorPos_undo != NULL) {
utarray_clear(selection->anchorPos_undo);
utarray_free(selection->anchorPos_undo);
selection->anchorPos_undo = NULL;
}
if (selection->curPos_undo != NULL) {
utarray_clear(selection->curPos_undo);
utarray_free(selection->curPos_undo);
selection->curPos_undo = NULL;
}
if (selection->anchorVS_undo != NULL) {
utarray_clear(selection->anchorVS_undo);
utarray_free(selection->anchorVS_undo);
selection->anchorVS_undo = NULL;
}
if (selection->curVS_undo != NULL) {
utarray_clear(selection->curVS_undo);
utarray_free(selection->curVS_undo);
selection->curVS_undo = NULL;
}
if (selection->anchorPos_redo != NULL) {
utarray_clear(selection->anchorPos_redo);
utarray_free(selection->anchorPos_redo);
selection->anchorPos_redo = NULL;
}
if (selection->curPos_redo != NULL) {
utarray_clear(selection->curPos_redo);
utarray_free(selection->curPos_redo);
selection->curPos_redo = NULL;
}
if (selection->anchorVS_redo != NULL) {
utarray_clear(selection->anchorVS_redo);
utarray_free(selection->anchorVS_redo);
selection->anchorVS_redo = NULL;
}
if (selection->curVS_redo != NULL) {
utarray_clear(selection->curVS_redo);
utarray_free(selection->curVS_redo);
selection->curVS_redo = NULL;
}
}
}
static void CopyUndoRedoSelection(void* dst, const void* src)
{
UndoRedoSelection_t* dst_sel = (UndoRedoSelection_t*)dst;
const UndoRedoSelection_t* src_sel = (UndoRedoSelection_t*)src;
DocPos* pPos = NULL;
InitUndoRedoSelection(dst);
dst_sel->selMode_undo = (src_sel) ? src_sel->selMode_undo : SC_SEL_STREAM;
utarray_new(dst_sel->anchorPos_undo, &UndoRedoSelElement_icd);
if (src_sel) {
while ((pPos = (DocPos*)utarray_next(src_sel->anchorPos_undo, pPos)) != NULL) {
utarray_push_back(dst_sel->anchorPos_undo, pPos);
}
}
utarray_new(dst_sel->curPos_undo, &UndoRedoSelElement_icd);
if (src_sel) {
while ((pPos = (DocPos*)utarray_next(src_sel->curPos_undo, pPos)) != NULL) {
utarray_push_back(dst_sel->curPos_undo, pPos);
}
}
utarray_new(dst_sel->anchorVS_undo, &UndoRedoSelElement_icd);
if (src_sel) {
while ((pPos = (DocPos*)utarray_next(src_sel->anchorVS_undo, pPos)) != NULL) {
utarray_push_back(dst_sel->anchorVS_undo, pPos);
}
}
utarray_new(dst_sel->curVS_undo, &UndoRedoSelElement_icd);
if (src_sel) {
while ((pPos = (DocPos*)utarray_next(src_sel->curVS_undo, pPos)) != NULL) {
utarray_push_back(dst_sel->curVS_undo, pPos);
}
}
dst_sel->selMode_redo = (src_sel) ? src_sel->selMode_redo : SC_SEL_STREAM;
utarray_new(dst_sel->anchorPos_redo, &UndoRedoSelElement_icd);
if (src_sel) {
while ((pPos = (DocPos*)utarray_next(src_sel->anchorPos_redo, pPos)) != NULL) {
utarray_push_back(dst_sel->anchorPos_redo, pPos);
}
}
utarray_new(dst_sel->curPos_redo, &UndoRedoSelElement_icd);
if (src_sel) {
while ((pPos = (DocPos*)utarray_next(src_sel->curPos_redo, pPos)) != NULL) {
utarray_push_back(dst_sel->curPos_redo, pPos);
}
}
utarray_new(dst_sel->anchorVS_redo, &UndoRedoSelElement_icd);
if (src_sel) {
while ((pPos = (DocPos*)utarray_next(src_sel->anchorVS_redo, pPos)) != NULL) {
utarray_push_back(dst_sel->anchorVS_redo, pPos);
}
}
utarray_new(dst_sel->curVS_redo, &UndoRedoSelElement_icd);
if (src_sel) {
while ((pPos = (DocPos*)utarray_next(src_sel->curVS_redo, pPos)) != NULL) {
utarray_push_back(dst_sel->curVS_redo, pPos);
}
}
}
static UT_icd UndoRedoSelection_icd = { sizeof(UndoRedoSelection_t), InitUndoRedoSelection, CopyUndoRedoSelection, DelUndoRedoSelection };
static UT_array* UndoRedoSelectionUTArray = NULL;
static bool _InUndoRedoTransaction();
static void _SaveRedoSelection(int token);
static int _SaveUndoSelection();
static int _UndoRedoActionMap(int token, const UndoRedoSelection_t** selection);
static void _SplitUndoTransaction(const int iModType);
// => _BEGIN_UNDO_ACTION_
// => _END_UNDO_ACTION_
// ----------------------------------------------------------------------------
static void _DelayClearZoomCallTip(int delay);
static void _DelaySplitUndoTransaction(int delay, int iModType);
//=============================================================================
//
// IgnoreNotifyChangeEvent(), ObserveNotifyChangeEvent(), CheckNotifyChangeEvent()
//
static volatile LONG iNotifyChangeStackCounter = 0L;
static __forceinline bool CheckNotifyChangeEvent()
{
return (InterlockedOr(&iNotifyChangeStackCounter, 0L) == 0L);
}
void IgnoreNotifyChangeEvent()
{
InterlockedIncrement(&iNotifyChangeStackCounter);
}
void ObserveNotifyChangeEvent()
{
if (!CheckNotifyChangeEvent()) {
InterlockedDecrement(&iNotifyChangeStackCounter);
}
if (CheckNotifyChangeEvent()) {
EditUpdateVisibleIndicators();
UpdateStatusbar(false);
}
}
// SCN_UPDATEUI notification
#define SC_UPDATE_NP3_INTERNAL_NOTIFY (SC_UPDATE_H_SCROLL << 1)
//=============================================================================
//
// Delay Message Queue Handling (TODO: MultiThreading)
//
static CmdMessageQueue_t* MessageQueue = NULL;
// ----------------------------------------------------------------------------
static int msgcmp(void* mqc1, void* mqc2)
{
CmdMessageQueue_t* const pMQC1 = (CmdMessageQueue_t*)mqc1;
CmdMessageQueue_t* const pMQC2 = (CmdMessageQueue_t*)mqc2;
if ((pMQC1->cmd == pMQC2->cmd)
//&& (pMQC1->hwnd == pMQC2->hwnd)
&& (pMQC1->wparam == pMQC2->wparam) // command
//&& (pMQC1->lparam == pMQC2->lparam)
){
return FALSE;
}
return 1;
}
// ----------------------------------------------------------------------------
#define _MQ_IMMEDIATE (2 * USER_TIMER_MINIMUM - 1)
#define _MQ_FAST (USER_TIMER_MINIMUM << 2)
#define _MQ_STD (USER_TIMER_MINIMUM << 3)
#define _MQ_LAZY (USER_TIMER_MINIMUM << 4)
#define _MQ_ms(T) ((T) / USER_TIMER_MINIMUM)
static void _MQ_AppendCmd(CmdMessageQueue_t* const pMsgQCmd, int cycles)
{
if (!pMsgQCmd) { return; }
CmdMessageQueue_t* pmqc = NULL;
DL_SEARCH(MessageQueue, pmqc, pMsgQCmd, msgcmp);
if (!pmqc) { // NOT found
pmqc = pMsgQCmd;
pmqc->delay = cycles;
DL_APPEND(MessageQueue, pmqc);
}
else {
pmqc->delay = (pmqc->delay + cycles) / 2; // increase delay
}
if (pmqc->delay < 2) {
// execute now (do not use PostMessage() here)
SendMessage(pMsgQCmd->hwnd, pMsgQCmd->cmd, pMsgQCmd->wparam, pMsgQCmd->lparam);
pmqc->delay = -1;
pmqc->lparam = 0;
}
}
// ----------------------------------------------------------------------------
/* UNUSED yet
static void _MQ_RemoveCmd(CmdMessageQueue_t* const pMsgQCmd)
{
CmdMessageQueue_t* pmqc;
DL_FOREACH(MessageQueue, pmqc)
{
if ((pMsgQCmd->hwnd == pmqc->hwnd)
&& (pMsgQCmd->cmd == pmqc->cmd)
&& (pMsgQCmd->wparam == pmqc->wparam))
{
pmqc->delay = -1;
}
}
}
*/
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
//
// called by Timer(IDT_TIMER_MRKALL)
//
static void CALLBACK MQ_ExecuteNext(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
UNUSED(hwnd); // must be main window handle
UNUSED(uMsg); // must be WM_TIMER
UNUSED(idEvent); // must be IDT_TIMER_MRKALL
UNUSED(dwTime); // This is the value returned by the GetTickCount function
CmdMessageQueue_t* pmqc;
DL_FOREACH(MessageQueue, pmqc)
{
if (pmqc->delay == 0) {
SendMessage(pmqc->hwnd, pmqc->cmd, pmqc->wparam, pmqc->lparam);
pmqc->delay = -1;
pmqc->lparam = 0;
}
else if (pmqc->delay >= 0) {
pmqc->delay -= 1; // decrease
}
}
}
//=============================================================================
//
// InvalidateStyleRedraw
//
static inline void InvalidateStyleRedraw()
{
SciCall_SetViewEOL(Settings.ViewEOLs);
}
//=============================================================================
//
// CommandLine Parsing Flags
//
static LPWSTR s_lpSchemeArg = NULL;
static LPWSTR s_lpOrigFileArg = NULL;
static WCHAR s_lpFileArg[MAX_PATH + 1] = { L'\0' };
static cpi_enc_t s_flagSetEncoding = CPI_NONE;
static int s_flagSetEOLMode = 0;
static bool s_flagStartAsTrayIcon = false;
static int s_flagAlwaysOnTop = 0;
static bool s_flagKeepTitleExcerpt = false;
static bool s_flagNewFromClipboard = false;
static bool s_flagPasteBoard = false;
static bool s_flagJumpTo = false;
static FILE_WATCHING_MODE s_flagChangeNotify = FWM_DONT_CARE;
static bool s_flagQuietCreate = false;
static bool s_flagLexerSpecified = false;
static bool s_flagAppIsClosing = false;
static bool s_flagDisplayHelp = false;
//==============================================================================
// static forward declarations
static void _UpdateStatusbarDelayed(bool bForceRedraw);
static void _UpdateToolbarDelayed();
//==============================================================================
//
// Save Needed Flag
//
//
static bool s_DocNeedSaving = false; // dirty-flag
static void SetSaveNeeded()
{
if (!s_DocNeedSaving) {
s_DocNeedSaving = true;
UpdateTitleBar();
}
UpdateToolbar();
if (IsWindow(Globals.hwndDlgFindReplace)) {
PostWMCommand(Globals.hwndDlgFindReplace, IDC_DOC_MODIFIED);
}
}
void SetSavePoint()
{
if (SciCall_GetModify()) {
SciCall_SetSavePoint();
}
s_DocNeedSaving = false;
UpdateToolbar();
UpdateTitleBar();
}
inline static bool GetDocModified() {
if (SciCall_GetModify() && !s_DocNeedSaving) {
SetSaveNeeded();
}
return s_DocNeedSaving;
}
//==============================================================================
static void _InitGlobals()
{
ZeroMemory(&Globals, sizeof(GLOBALS_T));
ZeroMemory(&Defaults, sizeof(SETTINGS_T));
ZeroMemory(&Settings, sizeof(SETTINGS_T));
ZeroMemory(&Defaults2, sizeof(SETTINGS_T));
ZeroMemory(&Settings2, sizeof(SETTINGS2_T));
ZeroMemory(&Flags, sizeof(FLAGS_T));
ZeroMemory(&(Globals.fvCurFile), sizeof(FILEVARS));
Globals.WindowsBuildNumber = GetWindowsBuildNumber(NULL, NULL);
Globals.hDlgIcon256 = NULL;
Globals.hDlgIcon128 = NULL;
Globals.hDlgIconBig = NULL;
Globals.hDlgIconSmall = NULL;
Globals.hDlgIconPrefs256 = NULL;
Globals.hDlgIconPrefs128 = NULL;
Globals.hDlgIconPrefs64 = NULL;
Globals.hMainMenu = NULL;
Globals.pFileMRU = NULL;
Globals.pMRUfind = NULL;
Globals.pMRUreplace = NULL;
Globals.iAvailLngCount = 1;
Globals.iPrefLANGID = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
Globals.iWrapCol = 80;
Globals.CallTipType = CT_NONE;
Globals.CmdLnFlag_PosParam = false;
Globals.CmdLnFlag_WindowPos = 0;
Globals.CmdLnFlag_ReuseWindow = 0;
Globals.CmdLnFlag_SingleFileInstance = 0;
Globals.CmdLnFlag_MultiFileArg = 0;
Globals.CmdLnFlag_ShellUseSystemMRU = 0;
Globals.CmdLnFlag_PrintFileAndLeave = 0;
Globals.DOSEncoding = CPI_NONE;
Globals.bZeroBasedColumnIndex = false;
Globals.bZeroBasedCharacterCount = false;
Globals.iReplacedOccurrences = 0;
Globals.iMarkOccurrencesCount = 0;
Globals.bUseLimitedAutoCCharSet = false;
Globals.bIsCJKInputCodePage = false;
Globals.bIniFileFromScratch = false;
Globals.bFindReplCopySelOrClip = true;
Globals.bReplaceInitialized = false;
Globals.FindReplaceMatchFoundState = FND_NOP;
Globals.bDocHasInconsistentEOLs = false;
Globals.idxLightModeTheme = 1; // Default(0), Standard(1)
Globals.idxDarkModeTheme = 1; // buildin Standard(1)
Globals.InitialFontSize = (IsFullHD(NULL, -1, -1) < 0) ? 10 : 11;
Flags.bLargeFileLoaded = DefaultFlags.bLargeFileLoaded = false;
Flags.bDevDebugMode = DefaultFlags.bDevDebugMode = false;
Flags.bStickyWindowPosition = DefaultFlags.bStickyWindowPosition = false;
Flags.bReuseWindow = DefaultFlags.bReuseWindow = false;
Flags.bSingleFileInstance = DefaultFlags.bSingleFileInstance = true;
Flags.MultiFileArg = DefaultFlags.MultiFileArg = false;
Flags.RelativeFileMRU = DefaultFlags.RelativeFileMRU = true;
Flags.PortableMyDocs = DefaultFlags.PortableMyDocs = Flags.RelativeFileMRU;
Flags.NoFadeHidden = DefaultFlags.NoFadeHidden = false;
Flags.ToolbarLook = DefaultFlags.ToolbarLook = IsWindowsXPSP3OrGreater() ? 1 : 2;
Flags.SimpleIndentGuides = DefaultFlags.SimpleIndentGuides = false;
Flags.NoHTMLGuess =DefaultFlags.NoHTMLGuess = false;
Flags.NoCGIGuess = DefaultFlags.NoCGIGuess = false;
Flags.NoFileVariables = DefaultFlags.NoFileVariables = false;
Flags.ShellUseSystemMRU = DefaultFlags.ShellUseSystemMRU = true;
Flags.PrintFileAndLeave = DefaultFlags.PrintFileAndLeave = 0;
Flags.bPreserveFileModTime = DefaultFlags.bPreserveFileModTime = false;
Flags.bDoRelaunchElevated = DefaultFlags.bDoRelaunchElevated = false;
Flags.bSearchPathIfRelative = DefaultFlags.bSearchPathIfRelative = false;
Flags.bSettingsFileSoftLocked = DefaultFlags.bSettingsFileSoftLocked = false;
FocusedView.HideNonMatchedLines = false;
FocusedView.CodeFoldingAvailable = false;
FocusedView.ShowCodeFolding = true;
FileWatching.flagChangeNotify = FWM_DONT_CARE;
FileWatching.FileWatchingMode = FWM_DONT_CARE;
FileWatching.ResetFileWatching = true;
FileWatching.MonitoringLog = false;
}
//=============================================================================
//
// _InsertLanguageMenu()
//
//typedef struct _lng_menu_t {
// LANGID LangID;
// const WCHAR* MenuItem;
//} LNG_MENU_T;
static HMENU s_hmenuLanguage = NULL;
static bool _InsertLanguageMenu(HMENU hMenuBar)
{
// check, if we need a language switching menu
if (Globals.iAvailLngCount < 2) {
return false;
}
if (s_hmenuLanguage) { DestroyMenu(s_hmenuLanguage); }
s_hmenuLanguage = CreatePopupMenu();
WCHAR wchMenuItemFmt[128] = { L'\0' };
WCHAR wchMenuItemStrg[196] = { L'\0' };
for (int lng = 0; lng < MuiLanguages_CountOf(); ++lng)
{
if (MUI_LanguageDLLs[lng].bHasDLL)
{
StringCchCopy(wchMenuItemFmt, COUNTOF(wchMenuItemFmt), MUI_LanguageDLLs[lng].szMenuItem);
StringCchPrintfW(wchMenuItemStrg, COUNTOF(wchMenuItemStrg), wchMenuItemFmt, MUI_LanguageDLLs[lng].szLocaleName);
AppendMenu(s_hmenuLanguage, MF_ENABLED | MF_STRING, MUI_LanguageDLLs[lng].rid, wchMenuItemStrg);
}
}
// --- insert ---
int const pos = GetMenuItemCount(hMenuBar) - 1;
if (pos >= 0) {
GetLngString(IDS_MUI_MENU_LANGUAGE, wchMenuItemStrg, COUNTOF(wchMenuItemStrg));
//return InsertMenu(hMenuBar, pos, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR)s_hmenuLanguage, wchMenuItemStrg);
bool const res = InsertMenu(hMenuBar, IDM_VIEW_TABSASSPACES, MF_BYCOMMAND | MF_POPUP | MF_STRING, (UINT_PTR)s_hmenuLanguage, wchMenuItemStrg);
InsertMenu(hMenuBar, IDM_VIEW_TABSASSPACES, MF_BYCOMMAND | MF_SEPARATOR, (UINT_PTR)NULL, NULL);
return res;
}
return false;
}
//=============================================================================
//
// _CleanUpResources()
//
static _invalid_parameter_handler _hOldInvalidParamHandler = NULL;
static void _CleanUpResources(const HWND hwnd, bool bIsInitialized)
{
if (hwnd) {
KillTimer(hwnd, IDT_TIMER_MRKALL);
}
CmdMessageQueue_t* pmqc = NULL;
CmdMessageQueue_t* dummy;
DL_FOREACH_SAFE(MessageQueue, pmqc, dummy)
{
DL_DELETE(MessageQueue, pmqc);
//~FreeMem(pmqc); // No AllocMem Anymore
}
if (UndoRedoSelectionUTArray != NULL) {
utarray_clear(UndoRedoSelectionUTArray);
utarray_free(UndoRedoSelectionUTArray);
UndoRedoSelectionUTArray = NULL;
}
// -------------------------------
// Save Settings is done elsewhere
// -------------------------------
if (Globals.hMainMenu) {
DestroyMenu(Globals.hMainMenu);
}
FreeLanguageResources();
Scintilla_ReleaseResources();
OleUninitialize();
if (bIsInitialized) {
//~UnregisterClass(s_ToolbarWndClassName, Globals.hInstance);
UnregisterClass(s_wchWndClass, Globals.hInstance);
}
ReleaseDarkMode();
if (s_lpOrigFileArg) {
FreeMem(s_lpOrigFileArg);
s_lpOrigFileArg = NULL;
}
if (_hOldInvalidParamHandler) {
_set_invalid_parameter_handler(_hOldInvalidParamHandler);
}
}
//=============================================================================
//
// InvalidParameterHandler()
//
void InvalidParameterHandler(const wchar_t* expression,
const wchar_t* function,
const wchar_t* file,
unsigned int line,
uintptr_t pReserved)
{
UNUSED(expression);
UNUSED(pReserved);
WCHAR msg[256];
StringCchPrintf(msg, COUNTOF(msg),
L"Invalid Parameter in function '%s()' - File:'%s' Line:%i !",
function, file, line);
DbgMsgBoxLastError(msg, ERROR_INVALID_PARAMETER);
}
//=============================================================================
//
// WinMain()
//
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nShowCmd)
{
_invalid_parameter_handler const hNewInvalidParamHandler = InvalidParameterHandler;
_hOldInvalidParamHandler= _set_invalid_parameter_handler(hNewInvalidParamHandler);
_CrtSetReportMode(_CRT_ASSERT, 0); // Disable the message box for assertions.
_InitGlobals();
InitDarkMode();
// Set global variable Globals.hInstance
Globals.hInstance = hInstance;
Globals.hPrevInst = hPrevInstance;
Globals.hndlProcessHeap = GetProcessHeap();
WCHAR wchAppDir[MAX_PATH] = { L'\0' };
PathGetAppDirectory(wchAppDir, COUNTOF(wchAppDir));
if (!GetCurrentDirectory(COUNTOF(Globals.WorkingDirectory),Globals.WorkingDirectory)) {
StringCchCopy(Globals.WorkingDirectory,COUNTOF(Globals.WorkingDirectory),wchAppDir);
}
// Don't keep working directory locked
SetCurrentDirectory(wchAppDir);
SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
// check if running at least on Windows 7 (SP1)
if (!IsWindows7SP1OrGreater()) {
MsgBoxLastError(L"Application Initialization", ERROR_OLD_WIN_VERSION);
return 1; // exit
}
// Check if running with elevated privileges
s_bIsProcessElevated = IsProcessElevated();
s_bIsUserInAdminGroup = IsUserInAdminGroup();
s_bIsRunAsAdmin = IsRunAsAdmin();
// Default Encodings (may already be used for command line parsing)
Encoding_InitDefaults();
// Command Line, Ini File and Flags
ParseCommandLine();
FindIniFile();
TestIniFile();
DWORD dwFileSize = 0UL;
Globals.bCanSaveIniFile = CreateIniFile(Globals.IniFile, &dwFileSize);
Globals.bIniFileFromScratch = (dwFileSize == 0UL);
if (Globals.bIniFileFromScratch && Globals.bCanSaveIniFile) {
// Set at least Application Name Section
IniFileSetString(Globals.IniFile, _W(SAPPNAME), NULL, NULL);
}
LoadSettings();
// set AppUserModelID
PrivateSetCurrentProcessExplicitAppUserModelID(Settings2.AppUserModelID);
// Adapt window class name
StringCchCat(s_wchWndClass, COUNTOF(s_wchWndClass), _W(SAPPNAME));
if (s_bIsProcessElevated) {
StringCchCat(s_wchWndClass, COUNTOF(s_wchWndClass), L"U");
}
if (s_flagPasteBoard) {
StringCchCat(s_wchWndClass, COUNTOF(s_wchWndClass), L"B");
}
(void)OleInitialize(NULL);
INITCOMMONCONTROLSEX icex;
ZeroMemory(&icex, sizeof(INITCOMMONCONTROLSEX));
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_WIN95_CLASSES | ICC_USEREX_CLASSES | ICC_COOL_CLASSES | ICC_NATIVEFNTCTL_CLASS | ICC_STANDARD_CLASSES;
InitCommonControlsEx(&icex);
Scintilla_RegisterClasses(hInstance);
#ifdef D_NP3_WIN10_DARK_MODE
SetDarkMode(IsDarkModeSupported() && Settings.WinThemeDarkMode); // settings
#endif
Style_ImportTheme(GetModeThemeIndex());
//SetProcessDPIAware(); -> .manifest
//SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
Scintilla_LoadDpiForWindow();
// ----------------------------------------------------
// MultiLingual
//
SetPreferredLanguage(LoadLanguageResources());
// ----------------------------------------------------
// ICON_BIG
int const cxb = GetSystemMetrics(SM_CXICON) << 2;
int const cyb = GetSystemMetrics(SM_CYICON) << 2;
// ICON_SMALL
int const cxs = GetSystemMetrics(SM_CXSMICON) << 1;
int const cys = GetSystemMetrics(SM_CYSMICON) << 1;
//UINT const fuLoad = LR_DEFAULTCOLOR | LR_SHARED;
if (!Globals.hDlgIcon256) {
LoadIconWithScaleDown(hInstance, MAKEINTRESOURCE(IDR_MAINWND), 256, 256, &(Globals.hDlgIcon256));
}
if (!Globals.hDlgIcon128) {
LoadIconWithScaleDown(hInstance, MAKEINTRESOURCE(IDR_MAINWND), 128, 128, &(Globals.hDlgIcon128));
}
if (!Globals.hDlgIconBig) {
LoadIconWithScaleDown(hInstance, MAKEINTRESOURCE(IDR_MAINWND), cxb, cyb, &(Globals.hDlgIconBig));
}
if (!Globals.hDlgIconSmall) {
LoadIconWithScaleDown(hInstance, MAKEINTRESOURCE(IDR_MAINWND), cxs, cys, &(Globals.hDlgIconSmall));
}
if (!Globals.hDlgIconPrefs256) {
LoadIconWithScaleDown(hInstance, MAKEINTRESOURCE(IDI_MUI_STYLES), 256, 256, &(Globals.hDlgIconPrefs256));
}
if (!Globals.hDlgIconPrefs128) {
LoadIconWithScaleDown(hInstance, MAKEINTRESOURCE(IDI_MUI_STYLES), 128, 128, &(Globals.hDlgIconPrefs128));
}
if (!Globals.hDlgIconPrefs64) {
LoadIconWithScaleDown(hInstance, MAKEINTRESOURCE(IDI_MUI_STYLES), 64, 64, &(Globals.hDlgIconPrefs64));
}
if (!Globals.hIconMsgUser) {
LoadIconWithScaleDown(hInstance, MAKEINTRESOURCE(IDR_MAINWND), cxb, cyb, &(Globals.hIconMsgUser));
}
if (!Globals.hIconMsgInfo) {
LoadIconWithScaleDown(NULL, IDI_INFORMATION, cxb, cyb, &(Globals.hIconMsgInfo));
}
if (!Globals.hIconMsgWarn) {
LoadIconWithScaleDown(NULL, IDI_WARNING, cxb, cyb, &(Globals.hIconMsgWarn));
}
if (!Globals.hIconMsgError) {
LoadIconWithScaleDown(NULL, IDI_ERROR, cxb, cyb, &(Globals.hIconMsgError));
}
if (!Globals.hIconMsgQuest) {
LoadIconWithScaleDown(NULL, IDI_QUESTION, cxb, cyb, &(Globals.hIconMsgQuest));
}
if (!Globals.hIconMsgShield) {
LoadIconWithScaleDown(NULL, IDI_SHIELD, cxb, cyb, &(Globals.hIconMsgShield));
}
//if (!Globals.hIconMsgWinLogo) {
// LoadIconWithScaleDown(NULL, IDI_WINLOGO, cxl, cyl, &(Globals.hIconMsgWinLogo));
//}
if (s_IsThisAnElevatedRelaunch && !IsRunAsAdmin()) {
InfoBoxLng(MB_ICONSHIELD, NULL, IDS_MUI_ERR_ELEVATED_RIGHTS);
s_flagSaveOnRelaunch = false;
}
// Try to Relaunch with elevated privileges
if (RelaunchElevated(NULL)) {
return FALSE;
}
// Try to run multiple instances
if (RelaunchMultiInst()) {
return FALSE;
}
// Try to activate another window
if (ActivatePrevInst()) {
return FALSE;
}
// Command Line Help Dialog
if (s_flagDisplayHelp) {
DisplayCmdLineHelp(NULL);
_CleanUpResources(NULL, false);
return FALSE;
}
s_msgTaskbarCreated = RegisterWindowMessage(L"TaskbarCreated");
Globals.hMainMenu = LoadMenu(Globals.hLngResContainer, MAKEINTRESOURCE(IDR_MUI_MAINMENU));
if (!Globals.hMainMenu) {
MsgBoxLastError(L"LoadMenu()", 0);
_CleanUpResources(NULL, false);
return 1;
}
_InsertLanguageMenu(Globals.hMainMenu);
Style_InsertThemesMenu(Globals.hMainMenu);
if (!InitApplication(Globals.hInstance))
{
_CleanUpResources(NULL, false);
return 1;
}
HWND const hwnd = InitInstance(Globals.hInstance, lpCmdLine, nShowCmd);
if (!hwnd) {
_CleanUpResources(hwnd, true);
return 1;
}
DrawMenuBar(hwnd);
HACCEL const hAccMain = LoadAccelerators(hInstance,MAKEINTRESOURCE(IDR_MAINWND));
HACCEL const hAccFindReplace = LoadAccelerators(hInstance,MAKEINTRESOURCE(IDR_ACCFINDREPLACE));
HACCEL const hAccCoustomizeSchemes = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCCUSTOMSCHEMES));
SetTimer(hwnd, IDT_TIMER_MRKALL, USER_TIMER_MINIMUM, (TIMERPROC)MQ_ExecuteNext);
if (Globals.bPrefLngNotAvail) {
const WCHAR* const suprMsg = L"MsgPrefLanguageNotAvailable";
InfoBoxLng(MB_ICONWARNING, suprMsg, IDS_WARN_PREF_LNG_NOT_AVAIL, Settings2.PreferredLanguageLocaleName);
int const noMsg = IniFileGetInt(Globals.IniFile, Constants.SectionSuppressedMessages, suprMsg, 0);
if (noMsg && Globals.bCanSaveIniFile) {
IniFileSetString(Globals.IniFile, Constants.Settings2_Section, L"PreferredLanguageLocaleName", MUI_LanguageDLLs[0].szLocaleName);
}
}
MSG msg;
while (GetMessage(&msg,NULL,0,0))
{
if (IsWindow(Globals.hwndDlgFindReplace) && ((msg.hwnd == Globals.hwndDlgFindReplace) || IsChild(Globals.hwndDlgFindReplace, msg.hwnd)))
{
const int iTr = TranslateAccelerator(Globals.hwndDlgFindReplace, hAccFindReplace, &msg);
if (iTr || IsDialogMessage(Globals.hwndDlgFindReplace, &msg))
continue;
}
if (IsWindow(Globals.hwndDlgCustomizeSchemes) && ((msg.hwnd == Globals.hwndDlgCustomizeSchemes) || IsChild(Globals.hwndDlgCustomizeSchemes, msg.hwnd))) {
const int iTr = TranslateAccelerator(Globals.hwndDlgCustomizeSchemes, hAccCoustomizeSchemes, &msg);
if (iTr || IsDialogMessage(Globals.hwndDlgCustomizeSchemes, &msg))
continue;
}
if (!TranslateAccelerator(hwnd, hAccMain, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
_CleanUpResources(hwnd, true);
return (int)(msg.wParam);
}
//=============================================================================
//
// GetFactoryDefaultWndPos()
//
//
WININFO GetFactoryDefaultWndPos(const int flagsPos)
{
RECT rc;
GetWindowRect(GetDesktopWindow(), &rc);
MONITORINFO mi;
GetMonitorInfoFromRect(&rc, &mi);
WININFO winfo = INIT_WININFO;
winfo.y = mi.rcMonitor.top;
winfo.cy = mi.rcWork.bottom - mi.rcWork.top;
winfo.cx = (mi.rcWork.right - mi.rcWork.left) / 2;
winfo.x = (flagsPos == 3) ? mi.rcMonitor.left : winfo.cx;
winfo.max = 0;
winfo.zoom = 100;
return winfo;
}
// ----------------------------------------------------------------------------
//=============================================================================
//
// GetWinInfoByFlag()
//
//
WININFO GetWinInfoByFlag(const int flagsPos)
{
WININFO winfo = INIT_WININFO;
if (flagsPos < 0) {
winfo = GetMyWindowPlacement(Globals.hwndMain, NULL); // current window position
}
else if (flagsPos == 0) {
winfo = g_IniWinInfo; // initial window position
}
else if (flagsPos == 1) {
winfo.x = winfo.y = winfo.cx = winfo.cy = CW_USEDEFAULT;
winfo.max = false;
winfo.zoom = 100;
}
else if (flagsPos == 2)
{
winfo = g_DefWinInfo; // NP3 default window position
}
else if (flagsPos == 3)
{
winfo = GetFactoryDefaultWndPos(flagsPos);
}
else if ((flagsPos >= 4) && (flagsPos < 256))
{
RECT rc;
GetWindowRect(GetDesktopWindow(), &rc);
MONITORINFO mi;
GetMonitorInfoFromRect(&rc, &mi);
int const width = (mi.rcWork.right - mi.rcWork.left);
int const height = (mi.rcWork.bottom - mi.rcWork.top);
if (flagsPos & 8)
winfo.x = mi.rcMonitor.left + (width >> 1);
else
winfo.x = mi.rcMonitor.left;
if (flagsPos & (4 | 8))
winfo.cx = (width >> 1);
else
winfo.cx = width;
if (flagsPos & 32)
winfo.y = mi.rcMonitor.top + (height >> 1);
else
winfo.y = mi.rcMonitor.top;
if (flagsPos & (16 | 32))
winfo.cy = (height >> 1);
else
winfo.cy = height;
if (flagsPos & 64) {
winfo.x = mi.rcMonitor.left;
winfo.y = mi.rcMonitor.top;
winfo.cx = width;
winfo.cy = height;
}
if (flagsPos & 128) {
winfo = g_DefWinInfo;
winfo.max = true;
winfo.zoom = 100;
}
}
else { // ( > 256) restore window, move upper left corner to Work Area
MONITORINFO mi;
RECT const rc = RectFromWinInfo(&winfo);
GetMonitorInfoFromRect(&rc, &mi);
WININFO wi = winfo; wi.cx = wi.cy = 16; // really small
FitIntoMonitorGeometry(&(mi.rcWork), &wi, SCR_NORMAL);
winfo.x = wi.x;
winfo.y = wi.y;
}
return winfo;
}
//=============================================================================
//
// Set/Get FindPattern()
//
static WCHAR sCurrentFindPattern[FNDRPL_BUFFER] = { L'\0' };
bool IsFindPatternEmpty()
{
return StrIsEmpty(sCurrentFindPattern);
}
//=============================================================================
//
// SetFindPattern()
//
void SetFindPattern(LPCWSTR wchFindPattern)
{
StringCchCopy(sCurrentFindPattern, COUNTOF(sCurrentFindPattern), (wchFindPattern ? wchFindPattern : L""));
}
//=============================================================================
//
// SetFindPatternMB()
//
void SetFindPatternMB(LPCSTR chFindPattern)
{
MultiByteToWideCharEx(Encoding_SciCP, 0, chFindPattern, -1, sCurrentFindPattern, COUNTOF(sCurrentFindPattern));
}
//=============================================================================
//
// LengthOfFindPattern()
//
size_t LengthOfFindPattern()
{
return StringCchLen(sCurrentFindPattern, 0);
}
//=============================================================================
//
// GetFindPattern()
//
LPCWSTR GetFindPattern()
{
return sCurrentFindPattern;
}
//=============================================================================
//
// CopyFindPattern()
//
void CopyFindPattern(LPWSTR wchFindPattern, size_t bufferCount)
{
StringCchCopy(wchFindPattern, bufferCount, sCurrentFindPattern);
}
//=============================================================================
//
// CopyFindPatternMB()
//
void CopyFindPatternMB(LPSTR chFindPattern, size_t bufferCount)
{
WideCharToMultiByte(Encoding_SciCP, 0, sCurrentFindPattern, -1, chFindPattern, (int)bufferCount, NULL, NULL);
}
static EDITFINDREPLACE s_FindReplaceData = INIT_EFR_DATA;
//=============================================================================
//
// SetFindReplaceData()
//
static void SetFindReplaceData()
{
s_FindReplaceData = Settings.EFR_Data; // reset
if (!IsFindPatternEmpty()) {
CopyFindPatternMB(s_FindReplaceData.szFind, COUNTOF(s_FindReplaceData.szFind));
CopyFindPatternMB(Settings.EFR_Data.szFind, COUNTOF(Settings.EFR_Data.szFind));
}
if (g_flagMatchText) // cmd line
{
if (g_flagMatchText & 4) {
s_FindReplaceData.fuFlags = (SCFIND_REGEXP | SCFIND_POSIX);
}
if (g_flagMatchText & 8) {
s_FindReplaceData.fuFlags |= SCFIND_MATCHCASE;
}
if (g_flagMatchText & 16) {
s_FindReplaceData.fuFlags |= SCFIND_DOT_MATCH_ALL;
}
if (g_flagMatchText & 32) {
s_FindReplaceData.bTransformBS = true;
}
s_FindReplaceData.bOverlappingFind = false;
s_FindReplaceData.bWildcardSearch = false;
s_FindReplaceData.bReplaceClose = false;
}
}
//=============================================================================
//
// SetCurrentSelAsFindReplaceData()
//
static bool SetCurrentSelAsFindReplaceData()
{
if (SciCall_IsSelectionEmpty()) {
EditSelectWordAtPos(SciCall_GetCurrentPos(), true);
}
size_t const cchSelection = SciCall_GetSelText(NULL);
if (1 < cchSelection) {
char* szSelection = AllocMem(cchSelection, HEAP_ZERO_MEMORY);
if (szSelection) {
SciCall_GetSelText(szSelection);
SetFindPatternMB(szSelection);
SetFindReplaceData(); // s_FindReplaceData
FreeMem(szSelection);
return true;
}
}
return false;
}
//=============================================================================
//
// InitApplication()
//
//
bool InitApplication(const HINSTANCE hInstance)
{
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_BYTEALIGNWINDOW | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = Globals.hDlgIcon256;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
#ifdef D_NP3_WIN10_DARK_MODE
wc.hbrBackground = UseDarkMode() ? Globals.hbrDarkModeBkgBrush : (HBRUSH)(COLOR_WINDOW + 1);
#else
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
#endif
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MUI_MAINMENU);
wc.lpszClassName = s_wchWndClass;
return RegisterClassEx(&wc);
}
#if 0
//=============================================================================
//
// InitToolbarWndClass()
//
bool InitWndClass(const HINSTANCE hInstance, LPCWSTR lpszWndClassName, LPCWSTR lpszCopyFromWC, bool bUnregisterFirst) {
WNDCLASSEX wcx;
if (bUnregisterFirst) {
UnregisterClass(lpszWndClassName, hInstance);
}
ZeroMemory(&wcx, sizeof(WNDCLASSEX));
wcx.cbSize = sizeof(WNDCLASSEX);
GetClassInfoEx(hInstance, lpszCopyFromWC, &wcx); // copy members
//wcx.lpfnWndProc = (WNDPROC)TBWndProc; ~ don't do that
wcx.hInstance = hInstance; // done already
wcx.hCursor = LoadCursor(NULL, IDC_HAND);
wcx.hbrBackground = UseDarkMode() ? Globals.hbrDarkModeBkgBrush : (HBRUSH)(COLOR_WINDOW + 1);
wcx.lpszClassName = lpszWndClassName;
return RegisterClassEx(&wcx);
}
#endif
//=============================================================================
//
// InitInstance() - DarkMode already initialized !
//
HWND InitInstance(const HINSTANCE hInstance, LPCWSTR pszCmdLine, int nCmdShow)
{
UNUSED(pszCmdLine);
g_IniWinInfo = GetWinInfoByFlag(Globals.CmdLnFlag_WindowPos);
s_WinCurrentWidth = g_IniWinInfo.cx;
// get monitor coordinates from g_IniWinInfo
WININFO srcninfo = g_IniWinInfo;
WinInfoToScreen(&srcninfo);
Globals.hwndMain = CreateWindowEx(
0,
s_wchWndClass,
_W(SAPPNAME),
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
srcninfo.x,
srcninfo.y,
srcninfo.cx,
srcninfo.cy,
NULL,
NULL,
hInstance,
NULL);
if (g_IniWinInfo.max) {
nCmdShow = SW_SHOWMAXIMIZED;
}
if ((Settings.AlwaysOnTop || s_flagAlwaysOnTop == 2) && s_flagAlwaysOnTop != 1) {
SetWindowPos(Globals.hwndMain, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
SetDialogIconNP3(Globals.hwndMain);
InitWindowCommon(Globals.hwndMain, true);
if (Settings.TransparentMode) {
SetWindowTransparentMode(Globals.hwndMain, true, Settings2.OpacityLevel);
}
SetMenu(Globals.hwndMain, Globals.hMainMenu);
SetMenu(Globals.hwndMain, (Settings.ShowMenubar ? Globals.hMainMenu : NULL));
DrawMenuBar(Globals.hwndMain);
// Current file information -- moved in front of ShowWindow()
FileLoad(true,true,false,Settings.SkipUnicodeDetection,Settings.SkipANSICodePageDetection,false,L"");
if (!s_flagStartAsTrayIcon) {
ShowWindow(Globals.hwndMain,nCmdShow);
UpdateWindow(Globals.hwndMain);
}
else {
ShowWindow(Globals.hwndMain,SW_HIDE); // trick ShowWindow()
ShowNotifyIcon(Globals.hwndMain,true);
}
// Source Encoding
Encoding_Forced(s_flagSetEncoding);
// Pathname parameter
if (s_IsThisAnElevatedRelaunch || (StrIsNotEmpty(s_lpFileArg) /*&& !g_flagNewFromClipboard*/))
{
bool bOpened = false;
// Open from Directory
if (!s_IsThisAnElevatedRelaunch && PathIsDirectory(s_lpFileArg)) {
WCHAR tchFile[MAX_PATH] = { L'\0' };
if (OpenFileDlg(Globals.hwndMain, tchFile, COUNTOF(tchFile), s_lpFileArg))
bOpened = FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchFile);
}
else {
LPCWSTR lpFileToOpen = s_IsThisAnElevatedRelaunch ? s_wchTmpFilePath : s_lpFileArg;
bOpened = FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, lpFileToOpen);
if (bOpened) {
if (s_IsThisAnElevatedRelaunch)
{
if (StrIsNotEmpty(s_lpFileArg)) {
StringCchCopy(Globals.CurrentFile, COUNTOF(Globals.CurrentFile), s_lpFileArg);
InstallFileWatching(Globals.CurrentFile);
}
else {
StringCchCopy(Globals.CurrentFile, COUNTOF(Globals.CurrentFile), L"");
}
if (!s_flagLexerSpecified) {
Style_SetLexerFromFile(Globals.hwndEdit, Globals.CurrentFile);
}
// check for temp file and delete
if (s_IsThisAnElevatedRelaunch && PathIsExistingFile(s_wchTmpFilePath))
{
DeleteFile(s_wchTmpFilePath);
// delete possible .tmp guard
size_t const len = StringCchLen(s_wchTmpFilePath, MAX_PATH);
LPWSTR p = PathFindExtension(s_wchTmpFilePath);
if (p && *p) {
StringCchCopy(p, (MAX_PATH - len), L".tmp");
}
if (PathIsExistingFile(s_wchTmpFilePath)) {
DeleteFile(s_wchTmpFilePath);
}
}
UndoRedoReset();
SetSaveNeeded();
if (StrIsNotEmpty(Globals.CurrentFile)) {
if (s_flagSaveOnRelaunch) {
FileSave(true, false, false, false, Flags.bPreserveFileModTime); // issued from elevation instances
}
}
}
if (s_flagJumpTo) { // Jump to position
EditJumpTo(s_iInitialLine,s_iInitialColumn);
}
}
}
s_lpFileArg[0] = L'\0';
if (bOpened) {
switch (s_flagChangeNotify) {
case FWM_MSGBOX:
FileWatching.FileWatchingMode = FWM_DONT_CARE;
FileWatching.ResetFileWatching = true;
InstallFileWatching(Globals.CurrentFile);
break;
case FWM_AUTORELOAD:
if (!FileWatching.MonitoringLog) {
PostWMCommand(Globals.hwndMain, IDM_VIEW_CHASING_DOCTAIL);
}
else {
FileWatching.FileWatchingMode = FWM_AUTORELOAD;
FileWatching.ResetFileWatching = true;
InstallFileWatching(Globals.CurrentFile);
}
break;
case FWM_DONT_CARE:
default:
break;
}
}
}
else {
cpi_enc_t const forcedEncoding = Encoding_Forced(CPI_GET);
if (Encoding_IsValid(forcedEncoding)) {
Encoding_Current(forcedEncoding);
}
}
// reset
Encoding_Forced(CPI_NONE);
s_flagQuietCreate = false;
s_flagKeepTitleExcerpt = false;
// undo / redo selections
if (UndoRedoSelectionUTArray != NULL) {
utarray_clear(UndoRedoSelectionUTArray);
utarray_free(UndoRedoSelectionUTArray);
UndoRedoSelectionUTArray = NULL;
}
utarray_new(UndoRedoSelectionUTArray, &UndoRedoSelection_icd);
utarray_reserve(UndoRedoSelectionUTArray,256);
// Check for /c [if no file is specified] -- even if a file is specified
/*else */if (s_flagNewFromClipboard) {
if (SciCall_CanPaste()) {
bool bAutoIndent2 = Settings.AutoIndent;
Settings.AutoIndent = 0;
EditJumpTo(-1, 0);
_BEGIN_UNDO_ACTION_;
if (!Sci_IsDocEmpty()) {
SciCall_NewLine();
}
SciCall_Paste();
SciCall_NewLine();
_END_UNDO_ACTION_;
Settings.AutoIndent = bAutoIndent2;
if (s_flagJumpTo)
EditJumpTo(s_iInitialLine, s_iInitialColumn);
else
EditEnsureSelectionVisible();
}
}
// Encoding
if (s_flagSetEncoding != CPI_NONE) {
SendMessage(Globals.hwndMain, WM_COMMAND, MAKELONG(IDM_ENCODING_SELECT, IDM_ENCODING_SELECT + s_flagSetEncoding), 0);
s_flagSetEncoding = CPI_NONE;
}
// EOL mode
if (s_flagSetEOLMode != 0) {
SendWMCommand(Globals.hwndMain, IDM_LINEENDINGS_CRLF + s_flagSetEOLMode - 1);
s_flagSetEOLMode = 0;
}
// Match Text
if (g_flagMatchText && !IsFindPatternEmpty())
{
if (!Sci_IsDocEmpty()) {
SetFindReplaceData(); // s_FindReplaceData
if (g_flagMatchText & 2) {
if (!s_flagJumpTo) { SciCall_DocumentEnd(); }
EditFindPrev(Globals.hwndEdit,&s_FindReplaceData,false,false);
}
else {
if (!s_flagJumpTo) { SciCall_DocumentStart(); }
EditFindNext(Globals.hwndEdit,&s_FindReplaceData,false,false);
}
}
}
// Check for Paste Board option -- after loading files
if (s_flagPasteBoard) {
s_bLastCopyFromMe = true;
s_hwndNextCBChain = SetClipboardViewer(Globals.hwndMain);
s_uidsAppTitle = IDS_MUI_APPTITLE_PASTEBOARD;
s_bLastCopyFromMe = false;
s_dwLastCopyTime = 0;
SetTimer(Globals.hwndMain,ID_PASTEBOARDTIMER,100,PasteBoardTimer);
}
// check if a lexer was specified from the command line
if (s_flagLexerSpecified) {
if (s_lpSchemeArg) {
Style_SetLexerFromName(Globals.hwndEdit,Globals.CurrentFile,s_lpSchemeArg);
LocalFree(s_lpSchemeArg); // StrDup()
}
else if ((s_iInitialLexer >= 0) && (s_iInitialLexer < NUMLEXERS)) {
Style_SetLexerFromID(Globals.hwndEdit, s_iInitialLexer);
}
s_flagLexerSpecified = false;
}
// If start as tray icon, set current filename as tooltip
if (s_flagStartAsTrayIcon) {
SetNotifyIconTitle(Globals.hwndMain);
}
Globals.iReplacedOccurrences = 0;
Globals.iMarkOccurrencesCount = 0;
UpdateToolbar();
UpdateStatusbar(true);
UpdateMarginWidth();
UpdateMouseDWellTime();
// print file immediately and quit
if (Globals.CmdLnFlag_PrintFileAndLeave)
{
WCHAR *pszTitle;
WCHAR tchUntitled[32] = { L'\0' };
WCHAR tchPageFmt[32] = { L'\0' };
WCHAR szDisplayName[MAX_PATH];
if (StrIsNotEmpty(Globals.CurrentFile)) {
PathGetDisplayName(szDisplayName, COUNTOF(szDisplayName), Globals.CurrentFile);
pszTitle = szDisplayName;
}
else {
GetLngString(IDS_MUI_UNTITLED, tchUntitled, COUNTOF(tchUntitled));
pszTitle = tchUntitled;
}
GetLngString(IDS_MUI_PRINT_PAGENUM, tchPageFmt, COUNTOF(tchPageFmt));
if (!EditPrint(Globals.hwndEdit, pszTitle, tchPageFmt)) {
InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_PRINT_ERROR, pszTitle);
}
}
if (s_flagAppIsClosing || Globals.CmdLnFlag_PrintFileAndLeave) {
CloseApplication();
}
return(Globals.hwndMain);
}
//=============================================================================
//
// MainWndProc()
//
// Messages are distributed to the MsgXXX-handlers
//
//
//inline bool KeyboardIsKeyDown(int key) { return (GetKeyState(key) & 0x8000) != 0; }
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
{
switch(umsg)
{
case WM_CREATE:
return MsgCreate(hwnd, wParam, lParam);
case WM_SETFOCUS:
SetFocus(Globals.hwndEdit);
break;
case WM_CLOSE:
s_flagAppIsClosing = true;
if (FileSave(false, true, false, false, Flags.bPreserveFileModTime)) {
DestroyWindow(Globals.hwndMain);
}
break;
case WM_QUERYENDSESSION:
if (FileSave(false, true, false, false, Flags.bPreserveFileModTime)) {
return TRUE;
}
break;
case WM_DESTROY:
case WM_ENDSESSION:
return MsgEndSession(hwnd, umsg, wParam, lParam);
// Reinitialize theme-dependent values and resize windows
case WM_THEMECHANGED:
return MsgThemeChanged(hwnd, wParam, lParam);
case WM_DPICHANGED:
return MsgDPIChanged(hwnd, wParam, lParam);
// update Scintilla colors
case WM_SYSCOLORCHANGE:
if (Flags.bLargeFileLoaded) {
EditUpdateVisibleIndicators();
}
else {
EditUpdateIndicators(0, -1, false);
}
MarkAllOccurrences(0, true);
UpdateToolbar();
UpdateStatusbar(true);
UpdateMarginWidth();
return DefWindowProc(hwnd,umsg,wParam,lParam);
case WM_SIZE:
return MsgSize(hwnd, wParam, lParam);
#ifdef D_NP3_WIN10_DARK_MODE
case WM_SETTINGCHANGE: {
if (IsColorSchemeChangeMessage(lParam)) {
RefreshTitleBarThemeColor(hwnd);
SendMessage(Globals.hwndEdit, WM_THEMECHANGED, 0, 0);
}
}
break;
#endif
case WM_DRAWITEM:
return MsgDrawItem(hwnd, wParam, lParam);
case WM_DROPFILES:
// see SCN_URIDROPP
return MsgDropFiles(hwnd, wParam, lParam);
case WM_COPYDATA:
return MsgCopyData(hwnd, wParam, lParam);
case WM_CONTEXTMENU:
MsgContextMenu(hwnd, umsg, wParam, lParam);
break;
case WM_ENTERMENULOOP:
return MsgEnterMenuLoop(hwnd, wParam);
case WM_INITMENU:
return MsgInitMenu(hwnd, wParam, lParam);
case WM_EXITMENULOOP:
return MsgExitMenuLoop(hwnd, wParam);
case WM_NOTIFY:
return MsgNotify(hwnd, wParam, lParam);
case WM_CHANGENOTIFY:
return MsgChangeNotify(hwnd, wParam, lParam);
//case WM_PARENTNOTIFY:
// if (iLoWParam & WM_DESTROY) {
// if (IsWindow(hDlgFindReplace) && (hDlgFindReplace == (HWND)lParam)) {
// hDlgFindReplace = NULL;
// }
// }
// break;
case WM_COMMAND:
return MsgCommand(hwnd, umsg, wParam, lParam);
case WM_TRAYMESSAGE:
return MsgTrayMessage(hwnd, wParam, lParam);
//// This message is posted before Notepad3 reactivates itself
//case WM_CHANGENOTIFYCLEAR:
// bPendingChangeNotify = false;
// break;
case WM_DRAWCLIPBOARD:
if (!s_bLastCopyFromMe)
s_dwLastCopyTime = GetTickCount();
else
s_bLastCopyFromMe = false;
if (s_hwndNextCBChain)
SendMessage(s_hwndNextCBChain,WM_DRAWCLIPBOARD,wParam,lParam);
break;
case WM_CHANGECBCHAIN:
if ((HWND)wParam == s_hwndNextCBChain)
s_hwndNextCBChain = (HWND)lParam;
if (s_hwndNextCBChain)
SendMessage(s_hwndNextCBChain,WM_CHANGECBCHAIN,lParam,wParam);
break;
case WM_SYSCOMMAND:
return MsgSysCommand(hwnd, umsg, wParam, lParam);
case WM_MBUTTONDOWN:
{
DocPos const pos = SciCall_CharPositionFromPointClose(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
if (pos >= 0) {
HandleHotSpotURLClicked(pos, OPEN_WITH_BROWSER);
}
}
break;
//case WM_LBUTTONDBLCLK:
// //return DefWindowProc(hwnd, umsg, wParam, lParam);
// break;
case WM_MOUSEWHEEL:
if (wParam & MK_CONTROL) {
ShowZoomCallTip();
}
else if (wParam & MK_RBUTTON) {
// Hold RIGHT MOUSE BUTTON and SCROLL to cycle through UNDO history
if (GET_WHEEL_DELTA_WPARAM(wParam) > 0) {
s_bUndoRedoScroll = true;
SciCall_Redo();
}
else if (GET_WHEEL_DELTA_WPARAM(wParam) < 0) {
s_bUndoRedoScroll = true;
SciCall_Undo();
}
}
break;
case WM_INPUTLANGCHANGE:
Globals.bIsCJKInputCodePage = IsDBCSCodePage(Scintilla_InputCodePage());
break;
default:
if (umsg == s_msgTaskbarCreated) {
if (!IsWindowVisible(hwnd)) { ShowNotifyIcon(hwnd, true); }
SetNotifyIconTitle(hwnd);
}
return DefWindowProc(hwnd, umsg, wParam, lParam);
}
return FALSE;
}
//=============================================================================
//
// _SetWrapStartIndent()
//
static void _SetWrapStartIndent()
{
int i = 0;
switch (Settings.WordWrapIndent) {
case 1: i = 1; break;
case 2: i = 2; break;
case 3: i = (Globals.fvCurFile.iIndentWidth) ? 1 * Globals.fvCurFile.iIndentWidth : 1 * Globals.fvCurFile.iTabWidth; break;
case 4: i = (Globals.fvCurFile.iIndentWidth) ? 2 * Globals.fvCurFile.iIndentWidth : 2 * Globals.fvCurFile.iTabWidth; break;
default: break;
}
SciCall_SetWrapStartIndent(i);
}
//=============================================================================
//
// _SetWrapIndentMode()
//
static void _SetWrapIndentMode()
{
int const wrap_mode = (!Globals.fvCurFile.bWordWrap ? SC_WRAP_NONE : ((Settings.WordWrapMode == 0) ? SC_WRAP_WHITESPACE : SC_WRAP_CHAR));
SciCall_SetWrapMode(wrap_mode);
if (Settings.WordWrapIndent == 5) {
SciCall_SetWrapIndentMode(SC_WRAPINDENT_SAME);
}
else if (Settings.WordWrapIndent == 6) {
SciCall_SetWrapIndentMode(SC_WRAPINDENT_INDENT);
}
else if (Settings.WordWrapIndent == 7) {
SciCall_SetWrapIndentMode(SC_WRAPINDENT_DEEPINDENT);
}
else {
_SetWrapStartIndent();
SciCall_SetWrapIndentMode(SC_WRAPINDENT_FIXED);
}
}
//=============================================================================
//
// _SetWrapVisualFlags()
//
static void _SetWrapVisualFlags(HWND hwndEditCtrl)
{
if (Settings.ShowWordWrapSymbols) {
int wrapVisualFlags = 0;
int wrapVisualFlagsLocation = 0;
if (Settings.WordWrapSymbols == 0) {
Settings.WordWrapSymbols = 22;
}
switch (Settings.WordWrapSymbols % 10) {
case 1:
wrapVisualFlags |= SC_WRAPVISUALFLAG_END;
wrapVisualFlagsLocation |= SC_WRAPVISUALFLAGLOC_END_BY_TEXT;
break;
case 2:
wrapVisualFlags |= SC_WRAPVISUALFLAG_END;
break;
}
switch (((Settings.WordWrapSymbols % 100) - (Settings.WordWrapSymbols % 10)) / 10) {
case 1:
wrapVisualFlags |= SC_WRAPVISUALFLAG_START;
wrapVisualFlagsLocation |= SC_WRAPVISUALFLAGLOC_START_BY_TEXT;
break;
case 2:
wrapVisualFlags |= SC_WRAPVISUALFLAG_START;
break;
}
SendMessage(hwndEditCtrl, SCI_SETWRAPVISUALFLAGSLOCATION, wrapVisualFlagsLocation, 0);
SendMessage(hwndEditCtrl, SCI_SETWRAPVISUALFLAGS, wrapVisualFlags, 0);
}
else {
SendMessage(hwndEditCtrl, SCI_SETWRAPVISUALFLAGS, 0, 0);
}
}
//=============================================================================
//
// InitializeSciEditCtrl()
//
static void _InitializeSciEditCtrl(HWND hwndEditCtrl)
{
InitWindowCommon(hwndEditCtrl, true);
SendMessage(hwndEditCtrl, SCI_SETTECHNOLOGY, (WPARAM)Settings.RenderingTechnology, 0);
Settings.RenderingTechnology = SciCall_GetTechnology();
SendMessage(hwndEditCtrl, SCI_SETBIDIRECTIONAL, (WPARAM)Settings.Bidirectional, 0); // experimental
Settings.Bidirectional = SciCall_GetBidirectional();
// Current platforms perform window buffering so it is almost always better for this option to be turned off.
// There are some older platforms and unusual modes where buffering may still be useful
SendMessage(hwndEditCtrl, SCI_SETBUFFEREDDRAW, (WPARAM)(Settings.RenderingTechnology == SC_TECHNOLOGY_DEFAULT), 0);
//~SendMessage(hwndEditCtrl, SCI_SETPHASESDRAW, SC_PHASES_TWO, 0); // (= default)
SendMessage(hwndEditCtrl, SCI_SETPHASESDRAW, SC_PHASES_MULTIPLE, 0);
//~SendMessage(hwndEditCtrl, SCI_SETLAYOUTCACHE, SC_CACHE_DOCUMENT, 0); // memory consumption !
SendMessage(hwndEditCtrl, SCI_SETLAYOUTCACHE, SC_CACHE_PAGE, 0);
//~SendMessage(hwndEditCtrl, SCI_SETPOSITIONCACHE, 1024, 0); // default = 1024
SendMessage(hwndEditCtrl, SCI_SETPOSITIONCACHE, 2048, 0); // default = 1024
// The possible notification types are the same as the modificationType bit flags used by SCN_MODIFIED:
// SC_MOD_INSERTTEXT, SC_MOD_DELETETEXT, SC_MOD_CHANGESTYLE, SC_MOD_CHANGEFOLD, SC_PERFORMED_USER,
// SC_PERFORMED_UNDO, SC_PERFORMED_REDO, SC_MULTISTEPUNDOREDO, SC_LASTSTEPINUNDOREDO, SC_MOD_CHANGEMARKER,
// SC_MOD_BEFOREINSERT, SC_MOD_BEFOREDELETE, SC_MULTILINEUNDOREDO, and SC_MODEVENTMASKALL.
//
///~ int const evtMask = SC_MODEVENTMASKALL; (!) - don't listen to all events (SC_MOD_CHANGESTYLE) => RECURSON!
///~ SendMessage(hwndEditCtrl, SCI_SETMODEVENTMASK, (WPARAM)evtMask, 0);
///~ Don't use: SC_PERFORMED_USER | SC_MOD_CHANGESTYLE;
/// SC_MOD_CHANGESTYLE and SC_MOD_CHANGEINDICATOR needs SCI_SETCOMMANDEVENTS=true
int const evtMask1 = SC_MOD_CONTAINER | SC_PERFORMED_UNDO | SC_PERFORMED_REDO | SC_MULTILINEUNDOREDO;
int const evtMask2 = SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT | SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE;
SendMessage(hwndEditCtrl, SCI_SETMODEVENTMASK, (WPARAM)(evtMask1 | evtMask2), 0);
SendMessage(hwndEditCtrl, SCI_SETCOMMANDEVENTS, false, 0); // speedup folding
SendMessage(hwndEditCtrl, SCI_SETCODEPAGE, (WPARAM)SC_CP_UTF8, 0); // fixed internal UTF-8 (Sci:default)
SendMessage(hwndEditCtrl, SCI_SETEOLMODE, Settings.DefaultEOLMode, 0);
SendMessage(hwndEditCtrl, SCI_SETPASTECONVERTENDINGS, true, 0);
SendMessage(hwndEditCtrl, SCI_USEPOPUP, false, 0);
SendMessage(hwndEditCtrl, SCI_SETSCROLLWIDTH, 1, 0);
SendMessage(hwndEditCtrl, SCI_SETSCROLLWIDTHTRACKING, true, 0);
SendMessage(hwndEditCtrl, SCI_SETENDATLASTLINE, true, 0);
SendMessage(hwndEditCtrl, SCI_SETMULTIPLESELECTION, true, 0);
SendMessage(hwndEditCtrl, SCI_SETADDITIONALSELECTIONTYPING, true, 0);
SendMessage(hwndEditCtrl, SCI_SETMULTIPASTE, SC_MULTIPASTE_EACH, 0); // paste into rectangular selection
SendMessage(hwndEditCtrl, SCI_AUTOCSETMULTI, SC_MULTIAUTOC_EACH, 0);
SendMessage(hwndEditCtrl, SCI_SETMOUSESELECTIONRECTANGULARSWITCH, true, 0);
SendMessage(hwndEditCtrl, SCI_SETVIRTUALSPACEOPTIONS, NP3_VIRTUAL_SPACE_ACCESS_OPTIONS, 0);
SendMessage(hwndEditCtrl, SCI_SETADDITIONALCARETSBLINK, true, 0);
SendMessage(hwndEditCtrl, SCI_SETADDITIONALCARETSVISIBLE, true, 0);
// Idle Styling (very large text)
//~~~SendMessage(hwndEditCtrl, SCI_SETIDLESTYLING, SC_IDLESTYLING_AFTERVISIBLE, 0);
//~~~SendMessage(hwndEditCtrl, SCI_SETIDLESTYLING, SC_IDLESTYLING_ALL, 0);
SendMessage(hwndEditCtrl, SCI_SETIDLESTYLING, SC_IDLESTYLING_NONE, 0); // needed for focused view
// assign command keys
SendMessage(hwndEditCtrl, SCI_ASSIGNCMDKEY, (SCK_NEXT + (SCMOD_CTRL << 16)), SCI_PARADOWN);
SendMessage(hwndEditCtrl, SCI_ASSIGNCMDKEY, (SCK_PRIOR + (SCMOD_CTRL << 16)), SCI_PARAUP);
SendMessage(hwndEditCtrl, SCI_ASSIGNCMDKEY, (SCK_NEXT + ((SCMOD_CTRL | SCMOD_SHIFT) << 16)), SCI_PARADOWNEXTEND);
SendMessage(hwndEditCtrl, SCI_ASSIGNCMDKEY, (SCK_PRIOR + ((SCMOD_CTRL | SCMOD_SHIFT) << 16)), SCI_PARAUPEXTEND);
SendMessage(hwndEditCtrl, SCI_ASSIGNCMDKEY, (SCK_HOME + (0 << 16)), SCI_VCHOMEWRAP);
SendMessage(hwndEditCtrl, SCI_ASSIGNCMDKEY, (SCK_END + (0 << 16)), SCI_LINEENDWRAP);
SendMessage(hwndEditCtrl, SCI_ASSIGNCMDKEY, (SCK_HOME + (SCMOD_SHIFT << 16)), SCI_VCHOMEWRAPEXTEND);
SendMessage(hwndEditCtrl, SCI_ASSIGNCMDKEY, (SCK_END + (SCMOD_SHIFT << 16)), SCI_LINEENDWRAPEXTEND);
// set indicator styles (foreground and alpha maybe overridden by style settings)
SendMessage(hwndEditCtrl, SCI_INDICSETSTYLE, INDIC_NP3_MATCH_BRACE, INDIC_FULLBOX);
SendMessage(hwndEditCtrl, SCI_INDICSETFORE, INDIC_NP3_MATCH_BRACE, RGB(0x00, 0xFF, 0x00));
SendMessage(hwndEditCtrl, SCI_INDICSETALPHA, INDIC_NP3_MATCH_BRACE, 120);
SendMessage(hwndEditCtrl, SCI_INDICSETOUTLINEALPHA, INDIC_NP3_MATCH_BRACE, 120);
SendMessage(hwndEditCtrl, SCI_INDICSETSTYLE, INDIC_NP3_BAD_BRACE, INDIC_FULLBOX);
SendMessage(hwndEditCtrl, SCI_INDICSETFORE, INDIC_NP3_BAD_BRACE, RGB(0xFF, 0x00, 0x00));
SendMessage(hwndEditCtrl, SCI_INDICSETALPHA, INDIC_NP3_BAD_BRACE, 120);
SendMessage(hwndEditCtrl, SCI_INDICSETOUTLINEALPHA, INDIC_NP3_BAD_BRACE, 120);
if (!Settings2.UseOldStyleBraceMatching) {
SendMessage(hwndEditCtrl, SCI_BRACEHIGHLIGHTINDICATOR, true, INDIC_NP3_MATCH_BRACE);
SendMessage(hwndEditCtrl, SCI_BRACEBADLIGHTINDICATOR, true, INDIC_NP3_BAD_BRACE);
}
SendMessage(hwndEditCtrl, SCI_INDICSETSTYLE, INDIC_NP3_MARK_OCCURANCE, INDIC_ROUNDBOX);
SendMessage(hwndEditCtrl, SCI_INDICSETFORE, INDIC_NP3_MARK_OCCURANCE, RGB(0x00, 0x00, 0xFF));
SendMessage(hwndEditCtrl, SCI_INDICSETALPHA, INDIC_NP3_MARK_OCCURANCE, 100);
SendMessage(hwndEditCtrl, SCI_INDICSETOUTLINEALPHA, INDIC_NP3_MARK_OCCURANCE, 100);
SendMessage(hwndEditCtrl, SCI_INDICSETSTYLE, INDIC_NP3_HYPERLINK, INDIC_TEXTFORE);
SendMessage(hwndEditCtrl, SCI_INDICSETFORE, INDIC_NP3_HYPERLINK, RGB(0x00, 0x00, 0xA0));
SendMessage(hwndEditCtrl, SCI_INDICSETSTYLE, INDIC_NP3_HYPERLINK_U, INDIC_COMPOSITIONTHIN);
SendMessage(hwndEditCtrl, SCI_INDICSETFORE, INDIC_NP3_HYPERLINK_U, RGB(0x00, 0x00, 0xA0));
SendMessage(hwndEditCtrl, SCI_INDICSETHOVERSTYLE, INDIC_NP3_HYPERLINK, INDIC_TEXTFORE);
SendMessage(hwndEditCtrl, SCI_INDICSETHOVERFORE, INDIC_NP3_HYPERLINK, RGB(0x00, 0x00, 0xFF));
SendMessage(hwndEditCtrl, SCI_INDICSETHOVERSTYLE, INDIC_NP3_HYPERLINK_U, INDIC_COMPOSITIONTHICK);
SendMessage(hwndEditCtrl, SCI_INDICSETHOVERFORE, INDIC_NP3_HYPERLINK_U, RGB(0x00, 0x00, 0xFF));
SendMessage(hwndEditCtrl, SCI_INDICSETSTYLE, INDIC_NP3_COLOR_DEF, INDIC_COMPOSITIONTHIN /*INDIC_HIDDEN*/); // MARKER only
SendMessage(hwndEditCtrl, SCI_INDICSETUNDER, INDIC_NP3_COLOR_DEF, true);
SendMessage(hwndEditCtrl, SCI_INDICSETALPHA, INDIC_NP3_COLOR_DEF, SC_ALPHA_TRANSPARENT); // reset on hover
SendMessage(hwndEditCtrl, SCI_INDICSETOUTLINEALPHA, INDIC_NP3_COLOR_DEF, SC_ALPHA_OPAQUE);
SendMessage(hwndEditCtrl, SCI_INDICSETHOVERSTYLE, INDIC_NP3_COLOR_DEF, INDIC_ROUNDBOX); // HOVER
SendMessage(hwndEditCtrl, SCI_INDICSETHOVERFORE, INDIC_NP3_COLOR_DEF, RGB(0x00, 0x00, 0x00)); // recalc on hover
SendMessage(hwndEditCtrl, SCI_INDICSETSTYLE, INDIC_NP3_COLOR_DEF_T, INDIC_HIDDEN ); // invisible
SendMessage(hwndEditCtrl, SCI_INDICSETHOVERSTYLE, INDIC_NP3_COLOR_DEF_T, INDIC_TEXTFORE); // HOVER
SendMessage(hwndEditCtrl, SCI_INDICSETHOVERFORE, INDIC_NP3_COLOR_DEF_T, RGB(0x00, 0x00, 0x00)); // recalc on hover
SendMessage(hwndEditCtrl, SCI_INDICSETSTYLE, INDIC_NP3_UNICODE_POINT, INDIC_COMPOSITIONTHIN /*INDIC_HIDDEN*/); // MARKER only
//SendMessage(hwndEditCtrl, SCI_INDICSETUNDER, INDIC_NP3_UNICODE_POINT, false);
SendMessage(hwndEditCtrl, SCI_INDICSETALPHA, INDIC_NP3_UNICODE_POINT, SC_ALPHA_TRANSPARENT);
SendMessage(hwndEditCtrl, SCI_INDICSETOUTLINEALPHA, INDIC_NP3_UNICODE_POINT, SC_ALPHA_NOALPHA);
SendMessage(hwndEditCtrl, SCI_INDICSETHOVERSTYLE, INDIC_NP3_UNICODE_POINT, INDIC_ROUNDBOX); // HOVER
//SendMessage(hwndEditCtrl, SCI_INDICSETHOVERFORE, INDIC_NP3_UNICODE_POINT, RGB(0xE0, 0xE0, 0xE0));
SendMessage(hwndEditCtrl, SCI_INDICSETSTYLE, INDIC_NP3_MULTI_EDIT, INDIC_ROUNDBOX);
SendMessage(hwndEditCtrl, SCI_INDICSETFORE, INDIC_NP3_MULTI_EDIT, RGB(0xFF, 0xA5, 0x00));
SendMessage(hwndEditCtrl, SCI_INDICSETALPHA, INDIC_NP3_MULTI_EDIT, 60);
SendMessage(hwndEditCtrl, SCI_INDICSETOUTLINEALPHA, INDIC_NP3_MULTI_EDIT, 180);
// No SC_AUTOMATICFOLD_CLICK, performed by
SendMessage(hwndEditCtrl, SCI_SETAUTOMATICFOLD, (WPARAM)(SC_AUTOMATICFOLD_SHOW | SC_AUTOMATICFOLD_CHANGE), 0);
// Properties
SendMessage(hwndEditCtrl, SCI_SETCARETSTICKY, (WPARAM)SC_CARETSTICKY_OFF, 0);
//SendMessage(hwndEditCtrl,SCI_SETCARETSTICKY,SC_CARETSTICKY_WHITESPACE,0);
if (Settings.ShowHypLnkToolTip || IsColorDefHotspotEnabled()) {
SendMessage(hwndEditCtrl, SCI_SETMOUSEDWELLTIME, (WPARAM)100, 0);
}
else {
SendMessage(hwndEditCtrl, SCI_SETMOUSEDWELLTIME, (WPARAM)SC_TIME_FOREVER, 0); // default
}
#define _CARET_SYMETRY CARET_EVEN /// CARET_EVEN or 0
#define _CARET_ENFORCE CARET_STRICT /// CARET_STRICT or 0
if (Settings2.CurrentLineHorizontalSlop > 0)
SendMessage(hwndEditCtrl, SCI_SETXCARETPOLICY, (WPARAM)(CARET_SLOP | _CARET_SYMETRY | _CARET_ENFORCE), Settings2.CurrentLineHorizontalSlop);
else
SendMessage(hwndEditCtrl, SCI_SETXCARETPOLICY, (WPARAM)(CARET_SLOP | _CARET_SYMETRY | _CARET_ENFORCE), (LPARAM)0);
if (Settings2.CurrentLineVerticalSlop > 0) {
SendMessage(hwndEditCtrl, SCI_SETYCARETPOLICY, (WPARAM)(CARET_SLOP | _CARET_SYMETRY | _CARET_ENFORCE), Settings2.CurrentLineVerticalSlop);
}
else {
SendMessage(hwndEditCtrl, SCI_SETYCARETPOLICY, (WPARAM)(_CARET_SYMETRY), 0);
}
SendMessage(hwndEditCtrl, SCI_SETENDATLASTLINE, (WPARAM)((Settings.ScrollPastEOF) ? 0 : 1), 0);
// Tabs
SendMessage(hwndEditCtrl, SCI_SETUSETABS, (WPARAM)!Globals.fvCurFile.bTabsAsSpaces, 0);
SendMessage(hwndEditCtrl, SCI_SETTABINDENTS, (WPARAM)Globals.fvCurFile.bTabIndents, 0);
SendMessage(hwndEditCtrl, SCI_SETBACKSPACEUNINDENTS, (WPARAM)Settings.BackspaceUnindents, 0);
SendMessage(hwndEditCtrl, SCI_SETTABWIDTH, (WPARAM)Globals.fvCurFile.iTabWidth, 0);
SendMessage(hwndEditCtrl, SCI_SETINDENT, (WPARAM)Globals.fvCurFile.iIndentWidth, 0);
// Indent Guides
Style_SetIndentGuides(hwndEditCtrl, Settings.ShowIndentGuides);
// Word Wrap
_SetWrapIndentMode(hwndEditCtrl);
_SetWrapVisualFlags(hwndEditCtrl);
// Long Lines
if (Settings.MarkLongLines) {
SendMessage(hwndEditCtrl, SCI_SETEDGEMODE, (WPARAM)((Settings.LongLineMode == EDGE_BACKGROUND) ? EDGE_BACKGROUND : EDGE_LINE), 0);
}
else {
SendMessage(hwndEditCtrl, SCI_SETEDGEMODE, (WPARAM)EDGE_NONE, 0);
}
SendMessage(hwndEditCtrl, SCI_SETEDGECOLUMN, (WPARAM)Settings.LongLinesLimit, 0);
// general margin
SendMessage(hwndEditCtrl, SCI_SETMARGINOPTIONS, (WPARAM)SC_MARGINOPTION_SUBLINESELECT, 0);
// Nonprinting characters
SendMessage(hwndEditCtrl, SCI_SETVIEWWS, (WPARAM)(Settings.ViewWhiteSpace ? SCWS_VISIBLEALWAYS : SCWS_INVISIBLE), 0);
SendMessage(hwndEditCtrl, SCI_SETVIEWEOL, (WPARAM)Settings.ViewEOLs, 0);
// IME Interaction
SendMessage(hwndEditCtrl, SCI_SETIMEINTERACTION, (WPARAM)Settings2.IMEInteraction, 0);
// word delimiter handling
EditInitWordDelimiter(hwndEditCtrl);
EditSetAccelWordNav(hwndEditCtrl, Settings.AccelWordNavigation);
UpdateMarginWidth();
}
//=============================================================================
//
// _EvalTinyExpr() - called on '?' or ENTER insert
//
static bool _EvalTinyExpr(bool qmark)
{
if (!Settings.EvalTinyExprOnSelection) { return false; }
DocPos const posCur = SciCall_GetCurrentPos();
DocPos const posBegin = qmark ? SciCall_PositionBefore(posCur) : posCur;
DocPos posBefore = SciCall_PositionBefore(posBegin);
char chBefore = SciCall_GetCharAt(posBefore);
while (IsBlankChar(chBefore) && (posBefore > 0)) {
posBefore = SciCall_PositionBefore(posBefore);
chBefore = SciCall_GetCharAt(posBefore);
}
if (chBefore == '=') // got "=?" or ENTER : evaluate expression trigger
{
int const lineLen = (int)SciCall_LineLength(SciCall_LineFromPosition(posCur)) + 1;
char *lineBuf = (char *)AllocMem(lineLen, HEAP_ZERO_MEMORY);
WCHAR *lineBufW = (WCHAR *)AllocMem(lineLen * sizeof(WCHAR), HEAP_ZERO_MEMORY);
if (lineBuf && lineBufW)
{
DocPos const iLnCaretPos = SciCall_GetCurLine((lineLen - 1), lineBuf);
lineBuf[iLnCaretPos - (posCur - posBefore)] = '\0'; // exclude "=?"
char const defchar = (char)0x24;
MultiByteToWideChar(Encoding_SciCP, 0, lineBuf, -1, lineBufW, lineLen);
WideCharToMultiByte(1252, (WC_COMPOSITECHECK | WC_DISCARDNS), lineBufW, -1, lineBuf, lineLen, &defchar, NULL);
StrDelChrA(lineBuf, chr_currency);
FreeMem(lineBufW);
const char *pBegin = lineBuf;
while (IsBlankChar(*pBegin)) { ++pBegin; }
double dExprEval = 0.0;
te_xint_t exprErr = 1;
while (*pBegin && exprErr) {
dExprEval = te_interp(pBegin++, &exprErr);
}
FreeMem(lineBuf);
if (!exprErr) {
char chExpr[64] = { '\0' };
StringCchPrintfA(chExpr, COUNTOF(chExpr), "%.6G", dExprEval);
SciCall_SetSel(posBegin, posCur);
SciCall_ReplaceSel(chExpr);
return true;
}
}
}
return false;
}
//=============================================================================
//
// _HandleEditWndFrame()
//
static void _HandleEditWndFrame()
{
s_bIsAppThemed = IsAppThemed();
if (s_bIsAppThemed) {
SetWindowLongPtr(Globals.hwndEdit, GWL_EXSTYLE, GetWindowLongPtr(Globals.hwndEdit, GWL_EXSTYLE) & ~WS_EX_CLIENTEDGE);
SetWindowPos(Globals.hwndEdit, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
if (IsWindowsVistaOrGreater()) {
s_cxEditFrame = 0;
s_cyEditFrame = 0;
} else {
SetWindowPos(s_hwndEditFrame, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
RECT rc, rc2;
GetClientRect(s_hwndEditFrame, &rc);
GetWindowRect(s_hwndEditFrame, &rc2);
s_cxEditFrame = ((rc2.right - rc2.left) - (rc.right - rc.left)) / 2;
s_cyEditFrame = ((rc2.bottom - rc2.top) - (rc.bottom - rc.top)) / 2;
}
} else {
SetWindowLongPtr(Globals.hwndEdit, GWL_EXSTYLE, WS_EX_CLIENTEDGE | GetWindowLongPtr(Globals.hwndEdit, GWL_EXSTYLE));
SetWindowPos(Globals.hwndEdit, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
s_cxEditFrame = 0;
s_cyEditFrame = 0;
}
}
//=============================================================================
//
// MsgCreate() - Handles WM_CREATE
//
//
LRESULT MsgCreate(HWND hwnd, WPARAM wParam,LPARAM lParam)
{
UNUSED(wParam);
#ifdef D_NP3_WIN10_DARK_MODE
if (IsDarkModeSupported()) {
AllowDarkModeForWindow(hwnd, CheckDarkModeEnabled());
RefreshTitleBarThemeColor(hwnd);
}
#endif
HINSTANCE const hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
// Setup edit control
Globals.hwndEdit = CreateWindowEx(
WS_EX_CLIENTEDGE,
L"Scintilla",
NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
0, 0, 0, 0,
hwnd,
(HMENU)IDC_EDIT,
hInstance,
NULL);
Globals.hndlScintilla = (HANDLE)SendMessage(Globals.hwndEdit, SCI_GETDIRECTPOINTER, 0, 0);
_InitializeSciEditCtrl(Globals.hwndEdit);
s_hwndEditFrame = CreateWindowEx(
WS_EX_CLIENTEDGE,
WC_LISTVIEW,
NULL,
WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,
0,0,100,100,
hwnd,
(HMENU)IDC_EDITFRAME,
hInstance,
NULL);
_HandleEditWndFrame();
// Create Toolbar and Statusbar
CreateBars(hwnd, hInstance);
// Window Initialization
(void)CreateWindow(
WC_STATIC,
NULL,
WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,
0,0,10,10,
hwnd,
(HMENU)IDC_FILENAME,
hInstance,
NULL);
SetDlgItemText(hwnd,IDC_FILENAME,Globals.CurrentFile);
(void)CreateWindow(
WC_STATIC,
NULL,
WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,
10,10,10,10,
hwnd,
(HMENU)IDC_REUSELOCK,
hInstance,
NULL);
SetDlgItemInt(hwnd,IDC_REUSELOCK,GetTickCount(),false);
// Menu
//SetMenuDefaultItem(GetSubMenu(GetMenu(hwnd),0),0);
// Drag & Drop
DragAcceptFiles(hwnd,true);
if (Globals.hwndEdit == NULL || s_hwndEditFrame == NULL ||
Globals.hwndStatus == NULL || Globals.hwndToolbar == NULL || Globals.hwndRebar == NULL) {
return -1LL;
}
Style_SetDefaultLexer(Globals.hwndEdit);
Encoding_Current(Settings.DefaultEncoding);
ObserveNotifyChangeEvent();
if (g_IniWinInfo.zoom) {
SciCall_SetZoom(g_IniWinInfo.zoom);
}
return 0LL;
}
//=============================================================================
//
// SelectExternalToolBar() - Select and Load an external Bitmal as ToolBarImage
//
bool SelectExternalToolBar(HWND hwnd)
{
UNUSED(hwnd);
WCHAR szArgs[MAX_PATH] = { L'\0' };
WCHAR szArg2[MAX_PATH] = { L'\0' };
WCHAR szFile[MAX_PATH] = { L'\0' };
WCHAR szFilter[MAX_PATH] = { L'\0' };
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(OPENFILENAME));
GetDlgItemText(hwnd, IDC_COMMANDLINE, szArgs, COUNTOF(szArgs));
ExpandEnvironmentStringsEx(szArgs, COUNTOF(szArgs));
ExtractFirstArgument(szArgs, szFile, szArg2, MAX_PATH);
GetLngString(IDS_MUI_FILTER_BITMAP, szFilter, COUNTOF(szFilter));
PrepareFilterStr(szFilter);
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = szFilter;
ofn.lpstrFile = szFile;
ofn.nMaxFile = COUNTOF(szFile);
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_DONTADDTORECENT
| OFN_PATHMUSTEXIST | OFN_SHAREAWARE | OFN_NODEREFERENCELINKS;
if (GetOpenFileName(&ofn)) {
PathQuoteSpaces(szFile);
if (StrIsNotEmpty(szArg2))
{
StringCchCat(szFile, COUNTOF(szFile), L" ");
StringCchCat(szFile, COUNTOF(szFile), szArg2);
}
PathRelativeToApp(szFile, g_tchToolbarBitmap, COUNTOF(g_tchToolbarBitmap), true,true, true);
if (Globals.bCanSaveIniFile) {
IniFileSetString(Globals.IniFile, L"Toolbar Images", L"BitmapDefault", g_tchToolbarBitmap);
}
}
if (StrIsNotEmpty(g_tchToolbarBitmap))
{
StringCchCopy(szFile, COUNTOF(szFile), g_tchToolbarBitmap);
PathRemoveExtension(szFile);
StringCchCat(szFile, COUNTOF(szFile), L"Hot.bmp");
if (Globals.bCanSaveIniFile) {
if (PathIsExistingFile(szFile)) {
PathRelativeToApp(szFile, g_tchToolbarBitmapHot, COUNTOF(g_tchToolbarBitmapHot), true, true, true);
IniFileSetString(Globals.IniFile, L"Toolbar Images", L"BitmapHot", g_tchToolbarBitmapHot);
}
else {
StringCchCopy(g_tchToolbarBitmapHot, COUNTOF(g_tchToolbarBitmapHot), L"");
IniFileDelete(Globals.IniFile, L"Toolbar Images", L"BitmapHot", false);
}
}
StringCchCopy(szFile, COUNTOF(szFile), g_tchToolbarBitmap);
PathRemoveExtension(szFile);
StringCchCat(szFile, COUNTOF(szFile), L"Disabled.bmp");
if (Globals.bCanSaveIniFile) {
if (PathIsExistingFile(szFile)) {
PathRelativeToApp(szFile, g_tchToolbarBitmapDisabled, COUNTOF(g_tchToolbarBitmapDisabled), true, true, true);
IniFileSetString(Globals.IniFile, L"Toolbar Images", L"BitmapDisabled", g_tchToolbarBitmapDisabled);
}
else {
StringCchCopy(g_tchToolbarBitmapHot, COUNTOF(g_tchToolbarBitmapHot), L"");
IniFileDelete(Globals.IniFile, L"Toolbar Images", L"BitmapDisabled", false);
}
}
Settings.ToolBarTheme = 2;
return true;
}
else {
IniFileDelete(Globals.IniFile, L"Toolbar Images", L"BitmapHot", false);
IniFileDelete(Globals.IniFile, L"Toolbar Images", L"BitmapDisabled", false);
}
return false;
}
//=============================================================================
//
// LoadBitmapFile()
//
static HBITMAP LoadBitmapFile(LPCWSTR path)
{
WCHAR szTmp[MAX_PATH];
if (PathIsRelative(path)) {
PathGetAppDirectory(szTmp, COUNTOF(szTmp));
PathAppend(szTmp, path);
path = szTmp;
}
if (!PathIsExistingFile(path)) { return NULL; }
HBITMAP hbmp = (HBITMAP)LoadImage(NULL, path, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
bool bDimOK = false;
int height = 16;
if (hbmp) {
BITMAP bmp; GetObject(hbmp, sizeof(BITMAP), &bmp);
height = bmp.bmHeight;
bDimOK = (bmp.bmWidth >= (height * NUMTOOLBITMAPS));
}
if (!bDimOK) {
InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_ERR_BITMAP, path, (height * NUMTOOLBITMAPS), height, NUMTOOLBITMAPS);
if (hbmp) { DeleteObject(hbmp); }
hbmp = NULL;
}
return hbmp;
}
//=============================================================================
//
// CreateScaledImageListFromBitmap()
//
static HIMAGELIST CreateScaledImageListFromBitmap(HWND hWnd, HBITMAP hBmp)
{
BITMAP bmp;
GetObject(hBmp, sizeof(BITMAP), &bmp);
int const mod = bmp.bmWidth % NUMTOOLBITMAPS;
int const cx = (bmp.bmWidth - mod) / NUMTOOLBITMAPS;
int const cy = bmp.bmHeight;
HIMAGELIST himl = ImageList_Create(cx, cy, ILC_COLOR32 | ILC_MASK, NUMTOOLBITMAPS, NUMTOOLBITMAPS);
ImageList_AddMasked(himl, hBmp, CLR_DEFAULT);
DPI_T dpi = Scintilla_GetWindowDPI(hWnd);
if (!Settings.DpiScaleToolBar ||
((dpi.x == USER_DEFAULT_SCREEN_DPI) && (dpi.y == USER_DEFAULT_SCREEN_DPI)))
{
return himl; // default DPI, we are done
}
// Scale button icons/images
int const scx = ScaleIntToDPI_X(hWnd, cx);
int const scy = ScaleIntToDPI_Y(hWnd, cy);
HIMAGELIST hsciml = ImageList_Create(scx, scy, ILC_COLOR32 | ILC_MASK | ILC_HIGHQUALITYSCALE, NUMTOOLBITMAPS, NUMTOOLBITMAPS);
for (int i = 0; i < NUMTOOLBITMAPS; ++i)
{
HICON const hicon = ImageList_GetIcon(himl, i, ILD_TRANSPARENT | ILD_PRESERVEALPHA | ILD_SCALE);
ImageList_AddIcon(hsciml, hicon);
DestroyIcon(hicon);
}
ImageList_Destroy(himl);
return hsciml;
}
//==== Toolbar Style ==========================================================
#define NP3_WS_TOOLBAR (WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | \
TBSTYLE_TOOLTIPS | TBSTYLE_FLAT | TBSTYLE_ALTDRAG | TBSTYLE_LIST | \
CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_ADJUSTABLE)
//==== ReBar Style ============================================================
#define NP3_WS_REBAR (WS_CHILD | WS_CLIPCHILDREN | WS_BORDER | RBS_VARHEIGHT | \
RBS_BANDBORDERS | CCS_NODIVIDER | CCS_NOPARENTALIGN)
//=============================================================================
//
// CreateBars() - Create Toolbar and Statusbar
//
//
void CreateBars(HWND hwnd, HINSTANCE hInstance)
{
DWORD dwToolbarStyle = NP3_WS_TOOLBAR /*| TBSTYLE_CUSTOMERASE */ | TBSTYLE_TRANSPARENT;
DWORD dwToolbarExStyle = TBSTYLE_EX_DOUBLEBUFFER /* | TBSTYLE_EX_HIDECLIPPEDBUTTONS */;
if (Settings.ToolBarTheme < 0) { // undefined: determine High DPI screen
DPI_T const dpi = Scintilla_GetWindowDPI(hwnd);
Settings.ToolBarTheme = (dpi.y < LargeIconDPI()) ? 0 : 1;
}
if (Globals.hwndToolbar)
{
HIMAGELIST himl = (HIMAGELIST)SendMessage(Globals.hwndToolbar, TB_GETIMAGELIST, 0, 0);
if (himl) { ImageList_Destroy(himl); }
himl = (HIMAGELIST)SendMessage(Globals.hwndToolbar, TB_GETHOTIMAGELIST, 0, 0);
if (himl) { ImageList_Destroy(himl); }
himl = (HIMAGELIST)SendMessage(Globals.hwndToolbar, TB_GETDISABLEDIMAGELIST, 0, 0);
if (himl) { ImageList_Destroy(himl); }
DestroyWindow(Globals.hwndToolbar);
}
bool bOpendByMe = false;
OpenSettingsFile(&bOpendByMe);
bool bDirtyFlag = false;
//InitToolbarWndClass(hInstance);
Globals.hwndToolbar = CreateWindowEx(dwToolbarExStyle, TOOLBARCLASSNAME, NULL, dwToolbarStyle,
0,0,0,0,hwnd,(HMENU)IDC_TOOLBAR,hInstance,NULL);
//Globals.hwndToolbar = CreateWindowEx(
// dwToolbarExStyle, // no extended styles
// s_ToolbarWndClassName, // name of status bar class
// (PCTSTR)NULL, // no text when first created
// dwToolbarStyle, // creates a visible child window
// 0, 0, 0, 0, // ignores size and position
// hwnd, // handle to parent window
// (HMENU)IDC_TOOLBAR, // child window identifier
// hInstance, // handle to application instance
// NULL); // no window creation data
InitWindowCommon(Globals.hwndToolbar, true); // (!) themed = true : glow effects
#ifdef D_NP3_WIN10_DARK_MODE
if (IsDarkModeSupported()) {
AllowDarkModeForWindow(Globals.hwndToolbar, CheckDarkModeEnabled());
}
#endif
SendMessage(Globals.hwndToolbar,TB_BUTTONSTRUCTSIZE,(WPARAM)sizeof(TBBUTTON),0);
// -------------------------
// Add Toolbar Bitmap
// -------------------------
HBITMAP hbmp = NULL;
HBITMAP hbmpCopy = NULL;
if ((Settings.ToolBarTheme == 2) && StrIsNotEmpty(g_tchToolbarBitmap))
{
hbmp = LoadBitmapFile(g_tchToolbarBitmap);
if (!hbmp) {
StringCchCopy(g_tchToolbarBitmap, COUNTOF(g_tchToolbarBitmap), L"");
IniSectionDelete(L"Toolbar Images", L"BitmapDefault", false);
bDirtyFlag = true;
}
}
if (!hbmp) {
Settings.ToolBarTheme = Settings.ToolBarTheme % 2;
LPCWSTR toolBarIntRes = (Settings.ToolBarTheme == 0) ? (LPCWSTR)MAKEINTRESOURCE(IDR_MAINWNDTB) : (LPCWSTR)MAKEINTRESOURCE(IDR_MAINWNDTB2);
hbmp = LoadImage(hInstance, toolBarIntRes, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
}
// use copy for alphablend a disabled Toolbar (if not provided)
hbmpCopy = CopyImage(hbmp, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
HIMAGELIST himl = CreateScaledImageListFromBitmap(hwnd, hbmp);
DeleteObject(hbmp);
hbmp = NULL;
SendMessage(Globals.hwndToolbar,TB_SETIMAGELIST,0,(LPARAM)himl);
// --------------------------
// Add a Hot Toolbar Bitmap
// --------------------------
if ((Settings.ToolBarTheme == 2) && StrIsNotEmpty(g_tchToolbarBitmapHot))
{
hbmp = LoadBitmapFile(g_tchToolbarBitmapHot);
if (!hbmp) {
StringCchCopy(g_tchToolbarBitmapHot, COUNTOF(g_tchToolbarBitmapHot), L"");
IniSectionDelete(L"Toolbar Images", L"BitmapHot", false);
bDirtyFlag = true;
}
}
if (!hbmp && (Settings.ToolBarTheme < 2)) {
LPCWSTR toolBarIntRes = (Settings.ToolBarTheme == 0) ? (LPCWSTR)MAKEINTRESOURCE(IDR_MAINWNDTBHOT) : (LPCWSTR)MAKEINTRESOURCE(IDR_MAINWNDTB2HOT);
hbmp = LoadImage(hInstance, toolBarIntRes, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
}
if (hbmp)
{
himl = CreateScaledImageListFromBitmap(hwnd, hbmp);
DeleteObject(hbmp);
hbmp = NULL;
SendMessage(Globals.hwndToolbar, TB_SETHOTIMAGELIST, 0, (LPARAM)himl);
}
else { // clear the old one
SendMessage(Globals.hwndToolbar, TB_SETHOTIMAGELIST, 0, 0);
}
// ------------------------------
// Add a disabled Toolbar Bitmap
// ------------------------------
if ((Settings.ToolBarTheme == 2) && StrIsNotEmpty(g_tchToolbarBitmapDisabled))
{
hbmp = LoadBitmapFile(g_tchToolbarBitmapDisabled);
if (!hbmp) {
StringCchCopy(g_tchToolbarBitmapDisabled, COUNTOF(g_tchToolbarBitmapDisabled), L"");
IniSectionDelete(L"Toolbar Images", L"BitmapDisabled", false);
bDirtyFlag = true;
}
}
if (!hbmp && (Settings.ToolBarTheme < 2)) {
LPCWSTR toolBarIntRes = (Settings.ToolBarTheme == 0) ? (LPCWSTR)MAKEINTRESOURCE(IDR_MAINWNDTBDIS) : (LPCWSTR)MAKEINTRESOURCE(IDR_MAINWNDTB2DIS);
hbmp = LoadImage(hInstance, toolBarIntRes, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
}
if (hbmp)
{
himl = CreateScaledImageListFromBitmap(hwnd, hbmp);
DeleteObject(hbmp);
hbmp = NULL;
SendMessage(Globals.hwndToolbar, TB_SETDISABLEDIMAGELIST, 0, (LPARAM)himl);
}
else { // create disabled Toolbar, no external bitmap is supplied
if ((Settings.ToolBarTheme == 2) && StrIsEmpty(g_tchToolbarBitmapDisabled))
{
bool bProcessed = false;
if (Flags.ToolbarLook == 1) {
bProcessed = BitmapAlphaBlend(hbmpCopy, GetSysColor(COLOR_3DFACE), 0x60);
}
else if (Flags.ToolbarLook == 2 || (!IsWindowsXPSP3OrGreater() && Flags.ToolbarLook == 0)) {
bProcessed = BitmapGrayScale(hbmpCopy);
}
if (bProcessed && !IsWindowsXPSP3OrGreater()) {
BitmapMergeAlpha(hbmpCopy, GetSysColor(COLOR_3DFACE));
}
if (bProcessed)
{
himl = CreateScaledImageListFromBitmap(hwnd, hbmpCopy);
SendMessage(Globals.hwndToolbar, TB_SETDISABLEDIMAGELIST, 0, (LPARAM)himl);
}
}
}
if (hbmpCopy) {
DeleteObject(hbmpCopy);
hbmpCopy = NULL;
}
// Load toolbar labels
WCHAR tchDesc[256] = { L'\0' };
WCHAR tchIndex[256] = { L'\0' };
for (int i = 0; i < COUNTOF(s_tbbMainWnd); ++i) {
if (s_tbbMainWnd[i].fsStyle == BTNS_SEP) { continue; }
int n = s_tbbMainWnd[i].iBitmap + 1;
StringCchPrintf(tchIndex, COUNTOF(tchIndex), L"%02i", n);
if (IniSectionGetString(L"Toolbar Labels", tchIndex, L"", tchDesc, COUNTOF(tchDesc)) > 0) {
s_tbbMainWnd[i].iString = SendMessage(Globals.hwndToolbar, TB_ADDSTRING, 0, (LPARAM)tchDesc);
s_tbbMainWnd[i].fsStyle |= BTNS_AUTOSIZE | BTNS_SHOWTEXT;
}
else {
GetLngString(s_tbbMainWnd[i].idCommand, tchDesc, COUNTOF(tchDesc));
s_tbbMainWnd[i].iString = SendMessage(Globals.hwndToolbar, TB_ADDSTRING, 0, (LPARAM)tchDesc); // tooltip
s_tbbMainWnd[i].fsStyle &= ~(BTNS_AUTOSIZE | BTNS_SHOWTEXT);
}
}
//~SendMessage(Globals.hwndToolbar, TB_SETMAXTEXTROWS, 0, 0);
DWORD const tbxstyle = (DWORD)SendMessage(Globals.hwndToolbar, TB_GETEXTENDEDSTYLE, 0, 0);
SendMessage(Globals.hwndToolbar,TB_SETEXTENDEDSTYLE,0,(tbxstyle | (TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DOUBLEBUFFER)));
SendMessage(Globals.hwndToolbar, TB_ADDBUTTONS, COUNTOF(s_tbbMainWnd), (LPARAM)s_tbbMainWnd);
if (Toolbar_SetButtons(Globals.hwndToolbar, IDT_FILE_NEW, Settings.ToolbarButtons, s_tbbMainWnd, COUNTOF(s_tbbMainWnd)) == 0) {
SendMessage(Globals.hwndToolbar, TB_ADDBUTTONS, COUNTOF(s_tbbMainWnd), (LPARAM)s_tbbMainWnd);
}
CloseSettingsFile(bDirtyFlag, bOpendByMe);
// ------------------------------
// Create ReBar and add Toolbar
// ------------------------------
DWORD const dwReBarStyle = Settings.ShowToolbar ? (NP3_WS_REBAR | WS_VISIBLE) : (NP3_WS_REBAR);
if (Globals.hwndRebar) {
DestroyWindow(Globals.hwndRebar);
}
Globals.hwndRebar = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL, dwReBarStyle,
0,0,0,0,hwnd,(HMENU)IDC_REBAR,hInstance,NULL);
// Theme = false (!) ~ you cannot change a toolbar's color when a visual style is active
InitWindowCommon(Globals.hwndRebar, !(IsWindows10OrGreater() && IsDarkModeSupported()));
#ifdef D_NP3_WIN10_DARK_MODE
if (IsDarkModeSupported()) {
AllowDarkModeForWindow(Globals.hwndRebar, CheckDarkModeEnabled());
}
#endif
REBARINFO rbi;
rbi.cbSize = sizeof(REBARINFO);
rbi.fMask = 0;
rbi.himl = (HIMAGELIST)NULL;
SendMessage(Globals.hwndRebar, RB_SETBARINFO, 0, (LPARAM)&rbi);
RECT rc;
SendMessage(Globals.hwndToolbar, TB_GETITEMRECT, 0, (LPARAM)&rc);
//SendMessage(Globals.hwndToolbar,TB_SETINDENT,2,0);
REBARBANDINFO rbBand; ZeroMemory(&rbBand, sizeof(REBARBANDINFO));
rbBand.cbSize = sizeof(REBARBANDINFO);
rbBand.fMask = RBBIM_COLORS /*| RBBIM_TEXT | RBBIM_BACKGROUND */ |
RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE /*| RBBIM_SIZE*/;
//rbBand.fStyle = /*RBBS_CHILDEDGE |*//* RBBS_BREAK |*/ RBBS_FIXEDSIZE /*| RBBS_GRIPPERALWAYS*/;
rbBand.fStyle = s_bIsAppThemed ? (RBBS_FIXEDSIZE | RBBS_CHILDEDGE) : RBBS_FIXEDSIZE;
rbBand.hbmBack = NULL;
rbBand.lpText = L"Toolbar";
rbBand.clrFore = GetModeTextColor(UseDarkMode());
rbBand.clrBack = IsWindows10OrGreater() ? GetModeBkColor(UseDarkMode()) : GetModeBtnfaceColor(UseDarkMode());
rbBand.hwndChild = Globals.hwndToolbar;
rbBand.cxMinChild = (rc.right - rc.left) * COUNTOF(s_tbbMainWnd);
rbBand.cyMinChild = (rc.bottom - rc.top) + (2 * rc.top);
rbBand.cx = 0;
SendMessage(Globals.hwndRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
SetWindowPos(Globals.hwndRebar, NULL, 0, 0, 0, 0, SWP_NOZORDER);
GetWindowRect(Globals.hwndRebar, &rc);
s_cyReBar = (rc.bottom - rc.top);
s_cyReBarFrame = s_bIsAppThemed ? 0 : 2; // (!) frame color is same as INITIAL title-bar ???
// -------------------
// Create Statusbar
// -------------------
DWORD const dwStatusbarStyle = SBT_NOBORDERS | (Settings.ShowStatusbar ? (WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE) : (WS_CHILD | WS_CLIPSIBLINGS));
if (Globals.hwndStatus) { DestroyWindow(Globals.hwndStatus); }
//~Globals.hwndStatus = CreateStatusWindow(dwStatusbarStyle, NULL, hwnd, IDC_STATUSBAR);
Globals.hwndStatus = CreateWindowEx(
WS_EX_COMPOSITED, // => double-buffering avoids flickering
STATUSCLASSNAME, // name of status bar class
(PCTSTR)NULL, // no text when first created
dwStatusbarStyle, // creates a visible child window
0, 0, 0, 0, // ignores size and position
hwnd, // handle to parent window
(HMENU)IDC_STATUSBAR, // child window identifier
hInstance, // handle to application instance
NULL); // no window creation data
InitWindowCommon(Globals.hwndStatus, true); // (!) themed = true : resize grip
#ifdef D_NP3_WIN10_DARK_MODE
if (IsDarkModeSupported()) {
AllowDarkModeForWindow(Globals.hwndStatus, CheckDarkModeEnabled());
}
//~HDC const hdc = GetDC(Globals.hwndStatus);
//~SetBkColor(hdc, GetModeBtnfaceColor(UseDarkMode()));
//~SetTextColor(hdc, GetModeTextColor(UseDarkMode()));
//~ReleaseDC(Globals.hwndStatus, hdc);
#endif
}
//=============================================================================
//
// MsgEndSession() - Handle WM_ENDSESSION,WM_DESTROY
//
//
LRESULT MsgEndSession(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
{
UNUSED(wParam);
UNUSED(lParam);
static bool bShutdownOK = false;
if (!bShutdownOK) {
if (s_bPrevFullScreenFlag) {
SendWMCommand(hwnd, CMD_FULLSCRWINPOS);
}
// Terminate file watching
InstallFileWatching(NULL);
DragAcceptFiles(hwnd, true);
// Terminate clipboard watching
if (s_flagPasteBoard) {
KillTimer(hwnd, ID_PASTEBOARDTIMER);
ChangeClipboardChain(hwnd, s_hwndNextCBChain);
}
// close Find/Replace and CustomizeSchemes
CloseNonModalDialogs();
// call SaveAllSettings() when Globals.hwndToolbar is still valid
SaveAllSettings(false);
// Remove tray icon if necessary
ShowNotifyIcon(hwnd, false);
bShutdownOK = true;
}
if (umsg == WM_DESTROY) {
PostQuitMessage(0);
}
return FALSE;
}
//=============================================================================
//
// MsgDPIChanged() - Handle WM_DPICHANGED
//
//
LRESULT MsgDPIChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
//DPI_T dpi;
//dpi.x = LOWORD(wParam);
//dpi.y = HIWORD(wParam);
UNUSED(wParam);
//const RECT* const rc = (RECT*)lParam;
DocPos const pos = SciCall_GetCurrentPos();
UpdateWindowLayoutForDPI(hwnd, (RECT*)lParam, NULL);
SendMessage(Globals.hwndEdit, WM_DPICHANGED, wParam, lParam);
MsgThemeChanged(hwnd, wParam, lParam);
Sci_GotoPosChooseCaret(pos);
return TRUE;
}
//=============================================================================
//
// MsgThemeChanged() - Handle WM_THEMECHANGED
//
LRESULT MsgThemeChanged(HWND hwnd, WPARAM wParam ,LPARAM lParam)
{
UNUSED(lParam);
UNUSED(wParam);
#ifdef D_NP3_WIN10_DARK_MODE
AllowDarkModeForWindow(hwnd, UseDarkMode());
RefreshTitleBarThemeColor(hwnd);
#endif
UpdateTitleBar();
// reinitialize edit frame
_HandleEditWndFrame();
// recreate toolbar and statusbar
CreateBars(hwnd,Globals.hInstance);
Style_ResetCurrentLexer(Globals.hwndEdit);
Sci_RedrawScrollbars();
SetMenu(hwnd, (Settings.ShowMenubar ? Globals.hMainMenu : NULL));
DrawMenuBar(hwnd);
if (FocusedView.HideNonMatchedLines) {
EditToggleView(Globals.hwndEdit);
}
MarkAllOccurrences(0, false);
if (Flags.bLargeFileLoaded) {
EditDoVisibleStyling();
}
else {
EditDoStyling(0, -1);
}
EditUpdateVisibleIndicators();
UpdateToolbar();
UpdateStatusbar(true);
UpdateMarginWidth();
UpdateWindow(hwnd);
UpdateUI();
return FALSE;
}
//=============================================================================
//
// MsgSize() - Handles WM_SIZE
//
//
LRESULT MsgSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
UNUSED(hwnd);
if (wParam == SIZE_MINIMIZED) { return FALSE; }
int x = 0;
int y = 0;
int cx = GET_X_LPARAM(lParam);
int cy = GET_Y_LPARAM(lParam);
if (Settings.ShowToolbar)
{
//~SendMessage(Globals.hwndToolbar,WM_SIZE,0,0);
//~RECT rc;
//~GetWindowRect(Globals.hwndToolbar,&rc);
//~y = (rc.bottom - rc.top);
//~cy -= (rc.bottom - rc.top);
//~SendMessage(Globals.hwndToolbar,TB_GETITEMRECT,0,(LPARAM)&rc);
SetWindowPos(Globals.hwndRebar, NULL, 0, 0, LOWORD(lParam), s_cyReBar, SWP_NOZORDER);
// the ReBar automatically sets the correct height
// calling SetWindowPos() with the height of one toolbar button
// causes the control not to temporarily use the whole client area
// and prevents flickering
//GetWindowRect(Globals.hwndRebar,&rc);
y = s_cyReBar + s_cyReBarFrame; // define
cy -= s_cyReBar + s_cyReBarFrame; // border
}
if (Settings.ShowStatusbar)
{
SendMessage(Globals.hwndStatus,WM_SIZE,0,0);
RECT rc;
GetWindowRect(Globals.hwndStatus, &rc);
cy -= (rc.bottom - rc.top);
}
HDWP hdwp = BeginDeferWindowPos(2);
DeferWindowPos(hdwp,s_hwndEditFrame,NULL,x,y,cx,cy, SWP_NOZORDER | SWP_NOACTIVATE);
DeferWindowPos(hdwp,Globals.hwndEdit,NULL,x+s_cxEditFrame,y+s_cyEditFrame,
cx-2*s_cxEditFrame,cy-2*s_cyEditFrame,
SWP_NOZORDER | SWP_NOACTIVATE);
EndDeferWindowPos(hdwp);
s_WinCurrentWidth = cx;
UpdateToolbar();
UpdateStatusbar(true);
UpdateMarginWidth();
UpdateTitleBar();
return FALSE;
}
//=============================================================================
//
// MsgDrawItem() - Handles WM_DRAWITEM (needs SBT_OWNERDRAW)
//
// https://docs.microsoft.com/en-us/windows/win32/controls/status-bars#owner-drawn-status-bars
//
LRESULT MsgDrawItem(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
UNUSED(hwnd);
if (LOWORD(wParam) == IDC_STATUSBAR) // Statusbar SB_SETTEXT caused parent's WM_DRAWITEM message
{
const DRAWITEMSTRUCT* const pDIS = (const DRAWITEMSTRUCT* const)lParam;
HDC const hdc = pDIS->hDC;
RECT const rc = pDIS->rcItem;
//UINT const ctlId = pDIS->CtlID; // child window identifier
//~int const partId = (int)pDIS->itemID ~ don't use
//~int const stateId = (int)pDIS->itemState ~ don't use
//~PAINTSTRUCT ps;
//~BeginPaint(hWndItem, &ps); ~ not needed on WM_DRAWITEM
//~SetModeBkColor(hdc, UseDarkMode());
SetModeBtnFaceColor(hdc, UseDarkMode());
SetModeTextColor(hdc, UseDarkMode());
#ifdef D_NP3_WIN10_DARK_MODE
if (UseDarkMode()) {
// overpaint part frames
HWND const hWndItem = pDIS->hwndItem;
int const bdh = GetSystemMetrics(SM_CYFRAME);
HDC const hdcFrm = GetWindowDC(hWndItem);
RECT rcf = rc;
for (int i = 1; i < bdh; ++i) {
FrameRect(hdcFrm, &rcf, Globals.hbrDarkModeBtnFcBrush);
rcf.left -= 1;
rcf.top -= 1;
rcf.bottom += 1;
rcf.right += 1;
}
FrameRect(hdcFrm, &rcf, GetSysColorBrush(COLOR_3DDKSHADOW));
ReleaseDC(hWndItem, hdcFrm);
}
#endif
LPCWSTR const text = (LPCWSTR)(pDIS->itemData);
ExtTextOut(hdc, rc.left + 1, rc.top + 1, ETO_OPAQUE | ETO_NUMERICSLOCAL, &rc, text, lstrlen(text), NULL);
//~EndPaint(hWndItem, &ps);
return TRUE;
}
return FALSE;
}
//=============================================================================
//
// MsgDropFiles() - Handles WM_DROPFILES
//
//
LRESULT MsgDropFiles(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
UNUSED(lParam);
WCHAR szDropStrgBuf[MAX_PATH + 40];
HDROP hDrop = (HDROP)wParam;
if (IsIconic(hwnd)) {
ShowWindow(hwnd, SW_RESTORE);
}
DragQueryFile(hDrop, 0, szDropStrgBuf, COUNTOF(szDropStrgBuf));
if (PathIsDirectory(szDropStrgBuf)) {
WCHAR tchFile[MAX_PATH] = { L'\0' };
if (OpenFileDlg(Globals.hwndMain, tchFile, COUNTOF(tchFile), szDropStrgBuf)) {
FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchFile);
}
}
else if (PathIsExistingFile(szDropStrgBuf)) {
if (Flags.bReuseWindow) {
FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, szDropStrgBuf);
}
else {
DialogNewWindow(hwnd, Settings.SaveBeforeRunningTools, szDropStrgBuf);
}
}
else {
// delegated to SCN_URIDROPPED
// Windows Bug: wParam (HDROP) pointer is corrupted if dropped from 32-bit App
//~InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_DROP_NO_FILE);
}
if (DragQueryFile(hDrop, (UINT)(-1), NULL, 0) > 1) {
InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_ERR_DROP);
}
DragFinish(hDrop);
return FALSE;
}
//=============================================================================
//
// DropFilesProc() - Handles DROPFILES
//
//
static DWORD DropFilesProc(CLIPFORMAT cf, HGLOBAL hData, HWND hWnd, DWORD dwKeyState, POINTL pt, void *pUserData)
{
DWORD dwEffect = DROPEFFECT_NONE;
//HWND hEditWnd = (HWND)pUserData;
UNUSED(pUserData);
if (cf == CF_HDROP)
{
WCHAR szBuf[MAX_PATH + 40];
HDROP hDrop = (HDROP)hData;
if (IsIconic(hWnd))
ShowWindow(hWnd, SW_RESTORE);
DragQueryFile(hDrop, 0, szBuf, COUNTOF(szBuf));
if (PathIsDirectory(szBuf)) {
WCHAR tchFile[MAX_PATH] = { L'\0' };
if (OpenFileDlg(hWnd, tchFile, COUNTOF(tchFile), szBuf))
FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchFile);
}
else
FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, szBuf);
if (DragQueryFile(hDrop, (UINT)(-1), NULL, 0) > 1) {
InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_ERR_DROP);
}
dwEffect = DROPEFFECT_COPY;
}
UNUSED(dwKeyState);
UNUSED(pt);
return dwEffect;
}
//=============================================================================
//
// MsgCopyData() - Handles WM_COPYDATA
//
//
LRESULT MsgCopyData(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
UNUSED(wParam);
PCOPYDATASTRUCT pcds = (PCOPYDATASTRUCT)lParam;
// Reset Change Notify
//bPendingChangeNotify = false;
SetDlgItemInt(hwnd, IDC_REUSELOCK, GetTickCount(), false);
if (pcds->dwData == DATA_NOTEPAD3_PARAMS)
{
LPnp3params params = AllocMem(pcds->cbData, HEAP_ZERO_MEMORY);
if (params) {
CopyMemory(params, pcds->lpData, pcds->cbData);
if (params->flagLexerSpecified) {
s_flagLexerSpecified = true;
}
if (params->flagQuietCreate) {
s_flagQuietCreate = true;
}
if (params->flagFileSpecified) {
bool bOpened = false;
Encoding_Forced(params->flagSetEncoding);
if (PathIsDirectory(&params->wchData)) {
WCHAR tchFile[MAX_PATH] = { L'\0' };
if (OpenFileDlg(Globals.hwndMain, tchFile, COUNTOF(tchFile), &params->wchData))
bOpened = FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchFile);
}
else {
bOpened = FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, &params->wchData);
}
if (bOpened) {
if (params->flagChangeNotify == FWM_MSGBOX)
{
FileWatching.FileWatchingMode = FWM_DONT_CARE;
FileWatching.ResetFileWatching = true;
InstallFileWatching(Globals.CurrentFile);
}
else if (params->flagChangeNotify == FWM_AUTORELOAD) {
if (!FileWatching.MonitoringLog) {
PostWMCommand(Globals.hwndMain, IDM_VIEW_CHASING_DOCTAIL);
}
else {
FileWatching.FileWatchingMode = FWM_AUTORELOAD;
FileWatching.ResetFileWatching = true;
InstallFileWatching(Globals.CurrentFile);
}
}
if (params->flagSetEncoding != CPI_NONE) {
s_flagSetEncoding = params->flagSetEncoding;
SendMessage(hwnd, WM_COMMAND, MAKELONG(IDM_ENCODING_SELECT, IDM_ENCODING_SELECT + s_flagSetEncoding), 0);
s_flagSetEncoding = CPI_NONE;
}
if (0 != params->flagSetEOLMode) {
s_flagSetEOLMode = params->flagSetEOLMode;
SendWMCommand(Globals.hwndMain, IDM_LINEENDINGS_CRLF + s_flagSetEOLMode - 1);
s_flagSetEOLMode = 0;
}
if (params->flagLexerSpecified) {
if (params->iInitialLexer < 0) {
WCHAR wchExt[32] = { L'\0' };
StringCchCopy(wchExt, COUNTOF(wchExt), L".");
StringCchCopyN(CharNext(wchExt), 32, StrEnd(&params->wchData, 0) + 1, 31);
Style_SetLexerFromName(Globals.hwndEdit, &params->wchData, wchExt);
}
else if (params->iInitialLexer >= 0 && params->iInitialLexer < NUMLEXERS)
Style_SetLexerFromID(Globals.hwndEdit, params->iInitialLexer);
}
if (params->flagTitleExcerpt) {
StringCchCopyN(s_wchTitleExcerpt, COUNTOF(s_wchTitleExcerpt), StrEnd(&params->wchData, 0) + 1, COUNTOF(s_wchTitleExcerpt));
}
}
// reset
Encoding_Forced(CPI_NONE);
}
if (params->flagJumpTo) {
s_flagJumpTo = true;
EditJumpTo(params->iInitialLine, params->iInitialColumn);
}
if (params->flagMatchText)
{
g_flagMatchText = params->flagMatchText;
SetFindPattern(StrEnd(&params->wchData, 0) + 1);
SetFindReplaceData(); // s_FindReplaceData
if (g_flagMatchText & 2) {
if (!s_flagJumpTo) { SciCall_DocumentEnd(); }
EditFindPrev(Globals.hwndEdit, &s_FindReplaceData, false, false);
}
else {
if (!s_flagJumpTo) { SciCall_DocumentStart(); }
EditFindNext(Globals.hwndEdit, &s_FindReplaceData, false, false);
}
}
s_flagLexerSpecified = false;
s_flagQuietCreate = false;
FreeMem(params);
}
UpdateToolbar();
UpdateStatusbar(true);
UpdateMarginWidth();
}
return FALSE;
}
//=============================================================================
//
// MsgContextMenu() - Handles WM_CONTEXTMENU
//
//
LRESULT MsgContextMenu(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
{
bool const bMargin = (SCN_MARGINRIGHTCLICK == umsg);
int const nID = bMargin ? IDC_MARGIN : GetDlgCtrlID((HWND)wParam);
if ((nID != IDC_MARGIN) && (nID != IDC_EDIT) && (nID != IDC_STATUSBAR) && (nID != IDC_REBAR) && (nID != IDC_TOOLBAR)) {
return DefWindowProc(hwnd, umsg, wParam, lParam);
}
// no context menu after undo/redo history scrolling
if (s_bUndoRedoScroll) {
s_bUndoRedoScroll = false;
return FALSE;
}
HMENU const hMenuCtx = LoadMenu(Globals.hLngResContainer, MAKEINTRESOURCE(IDR_MUI_POPUPMENU));
//SetMenuDefaultItem(GetSubMenu(hmenu,1),0,false);
POINT pt;
pt.x = (int)(short)LOWORD(lParam);
pt.y = (int)(short)HIWORD(lParam);
int imenu = 0;
// modify configured items
HMENU const hStdCtxMenu = GetSubMenu(hMenuCtx, imenu);
if (StrIsNotEmpty(Settings2.WebTmpl1MenuName)) {
ModifyMenu(hStdCtxMenu, CMD_WEBACTION1, MF_BYCOMMAND | MF_STRING, CMD_WEBACTION1, Settings2.WebTmpl1MenuName);
}
if (StrIsNotEmpty(Settings2.WebTmpl2MenuName)) {
ModifyMenu(hStdCtxMenu, CMD_WEBACTION2, MF_BYCOMMAND | MF_STRING, CMD_WEBACTION2, Settings2.WebTmpl2MenuName);
}
switch (nID) {
case IDC_EDIT:
{
if (SciCall_IsSelectionEmpty() && (pt.x != -1) && (pt.y != -1)) {
POINT ptc;
ptc.x = pt.x; ptc.y = pt.y;
ScreenToClient(Globals.hwndEdit, &ptc);
//~SciCall_GotoPos(SciCall_PositionFromPoint(ptc.x, ptc.y));
}
if (pt.x == -1 && pt.y == -1) {
DocPos const iCurrentPos = SciCall_GetCurrentPos();
pt.x = (LONG)SciCall_PointXFromPosition(iCurrentPos);
pt.y = (LONG)SciCall_PointYFromPosition(iCurrentPos);
ClientToScreen(Globals.hwndEdit, &pt);
}
DocLn const curLn = Sci_GetCurrentLineNumber();
int const bitmask = SciCall_MarkerGet(curLn) & OCCURRENCE_MARKER_BITMASK() & ~(1 << MARKER_NP3_BOOKMARK);
imenu = (bitmask && ((Settings.FocusViewMarkerMode & FVMM_LN_BACKGR) || !Settings.ShowBookmarkMargin)) ? 2 : 0;
}
break;
case IDC_TOOLBAR:
case IDC_STATUSBAR:
case IDC_REBAR:
{
if ((pt.x == -1) && (pt.y == -1)) {
GetCursorPos(&pt);
}
imenu = 1;
}
break;
case IDC_MARGIN:
{
if ((pt.x == -1) && (pt.y == -1)) {
GetCursorPos(&pt);
}
DocLn const curLn = Sci_GetCurrentLineNumber();
int const bitmask = SciCall_MarkerGet(curLn) & OCCURRENCE_MARKER_BITMASK();
EnableCmd(hMenuCtx, IDM_EDIT_CLEAR_MARKER, bitmask);
EnableCmd(hMenuCtx, IDM_EDIT_CUT_MARKED, bitmask);
EnableCmd(hMenuCtx, IDM_EDIT_COPY_MARKED, bitmask);
EnableCmd(hMenuCtx, IDM_EDIT_DELETE_MARKED, bitmask);
//DocLn const curLn = Sci_GetCurrentLineNumber();
const SCNotification* const scn = (SCNotification*)wParam;
switch (scn->margin) {
case MARGIN_SCI_FOLDING:
//[[fallthrough]];
case MARGIN_SCI_LINENUM:
//[[fallthrough]];
case MARGIN_SCI_BOOKMRK:
imenu = 2;
break;
default:
imenu = 0;
break;
}
}
break;
}
TrackPopupMenuEx(GetSubMenu(hMenuCtx, imenu),
TPM_LEFTBUTTON | TPM_RIGHTBUTTON, pt.x + 1, pt.y + 1, hwnd, NULL);
DestroyMenu(hMenuCtx);
return (bMargin ? !0 : 0);
}
//=============================================================================
//
// MsgChangeNotify() - Handles WM_CHANGENOTIFY
//
LRESULT MsgChangeNotify(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
UNUSED(wParam);
UNUSED(lParam);
DocPos const iCurPos = SciCall_GetCurrentPos();
if (FileWatching.FileWatchingMode == FWM_MSGBOX || GetDocModified()) {
SetForegroundWindow(hwnd);
}
if (PathIsExistingFile(Globals.CurrentFile))
{
bool bRevertFile = (FileWatching.FileWatchingMode == FWM_AUTORELOAD && !GetDocModified());
if (!bRevertFile) {
INT_PTR const answer = InfoBoxLng(MB_YESNO | MB_ICONWARNING, NULL, IDS_MUI_FILECHANGENOTIFY);
bRevertFile = ((IDOK == answer) || (IDYES == answer));
}
if (bRevertFile)
{
FileRevert(Globals.CurrentFile, /*Encoding_Changed(CPI_GET)*/false);
if (FileWatching.MonitoringLog)
{
SciCall_SetReadOnly(FileWatching.MonitoringLog);
EditEnsureSelectionVisible();
}
else {
Sci_GotoPosChooseCaret(iCurPos);
}
}
}
else {
INT_PTR const answer = InfoBoxLng(MB_YESNO | MB_ICONWARNING, NULL, IDS_MUI_FILECHANGENOTIFY2);
if ((IDOK == answer) || (IDYES == answer)) {
FileSave(true, false, false, false, Flags.bPreserveFileModTime);
}
}
if (!s_bRunningWatch) {
InstallFileWatching(Globals.CurrentFile);
}
return FALSE;
}
//=============================================================================
//
// MsgTrayMessage() - Handles WM_TRAYMESSAGE
//
//
LRESULT MsgTrayMessage(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
UNUSED(wParam);
switch (lParam)
{
case WM_RBUTTONUP:
{
HMENU hTrayMenu = LoadMenu(Globals.hLngResContainer, MAKEINTRESOURCE(IDR_MUI_POPUPMENU));
HMENU hMenuPopup = GetSubMenu(hTrayMenu, 3);
POINT pt;
int iCmd;
SetForegroundWindow(hwnd);
GetCursorPos(&pt);
SetMenuDefaultItem(hMenuPopup, IDM_TRAY_RESTORE, false);
iCmd = TrackPopupMenu(hMenuPopup,
TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
pt.x, pt.y, 0, hwnd, NULL);
PostMessage(hwnd, WM_NULL, 0, 0);
DestroyMenu(hTrayMenu);
if (iCmd == IDM_TRAY_RESTORE) {
ShowNotifyIcon(hwnd, false);
RestoreWndFromTray(hwnd);
ShowOwnedPopups(hwnd, true);
}
else if (iCmd == IDM_TRAY_EXIT) {
//ShowNotifyIcon(hwnd,false);
CloseApplication();
}
}
break;
case WM_LBUTTONUP:
ShowNotifyIcon(hwnd, false);
RestoreWndFromTray(hwnd);
ShowOwnedPopups(hwnd, true);
break;
default:
return TRUE;
}
return FALSE;
}
//=============================================================================
//
// MsgEnterMenuLoop() - Handles WM_ENTERMENULOOP
//
//
LRESULT MsgEnterMenuLoop(HWND hwnd, WPARAM wParam)
{
if ((BOOL)wParam == FALSE) // is main menu
{
HMENU const hCurMenu = GetMenu(hwnd);
if (!hCurMenu)
{
SetMenu(hwnd, Globals.hMainMenu);
DrawMenuBar(hwnd);
//SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
}
}
return (LRESULT)wParam;
}
//=============================================================================
//
// MsgExitMenuLoop() - Handles WM_EXITMENULOOP
//
//
LRESULT MsgExitMenuLoop(HWND hwnd, WPARAM wParam)
{
if ((BOOL)wParam == FALSE) // is main menu
{
HMENU const hCurMenu = GetMenu(hwnd);
if (hCurMenu && !Settings.ShowMenubar)
{
SetMenu(hwnd, NULL);
DrawMenuBar(hwnd);
//SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
}
}
return (LRESULT)wParam;
}
//=============================================================================
//
// MsgInitMenu() - Handles WM_INITMENU
//
//
LRESULT MsgInitMenu(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
UNUSED(lParam);
HMENU const hmenu = wParam ? (HMENU)wParam : GetMenu(hwnd);
if (!hmenu) { return FALSE; }
bool const sav = Globals.bCanSaveIniFile;
bool const ro = SciCall_GetReadOnly(); // scintilla mode read-only
bool const faro = s_bFileReadOnly; // file attrib read-only
DocPos const iCurPos = SciCall_GetCurrentPos();
DocLn const iCurLine = SciCall_LineFromPosition(iCurPos);
bool const bPosInSel = Sci_IsPosInSelection(iCurPos);
bool const pst = SciCall_CanPaste();
bool const se = SciCall_IsSelectionEmpty();
bool const mrs = Sci_IsMultiOrRectangleSelection();
bool const cf = StrIsNotEmpty(Globals.CurrentFile);
bool const te = Sci_IsDocEmpty();
bool const mls = Sci_IsSelectionMultiLine();
//bool const lfl = Flags.bLargeFileLoaded;
EnableCmd(hmenu, IDM_FILE_REVERT, cf);
EnableCmd(hmenu, CMD_RELOADASCIIASUTF8, cf);
EnableCmd(hmenu, CMD_RELOADFORCEDETECTION, cf);
EnableCmd(hmenu, CMD_RECODEANSI, cf);
EnableCmd(hmenu, CMD_RECODEOEM, cf);
EnableCmd(hmenu, CMD_RELOADNOFILEVARS, cf);
EnableCmd(hmenu, CMD_RECODEDEFAULT, cf);
EnableCmd(hmenu, CMD_RECODEGB18030, cf);
EnableCmd(hmenu, IDM_FILE_LAUNCH, cf);
SetUACIcon(hwnd, hmenu, IDM_FILE_LAUNCH_ELEVATED);
CheckCmd(hmenu, IDM_FILE_LAUNCH_ELEVATED, s_bIsProcessElevated);
EnableCmd(hmenu, IDM_FILE_LAUNCH_ELEVATED, !s_bIsProcessElevated);
EnableCmd(hmenu, IDM_FILE_LAUNCH, cf);
EnableCmd(hmenu, IDM_FILE_PROPERTIES, cf);
EnableCmd(hmenu, IDM_FILE_CREATELINK, cf);
EnableCmd(hmenu, IDM_FILE_ADDTOFAV, cf);
EnableCmd(hmenu, IDM_FILE_READONLY, cf);
EnableCmd(hmenu, IDM_EDIT_INSERT_FILENAME, cf);
EnableCmd(hmenu, IDM_EDIT_INSERT_DIRNAME, cf);
EnableCmd(hmenu, IDM_EDIT_INSERT_PATHNAME, cf);
EnableCmd(hmenu, IDM_ENCODING_RECODE, cf);
CheckCmd(hmenu, IDM_FILE_READONLY, faro);
CheckCmd(hmenu, IDM_FILE_PRESERVE_FILEMODTIME, Flags.bPreserveFileModTime);
EnableCmd(hmenu, IDM_ENCODING_UNICODEREV, !ro);
EnableCmd(hmenu, IDM_ENCODING_UNICODE, !ro);
EnableCmd(hmenu, IDM_ENCODING_UTF8SIGN, !ro);
EnableCmd(hmenu, IDM_ENCODING_UTF8, !ro);
EnableCmd(hmenu, IDM_ENCODING_ANSI, !ro);
EnableCmd(hmenu, IDM_LINEENDINGS_CRLF, !ro);
EnableCmd(hmenu, IDM_LINEENDINGS_LF, !ro);
EnableCmd(hmenu, IDM_LINEENDINGS_CR, !ro);
int i;
if (Encoding_IsUNICODE_REVERSE(Encoding_GetCurrent())) {
i = IDM_ENCODING_UNICODEREV;
}
else if (Encoding_IsUNICODE(Encoding_GetCurrent())) {
i = IDM_ENCODING_UNICODE;
}
else if (Encoding_IsUTF8_SIGN(Encoding_GetCurrent())) {
i = IDM_ENCODING_UTF8SIGN;
}
else if (Encoding_IsUTF8(Encoding_GetCurrent())) {
i = IDM_ENCODING_UTF8;
}
else if (Encoding_IsANSI(Encoding_GetCurrent())) {
i = IDM_ENCODING_ANSI;
}
else {
i = -1;
}
CheckMenuRadioItem(hmenu,IDM_ENCODING_ANSI,IDM_ENCODING_UTF8SIGN,i,MF_BYCOMMAND);
int const eol_mode = SciCall_GetEOLMode();
if (eol_mode == SC_EOL_CRLF) {
i = IDM_LINEENDINGS_CRLF;
}
else if (eol_mode == SC_EOL_CR) {
i = IDM_LINEENDINGS_CR;
}
else {
i = IDM_LINEENDINGS_LF;
}
CheckMenuRadioItem(hmenu,IDM_LINEENDINGS_CRLF,IDM_LINEENDINGS_LF,i,MF_BYCOMMAND);
EnableCmd(hmenu, IDM_FILE_RECENT, (MRU_Count(Globals.pFileMRU) > 0));
EnableCmd(hmenu, IDM_EDIT_UNDO, SciCall_CanUndo() && !ro);
EnableCmd(hmenu, IDM_EDIT_REDO, SciCall_CanRedo() && !ro);
EnableCmd(hmenu, IDM_EDIT_CUT, !te && !ro); // allow Ctrl-X w/o selection
EnableCmd(hmenu, IDM_EDIT_COPY, !te); // allow Ctrl-C w/o selection
EnableCmd(hmenu, IDM_EDIT_COPYALL, !te);
EnableCmd(hmenu, IDM_EDIT_COPYADD, !te);
EnableCmd(hmenu, IDM_EDIT_PASTE, pst && !ro);
EnableCmd(hmenu, IDM_EDIT_SWAP, (!se || pst) && !ro);
EnableCmd(hmenu, IDM_EDIT_CLEAR, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_SELECTALL, !te);
EnableCmd(hmenu, IDM_EDIT_GOTOLINE, !te);
OpenClipboard(hwnd);
EnableCmd(hmenu, IDM_EDIT_CLEARCLIPBOARD, CountClipboardFormats());
CloseClipboard();
EnableCmd(hmenu, IDM_EDIT_MOVELINEUP, !ro);
EnableCmd(hmenu, IDM_EDIT_MOVELINEDOWN, !ro);
EnableCmd(hmenu, IDM_EDIT_DUPLINEORSELECTION, !ro);
EnableCmd(hmenu, IDM_EDIT_LINETRANSPOSE, !ro);
EnableCmd(hmenu, IDM_EDIT_CUTLINE, !ro);
//EnableCmd(hmenu, IDM_EDIT_COPYLINE, true);
EnableCmd(hmenu, IDM_EDIT_DELETELINE, !ro);
EnableCmd(hmenu, IDM_EDIT_MERGEBLANKLINES, !ro);
EnableCmd(hmenu, IDM_EDIT_MERGEEMPTYLINES, !ro);
EnableCmd(hmenu, IDM_EDIT_REMOVEBLANKLINES, !ro);
EnableCmd(hmenu, IDM_EDIT_REMOVEEMPTYLINES, !ro);
EnableCmd(hmenu, IDM_EDIT_REMOVEDUPLICATELINES, !ro);
EnableCmd(hmenu, IDM_EDIT_INDENT, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_UNINDENT, !se && !ro);
EnableCmd(hmenu, CMD_JUMP2SELSTART, !se || mrs);
EnableCmd(hmenu, CMD_JUMP2SELEND, !se || mrs);
EnableCmd(hmenu, IDM_EDIT_PADWITHSPACES, !ro && !se);
EnableCmd(hmenu, IDM_EDIT_STRIP1STCHAR, !ro && !se);
EnableCmd(hmenu, IDM_EDIT_STRIPLASTCHAR, !ro && !se);
EnableCmd(hmenu, IDM_EDIT_TRIMLINES, !ro);
EnableCmd(hmenu, IDM_EDIT_COMPRESS_BLANKS, !ro);
EnableCmd(hmenu, IDM_EDIT_MODIFYLINES, !ro);
EnableCmd(hmenu, IDM_EDIT_ALIGN, mls && !ro);
EnableCmd(hmenu, IDM_EDIT_SORTLINES, mls && !ro);
//EnableCmd(hmenu,IDM_EDIT_COLUMNWRAP,i /*&& IsWindowsNT()*/);
EnableCmd(hmenu, IDM_EDIT_SPLITLINES, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_JOINLINES, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_JOINLN_NOSP, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_JOINLINES_PARA, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_CONVERTUPPERCASE, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_CONVERTLOWERCASE, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_INVERTCASE, !se && !ro /*&& IsWindowsNT()*/);
EnableCmd(hmenu, IDM_EDIT_TITLECASE, !se && !ro /*&& IsWindowsNT()*/);
EnableCmd(hmenu, IDM_EDIT_SENTENCECASE, !se && !ro /*&& IsWindowsNT()*/);
EnableCmd(hmenu, IDM_EDIT_CONVERTTABS, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_CONVERTSPACES, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_CONVERTTABS2, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_CONVERTSPACES2, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_URLENCODE, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_URLDECODE, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_ESCAPECCHARS, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_UNESCAPECCHARS, !se && !ro);
EnableCmd(hmenu, IDM_EDIT_CHAR2HEX, !ro); // Char2Hex allowed for char after current pos
EnableCmd(hmenu, IDM_EDIT_HEX2CHAR, !se && !ro);
EnableCmd(hmenu, IDM_VIEW_SHOWEXCERPT, !se);
i = SciCall_GetLexer();
EnableCmd(hmenu, IDM_EDIT_LINECOMMENT,
!(i == SCLEX_NULL || i == SCLEX_CSS || i == SCLEX_DIFF || i == SCLEX_MARKDOWN || i == SCLEX_JSON) && !ro);
EnableCmd(hmenu, IDM_EDIT_STREAMCOMMENT,
!(i == SCLEX_NULL || i == SCLEX_VBSCRIPT || i == SCLEX_MAKEFILE || i == SCLEX_VB || i == SCLEX_ASM ||
i == SCLEX_PERL || i == SCLEX_PYTHON || i == SCLEX_PROPERTIES || i == SCLEX_CONF ||
i == SCLEX_POWERSHELL || i == SCLEX_BATCH || i == SCLEX_DIFF || i == SCLEX_BASH || i == SCLEX_TCL ||
i == SCLEX_AU3 || i == SCLEX_LATEX || i == SCLEX_AHKL || i == SCLEX_RUBY || i == SCLEX_CMAKE || i == SCLEX_MARKDOWN ||
i == SCLEX_YAML || i == SCLEX_REGISTRY || i == SCLEX_NIM || i == SCLEX_TOML) && !ro);
EnableCmd(hmenu, CMD_INSERTNEWLINE, !ro);
EnableCmd(hmenu, IDM_EDIT_INSERT_TAG, !ro);
EnableCmd(hmenu, IDM_EDIT_INSERT_ENCODING, (Encoding_GetParseNames(Encoding_GetCurrent()) != NULL) && !ro);
EnableCmd(hmenu, IDM_EDIT_INSERT_SHORTDATE, !ro);
EnableCmd(hmenu, IDM_EDIT_INSERT_LONGDATE, !ro);
EnableCmd(hmenu, IDM_EDIT_INSERT_GUID, !ro);
EnableCmd(hmenu, IDM_EDIT_FIND, !te);
EnableCmd(hmenu, IDM_EDIT_SAVEFIND, !te);
EnableCmd(hmenu, IDM_EDIT_FINDNEXT, !te);
EnableCmd(hmenu, IDM_EDIT_FINDPREV, !te);
EnableCmd(hmenu, IDM_EDIT_REPLACE, !te && !ro);
EnableCmd(hmenu, IDM_EDIT_REPLACENEXT, !te && !ro);
EnableCmd(hmenu, IDM_EDIT_SELTONEXT, !te);
EnableCmd(hmenu, IDM_EDIT_SELTOPREV, !te);
EnableCmd(hmenu, IDM_EDIT_FINDMATCHINGBRACE, !te);
EnableCmd(hmenu, IDM_EDIT_SELTOMATCHINGBRACE, !te);
CheckCmd(hmenu, IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK, Settings.SplitUndoTypingSeqOnLnBreak);
EnableCmd(hmenu, BME_EDIT_BOOKMARKPREV, !te);
EnableCmd(hmenu, BME_EDIT_BOOKMARKNEXT, !te);
EnableCmd(hmenu, BME_EDIT_BOOKMARKTOGGLE, !te);
EnableCmd(hmenu, BME_EDIT_BOOKMARKCLEAR, !te);
EnableCmd(hmenu, IDM_EDIT_DELETELINELEFT, !te && !ro);
EnableCmd(hmenu, IDM_EDIT_DELETELINERIGHT, !te && !ro);
EnableCmd(hmenu, CMD_CTRLBACK, !te && !ro);
EnableCmd(hmenu, CMD_CTRLDEL, !te && !ro);
EnableCmd(hmenu, CMD_INSERT_TIMESTAMP, !ro);
EnableCmd(hmenu, CMD_UPDATE_TIMESTAMPS, !te && !ro);
EnableCmd(hmenu, IDM_VIEW_FONT, !IsWindow(Globals.hwndDlgCustomizeSchemes));
EnableCmd(hmenu, IDM_VIEW_CURRENTSCHEME, !IsWindow(Globals.hwndDlgCustomizeSchemes));
EnableCmd(hmenu, IDM_VIEW_FOLDING, FocusedView.CodeFoldingAvailable && !FocusedView.HideNonMatchedLines);
bool const fd = (FocusedView.CodeFoldingAvailable && FocusedView.ShowCodeFolding);
CheckCmd(hmenu, IDM_VIEW_FOLDING, fd);
EnableCmd(hmenu, IDM_VIEW_TOGGLEFOLDS, !te && fd);
EnableCmd(hmenu, CMD_FOLDJUMPDOWN, !te && fd);
EnableCmd(hmenu, CMD_FOLDJUMPUP, !te && fd);
EnableCmd(hmenu, CMD_FOLDCOLLAPSE, !te && fd);
EnableCmd(hmenu, CMD_FOLDEXPAND, !te && fd);
bool const bF = (SC_FOLDLEVELBASE < (SciCall_GetFoldLevel(iCurLine) & SC_FOLDLEVELNUMBERMASK));
bool const bH = (SciCall_GetFoldLevel(iCurLine) & SC_FOLDLEVELHEADERFLAG);
EnableCmd(hmenu, IDM_VIEW_TOGGLE_CURRENT_FOLD, !te && fd && (bF || bH));
CheckCmdPos(GetSubMenu(GetMenu(Globals.hwndMain), 2), 18, fd);
CheckCmd(hmenu, IDM_VIEW_USE2NDDEFAULT, Style_GetUse2ndDefault());
CheckCmd(hmenu, IDM_VIEW_WORDWRAP, Globals.fvCurFile.bWordWrap);
CheckCmd(hmenu, IDM_VIEW_LONGLINEMARKER, Settings.MarkLongLines);
CheckCmd(hmenu, IDM_VIEW_TABSASSPACES, Globals.fvCurFile.bTabsAsSpaces);
CheckCmd(hmenu, IDM_VIEW_SHOWINDENTGUIDES, Settings.ShowIndentGuides);
CheckCmd(hmenu, IDM_VIEW_AUTOINDENTTEXT, Settings.AutoIndent);
CheckCmd(hmenu, IDM_VIEW_LINENUMBERS, Settings.ShowLineNumbers);
CheckCmd(hmenu, IDM_VIEW_BOOKMARK_MARGIN, Settings.ShowBookmarkMargin);
CheckCmd(hmenu, IDM_VIEW_CHASING_DOCTAIL, FileWatching.MonitoringLog);
EnableCmd(hmenu, IDM_EDIT_COMPLETEWORD, !te && !ro);
CheckCmd(hmenu, IDM_VIEW_AUTOCOMPLETEWORDS, Settings.AutoCompleteWords && !ro);
CheckCmd(hmenu, IDM_VIEW_AUTOCLEXKEYWORDS, Settings.AutoCLexerKeyWords && !ro);
CheckCmd(hmenu, IDM_VIEW_ACCELWORDNAV, Settings.AccelWordNavigation);
CheckCmd(hmenu, IDM_VIEW_EDIT_LINECOMMENT, Settings.EditLineCommentBlock);
CheckCmd(hmenu, IDM_VIEW_MARKOCCUR_ONOFF, IsMarkOccurrencesEnabled());
CheckCmd(hmenu, IDM_VIEW_MARKOCCUR_BOOKMARKS, Settings.MarkOccurrencesBookmark);
CheckCmd(hmenu, IDM_VIEW_MARKOCCUR_VISIBLE, Settings.MarkOccurrencesMatchVisible);
CheckCmd(hmenu, IDM_VIEW_MARKOCCUR_CASE, Settings.MarkOccurrencesMatchCase);
EnableCmd(hmenu, IDM_VIEW_TOGGLE_VIEW, IsFocusedViewAllowed());
CheckCmd(hmenu, IDM_VIEW_TOGGLE_VIEW, FocusedView.HideNonMatchedLines);
i = IDM_VIEW_FV_FOLD;
int const fvm_mode = Settings.FocusViewMarkerMode;
if (fvm_mode == FVMM_MARGIN) {
i = IDM_VIEW_FV_BOOKMARK;
} else if (fvm_mode == FVMM_LN_BACKGR) {
i = IDM_VIEW_FV_HIGHLIGHT;
} else if (fvm_mode == (FVMM_MARGIN | FVMM_FOLD)) {
i = IDM_VIEW_FV_BKMRKFOLD;
} else if (fvm_mode == (FVMM_LN_BACKGR | FVMM_FOLD)) {
i = IDM_VIEW_FV_HIGHLGFOLD;
} else {
i = IDM_VIEW_FV_FOLD;
}
CheckMenuRadioItem(hmenu, IDM_VIEW_FV_FOLD, IDM_VIEW_FV_HIGHLGFOLD, i, MF_BYCOMMAND);
CheckCmd(hmenu, IDM_VIEW_HYPERLINKHOTSPOTS, Settings.HyperlinkHotspot);
i = IDM_VIEW_COLORDEFHOTSPOTS + Settings.ColorDefHotspot;
CheckMenuRadioItem(hmenu, IDM_VIEW_COLORDEFHOTSPOTS, IDM_VIEW_COLOR_BGRA, i, MF_BYCOMMAND);
CheckCmdPos(GetSubMenu(GetMenu(Globals.hwndMain), 2), 9, IsColorDefHotspotEnabled());
CheckCmd(hmenu, IDM_VIEW_UNICODE_POINTS, Settings.HighlightUnicodePoints);
CheckCmd(hmenu, IDM_VIEW_MATCHBRACES, Settings.MatchBraces);
i = IDM_VIEW_HILITCURLN_NONE + Settings.HighlightCurrentLine;
CheckMenuRadioItem(hmenu, IDM_VIEW_HILITCURLN_NONE, IDM_VIEW_HILITCURLN_FRAME, i, MF_BYCOMMAND);
CheckCmdPos(GetSubMenu(GetMenu(Globals.hwndMain), 2), 12, (i != IDM_VIEW_HILITCURLN_NONE));
#ifdef D_NP3_WIN10_DARK_MODE
EnableCmd(hmenu, IDM_VIEW_WIN_DARK_MODE, IsDarkModeSupported());
CheckCmd(hmenu, IDM_VIEW_WIN_DARK_MODE, Settings.WinThemeDarkMode);
#else
RemoveMenu(hmenu, IDM_VIEW_WIN_DARK_MODE, 0);
#endif
// --------------------------------------------------------------------------
int const mnuMain = 2;
int const mnuSubOcc = 13;
int const mnuSubSubWord = 6;
if (Settings.MarkOccurrencesMatchWholeWords) {
i = IDM_VIEW_MARKOCCUR_WORD;
}
else if (Settings.MarkOccurrencesCurrentWord) {
i = IDM_VIEW_MARKOCCUR_CURRENT;
}
else {
i = IDM_VIEW_MARKOCCUR_WNONE;
}
CheckMenuRadioItem(hmenu, IDM_VIEW_MARKOCCUR_WNONE, IDM_VIEW_MARKOCCUR_CURRENT, i, MF_BYCOMMAND);
CheckCmdPos(GetSubMenu(GetSubMenu(GetMenu(Globals.hwndMain), mnuMain), mnuSubOcc), mnuSubSubWord, (i != IDM_VIEW_MARKOCCUR_WNONE));
i = IsMarkOccurrencesEnabled();
EnableCmd(hmenu, IDM_VIEW_MARKOCCUR_VISIBLE, i);
EnableCmd(hmenu, IDM_VIEW_MARKOCCUR_CASE, i);
EnableCmd(hmenu, IDM_VIEW_MARKOCCUR_WNONE, i);
EnableCmd(hmenu, IDM_VIEW_MARKOCCUR_WORD, i);
EnableCmd(hmenu, IDM_VIEW_MARKOCCUR_CURRENT, i);
EnableCmdPos(GetSubMenu(GetSubMenu(GetMenu(Globals.hwndMain), mnuMain), mnuSubOcc), mnuSubSubWord, i);
CheckCmdPos(GetSubMenu(GetMenu(Globals.hwndMain), mnuMain), mnuSubOcc, i);
// --------------------------------------------------------------------------
CheckCmd(hmenu, IDM_VIEW_SHOWBLANKS, Settings.ViewWhiteSpace);
CheckCmd(hmenu, IDM_VIEW_SHOWEOLS, Settings.ViewEOLs);
CheckCmd(hmenu, IDM_VIEW_WORDWRAPSYMBOLS, Settings.ShowWordWrapSymbols);
CheckCmd(hmenu, IDM_VIEW_MENUBAR, Settings.ShowMenubar);
CheckCmd(hmenu, IDM_VIEW_TOOLBAR, Settings.ShowToolbar);
EnableCmd(hmenu, IDM_VIEW_CUSTOMIZETB, Settings.ShowToolbar);
CheckCmd(hmenu, IDM_VIEW_STATUSBAR, Settings.ShowStatusbar);
CheckCmd(hmenu, IDM_VIEW_DPISCALETB, Settings.DpiScaleToolBar);
//i = SciCall_GetLexer();
//EnableCmd(hmenu,IDM_VIEW_AUTOCLOSETAGS,(i == SCLEX_HTML || i == SCLEX_XML));
CheckCmd(hmenu, IDM_VIEW_AUTOCLOSETAGS, Settings.AutoCloseTags /*&& (i == SCLEX_HTML || i == SCLEX_XML)*/);
CheckCmd(hmenu, IDM_VIEW_SHOW_HYPLNK_CALLTIP, Settings.ShowHypLnkToolTip);
CheckCmd(hmenu, IDM_VIEW_SCROLLPASTEOF, Settings.ScrollPastEOF);
CheckCmd(hmenu, IDM_VIEW_REUSEWINDOW, Flags.bReuseWindow);
EnableCmd(hmenu, IDM_VIEW_REUSEWINDOW, sav);
CheckCmd(hmenu, IDM_VIEW_SINGLEFILEINSTANCE, Flags.bSingleFileInstance);
EnableCmd(hmenu, IDM_VIEW_SINGLEFILEINSTANCE, sav);
CheckCmd(hmenu, IDM_VIEW_STICKYWINPOS, Flags.bStickyWindowPosition);
EnableCmd(hmenu, IDM_VIEW_STICKYWINPOS, sav);
EnableCmd(hmenu, CMD_SAVEASDEFWINPOS, sav);
CheckCmd(hmenu, IDM_VIEW_ALWAYSONTOP, ((Settings.AlwaysOnTop || s_flagAlwaysOnTop == 2) && s_flagAlwaysOnTop != 1));
CheckCmd(hmenu, IDM_VIEW_MINTOTRAY, Settings.MinimizeToTray);
CheckCmd(hmenu, IDM_VIEW_TRANSPARENT, Settings.TransparentMode);
bool const dwr = (Settings.RenderingTechnology > SC_TECHNOLOGY_DEFAULT);
//bool const gdi = ((Settings.RenderingTechnology % SC_TECHNOLOGY_DIRECTWRITEDC) == 0);
i = IDM_SET_RENDER_TECH_GDI + Settings.RenderingTechnology;
CheckMenuRadioItem(hmenu, IDM_SET_RENDER_TECH_GDI, IDM_SET_RENDER_TECH_D2DDC, i, MF_BYCOMMAND);
CheckCmd(hmenu, IDM_SET_RTL_LAYOUT_EDIT, Settings.EditLayoutRTL);
//~EnableCmd(hmenu, IDM_SET_RTL_LAYOUT_EDIT, gdi);
CheckCmd(hmenu, IDM_SET_RTL_LAYOUT_DLG, Settings.DialogsLayoutRTL);
if (dwr) {
i = IDM_SET_BIDIRECTIONAL_NONE + Settings.Bidirectional;
CheckMenuRadioItem(hmenu, IDM_SET_BIDIRECTIONAL_NONE, IDM_SET_BIDIRECTIONAL_R2L, i, MF_BYCOMMAND);
}
else {
i = IDM_SET_BIDIRECTIONAL_NONE;
CheckMenuRadioItem(hmenu, IDM_SET_BIDIRECTIONAL_NONE, IDM_SET_BIDIRECTIONAL_R2L, i, MF_BYCOMMAND);
}
EnableCmd(hmenu, IDM_SET_BIDIRECTIONAL_NONE, dwr);
EnableCmd(hmenu, IDM_SET_BIDIRECTIONAL_L2R, dwr);
EnableCmd(hmenu, IDM_SET_BIDIRECTIONAL_R2L, dwr);
CheckCmd(hmenu, IDM_VIEW_MUTE_MESSAGEBEEP, Settings.MuteMessageBeep);
CheckCmd(hmenu, IDM_VIEW_SAVEBEFORERUNNINGTOOLS, Settings.SaveBeforeRunningTools);
//~EnableCmd(hmenu, IDM_VIEW_SAVEBEFORERUNNINGTOOLS, !faro);
CheckCmd(hmenu, IDM_VIEW_NOSAVERECENT, Settings.SaveRecentFiles);
EnableCmd(hmenu, IDM_VIEW_NOSAVERECENT, sav);
CheckCmd(hmenu, IDM_VIEW_NOPRESERVECARET, Settings.PreserveCaretPos);
EnableCmd(hmenu, IDM_VIEW_NOPRESERVECARET, Settings.SaveRecentFiles && sav);
CheckCmd(hmenu, IDM_VIEW_NOSAVEFINDREPL, Settings.SaveFindReplace);
EnableCmd(hmenu, IDM_VIEW_NOSAVEFINDREPL, sav);
CheckCmd(hmenu, IDM_VIEW_EVALTINYEXPRONSEL, Settings.EvalTinyExprOnSelection);
CheckCmd(hmenu, IDM_VIEW_CHANGENOTIFY, Settings.FileWatchingMode);
if (StrIsNotEmpty(s_wchTitleExcerpt))
i = IDM_VIEW_SHOWEXCERPT;
else if (Settings.PathNameFormat == 0)
i = IDM_VIEW_SHOWFILENAMEONLY;
else if (Settings.PathNameFormat == 1)
i = IDM_VIEW_SHOWFILENAMEFIRST;
else
i = IDM_VIEW_SHOWFULLPATH;
CheckMenuRadioItem(hmenu, IDM_VIEW_SHOWFILENAMEONLY, IDM_VIEW_SHOWEXCERPT, i, MF_BYCOMMAND);
if (Settings.EscFunction == 1)
i = IDM_VIEW_ESCMINIMIZE;
else if (Settings.EscFunction == 2)
i = IDM_VIEW_ESCEXIT;
else
i = IDM_VIEW_NOESCFUNC;
CheckMenuRadioItem(hmenu, IDM_VIEW_NOESCFUNC, IDM_VIEW_ESCEXIT, i, MF_BYCOMMAND);
bool const bIsHLink = (SciCall_IndicatorValueAt(INDIC_NP3_HYPERLINK, iCurPos) > 0);
EnableCmd(hmenu, CMD_OPEN_HYPERLINK, !mrs && bIsHLink);
EnableCmd(hmenu, CMD_WEBACTION1, !se && !mrs && bPosInSel && !bIsHLink);
EnableCmd(hmenu, CMD_WEBACTION2, !se && !mrs && bPosInSel && !bIsHLink);
i = (int)StrIsNotEmpty(Settings2.AdministrationTool);
EnableCmd(hmenu, IDM_HELP_ADMINEXE, i);
for (int lng = 0; lng < MuiLanguages_CountOf(); ++lng) {
//EnableCmd(hmenu, MUI_LanguageDLLs[lng].rid, MUI_LanguageDLLs[lng].bHasDLL);
CheckCmd(hmenu, MUI_LanguageDLLs[lng].rid, MUI_LanguageDLLs[lng].bIsActive);
}
UpdateSaveSettingsCmds();
return FALSE;
}
//=============================================================================
//
// _DynamicLanguageMenuCmd() - Handles IDS_MUI_LANG_XX_YY messages
//
//
static void _DynamicLanguageMenuCmd(int cmd)
{
int const iLngIdx = (cmd - IDS_MUI_LANG_EN_US); // consecutive IDs
if ((iLngIdx < 0) || (iLngIdx >= MuiLanguages_CountOf())) {
return;
}
if (!MUI_LanguageDLLs[iLngIdx].bIsActive)
{
CloseNonModalDialogs();
DestroyMenu(Globals.hMainMenu);
// desired language
LANGID const desiredLngID = MUI_LanguageDLLs[iLngIdx].LangId;
SetPreferredLanguage(desiredLngID);
FreeLanguageResources();
LoadLanguageResources();
Globals.hMainMenu = LoadMenu(Globals.hLngResContainer, MAKEINTRESOURCE(IDR_MUI_MAINMENU));
if (!Globals.hMainMenu) {
MsgBoxLastError(L"LoadMenu()", 0);
CloseApplication();
return;
}
_InsertLanguageMenu(Globals.hMainMenu);
Style_InsertThemesMenu(Globals.hMainMenu);
SetMenu(Globals.hwndMain, (Settings.ShowMenubar ? Globals.hMainMenu : NULL));
DrawMenuBar(Globals.hwndMain);
UpdateUI();
}
return;
}
//=============================================================================
//
// MsgCommand() - Handles WM_COMMAND
//
static WCHAR tchMaxPathBuffer[MAX_PATH] = { L'\0' };
LRESULT MsgCommand(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
{
int const iLoWParam = LOWORD(wParam);
bool const bIsLngMenuCmd = ((iLoWParam >= IDS_MUI_LANG_EN_US) && (iLoWParam < (IDS_MUI_LANG_EN_US + MuiLanguages_CountOf())));
if (bIsLngMenuCmd) {
_DynamicLanguageMenuCmd(iLoWParam);
return FALSE;
}
bool const bIsThemesMenuCmd = ((iLoWParam >= IDM_THEMES_DEFAULT) && (iLoWParam < (int)(IDM_THEMES_DEFAULT + ThemeItems_CountOf())));
if (bIsThemesMenuCmd) {
Style_DynamicThemesMenuCmd(iLoWParam, GetModeThemeIndex());
return FALSE;
}
switch(iLoWParam)
{
case SCEN_CHANGE:
EditUpdateVisibleIndicators();
MarkAllOccurrences(Settings2.UpdateDelayMarkAllOccurrences, false);
break;
case IDT_TIMER_UPDATE_STATUSBAR:
_UpdateStatusbarDelayed((bool)lParam);
break;
case IDT_TIMER_UPDATE_TOOLBAR:
_UpdateToolbarDelayed();
break;
case IDT_TIMER_MAIN_MRKALL:
EditMarkAllOccurrences(Globals.hwndEdit, (bool)lParam);
break;
case IDT_TIMER_CLEAR_CALLTIP:
CancelCallTip();
break;
case IDT_TIMER_UNDO_TRANSACTION:
_SplitUndoTransaction((int)lParam);
break;
case IDM_FILE_NEW:
FileLoad(false,true,false,Settings.SkipUnicodeDetection,Settings.SkipANSICodePageDetection, false, L"");
break;
case IDM_FILE_OPEN:
FileLoad(false,false,false,Settings.SkipUnicodeDetection,Settings.SkipANSICodePageDetection, false, L"");
break;
case IDM_FILE_REVERT:
if (GetDocModified()) {
INT_PTR const answer = InfoBoxLng(MB_YESNO | MB_ICONQUESTION, NULL, IDS_MUI_ASK_REVERT);
if (!((IDOK == answer) || (IDYES == answer))) {
break;
}
//~ don't revert if no save needed
//~FileRevert(Globals.CurrentFile, Encoding_Changed(CPI_GET));
}
// revert in any case (manually forced)
FileRevert(Globals.CurrentFile, /*Encoding_Changed(CPI_GET)*/true);
break;
case IDM_FILE_SAVE:
FileSave(true, false, false, false, Flags.bPreserveFileModTime);
break;
case IDM_FILE_SAVEAS:
FileSave(true, false, true, false, Flags.bPreserveFileModTime);
break;
case IDM_FILE_SAVECOPY:
FileSave(true, false, true, true, Flags.bPreserveFileModTime);
break;
case IDM_FILE_PRESERVE_FILEMODTIME:
if (!Flags.bPreserveFileModTime) {
InfoBoxLng(MB_OK, L"PreserveFileModTime", IDS_MUI_INF_PRSVFILEMODTM);
}
Flags.bPreserveFileModTime = true;
FileSave(true, false, false, false, Flags.bPreserveFileModTime);
break;
case IDM_FILE_READONLY:
if (StrIsNotEmpty(Globals.CurrentFile))
{
DWORD dwFileAttributes = GetFileAttributes(Globals.CurrentFile);
if (dwFileAttributes != INVALID_FILE_ATTRIBUTES) {
if (s_bFileReadOnly) {
dwFileAttributes = (dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
}
else {
dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
}
if (!SetFileAttributes(Globals.CurrentFile, dwFileAttributes)) {
InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_READONLY_MODIFY, PathFindFileName(Globals.CurrentFile));
}
}
else {
InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_READONLY_MODIFY, PathFindFileName(Globals.CurrentFile));
}
s_bFileReadOnly = IsReadOnly(GetFileAttributes(Globals.CurrentFile)); // ensure setting
if (Flags.bSettingsFileSoftLocked) {
Globals.bCanSaveIniFile = CanAccessPath(Globals.IniFile, GENERIC_WRITE);
UpdateSaveSettingsCmds();
}
UpdateToolbar();
}
break;
case IDM_FILE_BROWSE:
DialogFileBrowse(hwnd);
break;
case IDM_GREP_WIN_SEARCH:
{
WCHAR wchBuffer[MIDSZ_BUFFER] = { L'\0' };
EditGetSelectedText(wchBuffer, COUNTOF(wchBuffer));
DialogGrepWin(hwnd, wchBuffer);
}
break;
case IDM_FILE_NEWWINDOW:
case IDM_FILE_NEWWINDOW2:
SaveAllSettings(false);
LPCWSTR lpcwFilePath = (iLoWParam != IDM_FILE_NEWWINDOW2) ? Globals.CurrentFile : NULL;
DialogNewWindow(hwnd, Settings.SaveBeforeRunningTools, lpcwFilePath);
break;
case IDM_FILE_LAUNCH:
{
if (StrIsEmpty(Globals.CurrentFile))
break;
if (Settings.SaveBeforeRunningTools && !FileSave(false,true,false,false,Flags.bPreserveFileModTime))
break;
StringCchCopy(tchMaxPathBuffer,COUNTOF(tchMaxPathBuffer),Globals.CurrentFile);
PathCchRemoveFileSpec(tchMaxPathBuffer, COUNTOF(tchMaxPathBuffer));
SHELLEXECUTEINFO sei;
ZeroMemory(&sei,sizeof(SHELLEXECUTEINFO));
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = 0;
sei.hwnd = hwnd;
sei.lpVerb = NULL;
sei.lpFile = Globals.CurrentFile;
sei.lpParameters = NULL;
sei.lpDirectory = tchMaxPathBuffer;
sei.nShow = SW_SHOWNORMAL;
ShellExecuteEx(&sei);
}
break;
case IDM_FILE_EXPLORE_DIR:
{
if (Settings.SaveBeforeRunningTools && !FileSave(false, true, false, false, Flags.bPreserveFileModTime)) {
break;
}
PIDLIST_ABSOLUTE pidl = NULL;
DWORD rfg = 0;
SHILCreateFromPath(StrIsEmpty(Globals.CurrentFile) ? Globals.WorkingDirectory : Globals.CurrentFile, &pidl, &rfg);
if (pidl) {
SHOpenFolderAndSelectItems(pidl, 0, NULL, 0);
ILFree(pidl);
}
}
break;
case IDM_FILE_LAUNCH_ELEVATED:
{
EditFileIOStatus fioStatus = INIT_FILEIO_STATUS;
fioStatus.iEncoding = Encoding_GetCurrent();
fioStatus.iEOLMode = SciCall_GetEOLMode();
if (DoElevatedRelaunch(&fioStatus, false))
{
CloseApplication();
}
else {
InfoBoxLng(MB_ICONSHIELD, NULL, IDS_MUI_ERR_ELEVATED_RIGHTS);
}
}
break;
case IDM_FILE_RUN:
{
if (Settings.SaveBeforeRunningTools && !FileSave(false, true, false, false, Flags.bPreserveFileModTime)) {
break;
}
StringCchCopy(tchMaxPathBuffer,COUNTOF(tchMaxPathBuffer),Globals.CurrentFile);
PathQuoteSpaces(tchMaxPathBuffer);
RunDlg(hwnd,tchMaxPathBuffer);
}
break;
case IDM_FILE_OPENWITH:
if (Settings.SaveBeforeRunningTools && !FileSave(false, true, false, false, Flags.bPreserveFileModTime))
break;
OpenWithDlg(hwnd,Globals.CurrentFile);
break;
case IDM_FILE_PAGESETUP:
EditPrintSetup(Globals.hwndEdit);
break;
case IDM_FILE_PRINT:
{
WCHAR *pszTitle;
WCHAR tchUntitled[32] = { L'\0' };
WCHAR tchPageFmt[32] = { L'\0' };
WCHAR szDisplayName[MAX_PATH];
if (StrIsNotEmpty(Globals.CurrentFile))
{
PathGetDisplayName(szDisplayName, COUNTOF(szDisplayName), Globals.CurrentFile);
pszTitle = szDisplayName;
}
else {
GetLngString(IDS_MUI_UNTITLED, tchUntitled, COUNTOF(tchUntitled));
pszTitle = tchUntitled;
}
GetLngString(IDS_MUI_PRINT_PAGENUM,tchPageFmt,COUNTOF(tchPageFmt));
if (!EditPrint(Globals.hwndEdit, pszTitle, tchPageFmt)) {
InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_PRINT_ERROR, pszTitle);
}
}
break;
case IDM_FILE_PROPERTIES:
{
if (StrIsEmpty(Globals.CurrentFile))
break;
SHELLEXECUTEINFO sei;
ZeroMemory(&sei,sizeof(SHELLEXECUTEINFO));
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_INVOKEIDLIST;
sei.hwnd = hwnd;
sei.lpVerb = L"properties";
sei.lpFile = Globals.CurrentFile;
sei.nShow = SW_SHOWNORMAL;
ShellExecuteEx(&sei);
}
break;
case IDM_FILE_CREATELINK:
{
if (StrIsEmpty(Globals.CurrentFile)) {
break;
}
if (!PathCreateDeskLnk(Globals.CurrentFile)) {
InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_ERR_CREATELINK);
}
}
break;
case IDM_FILE_OPENFAV:
if (FileSave(false, true, false, false, Flags.bPreserveFileModTime)) {
if (FavoritesDlg(hwnd,tchMaxPathBuffer))
{
if (PathIsLnkToDirectory(tchMaxPathBuffer,NULL,0))
PathGetLnkPath(tchMaxPathBuffer,tchMaxPathBuffer,COUNTOF(tchMaxPathBuffer));
if (PathIsDirectory(tchMaxPathBuffer))
{
if (OpenFileDlg(Globals.hwndMain, tchMaxPathBuffer, COUNTOF(tchMaxPathBuffer), tchMaxPathBuffer))
FileLoad(true, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchMaxPathBuffer);
}
else
FileLoad(true, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchMaxPathBuffer);
}
}
break;
case IDM_FILE_ADDTOFAV:
if (StrIsNotEmpty(Globals.CurrentFile)) {
WCHAR szDisplayName[MAX_PATH];
PathGetDisplayName(szDisplayName, COUNTOF(szDisplayName), Globals.CurrentFile);
AddToFavDlg(hwnd, szDisplayName, Globals.CurrentFile);
}
break;
case IDM_FILE_MANAGEFAV:
{
SHELLEXECUTEINFO sei;
ZeroMemory(&sei,sizeof(SHELLEXECUTEINFO));
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = 0;
sei.hwnd = hwnd;
sei.lpVerb = NULL;
sei.lpFile = Settings.FavoritesDir;
sei.lpParameters = NULL;
sei.lpDirectory = NULL;
sei.nShow = SW_SHOWNORMAL;
// Run favorites directory
ShellExecuteEx(&sei);
}
break;
case IDM_FILE_RECENT:
if (MRU_Count(Globals.pFileMRU) > 0) {
if (FileSave(false, true, false, false, Flags.bPreserveFileModTime)) {
WCHAR tchFile[MAX_PATH] = { L'\0' };
if (FileMRUDlg(hwnd, tchFile)) {
FileLoad(true, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchFile);
}
}
}
break;
case IDM_FILE_EXIT:
CloseApplication();
break;
case IDM_ENCODING_ANSI:
case IDM_ENCODING_UNICODE:
case IDM_ENCODING_UNICODEREV:
case IDM_ENCODING_UTF8:
case IDM_ENCODING_UTF8SIGN:
case IDM_ENCODING_SELECT:
{
cpi_enc_t iNewEncoding = (HIWORD(wParam) >= IDM_ENCODING_SELECT) ?
(cpi_enc_t)(HIWORD(wParam) - IDM_ENCODING_SELECT) : Encoding_GetCurrent();
if (iLoWParam == IDM_ENCODING_SELECT) {
if ((HIWORD(wParam) < IDM_ENCODING_SELECT) && !SelectEncodingDlg(hwnd, &iNewEncoding)) {
break; // no change
}
}
else {
switch (iLoWParam)
{
case IDM_ENCODING_UNICODE: iNewEncoding = CPI_UNICODEBOM; break;
case IDM_ENCODING_UNICODEREV: iNewEncoding = CPI_UNICODEBEBOM; break;
case IDM_ENCODING_UTF8: iNewEncoding = CPI_UTF8; break;
case IDM_ENCODING_UTF8SIGN: iNewEncoding = CPI_UTF8SIGN; break;
case IDM_ENCODING_ANSI: iNewEncoding = CPI_ANSI_DEFAULT; break;
}
}
BeginWaitCursor(true,L"Recoding...");
if (EditSetNewEncoding(Globals.hwndEdit, iNewEncoding, (s_flagSetEncoding != CPI_NONE)))
{
SetSaveNeeded();
}
EndWaitCursor();
UpdateToolbar();
UpdateStatusbar(false);
}
break;
case IDM_ENCODING_RECODE:
{
if (StrIsNotEmpty(Globals.CurrentFile))
{
cpi_enc_t iNewEncoding = Encoding_MapSignature(Encoding_GetCurrent());
if (GetDocModified()) {
INT_PTR const answer = InfoBoxLng(MB_YESNO | MB_ICONQUESTION, NULL, IDS_MUI_ASK_RECODE);
if (!((IDOK == answer) || (IDYES == answer))) {
break;
}
}
if (RecodeDlg(hwnd,&iNewEncoding))
{
StringCchCopy(tchMaxPathBuffer,COUNTOF(tchMaxPathBuffer),Globals.CurrentFile);
Encoding_Forced(iNewEncoding);
FileLoad(true, false, true, true, true, false, tchMaxPathBuffer);
}
}
}
break;
case IDM_ENCODING_SETDEFAULT:
SelectDefEncodingDlg(hwnd, &Settings.DefaultEncoding);
UpdateToolbar();
UpdateStatusbar(false);
break;
case IDM_LINEENDINGS_CRLF:
case IDM_LINEENDINGS_CR:
case IDM_LINEENDINGS_LF:
{
BeginWaitCursor(true,L"Line Breaks...");
_IGNORE_NOTIFY_CHANGE_;
int const _eol_mode = (iLoWParam - IDM_LINEENDINGS_CRLF); // SC_EOL_CRLF(0), SC_EOL_CR(1), SC_EOL_LF(2)
SciCall_SetEOLMode(_eol_mode);
EditEnsureConsistentLineEndings(Globals.hwndEdit);
_OBSERVE_NOTIFY_CHANGE_;
EndWaitCursor();
UpdateToolbar();
UpdateStatusbar(false);
}
break;
case IDM_LINEENDINGS_SETDEFAULT:
SelectDefLineEndingDlg(hwnd, (LPARAM)&Settings.DefaultEOLMode);
break;
case IDM_EDIT_UNDO:
if (SciCall_CanUndo()) {
_IGNORE_NOTIFY_CHANGE_;
SciCall_Undo();
_OBSERVE_NOTIFY_CHANGE_;
}
break;
case IDM_EDIT_REDO:
if (SciCall_CanRedo()) {
_IGNORE_NOTIFY_CHANGE_;
SciCall_Redo();
_OBSERVE_NOTIFY_CHANGE_;
}
break;
case IDM_EDIT_CUT:
{
if (s_flagPasteBoard) {
s_bLastCopyFromMe = true;
}
if (SciCall_IsSelectionEmpty())
{
if (!Settings2.NoCutLineOnEmptySelection) {
_BEGIN_UNDO_ACTION_;
SciCall_MarkerDelete(Sci_GetCurrentLineNumber(), -1);
SciCall_LineCut();
_END_UNDO_ACTION_;
}
}
else {
_BEGIN_UNDO_ACTION_;
SciCall_Cut();
_END_UNDO_ACTION_;
}
}
break;
case IDM_EDIT_CUTLINE:
{
if (s_flagPasteBoard) {
s_bLastCopyFromMe = true;
}
_BEGIN_UNDO_ACTION_;
SciCall_MarkerDelete(Sci_GetCurrentLineNumber(), -1);
SciCall_LineCut();
_END_UNDO_ACTION_;
}
break;
case IDM_EDIT_COPY:
{
if (s_flagPasteBoard) {
s_bLastCopyFromMe = true;
}
if (SciCall_IsSelectionEmpty()) {
if (!HandleHotSpotURLClicked(SciCall_GetCurrentPos(), COPY_HYPERLINK) &&
!Settings2.NoCopyLineOnEmptySelection)
{
// VisualStudio behavior
SciCall_CopyAllowLine();
}
}
else {
SciCall_Copy();
}
}
break;
case IDM_EDIT_COPYLINE:
{
if (s_flagPasteBoard) {
s_bLastCopyFromMe = true;
}
DocPos const iSelLnStart = SciCall_PositionFromLine(SciCall_LineFromPosition(SciCall_GetSelectionStart()));
DocPos const iLineSelLast = SciCall_LineFromPosition(SciCall_GetSelectionEnd());
// copy incl last line-breaks
DocPos const iSelLnEnd = SciCall_PositionFromLine(iLineSelLast) + SciCall_LineLength(iLineSelLast);
if (s_flagPasteBoard) {
s_bLastCopyFromMe = true;
}
_BEGIN_UNDO_ACTION_;
SciCall_CopyRange(iSelLnStart, iSelLnEnd);
_END_UNDO_ACTION_;
}
break;
case IDM_EDIT_COPYALL:
{
if (s_flagPasteBoard) {
s_bLastCopyFromMe = true;
}
SciCall_CopyRange(0, Sci_GetDocEndPosition());
}
break;
case IDM_EDIT_COPYADD:
{
if (SciCall_IsSelectionEmpty()) {
break;
}
if (Sci_IsMultiOrRectangleSelection()) {
InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECTORMULTI);
break;
}
DocPos const posSelStart = SciCall_GetSelectionStart();
DocPos const posSelEnd = SciCall_GetSelectionEnd();
if (s_flagPasteBoard) {
s_bLastCopyFromMe = true;
}
EditCopyRangeAppend(Globals.hwndEdit, posSelStart, posSelEnd, true);
}
break;
case IDM_EDIT_PASTE:
if (SciCall_CanPaste()) {
if (s_flagPasteBoard) {
s_bLastCopyFromMe = true;
}
_BEGIN_UNDO_ACTION_;
SciCall_Paste();
_END_UNDO_ACTION_;
}
break;
case IDM_EDIT_SWAP:
if (!SciCall_IsSelectionEmpty() && SciCall_CanPaste()) {
if (s_flagPasteBoard) {
s_bLastCopyFromMe = true;
}
_BEGIN_UNDO_ACTION_;
EditSwapClipboard(Globals.hwndEdit, Settings.SkipUnicodeDetection);
_END_UNDO_ACTION_;
}
break;
case IDM_EDIT_CLEARCLIPBOARD:
EditClearClipboard(Globals.hwndEdit);
break;
case IDM_EDIT_SELECTALL:
SciCall_SelectAll();
break;
case IDM_EDIT_SELECTWORD:
{
if (SciCall_IsSelectionEmpty()) {
EditSelectWordAtPos(SciCall_GetCurrentPos(), false);
if (!SciCall_IsSelectionEmpty()) {
SciCall_ChooseCaretX();
break;
}
}
// selection not empty or no word found - select line
DocPos const iLineStart = SciCall_LineFromPosition(SciCall_GetSelectionStart());
DocPos const iLineEnd = SciCall_LineFromPosition(SciCall_GetSelectionEnd());
SciCall_SetSelection(SciCall_GetLineEndPosition(iLineEnd), SciCall_PositionFromLine(iLineStart));
SciCall_ChooseCaretX();
}
break;
case IDM_EDIT_SELECTALLMATCHES:
{
if (!Sci_IsMultiOrRectangleSelection()) {
if (!IsWindow(Globals.hwndDlgFindReplace)) {
if (SciCall_IsSelectionEmpty()) {
EditSelectWordAtPos(SciCall_GetCurrentPos(), false);
}
EditSelectionMultiSelectAll();
}
else {
SetFindReplaceData(); // s_FindReplaceData
EditSelectionMultiSelectAllEx(s_FindReplaceData);
}
}
}
break;
case IDM_EDIT_MOVELINEUP:
EditMoveUp(Globals.hwndEdit);
break;
case IDM_EDIT_MOVELINEDOWN:
EditMoveDown(Globals.hwndEdit);
break;
case IDM_EDIT_DUPLINEORSELECTION:
_BEGIN_UNDO_ACTION_;
if (SciCall_IsSelectionEmpty()) {
SciCall_LineDuplicate();
}
else {
SciCall_SelectionDuplicate();
}
_END_UNDO_ACTION_;
break;
case IDM_EDIT_LINETRANSPOSE:
_BEGIN_UNDO_ACTION_;
SciCall_LineTranspose();
_END_UNDO_ACTION_;
break;
case IDM_EDIT_DELETELINE:
{
_BEGIN_UNDO_ACTION_;
SciCall_MarkerDelete(Sci_GetCurrentLineNumber(), -1);
SciCall_LineDelete();
_END_UNDO_ACTION_;
}
break;
case IDM_EDIT_DELETELINELEFT:
{
_BEGIN_UNDO_ACTION_;
SciCall_DelLineLeft();
_END_UNDO_ACTION_;
}
break;
case IDM_EDIT_DELETELINERIGHT:
{
_BEGIN_UNDO_ACTION_;
SciCall_DelLineRight();
_END_UNDO_ACTION_;
}
break;
case IDM_EDIT_INDENT:
EditIndentBlock(Globals.hwndEdit, SCI_TAB, true, false);
break;
case IDM_EDIT_UNINDENT:
EditIndentBlock(Globals.hwndEdit, SCI_BACKTAB, true, false);
break;
case CMD_TAB:
EditIndentBlock(Globals.hwndEdit, SCI_TAB, false, false);
break;
case CMD_BACKTAB:
EditIndentBlock(Globals.hwndEdit, SCI_BACKTAB, false, false);
break;
case CMD_CTRLTAB:
SciCall_SetUseTabs(true);
SciCall_SetTabIndents(false);
EditIndentBlock(Globals.hwndEdit, SCI_TAB, false, false);
SciCall_SetTabIndents(Globals.fvCurFile.bTabIndents);
SciCall_SetUseTabs(!Globals.fvCurFile.bTabsAsSpaces);
break;
case CMD_CHECK_INDENTATION:
{
EditFileIOStatus status = INIT_FILEIO_STATUS;
EditIndentationStatistic(Globals.hwndEdit, &status);
if (ConsistentIndentationCheck(&status)) {
InfoBoxLng(MB_ICONINFORMATION, NULL, IDS_MUI_INDENT_CONSISTENT);
}
}
break;
case CMD_DELETEBACK:
{
///~_BEGIN_UNDO_ACTION_;
EditDeleteMarkerInSelection();
SciCall_DeleteBack();
///~_END_UNDO_ACTION_;
}
break;
case CMD_VK_INSERT:
SciCall_EditToggleOverType();
break;
case IDM_EDIT_ENCLOSESELECTION:
if (EditEncloseSelectionDlg(hwnd,s_wchPrefixSelection,s_wchAppendSelection)) {
EditEncloseSelection(s_wchPrefixSelection,s_wchAppendSelection);
}
break;
case IDM_EDIT_PADWITHSPACES:
EditPadWithSpaces(Globals.hwndEdit, false, false);
break;
case IDM_EDIT_STRIP1STCHAR:
EditStripFirstCharacter(Globals.hwndEdit);
break;
case IDM_EDIT_STRIPLASTCHAR:
EditStripLastCharacter(Globals.hwndEdit, false, false);
break;
case IDM_EDIT_TRIMLINES:
EditStripLastCharacter(Globals.hwndEdit, false, true);
break;
case IDM_EDIT_COMPRESS_BLANKS:
EditCompressBlanks(Globals.hwndEdit);
break;
case IDM_EDIT_MERGEBLANKLINES:
EditRemoveBlankLines(Globals.hwndEdit, true, true);
break;
case IDM_EDIT_MERGEEMPTYLINES:
EditRemoveBlankLines(Globals.hwndEdit, true, false);
break;
case IDM_EDIT_REMOVEBLANKLINES:
EditRemoveBlankLines(Globals.hwndEdit, false, true);
break;
case IDM_EDIT_REMOVEEMPTYLINES:
EditRemoveBlankLines(Globals.hwndEdit, false, false);
break;
case IDM_EDIT_REMOVEDUPLICATELINES:
EditRemoveDuplicateLines(Globals.hwndEdit, false);
break;
case IDM_EDIT_CLEAR_MARKER:
EditBookmarkToggle(Globals.hwndEdit, Sci_GetCurrentLineNumber(), 0);
break;
case IDM_EDIT_CUT_MARKED:
EditFocusMarkedLinesCmd(Globals.hwndEdit, true, true);
break;
case IDM_EDIT_COPY_MARKED:
EditFocusMarkedLinesCmd(Globals.hwndEdit, true, false);
break;
case IDM_EDIT_DELETE_MARKED:
EditFocusMarkedLinesCmd(Globals.hwndEdit, false, true);
break;
case IDM_EDIT_MODIFYLINES:
if (EditModifyLinesDlg(hwnd,s_wchPrefixLines,s_wchAppendLines)) {
EditModifyLines(s_wchPrefixLines,s_wchAppendLines);
}
break;
case IDM_EDIT_ALIGN:
if (EditAlignDlg(hwnd,&s_iAlignMode)) {
EditAlignText(s_iAlignMode);
}
break;
case IDM_EDIT_SORTLINES:
if (EditSortDlg(hwnd,&s_iSortOptions)) {
EditSortLines(Globals.hwndEdit,s_iSortOptions);
}
break;
case IDM_EDIT_COLUMNWRAP:
{
UINT uWrpCol = Globals.iWrapCol;
if (ColumnWrapDlg(hwnd, IDD_MUI_COLUMNWRAP, &uWrpCol))
{
Globals.iWrapCol = clampi((int)uWrpCol, SciCall_GetTabWidth(), LONG_LINES_MARKER_LIMIT);
EditWrapToColumn(Globals.iWrapCol);
}
}
break;
case IDM_EDIT_SPLITLINES:
EditSplitLines(Globals.hwndEdit);
break;
case IDM_EDIT_JOINLINES:
EditJoinLinesEx(false, true);
break;
case IDM_EDIT_JOINLN_NOSP:
EditJoinLinesEx(false, false);
break;
case IDM_EDIT_JOINLINES_PARA:
EditJoinLinesEx(true, true);
break;
case IDM_EDIT_CONVERTUPPERCASE:
{
_BEGIN_UNDO_ACTION_;
SciCall_UpperCase();
_END_UNDO_ACTION_;
}
break;
case IDM_EDIT_CONVERTLOWERCASE:
{
_BEGIN_UNDO_ACTION_;
SciCall_LowerCase();
_END_UNDO_ACTION_;
}
break;
case IDM_EDIT_INVERTCASE:
EditInvertCase(Globals.hwndEdit);
break;
case IDM_EDIT_TITLECASE:
EditTitleCase(Globals.hwndEdit);
break;
case IDM_EDIT_SENTENCECASE:
EditSentenceCase(Globals.hwndEdit);
break;
case IDM_EDIT_CONVERTTABS:
EditTabsToSpaces(Globals.fvCurFile.iTabWidth, false);
break;
case IDM_EDIT_CONVERTSPACES:
EditSpacesToTabs(Globals.fvCurFile.iTabWidth, false);
break;
case IDM_EDIT_CONVERTTABS2:
EditTabsToSpaces(Globals.fvCurFile.iTabWidth, true);
break;
case IDM_EDIT_CONVERTSPACES2:
EditSpacesToTabs(Globals.fvCurFile.iTabWidth, true);
break;
case IDM_EDIT_INSERT_TAG:
{
WCHAR wszOpen[256] = { L'\0' };
WCHAR wszClose[256] = { L'\0' };
UINT repeat = 1;
if (EditInsertTagDlg(hwnd, wszOpen, wszClose, &repeat)) {
while (repeat > 0) {
EditEncloseSelection(wszOpen, wszClose);
--repeat;
}
}
}
break;
case IDM_EDIT_INSERT_ENCODING:
{
cpi_enc_t const iEncoding = Encoding_GetCurrent();
char chEncStrg[128] = { '\0' };
WideCharToMultiByteEx(Encoding_SciCP, 0, Encoding_GetLabel(iEncoding), -1, chEncStrg, COUNTOF(chEncStrg), NULL, NULL);
EditReplaceSelection(chEncStrg, false);
}
break;
case IDM_EDIT_INSERT_SHORTDATE:
case IDM_EDIT_INSERT_LONGDATE:
EditInsertDateTimeStrg((iLoWParam == IDM_EDIT_INSERT_SHORTDATE), false);
break;
case IDM_EDIT_INSERT_FILENAME:
case IDM_EDIT_INSERT_DIRNAME:
case IDM_EDIT_INSERT_PATHNAME:
{
WCHAR *pszInsert;
WCHAR tchUntitled[32];
WCHAR szDisplayName[MAX_PATH];
if (StrIsNotEmpty(Globals.CurrentFile)) {
if (iLoWParam == IDM_EDIT_INSERT_FILENAME)
{
PathGetDisplayName(szDisplayName, COUNTOF(szDisplayName), Globals.CurrentFile);
pszInsert = szDisplayName;
}
else if (iLoWParam == IDM_EDIT_INSERT_DIRNAME)
{
StringCchCopy(szDisplayName, COUNTOF(szDisplayName), Globals.CurrentFile);
PathCchRemoveFileSpec(szDisplayName, COUNTOF(szDisplayName));
pszInsert = szDisplayName;
}
else {
pszInsert = Globals.CurrentFile;
}
}
else {
GetLngString(IDS_MUI_UNTITLED, tchUntitled, COUNTOF(tchUntitled));
pszInsert = tchUntitled;
}
SetClipboardTextW(hwnd, pszInsert, StringCchLen(pszInsert, 0));
}
break;
case IDM_EDIT_INSERT_GUID:
{
GUID guid;
if (SUCCEEDED(CoCreateGuid(&guid))) {
if (StringFromGUID2(&guid, tchMaxPathBuffer,COUNTOF(tchMaxPathBuffer))) {
StrTrim(tchMaxPathBuffer, L"{}");
//char chMaxPathBuffer[MAX_PATH] = { '\0' };
//if (WideCharToMultiByteEx(Encoding_SciCP, 0, tchMaxPathBuffer, -1, chMaxPathBuffer, COUNTOF(chMaxPathBuffer), NULL, NULL)) {
// EditReplaceSelection(chMaxPathBuffer, false);
//}
SetClipboardTextW(hwnd, tchMaxPathBuffer, StringCchLen(tchMaxPathBuffer, 0));
}
}
}
break;
case IDM_EDIT_LINECOMMENT:
{
switch (SciCall_GetLexer()) {
case SCLEX_CPP:
case SCLEX_D:
case SCLEX_HTML:
case SCLEX_PASCAL:
case SCLEX_RUST:
case SCLEX_XML:
EditToggleLineComments(Globals.hwndEdit, L"//", false);
break;
case SCLEX_VB:
case SCLEX_VBSCRIPT:
EditToggleLineComments(Globals.hwndEdit, L"'", false);
break;
case SCLEX_AVS:
case SCLEX_BASH:
case SCLEX_CMAKE:
case SCLEX_COFFEESCRIPT:
case SCLEX_CONF:
case SCLEX_MAKEFILE:
case SCLEX_NIM:
case SCLEX_PERL:
case SCLEX_POWERSHELL:
case SCLEX_PYTHON:
case SCLEX_R:
case SCLEX_RUBY:
case SCLEX_TCL:
case SCLEX_TOML:
case SCLEX_YAML:
EditToggleLineComments(Globals.hwndEdit, L"#", true);
break;
case SCLEX_AHKL:
case SCLEX_ASM:
case SCLEX_AU3:
case SCLEX_INNOSETUP:
case SCLEX_NSIS: // # could also be used instead
case SCLEX_PROPERTIES:
case SCLEX_REGISTRY:
EditToggleLineComments(Globals.hwndEdit, L";", true);
break;
case SCLEX_LUA:
case SCLEX_SQL:
case SCLEX_VHDL:
EditToggleLineComments(Globals.hwndEdit, L"--", true);
break;
case SCLEX_BATCH:
EditToggleLineComments(Globals.hwndEdit, L"rem ", true);
break;
case SCLEX_LATEX:
case SCLEX_MATLAB:
EditToggleLineComments(Globals.hwndEdit, L"%", true);
break;
// ------------------
case SCLEX_NULL:
case SCLEX_CSS:
case SCLEX_DIFF:
case SCLEX_JSON:
case SCLEX_MARKDOWN:
default:
// do nothing
break;
}
}
break;
case IDM_EDIT_STREAMCOMMENT:
{
switch (SciCall_GetLexer()) {
case SCLEX_D:
//~EditEncloseSelection(Globals.hwndEdit, L"/+", L"+/");
//~break;
case SCLEX_AVS:
case SCLEX_CPP:
case SCLEX_CSS:
case SCLEX_HTML:
case SCLEX_NSIS:
case SCLEX_RUST:
case SCLEX_SQL:
case SCLEX_VHDL:
case SCLEX_XML:
EditEncloseSelection(L"/*", L"*/");
break;
case SCLEX_INNOSETUP:
case SCLEX_PASCAL:
EditEncloseSelection(L"{", L"}");
break;
case SCLEX_LUA:
EditEncloseSelection(L"--[[", L"]]");
break;
case SCLEX_COFFEESCRIPT:
EditEncloseSelection(L"###", L"###");
break;
case SCLEX_MATLAB:
EditEncloseSelection(L"%{", L"%}");
break;
// ------------------
case SCLEX_NULL:
case SCLEX_AHKL:
case SCLEX_ASM:
case SCLEX_AU3:
case SCLEX_BASH:
case SCLEX_BATCH:
case SCLEX_CMAKE:
case SCLEX_CONF:
case SCLEX_DIFF:
case SCLEX_JSON:
case SCLEX_LATEX:
case SCLEX_MAKEFILE:
case SCLEX_MARKDOWN:
case SCLEX_NIM:
case SCLEX_PERL:
case SCLEX_POWERSHELL:
case SCLEX_PROPERTIES:
case SCLEX_PYTHON:
case SCLEX_R:
case SCLEX_REGISTRY:
case SCLEX_RUBY:
case SCLEX_TCL:
case SCLEX_TOML:
case SCLEX_VB:
case SCLEX_VBSCRIPT:
case SCLEX_YAML:
default:
// do nothing
break;
}
}
break;
case IDM_EDIT_URLENCODE:
{
EditURLEncode(Globals.hwndEdit);
}
break;
case IDM_EDIT_URLDECODE:
{
EditURLDecode(Globals.hwndEdit);
}
break;
case IDM_EDIT_ESCAPECCHARS:
{
EditEscapeCChars(Globals.hwndEdit);
}
break;
case IDM_EDIT_UNESCAPECCHARS:
{
EditUnescapeCChars(Globals.hwndEdit);
}
break;
case IDM_EDIT_CHAR2HEX:
EditChar2Hex(Globals.hwndEdit);
break;
case IDM_EDIT_HEX2CHAR:
EditHex2Char(Globals.hwndEdit);
break;
case IDM_EDIT_FINDMATCHINGBRACE:
EditFindMatchingBrace(Globals.hwndEdit);
break;
case IDM_EDIT_SELTOMATCHINGBRACE:
EditSelectToMatchingBrace(Globals.hwndEdit);
break;
// Main Bookmark Functions
case BME_EDIT_BOOKMARKNEXT:
EditBookmarkNext(Globals.hwndEdit, Sci_GetCurrentLineNumber());
break;
case BME_EDIT_BOOKMARKPREV:
EditBookmarkPrevious(Globals.hwndEdit, Sci_GetCurrentLineNumber());
break;
case BME_EDIT_BOOKMARKTOGGLE:
EditBookmarkToggle(Globals.hwndEdit, Sci_GetCurrentLineNumber(), 0);
break;
case BME_EDIT_BOOKMARKCLEAR:
EditClearAllBookMarks(Globals.hwndEdit);
break;
case IDM_EDIT_FIND:
{
SetFindReplaceData(); // s_FindReplaceData
if (!IsWindow(Globals.hwndDlgFindReplace)) {
Globals.bFindReplCopySelOrClip = true;
/*Globals.hwndDlgFindReplace =*/ EditFindReplaceDlg(Globals.hwndEdit, &s_FindReplaceData, false);
}
else {
Globals.bFindReplCopySelOrClip = (GetForegroundWindow() != Globals.hwndDlgFindReplace);
if (GetDlgItem(Globals.hwndDlgFindReplace, IDC_REPLACE)) {
SendWMCommand(Globals.hwndDlgFindReplace, IDMSG_SWITCHTOFIND);
DestroyWindow(Globals.hwndDlgFindReplace);
/*Globals.hwndDlgFindReplace =*/ EditFindReplaceDlg(Globals.hwndEdit, &s_FindReplaceData, false);
}
else {
SetForegroundWindow(Globals.hwndDlgFindReplace);
PostMessage(Globals.hwndDlgFindReplace, WM_NEXTDLGCTL, (WPARAM)(GetDlgItem(Globals.hwndDlgFindReplace, IDC_FINDTEXT)), 1);
}
}
}
break;
case IDM_EDIT_REPLACE:
{
SetFindReplaceData(); // s_FindReplaceData
if (!IsWindow(Globals.hwndDlgFindReplace)) {
Globals.bFindReplCopySelOrClip = true;
/*Globals.hwndDlgFindReplace =*/ EditFindReplaceDlg(Globals.hwndEdit, &s_FindReplaceData, true);
}
else {
Globals.bFindReplCopySelOrClip = (GetForegroundWindow() != Globals.hwndDlgFindReplace);
if (!GetDlgItem(Globals.hwndDlgFindReplace, IDC_REPLACE)) {
SendWMCommand(Globals.hwndDlgFindReplace, IDMSG_SWITCHTOREPLACE);
DestroyWindow(Globals.hwndDlgFindReplace);
/*Globals.hwndDlgFindReplace =*/ EditFindReplaceDlg(Globals.hwndEdit, &s_FindReplaceData, true);
}
else {
SetForegroundWindow(Globals.hwndDlgFindReplace);
PostMessage(Globals.hwndDlgFindReplace, WM_NEXTDLGCTL, (WPARAM)(GetDlgItem(Globals.hwndDlgFindReplace, IDC_FINDTEXT)), 1);
}
}
}
break;
case IDM_EDIT_FINDNEXT:
case IDM_EDIT_FINDPREV:
case IDM_EDIT_REPLACENEXT:
case IDM_EDIT_SELTONEXT:
case IDM_EDIT_SELTOPREV:
if (Sci_IsDocEmpty()) { break; }
if (Sci_IsMultiSelection()) {
switch (iLoWParam) {
case IDM_EDIT_SELTONEXT:
{
SciCall_RotateSelection();
EditEnsureSelectionVisible();
}
break;
case IDM_EDIT_SELTOPREV:
{
DocPosU const iMain = SciCall_GetMainSelection();
if (iMain > 0) {
SciCall_SetMainSelection(iMain - 1);
} else {
DocPosU const iNewMain = SciCall_GetSelections() - 1;
SciCall_SetMainSelection(iNewMain);
}
EditEnsureSelectionVisible();
}
break;
default: break;
}
break; // done
}
SetFindReplaceData(); // s_FindReplaceData
if (IsFindPatternEmpty() && !StrIsEmptyA(s_FindReplaceData.szFind))
{
if (iLoWParam != IDM_EDIT_REPLACENEXT) {
SendWMCommand(hwnd, IDM_EDIT_FIND);
}
else {
SendWMCommand(hwnd, IDM_EDIT_REPLACE);
}
}
else {
switch (iLoWParam) {
case IDM_EDIT_FINDNEXT:
EditFindNext(Globals.hwndEdit,&s_FindReplaceData,false,false);
break;
case IDM_EDIT_FINDPREV:
EditFindPrev(Globals.hwndEdit,&s_FindReplaceData,false,false);
break;
case IDM_EDIT_REPLACENEXT:
if (Globals.bReplaceInitialized) {
EditReplace(Globals.hwndEdit, &s_FindReplaceData);
}
else {
SendWMCommand(hwnd, IDM_EDIT_REPLACE);
}
break;
case IDM_EDIT_SELTONEXT:
if (IsFindPatternEmpty()) {
if (!SetCurrentSelAsFindReplaceData()) {
break;
}
}
EditFindNext(Globals.hwndEdit,&s_FindReplaceData,true,false);
break;
case IDM_EDIT_SELTOPREV:
if (IsFindPatternEmpty()) {
if (!SetCurrentSelAsFindReplaceData()) {
break;
}
}
EditFindPrev(Globals.hwndEdit,&s_FindReplaceData,true,false);
break;
}
}
break;
case CMD_FINDNEXTSEL:
case CMD_FINDPREVSEL:
case IDM_EDIT_SAVEFIND:
{
if (SetCurrentSelAsFindReplaceData()) {
MRU_Add(Globals.pMRUfind, GetFindPattern(), 0, -1, -1, NULL);
s_FindReplaceData.fuFlags &= (~(SCFIND_REGEXP | SCFIND_POSIX));
s_FindReplaceData.bTransformBS = false;
switch (iLoWParam) {
case IDM_EDIT_SAVEFIND:
break;
case CMD_FINDNEXTSEL:
EditFindNext(Globals.hwndEdit, &s_FindReplaceData, false, false);
break;
case CMD_FINDPREVSEL:
EditFindPrev(Globals.hwndEdit, &s_FindReplaceData, false, false);
break;
}
}
}
break;
case IDM_EDIT_COMPLETEWORD:
EditAutoCompleteWord(Globals.hwndEdit, true);
break;
case IDM_EDIT_GOTOLINE:
EditLinenumDlg(Globals.hwndEdit);
break;
case IDM_VIEW_SCHEME:
Style_SelectLexerDlg(Globals.hwndEdit);
break;
case IDM_VIEW_USE2NDDEFAULT:
Style_ToggleUse2ndDefault(Globals.hwndEdit);
break;
case IDM_VIEW_SCHEMECONFIG:
if (!IsWindow(Globals.hwndDlgCustomizeSchemes)) {
Globals.hwndDlgCustomizeSchemes = Style_CustomizeSchemesDlg(Globals.hwndEdit);
}
else {
SetForegroundWindow(Globals.hwndDlgCustomizeSchemes);
}
PostWMCommand(Globals.hwndDlgCustomizeSchemes, IDC_SETCURLEXERTV);
UpdateMarginWidth();
UpdateUI();
break;
case IDM_VIEW_FONT:
if (!IsWindow(Globals.hwndDlgCustomizeSchemes)) {
Style_SetDefaultFont(Globals.hwndEdit, true);
}
UpdateMarginWidth();
UpdateUI();
break;
case IDM_VIEW_CURRENTSCHEME:
if (!IsWindow(Globals.hwndDlgCustomizeSchemes)) {
Style_SetDefaultFont(Globals.hwndEdit, false);
}
UpdateMarginWidth();
UpdateUI();
break;
case IDM_VIEW_WORDWRAP:
Settings.WordWrap = !Settings.WordWrap;
Globals.fvCurFile.bWordWrap = Settings.WordWrap;
_SetWrapIndentMode(Globals.hwndEdit);
EditEnsureSelectionVisible();
UpdateToolbar();
break;
case IDM_VIEW_WORDWRAPSETTINGS:
if (WordWrapSettingsDlg(hwnd,IDD_MUI_WORDWRAP, &Settings.WordWrapIndent)) {
_SetWrapIndentMode(Globals.hwndEdit);
_SetWrapVisualFlags(Globals.hwndEdit);
UpdateToolbar();
}
break;
case IDM_VIEW_WORDWRAPSYMBOLS:
Settings.ShowWordWrapSymbols = !Settings.ShowWordWrapSymbols;
_SetWrapVisualFlags(Globals.hwndEdit);
UpdateToolbar();
break;
case IDM_VIEW_LONGLINEMARKER:
{
Settings.MarkLongLines = !Settings.MarkLongLines;
size_t cnt = 0;
int edgeColumns[SMALL_BUFFER] = { 0 };
if (Settings.MarkLongLines) {
cnt = ReadVectorFromString(Globals.fvCurFile.wchMultiEdgeLines, edgeColumns, COUNTOF(edgeColumns), 0, LONG_LINES_MARKER_LIMIT, 0, true);
}
Style_SetMultiEdgeLine(edgeColumns, cnt);
}
break;
case IDM_VIEW_LONGLINESETTINGS:
{
int _iLongLinesLimit = Defaults.LongLinesLimit;
if (LongLineSettingsDlg(hwnd, IDD_MUI_LONGLINES, Globals.fvCurFile.wchMultiEdgeLines)) {
int edgeColumns[SMALL_BUFFER];
size_t const cnt = ReadVectorFromString(Globals.fvCurFile.wchMultiEdgeLines, edgeColumns, COUNTOF(edgeColumns), 0, LONG_LINES_MARKER_LIMIT, 0, true);
if (cnt == 0) {
Settings.MarkLongLines = false;
}
else if (cnt == 1) {
_iLongLinesLimit = edgeColumns[0];
Settings.MarkLongLines = true;
//~Settings.LongLineMode = EDGE_LINE|EDGE_BACKGROUND; // set by Dlg
}
else {
_iLongLinesLimit = edgeColumns[cnt - 1];
Settings.MarkLongLines = true;
Settings.LongLineMode = EDGE_MULTILINE;
}
Globals.iWrapCol = _iLongLinesLimit;
Settings.LongLinesLimit = _iLongLinesLimit;
// new multi-edge lines setting
WCHAR col[32];
Settings.MultiEdgeLines[0] = L'\0';
for (size_t i = 0; i < cnt; ++i) {
StringCchPrintf(col, COUNTOF(col), ((i == 0) ? L"%i" : L" %i"), edgeColumns[i]);
StringCchCat(Settings.MultiEdgeLines, COUNTOF(Settings.MultiEdgeLines), col);
}
// make current too
StringCchCopy(Globals.fvCurFile.wchMultiEdgeLines, COUNTOF(Globals.fvCurFile.wchMultiEdgeLines), Settings.MultiEdgeLines);
Style_SetMultiEdgeLine(edgeColumns, cnt);
}
}
break;
case IDM_VIEW_TABSASSPACES:
{
Settings.TabsAsSpaces = !Settings.TabsAsSpaces;
Globals.fvCurFile.bTabsAsSpaces = Settings.TabsAsSpaces;
SciCall_SetUseTabs(!Globals.fvCurFile.bTabsAsSpaces);
}
break;
case IDM_VIEW_TABSETTINGS:
if (TabSettingsDlg(hwnd,IDD_MUI_TABSETTINGS,NULL))
{
SciCall_SetUseTabs(!Globals.fvCurFile.bTabsAsSpaces);
SciCall_SetTabIndents(Globals.fvCurFile.bTabIndents);
SciCall_SetBackSpaceUnIndents(Settings.BackspaceUnindents);
SciCall_SetTabWidth(Globals.fvCurFile.iTabWidth);
SciCall_SetIndent(Globals.fvCurFile.iIndentWidth);
if (SendMessage(Globals.hwndEdit, SCI_GETWRAPINDENTMODE, 0, 0) == SC_WRAPINDENT_FIXED) {
_SetWrapStartIndent(Globals.hwndEdit);
}
}
break;
case IDM_VIEW_SHOWINDENTGUIDES:
Settings.ShowIndentGuides = !Settings.ShowIndentGuides;
Style_SetIndentGuides(Globals.hwndEdit,Settings.ShowIndentGuides);
break;
case IDM_VIEW_AUTOINDENTTEXT:
Settings.AutoIndent = !Settings.AutoIndent;
break;
case IDM_VIEW_LINENUMBERS:
Settings.ShowLineNumbers = !Settings.ShowLineNumbers;
UpdateMarginWidth();
break;
case IDM_VIEW_BOOKMARK_MARGIN:
Settings.ShowBookmarkMargin = !Settings.ShowBookmarkMargin;
UpdateMarginWidth();
break;
case IDM_VIEW_AUTOCOMPLETEWORDS:
Settings.AutoCompleteWords = !Settings.AutoCompleteWords;
SciCall_AutoCCancel();
break;
case IDM_VIEW_AUTOCLEXKEYWORDS:
Settings.AutoCLexerKeyWords = !Settings.AutoCLexerKeyWords;
SciCall_AutoCCancel();
break;
case IDM_VIEW_ACCELWORDNAV:
Settings.AccelWordNavigation = !Settings.AccelWordNavigation;
EditSetAccelWordNav(Globals.hwndEdit,Settings.AccelWordNavigation);
MarkAllOccurrences(Settings2.UpdateDelayMarkAllOccurrences, true);
break;
case IDM_VIEW_EDIT_LINECOMMENT:
Settings.EditLineCommentBlock = !Settings.EditLineCommentBlock;
break;
case IDM_VIEW_MARKOCCUR_ONOFF:
Settings.MarkOccurrences = !Settings.MarkOccurrences;
if (!Settings.MarkOccurrences && FocusedView.HideNonMatchedLines) {
EditToggleView(Globals.hwndEdit);
}
EnableCmd(GetMenu(hwnd), IDM_VIEW_TOGGLE_VIEW, IsFocusedViewAllowed());
if (IsMarkOccurrencesEnabled()) {
MarkAllOccurrences(0, true);
}
else {
EditClearAllOccurrenceMarkers(Globals.hwndEdit);
Globals.iMarkOccurrencesCount = 0;
}
break;
case IDM_VIEW_MARKOCCUR_BOOKMARKS:
Settings.MarkOccurrencesBookmark = !Settings.MarkOccurrencesBookmark;
SciCall_MarkerDefine(MARKER_NP3_OCCURRENCE, Settings.MarkOccurrencesBookmark ? SC_MARK_ARROWS : SC_MARK_BACKGROUND);
break;
case IDM_VIEW_MARKOCCUR_VISIBLE:
Settings.MarkOccurrencesMatchVisible = !Settings.MarkOccurrencesMatchVisible;
MarkAllOccurrences(0, true);
break;
case IDM_VIEW_TOGGLE_VIEW:
if (FocusedView.HideNonMatchedLines) {
EditToggleView(Globals.hwndEdit);
MarkAllOccurrences(0, true);
}
else {
EditToggleView(Globals.hwndEdit);
}
CheckCmd(GetMenu(hwnd), IDM_VIEW_TOGGLE_VIEW, FocusedView.HideNonMatchedLines);
break;
case IDM_VIEW_FV_FOLD:
case IDM_VIEW_FV_BOOKMARK:
case IDM_VIEW_FV_HIGHLIGHT:
case IDM_VIEW_FV_BKMRKFOLD:
case IDM_VIEW_FV_HIGHLGFOLD:
{
int newSetting = Settings.FocusViewMarkerMode;
switch (iLoWParam) {
case IDM_VIEW_FV_FOLD:
newSetting = (FVMM_FOLD);
break;
case IDM_VIEW_FV_BOOKMARK:
newSetting = (FVMM_MARGIN);
break;
case IDM_VIEW_FV_HIGHLIGHT:
newSetting = (FVMM_LN_BACKGR);
break;
case IDM_VIEW_FV_BKMRKFOLD:
newSetting = (FVMM_MARGIN | FVMM_FOLD);
break;
case IDM_VIEW_FV_HIGHLGFOLD:
newSetting = (FVMM_LN_BACKGR | FVMM_FOLD);
break;
}
if (newSetting != Settings.FocusViewMarkerMode)
{
if (FocusedView.HideNonMatchedLines) {
if ((newSetting & FVMM_FOLD) != (Settings.FocusViewMarkerMode & FVMM_FOLD)) {
EditToggleView(Globals.hwndEdit);
}
}
for (int m = MARKER_NP3_1; m < MARKER_NP3_BOOKMARK; ++m) {
SciCall_MarkerDefine(m, (newSetting & FVMM_LN_BACKGR) ? SC_MARK_BACKGROUND : SC_MARK_BOOKMARK);
}
Settings.FocusViewMarkerMode = newSetting;
}
} break;
case IDM_VIEW_MARKOCCUR_CASE:
Settings.MarkOccurrencesMatchCase = !Settings.MarkOccurrencesMatchCase;
MarkAllOccurrences(Settings2.UpdateDelayMarkAllOccurrences, true);
break;
case IDM_VIEW_MARKOCCUR_WNONE:
Settings.MarkOccurrencesMatchWholeWords = false;
Settings.MarkOccurrencesCurrentWord = false;
MarkAllOccurrences(Settings2.UpdateDelayMarkAllOccurrences, true);
break;
case IDM_VIEW_MARKOCCUR_WORD:
Settings.MarkOccurrencesMatchWholeWords = true;
Settings.MarkOccurrencesCurrentWord = false;
MarkAllOccurrences(Settings2.UpdateDelayMarkAllOccurrences, true);
break;
case IDM_VIEW_MARKOCCUR_CURRENT:
Settings.MarkOccurrencesMatchWholeWords = false;
Settings.MarkOccurrencesCurrentWord = true;
MarkAllOccurrences(Settings2.UpdateDelayMarkAllOccurrences, true);
break;
case IDM_VIEW_FOLDING:
Settings.ShowCodeFolding = !Settings.ShowCodeFolding;
FocusedView.ShowCodeFolding = Settings.ShowCodeFolding;
Style_SetFolding(Globals.hwndEdit, FocusedView.ShowCodeFolding);
if (!FocusedView.ShowCodeFolding) { EditToggleFolds(EXPAND, true); }
break;
case IDM_VIEW_TOGGLEFOLDS:
EditToggleFolds(SNIFF, SciCall_IsSelectionEmpty());
break;
case IDM_VIEW_TOGGLE_CURRENT_FOLD:
EditToggleFolds(SNIFF, false);
break;
case IDM_VIEW_SHOWBLANKS:
Settings.ViewWhiteSpace = !Settings.ViewWhiteSpace;
SciCall_SetViewWS(Settings.ViewWhiteSpace ? SCWS_VISIBLEALWAYS : SCWS_INVISIBLE);
break;
case IDM_VIEW_SHOWEOLS:
Settings.ViewEOLs = !Settings.ViewEOLs;
SciCall_SetViewEOL(Settings.ViewEOLs);
break;
case IDM_VIEW_MATCHBRACES:
Settings.MatchBraces = !Settings.MatchBraces;
if (Settings.MatchBraces)
EditMatchBrace(Globals.hwndEdit);
else
SciCall_BraceHighLight(INVALID_POSITION, INVALID_POSITION);
break;
case IDM_VIEW_AUTOCLOSETAGS:
Settings.AutoCloseTags = !Settings.AutoCloseTags;
break;
case IDM_VIEW_TOGGLE_HILITCURLN:
case IDM_VIEW_HILITCURLN_NONE:
case IDM_VIEW_HILITCURLN_BACK:
case IDM_VIEW_HILITCURLN_FRAME:
{
int const set = iLoWParam - IDM_VIEW_HILITCURLN_NONE;
Settings.HighlightCurrentLine = (set >= 0) ? set : ((Settings.HighlightCurrentLine + 1) % 3);
Style_HighlightCurrentLine(Globals.hwndEdit, Settings.HighlightCurrentLine);
}
break;
case IDM_VIEW_HYPERLINKHOTSPOTS:
Settings.HyperlinkHotspot = !Settings.HyperlinkHotspot;
EditUpdateVisibleIndicators();
break;
case IDM_VIEW_SHOW_HYPLNK_CALLTIP:
Settings.ShowHypLnkToolTip = !Settings.ShowHypLnkToolTip;
UpdateMouseDWellTime();
break;
case IDM_VIEW_COLORDEFHOTSPOTS:
case IDM_VIEW_COLOR_ARGB:
case IDM_VIEW_COLOR_RGBA:
case IDM_VIEW_COLOR_BGRA:
{
Settings.ColorDefHotspot = iLoWParam - IDM_VIEW_COLORDEFHOTSPOTS;
EditUpdateVisibleIndicators();
UpdateMouseDWellTime();
}
break;
case IDM_VIEW_UNICODE_POINTS:
Settings.HighlightUnicodePoints = !Settings.HighlightUnicodePoints;
EditUpdateVisibleIndicators();
UpdateMouseDWellTime();
break;
case IDM_VIEW_ZOOMIN:
{
SciCall_ZoomIn();
ShowZoomCallTip();
}
break;
case IDM_VIEW_ZOOMOUT:
{
SciCall_ZoomOut();
ShowZoomCallTip();
}
break;
case IDM_VIEW_RESETZOOM:
{
SciCall_SetZoom(100);
ShowZoomCallTip();
}
break;
case IDM_VIEW_CHASING_DOCTAIL:
{
FileWatching.MonitoringLog = !FileWatching.MonitoringLog; // toggle
SciCall_SetReadOnly(FileWatching.MonitoringLog);
if (FileWatching.MonitoringLog)
{
SetForegroundWindow(hwnd);
SendWMCommand(hwnd, IDM_FILE_REVERT);
FileWatching.flagChangeNotify = s_flagChangeNotify;
s_flagChangeNotify = FWM_AUTORELOAD;
FileWatching.FileWatchingMode = FWM_AUTORELOAD;
FileWatching.ResetFileWatching = true;
FileWatching.FileCheckInverval = 250UL;
FileWatching.AutoReloadTimeout = 250UL;
UndoRedoRecordingStop();
SciCall_SetEndAtLastLine(false);
}
else {
s_flagChangeNotify = FileWatching.flagChangeNotify;
FileWatching.FileWatchingMode = Settings.FileWatchingMode;
FileWatching.ResetFileWatching = Settings.ResetFileWatching;
FileWatching.FileCheckInverval = Settings2.FileCheckInverval;
FileWatching.AutoReloadTimeout = Settings2.AutoReloadTimeout;
UndoRedoRecordingStart();
SciCall_SetEndAtLastLine(!Settings.ScrollPastEOF);
}
EditEnsureSelectionVisible();
InstallFileWatching(Globals.CurrentFile); // force
CheckCmd(GetMenu(Globals.hwndMain), IDM_VIEW_CHASING_DOCTAIL, FileWatching.MonitoringLog);
}
break;
case IDM_VIEW_SCROLLPASTEOF:
Settings.ScrollPastEOF = !Settings.ScrollPastEOF;
SciCall_SetEndAtLastLine(!Settings.ScrollPastEOF);
break;
case IDM_VIEW_MENUBAR:
Settings.ShowMenubar = !Settings.ShowMenubar;
SetMenu(hwnd, (Settings.ShowMenubar ? Globals.hMainMenu : NULL));
DrawMenuBar(Globals.hwndMain);
break;
case IDM_VIEW_TOOLBAR:
Settings.ShowToolbar = !Settings.ShowToolbar;
ShowWindow(Globals.hwndRebar, (Settings.ShowToolbar ? SW_SHOW : SW_HIDE));
SendWMSize(hwnd, NULL);
break;
case IDM_VIEW_TOGGLETB:
Settings.ToolBarTheme = (Settings.ToolBarTheme + 1) % 3;
SendMessage(hwnd, WM_THEMECHANGED, 0, 0);
break;
case IDM_VIEW_CUSTOMIZETB:
SendMessage(Globals.hwndToolbar,TB_CUSTOMIZE,0,0);
break;
case IDM_VIEW_LOADTHEMETB:
if (SelectExternalToolBar(hwnd)) {
SendMessage(hwnd, WM_THEMECHANGED, 0, 0);
}
break;
case IDM_VIEW_DPISCALETB:
Settings.DpiScaleToolBar = !Settings.DpiScaleToolBar;
SendMessage(hwnd, WM_THEMECHANGED, 0, 0);
break;
case IDM_VIEW_STATUSBAR:
Settings.ShowStatusbar = !Settings.ShowStatusbar;
ShowWindow(Globals.hwndStatus, (Settings.ShowStatusbar ? SW_SHOW : SW_HIDE));
UpdateStatusbar(Settings.ShowStatusbar);
SendWMSize(hwnd, NULL);
break;
case IDM_VIEW_STICKYWINPOS:
if (IsCmdEnabled(hwnd, IDM_VIEW_STICKYWINPOS)) {
Flags.bStickyWindowPosition = !Flags.bStickyWindowPosition; // toggle
if (Flags.bStickyWindowPosition) { InfoBoxLng(MB_OK, L"MsgStickyWinPos", IDS_MUI_STICKYWINPOS); }
bool bOpendByMe = false;
OpenSettingsFile(&bOpendByMe);
SaveWindowPositionSettings(!Flags.bStickyWindowPosition);
if (Flags.bStickyWindowPosition != DefaultFlags.bStickyWindowPosition)
{
IniSectionSetBool(Constants.Settings2_Section, L"StickyWindowPosition", Flags.bStickyWindowPosition);
}
else {
IniSectionDelete(Constants.Settings2_Section, L"StickyWindowPosition", false);
}
CloseSettingsFile(true, bOpendByMe);
}
break;
case IDM_VIEW_REUSEWINDOW:
if (IsCmdEnabled(hwnd, IDM_VIEW_REUSEWINDOW)) {
Flags.bReuseWindow = !Flags.bReuseWindow; // reverse
if (Globals.bCanSaveIniFile) {
if (Flags.bReuseWindow != DefaultFlags.bReuseWindow) {
IniFileSetBool(Globals.IniFile, Constants.Settings2_Section, L"ReuseWindow", Flags.bReuseWindow);
}
else {
IniFileDelete(Globals.IniFile, Constants.Settings2_Section, L"ReuseWindow", false);
}
}
}
break;
case IDM_VIEW_SINGLEFILEINSTANCE:
if (IsCmdEnabled(hwnd, IDM_VIEW_SINGLEFILEINSTANCE)) {
Flags.bSingleFileInstance = !Flags.bSingleFileInstance; // reverse
if (Globals.bCanSaveIniFile) {
if (Flags.bSingleFileInstance != DefaultFlags.bSingleFileInstance) {
IniFileSetInt(Globals.IniFile, Constants.Settings2_Section, L"SingleFileInstance", Flags.bSingleFileInstance);
}
else {
IniFileDelete(Globals.IniFile, Constants.Settings2_Section, L"SingleFileInstance", false);
}
}
}
break;
case IDM_VIEW_ALWAYSONTOP:
if ((Settings.AlwaysOnTop || s_flagAlwaysOnTop == 2) && s_flagAlwaysOnTop != 1) {
Settings.AlwaysOnTop = false;
s_flagAlwaysOnTop = 0;
SetWindowPos(hwnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
}
else {
Settings.AlwaysOnTop = true;
s_flagAlwaysOnTop = 0;
SetWindowPos(hwnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
}
CheckCmd(GetMenu(Globals.hwndMain), IDM_VIEW_ALWAYSONTOP, Settings.AlwaysOnTop);
UpdateToolbar();
break;
case IDM_VIEW_MINTOTRAY:
Settings.MinimizeToTray = !Settings.MinimizeToTray;
break;
case IDM_VIEW_TRANSPARENT:
Settings.TransparentMode = !Settings.TransparentMode;
SetWindowTransparentMode(hwnd,Settings.TransparentMode, Settings2.OpacityLevel);
break;
case IDM_SET_RENDER_TECH_GDI:
case IDM_SET_RENDER_TECH_D2D:
case IDM_SET_RENDER_TECH_D2DRETAIN:
case IDM_SET_RENDER_TECH_D2DDC:
{
int const prevRT = Settings.RenderingTechnology;
Settings.RenderingTechnology = (iLoWParam - IDM_SET_RENDER_TECH_GDI);
SciCall_SetTechnology(Settings.RenderingTechnology);
Settings.RenderingTechnology = SciCall_GetTechnology();
SciCall_SetBufferedDraw(Settings.RenderingTechnology == SC_TECHNOLOGY_DEFAULT);
int const prevBD = Settings.Bidirectional;
SciCall_SetBidirectional(Settings.Bidirectional);
Settings.Bidirectional = SciCall_GetBidirectional();
if ((prevRT != Settings.RenderingTechnology) || (prevBD != Settings.Bidirectional)) {
UpdateMarginWidth();
}
}
break;
case IDM_SET_RTL_LAYOUT_EDIT:
Settings.EditLayoutRTL = !Settings.EditLayoutRTL;
SetWindowLayoutRTL(Globals.hwndEdit, Settings.EditLayoutRTL);
InvalidateStyleRedraw();
break;
case IDM_SET_RTL_LAYOUT_DLG:
Settings.DialogsLayoutRTL = !Settings.DialogsLayoutRTL;
SetWindowLayoutRTL(Globals.hwndMain, Settings.DialogsLayoutRTL);
SetWindowLayoutRTL(Globals.hwndToolbar, Settings.DialogsLayoutRTL);
SetWindowLayoutRTL(Globals.hwndRebar, Settings.DialogsLayoutRTL);
SetWindowLayoutRTL(Globals.hwndStatus, Settings.DialogsLayoutRTL);
break;
case IDM_SET_BIDIRECTIONAL_NONE:
case IDM_SET_BIDIRECTIONAL_L2R:
case IDM_SET_BIDIRECTIONAL_R2L:
{
SciCall_SetBidirectional(iLoWParam - IDM_SET_BIDIRECTIONAL_NONE);
Settings.Bidirectional = SciCall_GetBidirectional();
}
break;
#ifdef D_NP3_WIN10_DARK_MODE
case IDM_VIEW_WIN_DARK_MODE:
{
unsigned const iCurTheme = GetModeThemeIndex();
Settings.WinThemeDarkMode = !Settings.WinThemeDarkMode;
// hide/show bright menu strip on switching
if (Settings.ShowMenubar == Defaults.ShowMenubar) {
Settings.ShowMenubar = !Settings.WinThemeDarkMode;
}
Defaults.ShowMenubar = !Settings.WinThemeDarkMode; // (!) need for saving
SetDarkMode(Settings.WinThemeDarkMode);
Style_DynamicThemesMenuCmd(GetModeThemeIndex() + IDM_THEMES_DEFAULT, iCurTheme);
COND_SHOW_ZOOM_CALLTIP();
PostMessage(hwnd, WM_THEMECHANGED, 0, 0);
}
break;
#endif
case IDM_VIEW_MUTE_MESSAGEBEEP:
Settings.MuteMessageBeep = !Settings.MuteMessageBeep;
break;
case IDM_VIEW_SPLIT_UNDOTYPSEQ_LNBRK:
Settings.SplitUndoTypingSeqOnLnBreak = !Settings.SplitUndoTypingSeqOnLnBreak;
break;
//case IDM_SET_INLINE_IME:
// Settings2.IMEInteraction = (Settings2.IMEInteraction == SC_IME_WINDOWED) ? SC_IME_INLINE : SC_IME_WINDOWED;
// SciCall_SetIMEInteraction(Settings2.IMEInteraction);
// break;
case IDM_VIEW_SHOWFILENAMEONLY:
case IDM_VIEW_SHOWFILENAMEFIRST:
case IDM_VIEW_SHOWFULLPATH:
Settings.PathNameFormat = iLoWParam - IDM_VIEW_SHOWFILENAMEONLY;
StringCchCopy(s_wchTitleExcerpt,COUNTOF(s_wchTitleExcerpt),L"");
UpdateTitleBar();
break;
case IDM_VIEW_SHOWEXCERPT:
EditGetExcerpt(Globals.hwndEdit,s_wchTitleExcerpt,COUNTOF(s_wchTitleExcerpt));
UpdateTitleBar();
break;
case IDM_VIEW_NOSAVERECENT:
Settings.SaveRecentFiles = !Settings.SaveRecentFiles;
break;
case IDM_VIEW_NOPRESERVECARET:
Settings.PreserveCaretPos = !Settings.PreserveCaretPos;
break;
case IDM_VIEW_NOSAVEFINDREPL:
Settings.SaveFindReplace = !Settings.SaveFindReplace;
break;
case IDM_VIEW_SAVEBEFORERUNNINGTOOLS:
Settings.SaveBeforeRunningTools = !Settings.SaveBeforeRunningTools;
break;
case IDM_VIEW_EVALTINYEXPRONSEL:
Settings.EvalTinyExprOnSelection = !Settings.EvalTinyExprOnSelection;
UpdateStatusbar(false);
break;
case IDM_VIEW_CHANGENOTIFY:
if (ChangeNotifyDlg(hwnd)) {
InstallFileWatching(Globals.CurrentFile);
}
break;
case IDM_VIEW_NOESCFUNC:
case IDM_VIEW_ESCMINIMIZE:
case IDM_VIEW_ESCEXIT:
Settings.EscFunction = iLoWParam - IDM_VIEW_NOESCFUNC;
break;
case IDM_VIEW_SAVESETTINGS:
if (IsCmdEnabled(hwnd, IDM_VIEW_SAVESETTINGS)) {
Settings.SaveSettings = !Settings.SaveSettings;
if (Globals.bCanSaveIniFile) {
if (Settings.SaveSettings == Defaults.SaveSettings) {
IniFileDelete(Globals.IniFile, Constants.Settings_Section, L"SaveSettings", false);
}
else {
IniFileSetBool(Globals.IniFile, Constants.Settings_Section, L"SaveSettings", Settings.SaveSettings);
}
}
}
break;
case IDM_VIEW_SAVESETTINGSNOW:
if (IsCmdEnabled(hwnd, IDM_VIEW_SAVESETTINGSNOW))
{
CmdSaveSettingsNow();
}
break;
case IDM_HELP_ONLINEDOCUMENTATION:
ShellExecute(0, 0, ONLINE_HELP_WEBSITE, 0, 0, SW_SHOW);
break;
case IDM_HELP_ABOUT:
{
//~HMODULE hRichEdit = LoadLibrary(L"RICHED20.DLL"); // Use RICHEDIT_CONTROL_VER for control in common_res.h
HMODULE const hRichEdit = LoadLibrary(L"MSFTEDIT.DLL"); // Use "RichEdit50W" for control in common_res.h;
if (hRichEdit) {
ThemedDialogBox(Globals.hLngResContainer, MAKEINTRESOURCE(IDD_MUI_ABOUT), hwnd, AboutDlgProc);
FreeLibrary(hRichEdit);
}
}
break;
case IDM_SETPASS:
if (GetFileKey(Globals.hwndEdit)) {
SetSaveNeeded();
}
break;
case IDM_HELP_CMD:
DisplayCmdLineHelp(hwnd);
break;
case CMD_ESCAPE:
{
DocPos const iCurPos = SciCall_GetCurrentPos();
int skipLevel = Settings2.ExitOnESCSkipLevel;
if (SciCall_AutoCActive()) {
SciCall_AutoCCancel();
--skipLevel;
}
else if (SciCall_CallTipActive()) {
CancelCallTip();
s_bCallTipEscDisabled = true;
--skipLevel;
}
else if (s_bInMultiEditMode) {
//~_BEGIN_UNDO_ACTION_;
SciCall_SetIndicatorCurrent(INDIC_NP3_MULTI_EDIT);
SciCall_IndicatorClearRange(0, Sci_GetDocEndPosition());
SciCall_ClearSelections();
//~_END_UNDO_ACTION_;
SciCall_GotoPos(iCurPos);
s_bInMultiEditMode = false;
--skipLevel;
}
if ((!SciCall_IsSelectionEmpty() || Sci_IsMultiOrRectangleSelection()) && (skipLevel == Settings2.ExitOnESCSkipLevel)) {
//~_BEGIN_UNDO_ACTION_;
Sci_GotoPosChooseCaret(iCurPos);
//~_END_UNDO_ACTION_;
skipLevel -= Defaults2.ExitOnESCSkipLevel;
}
if ((skipLevel < 0) || (skipLevel == Settings2.ExitOnESCSkipLevel))
{
switch (Settings.EscFunction) {
case 1:
SendMessage(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
break;
case 2:
CloseApplication();
break;
default:
Sci_GotoPosChooseCaret(iCurPos);
break;
}
}
SciCall_Cancel();
}
break;
case CMD_SHIFTESC:
FileSave(false, false, false, false, Flags.bPreserveFileModTime);
case IDT_FILE_EXIT:
CloseApplication();
break;
case CMD_INSERTNEWLINE:
{
_BEGIN_UNDO_ACTION_;
const DocPos iPos = SciCall_GetCurrentPos();
const DocLn iLine = SciCall_LineFromPosition(iPos);
if (iLine <= 0) {
SciCall_GotoLine(0);
SciCall_NewLine();
SciCall_GotoLine(0);
}
else {
SciCall_GotoPos(SciCall_GetLineEndPosition(iLine - 1));
SciCall_NewLine();
}
_END_UNDO_ACTION_;
}
break;
case CMD_ENTER_RTURN:
{
_EvalTinyExpr(false);
SciCall_NewLine();
}
break;
// Newline with toggled auto indent setting
case CMD_SHIFTCTRLENTER:
Settings.AutoIndent = !Settings.AutoIndent;
SciCall_NewLine();
Settings.AutoIndent = !Settings.AutoIndent;
break;
case CMD_CLEAR:
case IDM_EDIT_CLEAR:
///~_BEGIN_UNDO_ACTION_;
EditDeleteMarkerInSelection();
SciCall_Clear();
///~_END_UNDO_ACTION_;
break;
case CMD_ARROW_UP:
if (Sci_IsMultiSelection())
{
SciCall_Cancel();
}
SciCall_LineUp();
break;
case CMD_ARROW_DOWN:
if (Sci_IsMultiSelection())
{
SciCall_Cancel();
}
SciCall_LineDown();
break;
case CMD_SCROLLUP:
if (Sci_IsMultiSelection())
{
SciCall_LineUpExtend();
}
else {
SciCall_LineScrollUp();
}
break;
case CMD_SCROLLDOWN:
if (Sci_IsMultiSelection())
{
SciCall_LineDownExtend();
}
else {
SciCall_LineScrollDown();
}
break;
case CMD_CTRLLEFT:
if (Sci_IsMultiSelection())
{
SciCall_CharLeftExtend();
}
else {
SciCall_WordLeft();
}
break;
case CMD_CTRLRIGHT:
if (Sci_IsMultiSelection())
{
SciCall_CharRightExtend();
}
else {
SciCall_WordRight();
}
break;
case CMD_CTRLBACK:
{
DocPos const iPos = SciCall_GetCurrentPos();
DocPos const iAnchor = SciCall_GetAnchor();
DocLn const iLine = SciCall_LineFromPosition(iPos);
DocPos const iStartPos = SciCall_PositionFromLine(iLine);
DocPos const iIndentPos = SciCall_GetLineIndentPosition(iLine);
if (iPos != iAnchor) {
_BEGIN_UNDO_ACTION_;
SciCall_SetSel(iPos, iPos);
_END_UNDO_ACTION_;
}
else {
if (iPos == iStartPos)
SciCall_DeleteBack();
else if (iPos <= iIndentPos)
SciCall_DelLineLeft();
else
SciCall_DelWordLeft();
}
}
break;
case CMD_CTRLDEL:
{
const DocPos iPos = SciCall_GetCurrentPos();
const DocPos iAnchor = SciCall_GetAnchor();
const DocLn iLine = SciCall_LineFromPosition(iPos);
const DocPos iStartPos = SciCall_PositionFromLine(iLine);
const DocPos iEndPos = SciCall_GetLineEndPosition(iLine);
if (iPos != iAnchor) {
_BEGIN_UNDO_ACTION_;
SciCall_SetSel(iPos, iPos);
_END_UNDO_ACTION_;
}
else {
if (iStartPos != iEndPos) {
SciCall_DelWordRight();
} else { // iStartPos == iEndPos
SciCall_MarkerDelete(Sci_GetCurrentLineNumber(), -1);
SciCall_LineDelete();
}
}
}
break;
case CMD_RECODEDEFAULT:
{
if (StrIsNotEmpty(Globals.CurrentFile)) {
StringCchCopy(tchMaxPathBuffer, COUNTOF(tchMaxPathBuffer), Globals.CurrentFile);
Encoding_Forced(Settings.DefaultEncoding);
FileLoad(false, false, true, true, true, false, tchMaxPathBuffer);
}
}
break;
case CMD_RECODEANSI:
{
if (StrIsNotEmpty(Globals.CurrentFile)) {
StringCchCopy(tchMaxPathBuffer, COUNTOF(tchMaxPathBuffer), Globals.CurrentFile);
Encoding_Forced(CPI_ANSI_DEFAULT);
FileLoad(false, false, true, true, true, false, tchMaxPathBuffer);
}
}
break;
case CMD_RECODEOEM:
{
if (StrIsNotEmpty(Globals.CurrentFile)) {
StringCchCopy(tchMaxPathBuffer, COUNTOF(tchMaxPathBuffer), Globals.CurrentFile);
Encoding_Forced(CPI_OEM);
FileLoad(false, false, true, true, true, false, tchMaxPathBuffer);
}
}
break;
case CMD_RECODEGB18030:
{
if (StrIsNotEmpty(Globals.CurrentFile)) {
StringCchCopy(tchMaxPathBuffer, COUNTOF(tchMaxPathBuffer), Globals.CurrentFile);
Encoding_Forced(Encoding_GetByCodePage(54936)); // GB18030
FileLoad(false, false, true, true, true, false, tchMaxPathBuffer);
}
}
break;
case CMD_RELOADASCIIASUTF8:
{
if (StrIsNotEmpty(Globals.CurrentFile))
{
StringCchCopy(tchMaxPathBuffer, COUNTOF(tchMaxPathBuffer), Globals.CurrentFile);
Encoding_Forced(CPI_UTF8);
FileLoad(false, false, true, true, true, false, tchMaxPathBuffer);
}
}
break;
case CMD_RELOADFORCEDETECTION:
{
if (StrIsNotEmpty(Globals.CurrentFile))
{
Encoding_Forced(CPI_NONE);
StringCchCopy(tchMaxPathBuffer, COUNTOF(tchMaxPathBuffer), Globals.CurrentFile);
FileLoad(false, false, true, false, false, true, tchMaxPathBuffer);
}
}
break;
case CMD_RELOADNOFILEVARS:
{
if (StrIsNotEmpty(Globals.CurrentFile))
{
bool const _fNoFileVariables = Flags.NoFileVariables;
bool const _bNoEncodingTags = Settings.NoEncodingTags;
Flags.NoFileVariables = true;
Settings.NoEncodingTags = true;
StringCchCopy(tchMaxPathBuffer,COUNTOF(tchMaxPathBuffer),Globals.CurrentFile);
FileLoad(false,false,true, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchMaxPathBuffer);
Flags.NoFileVariables = _fNoFileVariables;
Settings.NoEncodingTags = _bNoEncodingTags;
}
}
break;
case CMD_LEXDEFAULT:
Style_SetDefaultLexer(Globals.hwndEdit);
break;
//case CMD_LEXHTML:
// Style_SetHTMLLexer(Globals.hwndEdit);
// break;
//case CMD_LEXXML:
// Style_SetXMLLexer(Globals.hwndEdit);
// break;
case CMD_INSERT_TIMESTAMP:
EditInsertDateTimeStrg(true, true);
break;
case CMD_UPDATE_TIMESTAMPS:
EditUpdateTimestamps();
break;
case IDM_HELP_ADMINEXE:
DialogAdminExe(hwnd, true);
break;
case IDM_HELP_UPDATEWEBSITE:
DialogAdminExe(hwnd, false);
break;
case CMD_WEBACTION1:
case CMD_WEBACTION2:
{
StringCchCopyW(tchMaxPathBuffer, COUNTOF(tchMaxPathBuffer),
(iLoWParam == CMD_WEBACTION1) ? Settings2.WebTemplate1 : Settings2.WebTemplate2);
if (StringCchLenW(tchMaxPathBuffer,0) > 0) {
WCHAR wszSelection[HUGE_BUFFER] = { L'\0' };
size_t const cchSelection = EditGetSelectedText(wszSelection, HUGE_BUFFER);
if (1 < cchSelection)
{
// Check lpszSelection and truncate bad WCHARs
WCHAR* lpsz = StrChr(wszSelection, L'\r');
if (lpsz) *lpsz = L'\0';
lpsz = StrChr(wszSelection, L'\n');
if (lpsz) *lpsz = L'\0';
lpsz = StrChr(wszSelection, L'\t');
if (lpsz) *lpsz = L'\0';
int cmdsz = (512 + COUNTOF(tchMaxPathBuffer) + MAX_PATH + 32);
LPWSTR lpszCommand = AllocMem(sizeof(WCHAR) * cmdsz, HEAP_ZERO_MEMORY);
StringCchPrintf(lpszCommand, cmdsz, tchMaxPathBuffer, wszSelection);
ExpandEnvironmentStringsEx(lpszCommand, cmdsz);
WCHAR wchDirectory[MAX_PATH] = { L'\0' };
if (StrIsNotEmpty(Globals.CurrentFile)) {
StringCchCopy(wchDirectory, COUNTOF(wchDirectory), Globals.CurrentFile);
PathCchRemoveFileSpec(wchDirectory, COUNTOF(wchDirectory));
}
SHELLEXECUTEINFO sei;
ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO));
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_NOZONECHECKS;
sei.hwnd = NULL;
sei.lpVerb = NULL;
sei.lpFile = lpszCommand;
sei.lpParameters = NULL;
sei.lpDirectory = wchDirectory;
sei.nShow = SW_SHOWNORMAL;
ShellExecuteEx(&sei);
FreeMem(lpszCommand);
}
}
}
break;
/* ~~~
case CMD_INCLINELIMIT:
case CMD_DECLINELIMIT:
if (!Settings.MarkLongLines)
SendWMCommand(hwnd, IDM_VIEW_LONGLINEMARKER);
else {
if (iLoWParam == CMD_INCLINELIMIT)
Settings.LongLinesLimit++;
else
Settings.LongLinesLimit--;
Globals.fvCurFile.iLongLinesLimit = clampi(Settings.LongLinesLimit, 0, LONG_LINES_MARKER_LIMIT);
SendMessage(Globals.hwndEdit,SCI_SETEDGECOLUMN,Settings.LongLinesLimit,0);
//Globals.fvCurFile.iLongLinesLimit = Settings.LongLinesLimit;
}
break;
~~~ */
case CMD_STRINGIFY:
{
EditEncloseSelection(L"'", L"'");
}
break;
case CMD_STRINGIFY2:
{
EditEncloseSelection(L"\"", L"\"");
}
break;
case CMD_EMBRACE:
{
EditEncloseSelection(L"(", L")");
}
break;
case CMD_EMBRACE2:
{
EditEncloseSelection(L"[", L"]");
}
break;
case CMD_EMBRACE3:
{
EditEncloseSelection(L"{", L"}");
}
break;
case CMD_EMBRACE4:
{
EditEncloseSelection(L"`", L"`");
}
break;
case CMD_INCREASENUM:
EditModifyNumber(Globals.hwndEdit,true);
break;
case CMD_DECREASENUM:
EditModifyNumber(Globals.hwndEdit,false);
break;
case CMD_TOGGLETITLE:
EditGetExcerpt(Globals.hwndEdit,s_wchTitleExcerpt,COUNTOF(s_wchTitleExcerpt));
UpdateTitleBar();
break;
case CMD_JUMP2SELSTART:
if (!EditSetCaretToSelectionStart() && Sci_IsMultiOrRectangleSelection()) {
size_t const n = SciCall_GetSelections();
DocLn const lineStart = SciCall_LineFromPosition(SciCall_GetSelectionNCaret(0));
DocPos const beg = SciCall_PositionFromLine(lineStart);
SciCall_ClearSelections(); // needed to reset mode
SciCall_SetSelection(beg, beg);
for (size_t i = 1; i < n; ++i) {
DocPos const pos = SciCall_PositionFromLine(lineStart + i);
SciCall_AddSelection(pos, pos);
}
}
Sci_ScrollChooseCaret();
break;
case CMD_JUMP2SELEND:
if (!EditSetCaretToSelectionEnd() && Sci_IsMultiOrRectangleSelection()) {
size_t const n = SciCall_GetSelections();
DocLn const lineStart = SciCall_LineFromPosition(SciCall_GetSelectionNCaret(0));
DocPos const beg = SciCall_GetLineEndPosition(lineStart);
SciCall_ClearSelections(); // needed to reset mode
SciCall_SetSelection(beg, beg);
for (size_t i = 1; i < n; ++i) {
DocPos const pos = SciCall_GetLineEndPosition(lineStart + i);
SciCall_AddSelection(pos, pos);
}
}
Sci_ScrollChooseCaret();
break;
case CMD_COPYPATHNAME: {
WCHAR *pszCopy;
WCHAR tchUntitled[32] = { L'\0' };
if (StrIsNotEmpty(Globals.CurrentFile))
pszCopy = Globals.CurrentFile;
else {
GetLngString(IDS_MUI_UNTITLED, tchUntitled, COUNTOF(tchUntitled));
pszCopy = tchUntitled;
}
SetClipboardTextW(hwnd, pszCopy, StringCchLen(pszCopy,0));
}
break;
case CMD_COPYWINPOS: {
WININFO wi = GetMyWindowPlacement(Globals.hwndMain,NULL);
StringCchPrintf(tchMaxPathBuffer,COUNTOF(tchMaxPathBuffer),L"/pos %i,%i,%i,%i,%i",wi.x,wi.y,wi.cx,wi.cy,wi.max);
SetClipboardTextW(hwnd, tchMaxPathBuffer, StringCchLen(tchMaxPathBuffer, 0));
}
break;
case CMD_INITIALWINPOS:
SnapToWinInfoPos(hwnd, g_IniWinInfo, SCR_NORMAL);
break;
case CMD_FULLSCRWINPOS:
{
WININFO const wi = GetMyWindowPlacement(Globals.hwndMain, NULL);
SnapToWinInfoPos(hwnd, wi, SCR_FULL_SCREEN);
}
break;
case CMD_DEFAULTWINPOS:
SnapToWinInfoPos(hwnd, g_DefWinInfo, SCR_NORMAL);
break;
case CMD_SAVEASDEFWINPOS:
{
WININFO const wi = GetMyWindowPlacement(Globals.hwndMain, NULL);
WCHAR tchDefWinPos[80];
StringCchPrintf(tchDefWinPos, COUNTOF(tchDefWinPos), L"%i,%i,%i,%i,%i", wi.x, wi.y, wi.cx, wi.cy, wi.max);
if (Globals.bCanSaveIniFile) {
IniFileSetString(Globals.IniFile, Constants.Settings2_Section, L"DefaultWindowPosition", tchDefWinPos);
}
g_DefWinInfo = wi; //GetWinInfoByFlag(-1); // use current win pos as new default
}
break;
case CMD_CLEARSAVEDWINPOS:
g_DefWinInfo = GetFactoryDefaultWndPos(2);
IniFileDelete(Globals.IniFile, Constants.Settings2_Section, L"DefaultWindowPosition", false);
break;
case CMD_OPENINIFILE:
if (StrIsNotEmpty(Globals.IniFile)) {
SaveAllSettings(false);
FileLoad(false, false, false, false, true, false, Globals.IniFile);
}
break;
case CMD_OPEN_HYPERLINK:
HandleHotSpotURLClicked(SciCall_GetCurrentPos(), (OPEN_WITH_BROWSER | OPEN_WITH_NOTEPAD3));
break;
case CMD_FOLDJUMPDOWN:
EditFoldCmdKey(DOWN, SNIFF);
break;
case CMD_FOLDJUMPUP:
EditFoldCmdKey(UP, SNIFF);
break;
case CMD_FOLDCOLLAPSE:
EditFoldCmdKey(NONE, FOLD);
break;
case CMD_FOLDEXPAND:
EditFoldCmdKey(NONE, EXPAND);
break;
case IDT_FILE_NEW:
if (IsCmdEnabled(hwnd,IDM_FILE_NEW))
SendWMCommand(hwnd, IDM_FILE_NEW);
else
SimpleBeep();
break;
case IDT_FILE_OPEN:
if (IsCmdEnabled(hwnd,IDM_FILE_OPEN))
SendWMCommand(hwnd, IDM_FILE_OPEN);
else
SimpleBeep();
break;
case IDT_FILE_BROWSE:
if (IsCmdEnabled(hwnd,IDM_FILE_BROWSE))
SendWMCommand(hwnd, IDM_FILE_BROWSE);
else
SimpleBeep();
break;
case IDT_FILE_RECENT:
if (IsCmdEnabled(hwnd,IDM_FILE_RECENT))
SendWMCommand(hwnd, IDM_FILE_RECENT);
else
SimpleBeep();
break;
case IDT_FILE_SAVE:
if (IsCmdEnabled(hwnd,IDM_FILE_SAVE))
SendWMCommand(hwnd, IDM_FILE_SAVE);
else
SimpleBeep();
break;
case IDT_EDIT_UNDO:
if (IsCmdEnabled(hwnd,IDM_EDIT_UNDO))
SendWMCommand(hwnd, IDM_EDIT_UNDO);
else
SimpleBeep();
break;
case IDT_EDIT_REDO:
if (IsCmdEnabled(hwnd,IDM_EDIT_REDO))
SendWMCommand(hwnd, IDM_EDIT_REDO);
else
SimpleBeep();
break;
case IDT_EDIT_CUT:
if (IsCmdEnabled(hwnd,IDM_EDIT_CUT))
SendWMCommand(hwnd, IDM_EDIT_CUT);
else
SimpleBeep();
//SendWMCommand(hwnd, IDM_EDIT_CUTLINE);
break;
case IDT_EDIT_COPY:
if (IsCmdEnabled(hwnd,IDM_EDIT_COPY))
SendWMCommand(hwnd, IDM_EDIT_COPY);
else
SendWMCommand(hwnd, IDM_EDIT_COPYALL);
break;
case IDT_EDIT_PASTE:
if (IsCmdEnabled(hwnd,IDM_EDIT_PASTE))
SendWMCommand(hwnd, IDM_EDIT_PASTE);
else
SimpleBeep();
break;
case IDT_EDIT_FIND:
if (IsCmdEnabled(hwnd,IDM_EDIT_FIND))
SendWMCommand(hwnd, IDM_EDIT_FIND);
else
SimpleBeep();
break;
case IDT_EDIT_REPLACE:
if (IsCmdEnabled(hwnd,IDM_EDIT_REPLACE))
SendWMCommand(hwnd, IDM_EDIT_REPLACE);
else
SimpleBeep();
break;
case IDT_GREP_WIN_TOOL:
if (IsCmdEnabled(hwnd, IDM_GREP_WIN_SEARCH))
SendWMCommand(hwnd, IDM_GREP_WIN_SEARCH);
else
SimpleBeep();
break;
case IDT_VIEW_WORDWRAP:
if (IsCmdEnabled(hwnd,IDM_VIEW_WORDWRAP))
SendWMCommand(hwnd, IDM_VIEW_WORDWRAP);
else
SimpleBeep();
break;
case IDT_VIEW_ZOOMIN:
if (IsCmdEnabled(hwnd,IDM_VIEW_ZOOMIN))
SendWMCommand(hwnd, IDM_VIEW_ZOOMIN);
else
SimpleBeep();
break;
case IDT_VIEW_ZOOMOUT:
if (IsCmdEnabled(hwnd,IDM_VIEW_ZOOMOUT))
SendWMCommand(hwnd, IDM_VIEW_ZOOMOUT);
else
SimpleBeep();
break;
case IDT_VIEW_CHASING_DOCTAIL:
if (IsCmdEnabled(hwnd, IDM_VIEW_CHASING_DOCTAIL))
SendWMCommand(hwnd, IDM_VIEW_CHASING_DOCTAIL);
else
SimpleBeep();
break;
case IDT_VIEW_SCHEME:
if (IsCmdEnabled(hwnd,IDM_VIEW_SCHEME))
SendWMCommand(hwnd, IDM_VIEW_SCHEME);
else
SimpleBeep();
break;
case IDT_VIEW_SCHEMECONFIG:
if (IsCmdEnabled(hwnd,IDM_VIEW_SCHEMECONFIG))
SendWMCommand(hwnd, IDM_VIEW_SCHEMECONFIG);
else
SimpleBeep();
break;
case IDT_FILE_SAVEAS:
if (IsCmdEnabled(hwnd,IDM_FILE_SAVEAS))
SendWMCommand(hwnd, IDM_FILE_SAVEAS);
else
SimpleBeep();
break;
case IDT_FILE_SAVECOPY:
if (IsCmdEnabled(hwnd,IDM_FILE_SAVECOPY))
SendWMCommand(hwnd, IDM_FILE_SAVECOPY);
else
SimpleBeep();
break;
case IDT_EDIT_CLEAR:
if (IsCmdEnabled(hwnd,IDM_EDIT_CLEAR))
SendWMCommand(hwnd, IDM_EDIT_CLEAR);
else
SendMessage(Globals.hwndEdit,SCI_CLEARALL,0,0);
break;
case IDT_FILE_PRINT:
if (IsCmdEnabled(hwnd,IDM_FILE_PRINT))
SendWMCommand(hwnd, IDM_FILE_PRINT);
else
SimpleBeep();
break;
case IDT_FILE_OPENFAV:
if (IsCmdEnabled(hwnd,IDM_FILE_OPENFAV))
SendWMCommand(hwnd, IDM_FILE_OPENFAV);
else
SimpleBeep();
break;
case IDT_FILE_ADDTOFAV:
if (IsCmdEnabled(hwnd,IDM_FILE_ADDTOFAV))
SendWMCommand(hwnd, IDM_FILE_ADDTOFAV);
else
SimpleBeep();
break;
case IDT_VIEW_TOGGLEFOLDS:
if (IsCmdEnabled(hwnd,IDM_VIEW_TOGGLEFOLDS))
SendWMCommand(hwnd, IDM_VIEW_TOGGLEFOLDS);
else
SimpleBeep();
break;
case IDT_VIEW_TOGGLE_VIEW:
if (IsCmdEnabled(hwnd,IDM_VIEW_TOGGLE_VIEW))
SendWMCommand(hwnd, IDM_VIEW_TOGGLE_VIEW);
else
SimpleBeep();
break;
case IDT_VIEW_PIN_ON_TOP:
if (IsCmdEnabled(hwnd, IDM_VIEW_ALWAYSONTOP))
SendMessage(hwnd, WM_COMMAND, MAKELONG(IDM_VIEW_ALWAYSONTOP, 1), 0);
else
SimpleBeep();
break;
case IDT_FILE_LAUNCH:
if (IsCmdEnabled(hwnd,IDM_FILE_LAUNCH))
SendWMCommand(hwnd, IDM_FILE_LAUNCH);
else
SimpleBeep();
break;
default:
return DefWindowProc(hwnd, umsg, wParam, lParam);
}
return FALSE;
}
//=============================================================================
//
// MsgSysCommand() - Handles WM_SYSCOMMAND
//
LRESULT MsgSysCommand(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
{
switch (wParam) {
case SC_MINIMIZE:
ShowOwnedPopups(hwnd, false);
if (Settings.MinimizeToTray) {
MinimizeWndToTray(hwnd);
ShowNotifyIcon(hwnd, true);
SetNotifyIconTitle(hwnd);
return FALSE; // swallowed
}
break;
case SC_RESTORE:
{
LRESULT lrv = DefWindowProc(hwnd, umsg, wParam, lParam);
ShowOwnedPopups(hwnd, true);
return(lrv);
}
default:
break;
}
return DefWindowProc(hwnd, umsg, wParam, lParam);
}
//=============================================================================
//
// HandlePosChange()
//
void HandlePosChange()
{
static DocPos prevPosition = -1;
DocPos const curPos = SciCall_GetCurrentPos();
if (curPos == prevPosition) { return; }
prevPosition = curPos;
}
//=============================================================================
//
// HandleDWellStartEnd()
//
static DocPos prevCursorPosition = -1;
#define ARGB_TO_COLREF(X) (RGB(((X) >> 16) & SC_ALPHA_OPAQUE, ((X) >> 8) & SC_ALPHA_OPAQUE, (X) & SC_ALPHA_OPAQUE))
#define RGBA_TO_COLREF(X) (RGB(((X) >> 24) & SC_ALPHA_OPAQUE, ((X) >> 16) & SC_ALPHA_OPAQUE, ((X) >> 8) & SC_ALPHA_OPAQUE))
#define BGRA_TO_COLREF(X) (RGB(((X) >> 8) & SC_ALPHA_OPAQUE, ((X) >> 16) & SC_ALPHA_OPAQUE, ((X) >> 24) & SC_ALPHA_OPAQUE))
#define ARGB_GET_ALPHA(A) (((A) >> 24) & SC_ALPHA_OPAQUE)
#define RGBA_GET_ALPHA(A) ((A) & SC_ALPHA_OPAQUE)
#define BGRA_GET_ALPHA(A) RGBA_GET_ALPHA(A)
// ----------------------------------------------------------------------------
void HandleDWellStartEnd(const DocPos position, const UINT uid)
{
static DocPos prevStartPosition = -1;
static DocPos prevEndPosition = -1;
if (position >= 0) {
if (prevCursorPosition < 0) { prevCursorPosition = position; }
if (prevStartPosition < 0) { prevStartPosition = position; }
if (prevEndPosition < 0) { prevEndPosition = position; }
}
int indicator_id = INDICATOR_CONTAINER;
switch (uid)
{
case SCN_DWELLSTART:
{
if (position < 0) { CancelCallTip(); prevCursorPosition = -1; return; }
if (Settings.HyperlinkHotspot) {
if (SciCall_IndicatorValueAt(INDIC_NP3_HYPERLINK, position) > 0) {
indicator_id = INDIC_NP3_HYPERLINK;
if (position != prevCursorPosition) {
CancelCallTip();
}
}
}
if (IsColorDefHotspotEnabled()) {
if (SciCall_IndicatorValueAt(INDIC_NP3_COLOR_DEF, position) > 0) {
indicator_id = INDIC_NP3_COLOR_DEF;
}
}
if (Settings.HighlightUnicodePoints) {
if (SciCall_IndicatorValueAt(INDIC_NP3_UNICODE_POINT, position) > 0) {
indicator_id = INDIC_NP3_UNICODE_POINT;
}
}
switch (indicator_id)
{
case INDIC_NP3_HYPERLINK:
if (!Settings.ShowHypLnkToolTip || SciCall_CallTipActive()) { return; }
break;
case INDIC_NP3_UNICODE_POINT:
if (!Settings.HighlightUnicodePoints || SciCall_CallTipActive()) { return; }
break;
case INDIC_NP3_COLOR_DEF:
// ok
break;
// nothing to do for these indicators
case INDICATOR_CONTAINER:
default:
return;
}
// ----------------------------------------------------------------------
if ((position < prevStartPosition) || (position > prevEndPosition)) { s_bCallTipEscDisabled = false; }
//SciCall_SetCursor(SC_NP3_CURSORHAND);
DocPos const firstPos = SciCall_IndicatorStart(indicator_id, position);
DocPos const lastPos = SciCall_IndicatorEnd(indicator_id, position);
DocPos const length = (lastPos - firstPos);
// WebLinks and Color Refs are ASCII only - No need for UTF-8 conversion here
if (INDIC_NP3_HYPERLINK == indicator_id)
{
if (!s_bCallTipEscDisabled) {
char chText[MIDSZ_BUFFER] = { '\0' };
// No need for UTF-8 conversion here and
StringCchCopyNA(chText, COUNTOF(chText), SciCall_GetRangePointer(firstPos, length), length);
StrTrimA(chText, " \t\n\r");
if (StrIsEmptyA(chText)) { break; }
WCHAR wchCalltipAdd[SMALL_BUFFER] = { L'\0' };
if (StrStrIA(chText, "file:") == chText) {
GetLngString(IDS_MUI_URL_OPEN_FILE, wchCalltipAdd, COUNTOF(wchCalltipAdd));
}
else {
GetLngString(IDS_MUI_URL_OPEN_BROWSER, wchCalltipAdd, COUNTOF(wchCalltipAdd));
}
CHAR chAdd[LARGE_BUFFER] = { L'\0' };
WideCharToMultiByte(Encoding_SciCP, 0, wchCalltipAdd, -1, chAdd, (int)COUNTOF(chAdd), NULL, NULL);
char chCallTip[HUGE_BUFFER] = { '\0' };
StringCchCatA(chCallTip, COUNTOF(chCallTip), chText);
StringCchCatA(chCallTip, COUNTOF(chCallTip), chAdd);
//SciCall_CallTipSetPosition(true);
SciCall_CallTipShow(position, chCallTip);
SciCall_CallTipSetHlt(0, (int)length);
Globals.CallTipType = CT_DWELL;
}
}
else if (INDIC_NP3_COLOR_DEF == indicator_id)
{
char chText[MICRO_BUFFER] = { '\0' };
// Color Refs are ASCII only - No need for UTF-8 conversion here
StringCchCopyNA(chText, COUNTOF(chText), SciCall_GetRangePointer(firstPos, length), length);
unsigned int iValue = 0;
if (sscanf_s(&chText[1], "%x", &iValue) == 1)
{
COLORREF rgb = 0x000000;
int alpha = SC_ALPHA_OPAQUE;
if (length >= 8) // ARGB, RGBA, BGRA
{
switch (Settings.ColorDefHotspot) {
case 1:
rgb = ARGB_TO_COLREF(iValue);
alpha = ARGB_GET_ALPHA(iValue);
break;
case 2:
rgb = RGBA_TO_COLREF(iValue);
alpha = RGBA_GET_ALPHA(iValue);
break;
case 3:
rgb = BGRA_TO_COLREF(iValue);
alpha = BGRA_GET_ALPHA(iValue);
break;
case 0:
default:
break;
}
}
else // RGB
{
rgb = RGB((iValue >> 16) & 0xFF, (iValue >> 8) & 0xFF, iValue & 0xFF);
alpha = SC_ALPHA_OPAQUE;
}
COLORREF const fgr = CalcContrastColor(rgb, alpha);
SciCall_SetIndicatorCurrent(INDIC_NP3_COLOR_DEF_T);
SciCall_IndicatorFillRange(firstPos, length);
SciCall_IndicSetHoverFore(INDIC_NP3_COLOR_DEF_T, fgr);
SciCall_IndicSetAlpha(INDIC_NP3_COLOR_DEF, Sci_ClampAlpha(alpha));
SciCall_IndicSetHoverFore(INDIC_NP3_COLOR_DEF, rgb);
}
}
else if (INDIC_NP3_UNICODE_POINT == indicator_id)
{
if (!s_bCallTipEscDisabled) {
char chHex2Char[MIDSZ_BUFFER] = {'\0'};
// No need for UTF-8 conversion here and
StringCchCopyNA(chHex2Char, COUNTOF(chHex2Char), SciCall_GetRangePointer(firstPos, length), length);
//StrTrimA(chHex2Char, " \t\n\r");
Hex2Char(chHex2Char, COUNTOF(chHex2Char));
if (StrIsEmptyA(chHex2Char)) { break; }
//SciCall_CallTipSetPosition(true);
SciCall_CallTipShow(position, chHex2Char);
SciCall_CallTipSetHlt(0, (int)length);
Globals.CallTipType = CT_DWELL;
}
}
prevCursorPosition = position;
prevStartPosition = firstPos;
prevEndPosition = lastPos;
}
break;
case SCN_DWELLEND:
{
if ((position >= prevStartPosition) && ((position <= prevEndPosition))) { return; } // avoid flickering
CancelCallTip();
DocPos const curPos = SciCall_GetCurrentPos();
if ((curPos >= prevStartPosition) && ((curPos <= prevEndPosition))) { return; } // no change for if caret in range
s_bCallTipEscDisabled = false;
prevCursorPosition = -1;
// clear SCN_DWELLSTART visual styles
SciCall_SetIndicatorCurrent(INDIC_NP3_COLOR_DEF_T);
SciCall_IndicatorClearRange(0, Sci_GetDocEndPosition());
SciCall_IndicSetAlpha(INDIC_NP3_COLOR_DEF, SC_ALPHA_TRANSPARENT);
SciCall_IndicSetFore(INDIC_NP3_COLOR_DEF, 0);
HandlePosChange();
}
break;
default:
break;
}
}
//=============================================================================
//
// HandleHotSpotURLClicked()
//
//
bool HandleHotSpotURLClicked(const DocPos position, const HYPERLINK_OPS operation)
{
if (position < 0) { return false; }
//~PostMessage(Globals.hwndEdit, WM_LBUTTONUP, MK_LBUTTON, 0);
CancelCallTip();
bool bHandled = false;
if (SciCall_IndicatorValueAt(INDIC_NP3_HYPERLINK, position))
{
DocPos const firstPos = SciCall_IndicatorStart(INDIC_NP3_HYPERLINK, position);
DocPos const lastPos = SciCall_IndicatorEnd(INDIC_NP3_HYPERLINK, position);
DocPos const length = min_p(lastPos - firstPos, INTERNET_MAX_URL_LENGTH);
if (length < 4) { return false; }
const char* pszText = (const char*)SciCall_GetRangePointer(firstPos, length);
WCHAR szTextW[INTERNET_MAX_URL_LENGTH + 1];
ptrdiff_t const cchTextW = MultiByteToWideChar(Encoding_SciCP, 0, pszText, (int)length, szTextW, COUNTOF(szTextW));
szTextW[cchTextW] = L'\0';
StrTrim(szTextW, L" \r\n\t");
const WCHAR* chkPreFix = L"file://";
if (operation & SELECT_HYPERLINK)
{
SciCall_SetSelection(firstPos, lastPos);
bHandled = true;
}
else if (operation & COPY_HYPERLINK)
{
if (cchTextW > 0) {
DWORD cchEscapedW = (DWORD)(length * 3);
LPWSTR pszEscapedW = (LPWSTR)AllocMem(cchEscapedW * sizeof(WCHAR), HEAP_ZERO_MEMORY);
if (pszEscapedW) {
//~UrlEscape(szTextW, pszEscapedW, &cchEscapedW, (URL_BROWSER_MODE | URL_ESCAPE_AS_UTF8));
UrlEscapeEx(szTextW, pszEscapedW, &cchEscapedW, false);
SetClipboardTextW(Globals.hwndMain, pszEscapedW, cchEscapedW);
FreeMem(pszEscapedW);
bHandled = true;
}
}
}
else if ((operation & OPEN_WITH_NOTEPAD3) && (StrStrI(szTextW, chkPreFix) == szTextW))
{
size_t const lenPfx = StringCchLenW(chkPreFix, 0);
WCHAR* szFileName = &(szTextW[lenPfx]);
szTextW[lenPfx + MAX_PATH] = L'\0'; // limit length
StrTrim(szFileName, L"/");
PathCanonicalizeEx(szFileName, (DWORD)(COUNTOF(szTextW) - lenPfx));
if (PathIsDirectory(szFileName))
{
WCHAR tchFile[MAX_PATH] = { L'\0' };
if (OpenFileDlg(Globals.hwndMain, tchFile, COUNTOF(tchFile), szFileName))
{
FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchFile);
}
}
else {
FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, szFileName);
}
bHandled = true;
}
else if (operation & OPEN_WITH_BROWSER) // open in web browser
{
WCHAR wchDirectory[MAX_PATH] = { L'\0' };
if (StrIsNotEmpty(Globals.CurrentFile)) {
StringCchCopy(wchDirectory, COUNTOF(wchDirectory), Globals.CurrentFile);
PathCchRemoveFileSpec(wchDirectory, COUNTOF(wchDirectory));
}
SHELLEXECUTEINFO sei;
ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO));
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_NOZONECHECKS;
sei.hwnd = NULL;
sei.lpVerb = NULL;
sei.lpFile = szTextW;
sei.lpParameters = NULL;
sei.lpDirectory = wchDirectory;
sei.nShow = SW_SHOWNORMAL;
ShellExecuteEx(&sei);
bHandled = true;
}
}
if (!(operation & SELECT_HYPERLINK)) { SciCall_SetEmptySelection(position); }
return bHandled;
}
//=============================================================================
//
// HandleColorDefClicked()
//
void HandleColorDefClicked(HWND hwnd, const DocPos position)
{
if (SciCall_IndicatorValueAt(INDIC_NP3_COLOR_DEF, position) == 0) { return; }
DocPos const firstPos = SciCall_IndicatorStart(INDIC_NP3_COLOR_DEF, position);
DocPos const lastPos = SciCall_IndicatorEnd(INDIC_NP3_COLOR_DEF, position);
DocPos const length = (lastPos - firstPos);
char chText[32] = { '\0' };
// Color Refs are ASCII only - No need for UTF-8 conversion here
StringCchCopyNA(chText, COUNTOF(chText), SciCall_GetRangePointer(firstPos, length), length);
unsigned int iValue = 0;
if (sscanf_s(&chText[1], "%x", &iValue) == 1)
{
COLORREF rgbCur = 0x000000;
BYTE alpha = 0xFF;
if (length >= 8) // ARGB, RGBA, BGRA
{
switch (Settings.ColorDefHotspot) {
case 1:
rgbCur = ARGB_TO_COLREF(iValue);
alpha = ARGB_GET_ALPHA(iValue);
break;
case 2:
rgbCur = RGBA_TO_COLREF(iValue);
alpha = RGBA_GET_ALPHA(iValue);
break;
case 3:
rgbCur = BGRA_TO_COLREF(iValue);
alpha = BGRA_GET_ALPHA(iValue);
break;
case 0:
default:
break;
}
}
else // RGB
{
rgbCur = RGB((iValue >> 16) & 0xFF, (iValue >> 8) & 0xFF, iValue & 0xFF);
alpha = 0xFF;
}
CHOOSECOLOR cc;
ZeroMemory(&cc, sizeof(CHOOSECOLOR));
cc.lStructSize = sizeof(CHOOSECOLOR);
cc.hwndOwner = hwnd;
cc.rgbResult = rgbCur;
cc.lpCustColors = g_colorCustom;
//cc.Flags = CC_FULLOPEN | CC_RGBINIT | CC_SOLIDCOLOR;
cc.Flags = CC_FULLOPEN | CC_RGBINIT | CC_ANYCOLOR;
if (!ChooseColor(&cc)) { return; }
COLORREF const rgbNew = cc.rgbResult;
CHAR wchColor[32] = { L'\0' };
if (length >= 8) {
switch (Settings.ColorDefHotspot) {
case 1:
StringCchPrintfA(wchColor, COUNTOF(wchColor), "#%02X%02X%02X%02X", (int)(alpha),
(int)GetRValue(rgbNew), (int)GetGValue(rgbNew), (int)GetBValue(rgbNew));
break;
case 2:
StringCchPrintfA(wchColor, COUNTOF(wchColor), "#%02X%02X%02X%02X",
(int)GetRValue(rgbNew), (int)GetGValue(rgbNew), (int)GetBValue(rgbNew),
(int)(alpha));
break;
case 3:
StringCchPrintfA(wchColor, COUNTOF(wchColor), "#%02X%02X%02X%02X",
(int)GetBValue(rgbNew), (int)GetGValue(rgbNew), (int)GetRValue(rgbNew),
(int)(alpha));
break;
case 0:
default:
break;
}
}
else {
StringCchPrintfA(wchColor, COUNTOF(wchColor), "#%02X%02X%02X",
(int)GetRValue(rgbNew), (int)GetGValue(rgbNew), (int)GetBValue(rgbNew));
}
DocPos const saveTargetBeg = SciCall_GetTargetStart();
DocPos const saveTargetEnd = SciCall_GetTargetEnd();
SciCall_SetTargetRange(firstPos, lastPos);
SciCall_ReplaceTarget(length, wchColor);
SciCall_SetTargetRange(saveTargetBeg, saveTargetEnd); //restore
EditUpdateVisibleIndicators();
}
}
//=============================================================================
//
// _HandleAutoIndent()
//
static void _HandleAutoIndent(int const charAdded)
{
// TODO: handle indent after '{' and un-indent on '}' in C/C++ ?
// in CRLF mode handle LF only...
int const eol_mode = SciCall_GetEOLMode();
if (((SC_EOL_CRLF == eol_mode) && (charAdded != '\r')) || (SC_EOL_CRLF != eol_mode)) {
DocLn const iCurLine = Sci_GetCurrentLineNumber();
// Move bookmark along with line if inserting lines (pressing return within indent area of line) because Scintilla does not do this for us
if (iCurLine > 0) {
//~DocPos const iPrevLineLength = Sci_GetNetLineLength(iCurLine - 1);
if (SciCall_GetLineEndPosition(iCurLine - 1) == SciCall_GetLineIndentPosition(iCurLine - 1)) {
int const bitmask = SciCall_MarkerGet(iCurLine - 1) & bitmask32_n(MARKER_NP3_BOOKMARK + 1); // all bookmarks
if (bitmask) {
SciCall_MarkerDelete((iCurLine - 1), -1);
SciCall_MarkerAddSet(iCurLine, bitmask);
}
}
//~if (iLineLength <= 2)
{
DocLn const iPrevLine = iCurLine - 1;
DocPos const iPrevLineLength = SciCall_LineLength(iPrevLine);
char* pLineBuf = (char*)AllocMem(iPrevLineLength + 1, HEAP_ZERO_MEMORY);
if (pLineBuf) {
SciCall_GetLine_Safe(iPrevLine, pLineBuf);
for (char* pPos = pLineBuf; *pPos; pPos++) {
if ((*pPos != ' ') && (*pPos != '\t')) {
*pPos = '\0';
break;
}
}
if (*pLineBuf) {
_BEGIN_UNDO_ACTION_;
SciCall_AddText((DocPos)StringCchLenA(pLineBuf, SizeOfMem(pLineBuf)), pLineBuf);
_END_UNDO_ACTION_;
}
FreeMem(pLineBuf);
}
}
}
}
}
//=============================================================================
//
// _HandleAutoCloseTags()
//
static void _HandleAutoCloseTags()
{
///int lexerID = SciCall_GetLexer();
///if (lexerID == SCLEX_HTML || lexerID == SCLEX_XML)
DocPos const maxSearchBackward = 4096;
{
DocPos const iCurPos = SciCall_GetCurrentPos();
DocPos const iHelper = iCurPos - maxSearchBackward;
DocPos const iStartPos = max_p(0, iHelper);
DocPos const iSize = iCurPos - iStartPos;
if (iSize >= 3)
{
const char* pBegin = SciCall_GetRangePointer(iStartPos, iSize);
if (pBegin[iSize - 2] != '/')
{
const char* pCur = &pBegin[iSize - 2];
while (pCur > pBegin && *pCur != '<' && *pCur != '>') { --pCur; }
int cchIns = 2;
char replaceBuf[FNDRPL_BUFFER+2];
StringCchCopyA(replaceBuf, FNDRPL_BUFFER, "</");
if (*pCur == '<') {
++pCur;
while ((StrChrA(":_-.", *pCur) || IsCharAlphaNumericA(*pCur)) && (cchIns < (FNDRPL_BUFFER-2))) {
replaceBuf[cchIns++] = *pCur;
++pCur;
}
}
replaceBuf[cchIns++] = '>';
replaceBuf[cchIns] = '\0';
// except tags w/o closing tags
const char* const nonClosingTags[9] = { "</base>", "</bgsound>", "</br>", "</embed>", "</hr>", "</img>", "</input>", "</link>", "</meta>" };
int const cntCount = COUNTOF(nonClosingTags);
bool isNonClosingTag = false;
for (int i = 0; ((i < cntCount) && !isNonClosingTag); ++i) {
isNonClosingTag = (StringCchCompareXIA(replaceBuf, nonClosingTags[i]) == 0);
}
if ((cchIns > 3) && !isNonClosingTag)
{
EditReplaceSelection(replaceBuf,false);
SciCall_SetSel(iCurPos,iCurPos);
}
}
}
}
}
#if 0
//=============================================================================
//
// _IsIMEOpenInNoNativeMode()
//
static bool _IsIMEOpenInNoNativeMode()
{
bool result = false;
HIMC const himc = ImmGetContext(Globals.hwndEdit);
if (himc) {
if (ImmGetOpenStatus(himc)) {
DWORD dwConversion = IME_CMODE_ALPHANUMERIC, dwSentence = 0;
if (ImmGetConversionStatus(himc, &dwConversion, &dwSentence)) {
result = (dwConversion != IME_CMODE_ALPHANUMERIC);
}
}
ImmReleaseContext(Globals.hwndEdit, himc);
}
return result;
}
#endif
//=============================================================================
//
// MsgNotifyLean() - Handles WM_NOTIFY (only absolute neccessary events)
//
// !!! Set correct SCI_SETMODEVENTMASK in _InitializeSciEditCtrl()
//
inline static LRESULT _MsgNotifyLean(const LPNMHDR pnmh, const SCNotification* const scn)
{
static int _mod_insdel_token = -1;
// --- check only mandatory events (must be fast !!!) ---
if (pnmh->idFrom == IDC_EDIT) {
if (pnmh->code == SCN_MODIFIED) {
bool bModified = true;
int const iModType = scn->modificationType;
if (iModType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) {
if (!(iModType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO))) {
if (!_InUndoRedoTransaction() && (_mod_insdel_token < 0) &&
(!SciCall_IsSelectionEmpty() || Sci_IsMultiOrRectangleSelection())) {
int const tok = _SaveUndoSelection();
if (tok >= 0) {
_mod_insdel_token = tok;
}
}
}
bModified = false; // not yet
}
else if (iModType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) {
if (!(iModType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO))) {
if (!_InUndoRedoTransaction() && (_mod_insdel_token >= 0)) {
_SaveRedoSelection(_mod_insdel_token);
_mod_insdel_token = -1;
}
}
}
// check for ADDUNDOACTION step
if (iModType & SC_MOD_CONTAINER)
{
if (iModType & SC_PERFORMED_UNDO) {
RestoreAction(scn->token, UNDO);
}
else if (iModType & SC_PERFORMED_REDO) {
RestoreAction(scn->token, REDO);
}
}
if (bModified) {
DWORD const timeout = Settings2.UndoTransactionTimeout;
if (timeout != 0UL) {
if (timeout > _MQ_IMMEDIATE) {
_DelaySplitUndoTransaction(timeout, iModType);
}
else {
_SplitUndoTransaction(iModType);
}
}
}
}
else if (pnmh->code == SCN_SAVEPOINTREACHED) {
SetSavePoint();
}
else if (pnmh->code == SCN_SAVEPOINTLEFT) {
SetSaveNeeded();
}
else if (pnmh->code == SCN_MODIFYATTEMPTRO) {
if (FocusedView.HideNonMatchedLines) { EditToggleView(Globals.hwndEdit); }
}
}
return TRUE;
}
//=============================================================================
//
// _MsgNotifyFromEdit() - Handles WM_NOTIFY (only absolute neccessary events)
//
// !!! Set correct SCI_SETMODEVENTMASK in _InitializeSciEditCtrl()
//
static LRESULT _MsgNotifyFromEdit(HWND hwnd, const LPNMHDR pnmh, const SCNotification* const scn)
{
static int _s_indic_click_modifiers = SCMOD_NORM;
static int _mod_insdel_token = -1;
switch (pnmh->code)
{
// unused:
case SCN_HOTSPOTCLICK:
case SCN_HOTSPOTDOUBLECLICK:
case SCN_HOTSPOTRELEASECLICK:
return FALSE;
case SCN_AUTOCSELECTION:
{
switch (scn->listCompletionMethod)
{
case SC_AC_TAB:
case SC_AC_COMMAND:
case SC_AC_DOUBLECLICK:
// accepted
break;
case SC_AC_FILLUP:
// see: SciCall_AutoCSetFillups() -> accepted
break;
case SC_AC_NEWLINE:
if (!EditCheckNewLineInACFillUps()) {
SciCall_AutoCCancel(); // rejected
PostMessage(Globals.hwndEdit, SCI_NEWLINE, 0, 0);
}
break;
default:
SciCall_AutoCCancel(); // rejected
break;
}
}
break;
case SCN_MODIFIED:
{
int const iModType = scn->modificationType;
bool bModified = true;
if (iModType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) {
if (!(iModType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO))) {
if (!_InUndoRedoTransaction() && (_mod_insdel_token < 0) &&
(!SciCall_IsSelectionEmpty() || Sci_IsMultiOrRectangleSelection())) {
_mod_insdel_token = _SaveUndoSelection();
}
}
bModified = false; // not yet
}
else if (iModType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) {
if (!(iModType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO))) {
if (!_InUndoRedoTransaction() && (_mod_insdel_token >= 0)) {
_SaveRedoSelection(_mod_insdel_token);
_mod_insdel_token = -1;
}
}
}
if (iModType & SC_MOD_CONTAINER) {
if (iModType & SC_PERFORMED_UNDO) {
bModified = RestoreAction(scn->token, UNDO);
}
else if (iModType & SC_PERFORMED_REDO) {
bModified = RestoreAction(scn->token, REDO);
}
}
if (bModified) {
if (IsMarkOccurrencesEnabled()) {
MarkAllOccurrences(Settings2.UpdateDelayMarkAllOccurrences, true);
}
EditUpdateVisibleIndicators();
if (scn->linesAdded != 0) {
if (Settings.SplitUndoTypingSeqOnLnBreak && (scn->linesAdded == 1)) {
_SplitUndoTransaction(iModType);
}
UpdateMarginWidth();
}
DWORD const timeout = Settings2.UndoTransactionTimeout;
if (timeout != 0UL) {
if (timeout > _MQ_IMMEDIATE) {
_DelaySplitUndoTransaction(timeout, iModType);
}
else {
_SplitUndoTransaction(iModType);
}
}
}
if (s_bInMultiEditMode && !(iModType & SC_MULTILINEUNDOREDO)) {
if (!Sci_IsMultiSelection()) {
SciCall_SetIndicatorCurrent(INDIC_NP3_MULTI_EDIT);
SciCall_IndicatorClearRange(0, Sci_GetDocEndPosition());
s_bInMultiEditMode = false;
}
}
}
break;
case SCN_STYLENEEDED: // this event needs SCI_SETLEXER(SCLEX_CONTAINER)
{
EditDoStyling(-1, scn->position);
}
break;
case SCN_UPDATEUI:
{
int const iUpd = scn->updated;
if (iUpd & (SC_UPDATE_SELECTION | SC_UPDATE_CONTENT))
{
// Brace Match
if (Settings.MatchBraces) {
EditMatchBrace(Globals.hwndEdit);
}
if (iUpd & SC_UPDATE_SELECTION)
{
// clear marks only, if selection changed
if (IsMarkOccurrencesEnabled()) {
if (!SciCall_IsSelectionEmpty() || Settings.MarkOccurrencesCurrentWord)
{
MarkAllOccurrences(Settings2.UpdateDelayMarkAllOccurrences, true);
}
else {
if (Globals.iMarkOccurrencesCount > 0) {
EditClearAllOccurrenceMarkers(Globals.hwndEdit);
}
}
}
}
//~if (iUpd & SC_UPDATE_CONTENT) {
//~ ignoring SC_UPDATE_CONTENT cause Style and Marker are out of scope here
//~ using WM_COMMAND -> SCEN_CHANGE instead!
//~~~MarkAllOccurrences(Settings2.UpdateDelayMarkAllCoccurrences, false);
//~~~EditUpdateVisibleIndicators(); // will lead to recursion
//~}
HandlePosChange();
UpdateToolbar();
UpdateMarginWidth();
UpdateStatusbar(false);
}
else if (iUpd & SC_UPDATE_V_SCROLL)
{
if (IsMarkOccurrencesEnabled() && Settings.MarkOccurrencesMatchVisible) {
MarkAllOccurrences(Settings2.UpdateDelayMarkAllOccurrences, false);
}
EditUpdateVisibleIndicators();
}
}
break;
case SCN_DWELLSTART:
case SCN_DWELLEND:
{
HandleDWellStartEnd(scn->position, pnmh->code);
}
break;
case SCN_DOUBLECLICK:
{
HandleHotSpotURLClicked(scn->position, SELECT_HYPERLINK); // COPY_HYPERLINK
}
break;
case SCN_CALLTIPCLICK:
{
if (prevCursorPosition >= 0)
{
//~HandleHotSpotURLClicked(SciCall_CallTipPosStart(), OPEN_WITH_BROWSER);
HandleHotSpotURLClicked(prevCursorPosition, OPEN_WITH_BROWSER);
}
}
break;
case SCN_INDICATORCLICK:
{
_s_indic_click_modifiers = scn->modifiers;
}
break;
case SCN_INDICATORRELEASE:
{
if (SciCall_IndicatorValueAt(INDIC_NP3_HYPERLINK, scn->position) > 0)
{
if (_s_indic_click_modifiers & SCMOD_CTRL)
{
HandleHotSpotURLClicked(scn->position, OPEN_WITH_BROWSER);
}
else if (_s_indic_click_modifiers & SCMOD_ALT)
{
HandleHotSpotURLClicked(scn->position, OPEN_WITH_NOTEPAD3); // if applicable (file://)
}
}
else if (SciCall_IndicatorValueAt(INDIC_NP3_COLOR_DEF, scn->position) > 0)
{
if (_s_indic_click_modifiers & SCMOD_ALT)
{
HandleColorDefClicked(Globals.hwndEdit, scn->position);
}
}
_s_indic_click_modifiers = SCMOD_NORM;
}
break;
case SCN_CHARADDED:
{
int const ich = scn->ch;
if (Globals.CallTipType != CT_NONE) { CancelCallTip(); }
if (Sci_IsMultiSelection())
{
SciCall_SetIndicatorCurrent(INDIC_NP3_MULTI_EDIT);
DocPosU const selCount = SciCall_GetSelections();
for (DocPosU s = 0; s < selCount; ++s)
{
DocPos const pos = SciCall_GetSelectionNStart(s);
SciCall_IndicatorFillRange(SciCall_PositionBefore(pos), 1);
}
s_bInMultiEditMode = true;
}
switch (ich) {
case '\r':
case '\n':
if (Settings.AutoIndent) { _HandleAutoIndent(ich); }
break;
case '>':
if (Settings.AutoCloseTags) { _HandleAutoCloseTags(); }
break;
case '?':
_EvalTinyExpr(true);
break;
default:
break;
}
if ((Settings.AutoCompleteWords || Settings.AutoCLexerKeyWords))
{
if (!EditAutoCompleteWord(Globals.hwndEdit, false)) { return FALSE; }
}
}
break;
case SCN_AUTOCCHARDELETED:
if ((Settings.AutoCompleteWords || Settings.AutoCLexerKeyWords))
{
if (!EditAutoCompleteWord(Globals.hwndEdit, false)) { return FALSE; }
}
break;
case SCN_NEEDSHOWN:
{
DocLn const iFirstLine = SciCall_LineFromPosition(scn->position);
DocLn const iLastLine = SciCall_LineFromPosition(scn->position + scn->length - 1);
for (DocLn i = iFirstLine; i <= iLastLine; ++i) { SciCall_EnsureVisible(i); }
EditUpdateVisibleIndicators();
}
break;
case SCN_MARGINCLICK:
switch (scn->margin)
{
case MARGIN_SCI_FOLDING:
EditFoldClick(SciCall_LineFromPosition(scn->position), scn->modifiers);
break;
case MARGIN_SCI_BOOKMRK:
EditBookmarkToggle(Globals.hwndEdit, SciCall_LineFromPosition(scn->position), scn->modifiers);
break;
case MARGIN_SCI_LINENUM:
//~SciCall_GotoLine(SciCall_LineFromPosition(scn->position));
break;
default:
break;
}
break;
case SCN_MARGINRIGHTCLICK:
{
POINT pt = {-1,-1};
MsgContextMenu(hwnd, SCN_MARGINRIGHTCLICK, (WPARAM)scn, MAKELPARAM(pt.x,pt.y));
}
break;
// ~~~ Not used in Windows ~~~
// see: CMD_ALTUP / CMD_ALTDOWN
//case SCN_KEY:
// // Also see the corresponding patch in scintilla\src\Editor.cxx
// FoldAltArrow(scn->ch, scn->modifiers);
// break;
case SCN_SAVEPOINTREACHED:
SetSavePoint();
break;
case SCN_SAVEPOINTLEFT:
SetSaveNeeded();
break;
case SCN_ZOOM:
UpdateToolbar();
UpdateMarginWidth();
break;
case SCN_URIDROPPED:
{
// see WM_DROPFILES
WCHAR szBuf[MAX_PATH + 40];
if (MultiByteToWideCharEx(CP_UTF8, 0, scn->text, -1, szBuf, COUNTOF(szBuf)) > 0)
{
if (IsIconic(hwnd)) {
ShowWindow(hwnd, SW_RESTORE);
}
//SetForegroundWindow(hwnd);
if (PathIsDirectory(szBuf)) {
WCHAR tchFile[MAX_PATH];
if (OpenFileDlg(Globals.hwndMain, tchFile, COUNTOF(tchFile), szBuf)) {
FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchFile);
}
}
else if (PathIsExistingFile(szBuf)) {
FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, szBuf);
}
}
}
break;
default:
return FALSE;
}
return TRUE;
}
//=============================================================================
//
// MsgNotify() - Handles WM_NOTIFY
//
// !!! Set correct SCI_SETMODEVENTMASK in _InitializeSciEditCtrl()
//
static bool s_mod_ctrl_pressed = false;
static bool s_tb_reset_already = false;
LRESULT MsgNotify(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
UNUSED(wParam);
static bool _guard = false;
if (_guard) { return TRUE; } else { _guard = true; } // avoid recursion
#define GUARD_RETURN(res) { _guard = false; return(res); }
LPNMHDR const pnmh = (LPNMHDR)lParam;
const SCNotification* const scn = (SCNotification*)lParam;
if (!CheckNotifyChangeEvent())
{
LRESULT const res = _MsgNotifyLean(pnmh, scn);
GUARD_RETURN(res);
}
switch(pnmh->idFrom)
{
case IDC_EDIT:
{
LRESULT const res = _MsgNotifyFromEdit(hwnd, pnmh, scn);
GUARD_RETURN(res);
}
// ------------------------------------------------------------------------
case IDC_TOOLBAR:
switch (pnmh->code)
{
case TBN_QUERYDELETE:
case TBN_QUERYINSERT:
// (!) must exist and return true
GUARD_RETURN(TRUE);
case TBN_BEGINADJUST:
s_tb_reset_already = false;
GUARD_RETURN(FALSE);
case TBN_GETBUTTONINFO:
{
if (((LPTBNOTIFY)lParam)->iItem < COUNTOF(s_tbbMainWnd))
{
WCHAR tch[SMALL_BUFFER] = { L'\0' };
GetLngString(s_tbbMainWnd[((LPTBNOTIFY)lParam)->iItem].idCommand, tch, COUNTOF(tch));
StringCchCopyN(((LPTBNOTIFY)lParam)->pszText, ((LPTBNOTIFY)lParam)->cchText, tch, ((LPTBNOTIFY)lParam)->cchText);
CopyMemory(&((LPTBNOTIFY)lParam)->tbButton, &s_tbbMainWnd[((LPTBNOTIFY)lParam)->iItem], sizeof(TBBUTTON));
GUARD_RETURN(TRUE);
}
}
GUARD_RETURN(FALSE);
case TBN_RESET:
{
int const count = (int)SendMessage(Globals.hwndToolbar, TB_BUTTONCOUNT, 0, 0);
for (int i = 0; i < count; i++) {
SendMessage(Globals.hwndToolbar, TB_DELETEBUTTON, 0, 0);
}
if (s_tb_reset_already) {
if (Toolbar_SetButtons(Globals.hwndToolbar, IDT_FILE_NEW, Defaults.ToolbarButtons, s_tbbMainWnd, COUNTOF(s_tbbMainWnd)) == 0) {
SendMessage(Globals.hwndToolbar, TB_ADDBUTTONS, COUNTOF(s_tbbMainWnd), (LPARAM)s_tbbMainWnd);
}
}
else {
if (Toolbar_SetButtons(Globals.hwndToolbar, IDT_FILE_NEW, Settings.ToolbarButtons, s_tbbMainWnd, COUNTOF(s_tbbMainWnd)) == 0) {
SendMessage(Globals.hwndToolbar, TB_ADDBUTTONS, COUNTOF(s_tbbMainWnd), (LPARAM)s_tbbMainWnd);
}
}
s_tb_reset_already = !s_tb_reset_already;
}
GUARD_RETURN(FALSE);
case TBN_ENDADJUST:
UpdateToolbar();
GUARD_RETURN(TRUE);
default:
GUARD_RETURN(FALSE);
}
break;
// ------------------------------------------------------------------------
case IDC_STATUSBAR:
switch(pnmh->code)
{
case NM_CLICK: // single click
{
LPNMMOUSE const pnmm = (LPNMMOUSE)lParam;
switch (g_vSBSOrder[pnmm->dwItemSpec])
{
case STATUS_EOLMODE:
{
if (Globals.bDocHasInconsistentEOLs)
{
int const eol_mode = SciCall_GetEOLMode();
int const eol_cmd = (eol_mode == SC_EOL_CRLF) ? IDM_LINEENDINGS_CRLF :
((eol_mode == SC_EOL_CR) ? IDM_LINEENDINGS_CR : IDM_LINEENDINGS_LF);
UINT const msgid = (eol_mode == SC_EOL_CRLF) ? IDS_MUI_EOLMODENAME_CRLF :
((eol_mode == SC_EOL_CR) ? IDS_MUI_EOLMODENAME_CR : IDS_MUI_EOLMODENAME_LF);
WCHAR wch[64] = {L'\0'};
GetLngString(msgid, wch, COUNTOF(wch));
INT_PTR const answer = InfoBoxLng(MB_YESNO | MB_ICONWARNING, NULL, IDS_MUI_WARN_NORMALIZE_EOLS, wch);
if ((IDOK == answer) || (IDYES == answer))
{
PostWMCommand(hwnd, eol_cmd);
}
}
}
GUARD_RETURN(!0);
default:
break;
}
}
break;
case NM_DBLCLK: // double click
{
LPNMMOUSE const pnmm = (LPNMMOUSE)lParam;
switch (g_vSBSOrder[pnmm->dwItemSpec])
{
case STATUS_DOCLINE:
case STATUS_DOCCOLUMN:
PostWMCommand(hwnd, IDM_EDIT_GOTOLINE);
GUARD_RETURN(!0);
case STATUS_CODEPAGE:
PostWMCommand(hwnd, IDM_ENCODING_SELECT);
GUARD_RETURN(!0);
case STATUS_EOLMODE:
{
int const eol_mode = (SciCall_GetEOLMode() + 1) % 3;
int const eol_cmd = (eol_mode == SC_EOL_CRLF) ? IDM_LINEENDINGS_CRLF :
((eol_mode == SC_EOL_CR) ? IDM_LINEENDINGS_CR : IDM_LINEENDINGS_LF);
PostWMCommand(hwnd, eol_cmd);
}
GUARD_RETURN(!0);
case STATUS_OVRMODE:
PostWMCommand(hwnd, CMD_VK_INSERT);
GUARD_RETURN(!0);
case STATUS_2ND_DEF:
PostWMCommand(hwnd, IDM_VIEW_USE2NDDEFAULT);
GUARD_RETURN(!0);
case STATUS_LEXER:
PostWMCommand(hwnd, IDM_VIEW_SCHEME);
GUARD_RETURN(!0);
case STATUS_TINYEXPR:
{
char chBuf[80];
if (s_iExprError == 0) {
StringCchPrintfA(chBuf, COUNTOF(chBuf), "%.6G", s_dExpression);
SciCall_CopyText((DocPos)StringCchLenA(chBuf,80), chBuf);
}
else if (s_iExprError > 0) {
StringCchPrintfA(chBuf, COUNTOF(chBuf), "^[" TE_XINT_FMT "]", s_iExprError);
SciCall_CopyText((DocPos)StringCchLenA(chBuf,80), chBuf);
}
else {
SciCall_CopyText(0, "");
}
}
break;
default:
break;
}
}
break;
default:
break;
}
break;
// ------------------------------------------------------------------------
default:
switch(pnmh->code)
{
// ToolTip
case TTN_NEEDTEXT:
if (!(((LPTOOLTIPTEXT)lParam)->uFlags & TTF_IDISHWND))
{
WCHAR tch[SMALL_BUFFER] = { L'\0' };
GetLngString((UINT)pnmh->idFrom,tch,COUNTOF(tch));
WCHAR* pttText = ((LPTOOLTIPTEXT)lParam)->szText;
size_t const ttLen = COUNTOF(((LPTOOLTIPTEXT)lParam)->szText);
StringCchCopyN(pttText, ttLen, tch,COUNTOF(tch));
}
break;
default:
break;
}
break;
}
GUARD_RETURN(0);
}
//=============================================================================
//
// ParseCommandLine()
//
//
void ParseCommandLine()
{
LPWSTR lpCmdLine = GetCommandLine();
if (StrIsEmpty(lpCmdLine)) { return; }
// Good old console can also send args separated by Tabs
StrTab2Space(lpCmdLine);
DocPos const len = (DocPos)(StringCchLenW(lpCmdLine,0) + 2UL);
LPWSTR lp1 = AllocMem(sizeof(WCHAR)*len,HEAP_ZERO_MEMORY);
LPWSTR lp2 = AllocMem(sizeof(WCHAR)*len,HEAP_ZERO_MEMORY);
LPWSTR lp3 = AllocMem(sizeof(WCHAR)*len,HEAP_ZERO_MEMORY);
if (lp1 && lp2 && lp3)
{
bool bIsNotepadReplacement = false;
// Start with 2nd argument
ExtractFirstArgument(lpCmdLine, lp1, lp3, (int)len);
bool bContinue = true;
bool bIsFileArg = false;
s_flagSetEncoding = CPI_NONE;
while (bContinue && ExtractFirstArgument(lp3, lp1, lp2, (int)len)) {
// options
if (lp1[1] == L'\0') {
if (!bIsFileArg && (lp1[0] == L'+')) {
Globals.CmdLnFlag_MultiFileArg = 2;
bIsFileArg = true;
}
else if (!bIsFileArg && (lp1[0] == L'-')) {
Globals.CmdLnFlag_MultiFileArg = 1;
bIsFileArg = true;
}
}
else if (!bIsFileArg && ((*lp1 == L'/') || (*lp1 == L'-')))
{
// LTrim
StrLTrimI(lp1, L"-/");
// Encoding
cpi_enc_t const encoding = Encoding_MatchW(lp1);
if (StringCchCompareXI(lp1, L"ANSI") == 0 || StringCchCompareXI(lp1, L"A") == 0 || StringCchCompareXI(lp1, L"MBCS") == 0) {
s_flagSetEncoding = CPI_ANSI_DEFAULT;
}
else if (StringCchCompareXI(lp1, L"UNICODE") == 0 || StringCchCompareXI(lp1, L"W") == 0) {
s_flagSetEncoding = CPI_UNICODEBOM;
}
else if (StringCchCompareXI(lp1, L"UNICODEBE") == 0 || StringCchCompareXI(lp1, L"UNICODE-BE") == 0) {
s_flagSetEncoding = CPI_UNICODEBEBOM;
}
else if (StringCchCompareXI(lp1, L"UTF8") == 0 || StringCchCompareXI(lp1, L"UTF-8") == 0) {
s_flagSetEncoding = CPI_UTF8;
}
else if (StringCchCompareXI(lp1, L"UTF8SIG") == 0 || StringCchCompareXI(lp1, L"UTF-8SIG") == 0 ||
StringCchCompareXI(lp1, L"UTF8SIGNATURE") == 0 || StringCchCompareXI(lp1, L"UTF-8SIGNATURE") == 0 ||
StringCchCompareXI(lp1, L"UTF8-SIGNATURE") == 0 || StringCchCompareXI(lp1, L"UTF-8-SIGNATURE") == 0) {
s_flagSetEncoding = CPI_UTF8SIGN;
}
// maybe parsed encoding
else if (Encoding_IsValid(encoding)) {
s_flagSetEncoding = encoding;
}
// EOL Mode
else if (StringCchCompareXI(lp1, L"CRLF") == 0 || StringCchCompareXI(lp1, L"CR+LF") == 0) {
s_flagSetEOLMode = IDM_LINEENDINGS_CRLF - IDM_LINEENDINGS_CRLF + 1;
}
else if (StringCchCompareXI(lp1, L"CR") == 0) {
s_flagSetEOLMode = IDM_LINEENDINGS_CR - IDM_LINEENDINGS_CRLF + 1;
}
else if (StringCchCompareXI(lp1, L"LF") == 0) {
s_flagSetEOLMode = IDM_LINEENDINGS_LF - IDM_LINEENDINGS_CRLF + 1;
}
// Shell integration
else if (StrCmpNI(lp1, L"appid=", CSTRLEN(L"appid=")) == 0) {
StringCchCopyN(Settings2.AppUserModelID, COUNTOF(Settings2.AppUserModelID),
lp1 + CSTRLEN(L"appid="), len - CSTRLEN(L"appid="));
StrTrim(Settings2.AppUserModelID, L" ");
if (StrIsEmpty(Settings2.AppUserModelID)) {
StringCchCopy(Settings2.AppUserModelID, COUNTOF(Settings2.AppUserModelID), _W("Rizonesoft.") _W(SAPPNAME));
}
}
else if (StrCmpNI(lp1, L"sysmru=", CSTRLEN(L"sysmru=")) == 0) {
WCHAR wch[16];
StringCchCopyN(wch, COUNTOF(wch), lp1 + CSTRLEN(L"sysmru="), COUNTOF(wch));
StrTrim(wch, L" ");
if (*wch == L'1')
Globals.CmdLnFlag_ShellUseSystemMRU = 2;
else
Globals.CmdLnFlag_ShellUseSystemMRU = 1;
}
// Relaunch elevated
else if (StrCmpNI(lp1, RELAUNCH_ELEVATED_BUF_ARG, CSTRLEN(RELAUNCH_ELEVATED_BUF_ARG)) == 0) {
StringCchCopyN(s_wchTmpFilePath, COUNTOF(s_wchTmpFilePath),
lp1 + CSTRLEN(RELAUNCH_ELEVATED_BUF_ARG), len - CSTRLEN(RELAUNCH_ELEVATED_BUF_ARG));
TrimSpcW(s_wchTmpFilePath);
NormalizePathEx(s_wchTmpFilePath, COUNTOF(s_wchTmpFilePath), true, Flags.bSearchPathIfRelative);
s_IsThisAnElevatedRelaunch = true;
}
else {
switch (*CharUpper(lp1)) {
case L'N':
Globals.CmdLnFlag_ReuseWindow = 1;
if (*CharUpper(lp1 + 1) == L'S')
Globals.CmdLnFlag_SingleFileInstance = 2;
else
Globals.CmdLnFlag_SingleFileInstance = 1;
break;
case L'R':
if (*CharUpper(lp1 + 1) == L'P') {
Flags.bPreserveFileModTime = true;
}
else {
Globals.CmdLnFlag_ReuseWindow = 2;
if (*CharUpper(lp1 + 1) == L'S')
Globals.CmdLnFlag_SingleFileInstance = 2;
else
Globals.CmdLnFlag_SingleFileInstance = 1;
}
break;
case L'F':
if (*(lp1 + 1) == L'0' || *CharUpper(lp1 + 1) == L'O')
StringCchCopy(Globals.IniFile, COUNTOF(Globals.IniFile), L"*?");
else if (ExtractFirstArgument(lp2, lp1, lp2, (int)len)) {
StringCchCopyN(Globals.IniFile, COUNTOF(Globals.IniFile), lp1, len);
TrimSpcW(Globals.IniFile);
NormalizePathEx(Globals.IniFile, COUNTOF(Globals.IniFile), true, false);
}
break;
case L'I':
s_flagStartAsTrayIcon = true;
break;
case L'O':
if (*(lp1 + 1) == L'0' || *(lp1 + 1) == L'-' || *CharUpper(lp1 + 1) == L'O')
s_flagAlwaysOnTop = 1;
else
s_flagAlwaysOnTop = 2;
break;
case L'P':
{
WCHAR* lp = lp1;
if (StrCmpNI(lp1, L"POS:", CSTRLEN(L"POS:")) == 0)
lp += CSTRLEN(L"POS:") - 1;
else if (StrCmpNI(lp1, L"POS", CSTRLEN(L"POS")) == 0)
lp += CSTRLEN(L"POS") - 1;
else if (*(lp1 + 1) == L':')
lp += 1;
else if (bIsNotepadReplacement) {
if (*(lp1 + 1) == L'T')
ExtractFirstArgument(lp2, lp1, lp2, (int)len);
break;
}
if (*(lp + 1) == L'0' || *CharUpper(lp + 1) == L'O') {
Globals.CmdLnFlag_PosParam = true;
Globals.CmdLnFlag_WindowPos = 1;
}
else if (*CharUpper(lp + 1) == L'D' || *CharUpper(lp + 1) == L'S') {
Globals.CmdLnFlag_PosParam = true;
Globals.CmdLnFlag_WindowPos = (StrChrI((lp + 1), L'L')) ? 3 : 2;
}
else if (StrChrI(L"FLTRBM", *(lp + 1))) {
WCHAR* p = (lp + 1);
Globals.CmdLnFlag_PosParam = true;
Globals.CmdLnFlag_WindowPos = 0;
while (*p) {
switch (*CharUpper(p)) {
case L'F':
Globals.CmdLnFlag_WindowPos &= ~(4 | 8 | 16 | 32);
Globals.CmdLnFlag_WindowPos |= 64;
break;
case L'L':
Globals.CmdLnFlag_WindowPos &= ~(8 | 64);
Globals.CmdLnFlag_WindowPos |= 4;
break;
case L'R':
Globals.CmdLnFlag_WindowPos &= ~(4 | 64);
Globals.CmdLnFlag_WindowPos |= 8;
break;
case L'T':
Globals.CmdLnFlag_WindowPos &= ~(32 | 64);
Globals.CmdLnFlag_WindowPos |= 16;
break;
case L'B':
Globals.CmdLnFlag_WindowPos &= ~(16 | 64);
Globals.CmdLnFlag_WindowPos |= 32;
break;
case L'M':
if (Globals.CmdLnFlag_WindowPos == 0)
Globals.CmdLnFlag_WindowPos |= 64;
Globals.CmdLnFlag_WindowPos |= 128;
break;
}
p = CharNext(p);
}
}
else if (ExtractFirstArgument(lp2, lp1, lp2, (int)len)) {
WININFO wi = INIT_WININFO;
int bMaximize = 0;
int itok = swscanf_s(lp1, L"%i,%i,%i,%i,%i", &wi.x, &wi.y, &wi.cx, &wi.cy, &bMaximize);
if (itok == 4 || itok == 5) { // scan successful
Globals.CmdLnFlag_PosParam = true;
Globals.CmdLnFlag_WindowPos = 0;
if (bMaximize) wi.max = true;
if (itok == 4) wi.max = false;
g_IniWinInfo = wi; // set window placement
}
}
}
break;
case L'T':
if (ExtractFirstArgument(lp2, lp1, lp2, (int)len)) {
StringCchCopyN(s_wchTitleExcerpt, COUNTOF(s_wchTitleExcerpt), lp1, len);
s_flagKeepTitleExcerpt = true;
}
break;
case L'C':
s_flagNewFromClipboard = true;
break;
case L'B':
s_flagPasteBoard = true;
break;
case L'E':
if (ExtractFirstArgument(lp2, lp1, lp2, (int)len)) {
s_flagSetEncoding = Encoding_MatchW(lp1);
}
break;
case L'G':
if (ExtractFirstArgument(lp2, lp1, lp2, (int)len)) {
int itok =
swscanf_s(lp1, L"%i,%i", &s_iInitialLine, &s_iInitialColumn);
if (itok == 1 || itok == 2) { // scan successful
s_flagJumpTo = true;
}
}
break;
case L'M':
{
bool bFindUp = false;
bool bMatchCase = false;
bool bRegex = false;
bool bDotMatchAll = false;
bool bTransBS = false;
if (StrChr(lp1, L'-')) {
bFindUp = true;
}
if (StrChr(lp1, L'C')) {
bMatchCase = true;
}
if (StrChr(lp1, L'R')) {
bRegex = true;
bTransBS = true;
}
if (StrChr(lp1, L'A')) {
bDotMatchAll = true;
}
if (StrChr(lp1, L'B')) {
bTransBS = true;
}
if (ExtractFirstArgument(lp2, lp1, lp2, (int)len))
{
SetFindPattern(lp1);
g_flagMatchText = 1;
if (bFindUp) {
g_flagMatchText |= 2;
}
if (bRegex) {
g_flagMatchText |= 4;
}
if (bMatchCase) {
g_flagMatchText |= 8;
}
if (bDotMatchAll) {
g_flagMatchText |= 16;
}
if (bTransBS) {
g_flagMatchText |= 32;
}
}
}
break;
case L'L':
if (*(lp1 + 1) == L'0' || *(lp1 + 1) == L'-' || *CharUpper(lp1 + 1) == L'O')
s_flagChangeNotify = FWM_MSGBOX;
else
s_flagChangeNotify = FWM_AUTORELOAD;
break;
case L'Q':
if (*CharUpper(lp1 + 1) == L'S') {
s_flagSaveOnRelaunch = true;
}
else {
s_flagQuietCreate = true;
}
break;
case L'S':
if (ExtractFirstArgument(lp2, lp1, lp2, (int)len)) {
if (s_lpSchemeArg) { LocalFree(s_lpSchemeArg); } // StrDup()
s_lpSchemeArg = StrDup(lp1);
s_flagLexerSpecified = true;
}
break;
case L'D':
if (s_lpSchemeArg) {
LocalFree(s_lpSchemeArg); // StrDup()
s_lpSchemeArg = NULL;
}
s_iInitialLexer = 0;
s_flagLexerSpecified = true;
break;
case L'H':
if (s_lpSchemeArg) {
LocalFree(s_lpSchemeArg); // StrDup()
s_lpSchemeArg = NULL;
}
s_iInitialLexer = 35;
s_flagLexerSpecified = true;
break;
case L'X':
if (s_lpSchemeArg) {
LocalFree(s_lpSchemeArg); // StrDup()
s_lpSchemeArg = NULL;
}
s_iInitialLexer = 36;
s_flagLexerSpecified = true;
break;
case L'U':
if (*CharUpper(lp1 + 1) == L'C') {
s_flagAppIsClosing = true;
}
else {
Flags.bDoRelaunchElevated = true;
}
break;
case L'Y':
Flags.bSearchPathIfRelative = true;
break;
case L'Z':
ExtractFirstArgument(lp2, lp1, lp2, (int)len);
Globals.CmdLnFlag_MultiFileArg = 1;
bIsNotepadReplacement = true;
break;
case L'?':
s_flagDisplayHelp = true;
break;
case L'V':
Globals.CmdLnFlag_PrintFileAndLeave = 1;
if (*CharUpper(lp1 + 1) == L'D') {
Globals.CmdLnFlag_PrintFileAndLeave = 2; // open printer dialog
}
break;
default:
break;
}
}
}
// pathname
else {
LPWSTR lpFileBuf = AllocMem(sizeof(WCHAR)*len, HEAP_ZERO_MEMORY);
if (lpFileBuf) {
size_t const fileArgLen = StringCchLenW(lp3, len);
s_cchiFileList = (int)(StringCchLenW(lpCmdLine, len - 2) - fileArgLen);
if (s_lpOrigFileArg) {
FreeMem(s_lpOrigFileArg);
//s_lpOrigFileArg = NULL;
}
s_lpOrigFileArg = AllocMem(sizeof(WCHAR)*(fileArgLen + 1), HEAP_ZERO_MEMORY); // changed for ActivatePrevInst() needs
StringCchCopy(s_lpOrigFileArg, fileArgLen + 1, lp3);
StringCchCopy(s_lpFileArg, COUNTOF(s_lpFileArg), lp3);
PathFixBackslashes(s_lpFileArg);
if (!PathIsRelative(s_lpFileArg) && !PathIsUNC(s_lpFileArg) &&
PathGetDriveNumber(s_lpFileArg) == -1 /*&& PathGetDriveNumber(Globals.WorkingDirectory) != -1*/)
{
WCHAR wchPath[MAX_PATH] = { L'\0' };
StringCchCopy(wchPath, COUNTOF(wchPath), Globals.WorkingDirectory);
PathStripToRoot(wchPath);
PathCchAppend(wchPath, COUNTOF(wchPath), s_lpFileArg);
StringCchCopy(s_lpFileArg, COUNTOF(s_lpFileArg), wchPath);
}
StrTrim(s_lpFileArg, L" \"");
while ((s_cFileList < FILE_LIST_SIZE) && ExtractFirstArgument(lp3, lpFileBuf, lp3, (int)len)) {
PathQuoteSpaces(lpFileBuf);
s_lpFileList[s_cFileList++] = StrDup(lpFileBuf); // LocalAlloc()
}
bContinue = false;
FreeMem(lpFileBuf);
}
}
// Continue with next argument
if (bContinue) {
StringCchCopy(lp3, len, lp2);
}
}
FreeMem(lp1);
FreeMem(lp2);
FreeMem(lp3);
}
}
//=============================================================================
//
// _DelayUpdateStatusbar()
//
//
static void _DelayUpdateStatusbar(int delay, bool bForceRedraw)
{
static CmdMessageQueue_t mqc = MQ_WM_CMD_INIT(IDT_TIMER_UPDATE_STATUSBAR, 0);
mqc.hwnd = Globals.hwndMain;
if (bForceRedraw) {
mqc.lparam = (LPARAM)bForceRedraw;
}
_MQ_AppendCmd(&mqc, (UINT)(delay <= 0 ? 0 : _MQ_ms(delay)));
}
//=============================================================================
//
// _DelayUpdateToolbar()
//
//
static void _DelayUpdateToolbar(int delay)
{
static CmdMessageQueue_t mqc = MQ_WM_CMD_INIT(IDT_TIMER_UPDATE_TOOLBAR, 0);
mqc.hwnd = Globals.hwndMain;
//mqc.lparam = (LPARAM)2nd_param;
_MQ_AppendCmd(&mqc, (UINT)(delay <= 0 ? 0 : _MQ_ms(delay)));
}
//=============================================================================
//
// _DelayClearZoomCallTip()
//
//
static void _DelayClearZoomCallTip(int delay)
{
static CmdMessageQueue_t mqc = MQ_WM_CMD_INIT(IDT_TIMER_CLEAR_CALLTIP, 0);
mqc.hwnd = Globals.hwndMain;
//mqc.lparam = (LPARAM)2nd_param;
_MQ_AppendCmd(&mqc, (UINT)(delay <= 0 ? 0 : _MQ_ms(delay)));
}
//=============================================================================
//
// _DelaySplitUndoTransaction()
//
//
static void _DelaySplitUndoTransaction(int delay, int iModType)
{
static CmdMessageQueue_t mqc = MQ_WM_CMD_INIT(IDT_TIMER_UNDO_TRANSACTION, 0);
if (!((iModType & SC_PERFORMED_UNDO) || (iModType & SC_PERFORMED_REDO))) {
mqc.hwnd = Globals.hwndMain;
mqc.lparam = (LPARAM)iModType;
_MQ_AppendCmd(&mqc, (UINT)(delay <= 0 ? 0 : _MQ_ms(delay)));
}
}
//=============================================================================
//
// MarkAllOccurrences()
//
void MarkAllOccurrences(int delay, bool bForceClear)
{
static CmdMessageQueue_t mqc = MQ_WM_CMD_INIT(IDT_TIMER_MAIN_MRKALL, 0);
mqc.hwnd = Globals.hwndMain;
if (bForceClear) {
mqc.lparam = (LPARAM)bForceClear;
}
_MQ_AppendCmd(&mqc, (UINT)(delay <= 0 ? 0 : _MQ_ms(delay)));
}
//=============================================================================
//
// UpdateToolbar()
//
void UpdateToolbar()
{
_DelayUpdateToolbar(_MQ_STD);
}
//=============================================================================
static void _UpdateToolbarDelayed()
{
if (!Settings.ShowToolbar) { return; }
EnableTool(Globals.hwndToolbar, IDT_FILE_ADDTOFAV, StrIsNotEmpty(Globals.CurrentFile));
EnableTool(Globals.hwndToolbar, IDT_FILE_SAVE, GetDocModified() /*&& !bReadOnly*/);
EnableTool(Globals.hwndToolbar, IDT_FILE_RECENT, (MRU_Count(Globals.pFileMRU) > 0));
CheckTool(Globals.hwndToolbar, IDT_VIEW_WORDWRAP, Globals.fvCurFile.bWordWrap);
CheckTool(Globals.hwndToolbar, IDT_VIEW_CHASING_DOCTAIL, FileWatching.MonitoringLog);
CheckTool(Globals.hwndToolbar, IDT_VIEW_PIN_ON_TOP, Settings.AlwaysOnTop);
bool const b1 = SciCall_IsSelectionEmpty();
bool const b2 = !Sci_IsDocEmpty();
bool const ro = SciCall_GetReadOnly();
bool const tv = FocusedView.HideNonMatchedLines;
bool const zi = (SciCall_GetZoom() > 100);
bool const zo = (SciCall_GetZoom() < 100);
EnableTool(Globals.hwndToolbar, IDT_EDIT_UNDO, SciCall_CanUndo() && !ro);
EnableTool(Globals.hwndToolbar, IDT_EDIT_REDO, SciCall_CanRedo() && !ro);
EnableTool(Globals.hwndToolbar, IDT_EDIT_PASTE, SciCall_CanPaste() && !ro);
EnableTool(Globals.hwndToolbar, IDT_FILE_LAUNCH, b2);
EnableTool(Globals.hwndToolbar, IDT_EDIT_FIND, b2);
//EnableTool(Globals.hwndToolbar, ,b2);
//EnableTool(Globals.hwndToolbar, IDT_EDIT_FINDPREV,b2 && !StrIsEmptyA(s_FindReplaceData.szFind));
EnableTool(Globals.hwndToolbar, IDT_EDIT_REPLACE, b2 && !ro);
EnableTool(Globals.hwndToolbar, IDT_EDIT_CUT, !b1 && !ro);
EnableTool(Globals.hwndToolbar, IDT_EDIT_COPY, !b1 && !ro);
EnableTool(Globals.hwndToolbar, IDT_EDIT_CLEAR, !b1 && !ro);
EnableTool(Globals.hwndToolbar, IDT_VIEW_TOGGLEFOLDS, b2 && (FocusedView.CodeFoldingAvailable && FocusedView.ShowCodeFolding));
EnableTool(Globals.hwndToolbar, IDT_VIEW_TOGGLE_VIEW, b2 && IsFocusedViewAllowed());
CheckTool(Globals.hwndToolbar, IDT_VIEW_TOGGLE_VIEW, tv);
CheckTool(Globals.hwndToolbar, IDT_VIEW_ZOOMIN, zi);
CheckTool(Globals.hwndToolbar, IDT_VIEW_ZOOMOUT, zo);
}
//=============================================================================
//
// _StatusCalcPaneWidth()
//
static LONG _StatusCalcPaneWidth(HWND hwnd, LPCWSTR lpsz)
{
HDC const hdc = GetDC(hwnd);
HGDIOBJ const hfont = (HGDIOBJ)SendMessage(hwnd, WM_GETFONT, 0, 0);
HGDIOBJ const hfold = SelectObject(hdc, hfont);
int const mmode = SetMapMode(hdc, MM_TEXT);
SIZE size = { 0L, 0L };
GetTextExtentPoint32(hdc, lpsz, (int)StringCchLenW(lpsz,0), &size);
SetMapMode(hdc, mmode);
SelectObject(hdc, hfold);
ReleaseDC(hwnd, hdc);
return (size.cx + 8L);
}
//=============================================================================
//
// _CalculateStatusbarSections
// vSectionWidth[] must be pre-filled with -1
//
#define txtWidth 80
typedef WCHAR sectionTxt_t[txtWidth];
static void _CalculateStatusbarSections(int vSectionWidth[], sectionTxt_t tchStatusBar[], bool* bIsUpdNeeded)
{
// main window width changed ?
static int s_iWinFormerWidth = -1;
if (s_iWinFormerWidth != s_WinCurrentWidth) {
*bIsUpdNeeded = true;
s_iWinFormerWidth = s_WinCurrentWidth;
}
if (!(*bIsUpdNeeded)) { return; }
// count fixed and dynamic optimized pixels
int pxCount = 0;
for (int i = 0; i < STATUS_SECTOR_COUNT; ++i) {
if (g_iStatusbarVisible[i]) {
if (g_iStatusbarWidthSpec[i] == 0) { // dynamic optimized
vSectionWidth[i] = _StatusCalcPaneWidth(Globals.hwndStatus, tchStatusBar[i]);
}
else if (g_iStatusbarWidthSpec[i] < -1) { // fixed pixel count
vSectionWidth[i] = -(g_iStatusbarWidthSpec[i]);
}
//else { /* 0,-1 : relative counts */ }
// accumulate
if (vSectionWidth[i] > 0) { pxCount += vSectionWidth[i]; }
}
}
int const iPropSectTotalWidth = s_WinCurrentWidth - pxCount - STAUSBAR_RIGHT_MARGIN;
// init proportional section checker
bool bIsPropSection[STATUS_SECTOR_COUNT] = SBS_INIT_ZERO;
for (int i = 0; i < STATUS_SECTOR_COUNT; ++i) {
if ((g_iStatusbarVisible[i]) && (vSectionWidth[i] < 0)) {
assert(g_iStatusbarWidthSpec[i] > 0);
bIsPropSection[i] = true;
}
}
// get min. required widths
int vMinWidth[STATUS_SECTOR_COUNT] = SBS_INIT_ZERO;
int iTotalMinWidth = 0;
for (int i = 0; i < STATUS_SECTOR_COUNT; ++i) {
if (bIsPropSection[i]) {
int const iMinWidth = _StatusCalcPaneWidth(Globals.hwndStatus, tchStatusBar[i]);
vMinWidth[i] = iMinWidth;
iTotalMinWidth += iMinWidth;
}
}
if (iTotalMinWidth >= iPropSectTotalWidth)
{
for (int i = 0; i < STATUS_SECTOR_COUNT; ++i) {
if (bIsPropSection[i]) {
vSectionWidth[i] = vMinWidth[i];
}
}
}
else // space left for proportional elements
{
int vPropWidth[STATUS_SECTOR_COUNT] = SBS_INIT_ZERO;
int totalCnt = 0;
for (int i = 0; i < STATUS_SECTOR_COUNT; ++i) {
if (bIsPropSection[i]) {
vPropWidth[i] = iPropSectTotalWidth * g_iStatusbarWidthSpec[i];
totalCnt += g_iStatusbarWidthSpec[i];
}
}
// normalize
int const iCeilFloor = (totalCnt + 1) / 2;
//int iTotalPropWidth = 0;
for (int i = 0; i < STATUS_SECTOR_COUNT; ++i) {
if (bIsPropSection[i]) {
int const width = (totalCnt > 1) ? ((vPropWidth[i] + iCeilFloor) / totalCnt) : 0;
vPropWidth[i] = width;
//iTotalPropWidth += width;
}
}
// check for fitting
int iOverlappingText = 0;
int iOvlTxtCount = 0;
for (int i = 0; i < STATUS_SECTOR_COUNT; ++i) {
if (bIsPropSection[i]) {
if (vMinWidth[i] > vPropWidth[i]) {
iOverlappingText += (vMinWidth[i] - vPropWidth[i]);
++iOvlTxtCount;
}
}
}
if (iOvlTxtCount == 0) {
// we are fine
for (int i = 0; i < STATUS_SECTOR_COUNT; ++i) {
if (bIsPropSection[i]) {
vSectionWidth[i] = vPropWidth[i];
}
}
}
else // handling overlaps
{
while (iOverlappingText > 0) {
const int iNoProgress = iOverlappingText;
for (int i = 0; i < STATUS_SECTOR_COUNT; ++i) {
if (bIsPropSection[i]) {
if (vMinWidth[i] < vPropWidth[i]) {
vPropWidth[i] -= 1;
--iOverlappingText;
}
else if (vMinWidth[i] > vPropWidth[i]) {
vPropWidth[i] = vMinWidth[i];
}
}
if (iOverlappingText == 0) { break; /* for */}
}
if ((iOverlappingText == 0) || (iNoProgress == iOverlappingText)) { break; }
}
// fill missing widths
for (int i = 0; i < STATUS_SECTOR_COUNT; ++i) {
if (bIsPropSection[i]) {
vSectionWidth[i] = vPropWidth[i];
}
}
}
}
}
//=============================================================================
//
// _InterpMultiSelectionTinyExpr()
//
//
static double _InterpMultiSelectionTinyExpr(te_xint_t* piExprError)
{
#define _tmpBufCnt 128
char tmpRectSelN[_tmpBufCnt] = { '\0' };
DocPosU const selCount = SciCall_GetSelections();
int const calcBufSize = (int)(_tmpBufCnt * selCount + 1);
char* calcBuffer = (char*)AllocMem(calcBufSize, HEAP_ZERO_MEMORY);
WCHAR* calcBufferW = (WCHAR*)AllocMem(calcBufSize * sizeof(WCHAR), HEAP_ZERO_MEMORY);
bool bLastCharWasDigit = false;
for (DocPosU i = 0; i < selCount; ++i)
{
DocPos const posSelStart = SciCall_GetSelectionNStart(i);
DocPos const posSelEnd = SciCall_GetSelectionNEnd(i);
size_t const cchToCopy = (size_t)(posSelEnd - posSelStart);
StringCchCopyNA(tmpRectSelN, _tmpBufCnt, SciCall_GetRangePointer(posSelStart, (DocPos)cchToCopy), cchToCopy);
StrTrimA(tmpRectSelN, " ");
char const defchar = (char)0x24;
MultiByteToWideChar(Encoding_SciCP, 0, calcBuffer, -1, calcBufferW, calcBufSize);
WideCharToMultiByte(1252, (WC_COMPOSITECHECK | WC_DISCARDNS), calcBufferW, -1, calcBuffer, calcBufSize, &defchar, NULL);
StrDelChrA(calcBuffer, chr_currency);
if (!StrIsEmptyA(tmpRectSelN))
{
if (IsDigitA(tmpRectSelN[0]) && bLastCharWasDigit) {
StringCchCatA(calcBuffer, SizeOfMem(calcBuffer), "+"); // default: add numbers
}
bLastCharWasDigit = IsDigitA(tmpRectSelN[StringCchLenA(tmpRectSelN,COUNTOF(tmpRectSelN)) - 1]);
StringCchCatA(calcBuffer, SizeOfMem(calcBuffer), tmpRectSelN);
}
}
double const result = te_interp(calcBuffer, piExprError);
FreeMem(calcBufferW);
FreeMem(calcBuffer);
return result;
}
//=============================================================================
//
// UpdateStatusbar()
//
//
void UpdateStatusbar(bool bForceRedraw)
{
_DelayUpdateStatusbar(_MQ_FAST, bForceRedraw);
}
//=============================================================================
const static WCHAR* const FR_Status[] = { L"[>--<]", L"[>>--]", L"[>>-+]", L"[+->]>", L"[--<<]", L"[+-<<]", L"<[<-+]"};
static void _UpdateStatusbarDelayed(bool bForceRedraw)
{
if (!Settings.ShowStatusbar) { return; }
static sectionTxt_t tchStatusBar[STATUS_SECTOR_COUNT];
// ------------------------------------------------------
// common calculations
// ------------------------------------------------------
DocPos const iPos = SciCall_GetCurrentPos();
DocLn const iLnFromPos = SciCall_LineFromPosition(iPos);
DocPos const iLineBegin = SciCall_PositionFromLine(iLnFromPos);
DocPos const iLineBack = SciCall_GetLineEndPosition(iLnFromPos);
DocPos const iSelStart = SciCall_GetSelectionStart();
DocPos const iSelEnd = SciCall_GetSelectionEnd();
bool const bIsSelectionEmpty = SciCall_IsSelectionEmpty();
bool const bIsSelCharCountable = !(bIsSelectionEmpty || Sci_IsMultiOrRectangleSelection());
bool const bIsMultiSelection = Sci_IsMultiSelection();
bool const bIsWindowFindReplace = IsWindow(Globals.hwndDlgFindReplace);
bool bIsUpdateNeeded = bForceRedraw;
static WCHAR tchLn[32] = { L'\0' };
static WCHAR tchLines[32] = { L'\0' };
// ------------------------------------------------------
if (g_iStatusbarVisible[STATUS_DOCLINE] || bIsWindowFindReplace)
{
static DocLn s_iLnFromPos = -1;
static DocLn s_iLnCnt = -1;
if (bForceRedraw || (s_iLnFromPos != iLnFromPos)) {
StringCchPrintf(tchLn, COUNTOF(tchLn), DOCPOSFMTW, iLnFromPos + 1);
FormatNumberStr(tchLn, COUNTOF(tchLn), 0);
}
DocLn const iLnCnt = SciCall_GetLineCount();
if (bForceRedraw || (s_iLnCnt != iLnCnt)) {
StringCchPrintf(tchLines, COUNTOF(tchLines), DOCPOSFMTW, iLnCnt);
FormatNumberStr(tchLines, COUNTOF(tchLines), 0);
}
if (bForceRedraw || ((s_iLnFromPos != iLnFromPos) || (s_iLnCnt != iLnCnt)))
{
StringCchPrintf(tchStatusBar[STATUS_DOCLINE], txtWidth, L"%s%s / %s%s",
g_mxSBPrefix[STATUS_DOCLINE], tchLn, tchLines, g_mxSBPostfix[STATUS_DOCLINE]);
s_iLnFromPos = iLnFromPos;
s_iLnCnt = iLnCnt;
bIsUpdateNeeded = true;
}
}
// ------------------------------------------------------
static WCHAR tchCol[32] = { L'\0' };
if (g_iStatusbarVisible[STATUS_DOCCOLUMN] || bIsWindowFindReplace)
{
DocPos const colOffset = Globals.bZeroBasedColumnIndex ? 0 : 1;
static DocPos s_iCol = -1;
DocPos const iCol = SciCall_GetColumn(iPos) + SciCall_GetSelectionNCaretVirtualSpace(0);
if (bForceRedraw || (s_iCol != iCol)) {
StringCchPrintf(tchCol, COUNTOF(tchCol), DOCPOSFMTW, iCol + colOffset);
FormatNumberStr(tchCol, COUNTOF(tchCol), 0);
}
static DocPos s_iCols = -1;
static WCHAR tchCols[32] = { L'\0' };
DocPos const iCols = SciCall_GetColumn(iLineBack);
if (bForceRedraw || (s_iCols != iCols)) {
StringCchPrintf(tchCols, COUNTOF(tchCols), DOCPOSFMTW, iCols);
FormatNumberStr(tchCols, COUNTOF(tchCols), 0);
}
if (bForceRedraw || ((s_iCol != iCol) || (s_iCols != iCols))) {
StringCchPrintf(tchStatusBar[STATUS_DOCCOLUMN], txtWidth, L"%s%s / %s%s",
g_mxSBPrefix[STATUS_DOCCOLUMN], tchCol, tchCols, g_mxSBPostfix[STATUS_DOCCOLUMN]);
s_iCol = iCol;
s_iCols = iCols;
bIsUpdateNeeded = true;
}
}
// ------------------------------------------------------
if (g_iStatusbarVisible[STATUS_DOCCHAR])
{
static WCHAR tchChr[32] = { L'\0' };
static WCHAR tchChrs[32] = { L'\0' };
static DocPos s_iChr = -1;
DocPos const chrOffset = Globals.bZeroBasedCharacterCount ? 0 : 1;
DocPos const iChr = SciCall_CountCharacters(iLineBegin, iPos);
if (bForceRedraw || (s_iChr != iChr)) {
StringCchPrintf(tchChr, COUNTOF(tchChr), DOCPOSFMTW, iChr + chrOffset);
FormatNumberStr(tchChr, COUNTOF(tchChr), 0);
}
static DocPos s_iChrs = -1;
DocPos const iChrs = SciCall_CountCharacters(iLineBegin, iLineBack);
if (bForceRedraw || (s_iChrs != iChrs)) {
StringCchPrintf(tchChrs, COUNTOF(tchChrs), DOCPOSFMTW, iChrs);
FormatNumberStr(tchChrs, COUNTOF(tchChrs), 0);
}
if ((s_iChr != iChr) || (s_iChrs != iChrs)) {
StringCchPrintf(tchStatusBar[STATUS_DOCCHAR], txtWidth, L"%s%s / %s%s",
g_mxSBPrefix[STATUS_DOCCHAR], tchChr, tchChrs, g_mxSBPostfix[STATUS_DOCCHAR]);
s_iChr = iChr;
s_iChrs = iChrs;
bIsUpdateNeeded = true;
}
}
// ------------------------------------------------------
static WCHAR tchSel[32] = { L'\0' };
// number of selected chars in statusbar
if (g_iStatusbarVisible[STATUS_SELECTION] || g_iStatusbarVisible[STATUS_SELCTBYTES] || bIsWindowFindReplace)
{
static bool s_bIsSelCountable = false;
static bool s_bIsMultiSelection = false;
static DocPos s_iSelStart = -1;
static DocPos s_iSelEnd = -1;
if (bForceRedraw || ((s_bIsSelCountable != bIsSelCharCountable) || (s_iSelStart != iSelStart)
|| (s_iSelEnd != iSelEnd)) || (s_bIsMultiSelection != bIsMultiSelection))
{
static WCHAR tchSelB[64] = { L'\0' };
if (bIsSelCharCountable)
{
const DocPos iSel = (DocPos)SendMessage(Globals.hwndEdit, SCI_COUNTCHARACTERS, iSelStart, iSelEnd);
StringCchPrintf(tchSel, COUNTOF(tchSel), DOCPOSFMTW, iSel);
FormatNumberStr(tchSel, COUNTOF(tchSel), 0);
StrFormatByteSize((iSelEnd - iSelStart), tchSelB, COUNTOF(tchSelB));
}
else if (bIsMultiSelection) {
StringCchPrintf(tchSel, COUNTOF(tchSel), L"# " DOCPOSFMTW, SciCall_GetSelections());
tchSelB[0] = L'0'; tchSelB[1] = L'\0';
}
else {
tchSel[0] = L'-'; tchSel[1] = L'-'; tchSel[2] = L'\0';
tchSelB[0] = L'0'; tchSelB[1] = L'\0';
}
StringCchPrintf(tchStatusBar[STATUS_SELECTION], txtWidth, L"%s%s%s",
g_mxSBPrefix[STATUS_SELECTION], tchSel, g_mxSBPostfix[STATUS_SELECTION]);
StringCchPrintf(tchStatusBar[STATUS_SELCTBYTES], txtWidth, L"%s%s%s",
g_mxSBPrefix[STATUS_SELCTBYTES], tchSelB, g_mxSBPostfix[STATUS_SELCTBYTES]);
s_bIsSelCountable = bIsSelCharCountable;
s_bIsMultiSelection = bIsMultiSelection;
s_iSelStart = iSelStart;
s_iSelEnd = iSelEnd;
bIsUpdateNeeded = true;
}
}
// ------------------------------------------------------
// number of selected lines in statusbar
if (g_iStatusbarVisible[STATUS_SELCTLINES])
{
static bool s_bIsSelectionEmpty = true;
static DocLn s_iLinesSelected = -1;
DocLn const iLineStart = SciCall_LineFromPosition(iSelStart);
DocLn const iLineEnd = SciCall_LineFromPosition(iSelEnd);
DocPos const iStartOfLinePos = SciCall_PositionFromLine(iLineEnd);
DocLn const iLinesSelected = ((iSelStart != iSelEnd) && (iStartOfLinePos != iSelEnd)) ? ((iLineEnd - iLineStart) + 1) : (iLineEnd - iLineStart);
if (bForceRedraw || ((s_bIsSelectionEmpty != bIsSelectionEmpty) || (s_iLinesSelected != iLinesSelected)))
{
static bool s_bIsMultiSelection = false;
static WCHAR tchLinesSelected[32] = { L'\0' };
if (bIsSelectionEmpty || bIsMultiSelection) {
tchLinesSelected[0] = L'-';
tchLinesSelected[1] = L'-';
tchLinesSelected[2] = L'\0';
}
else {
StringCchPrintf(tchLinesSelected, COUNTOF(tchLinesSelected), DOCPOSFMTW, iLinesSelected);
FormatNumberStr(tchLinesSelected, COUNTOF(tchLinesSelected), 0);
}
StringCchPrintf(tchStatusBar[STATUS_SELCTLINES], txtWidth, L"%s%s%s",
g_mxSBPrefix[STATUS_SELCTLINES], tchLinesSelected, g_mxSBPostfix[STATUS_SELCTLINES]);
s_bIsSelectionEmpty = bIsSelectionEmpty;
s_bIsMultiSelection = bIsMultiSelection;
s_iLinesSelected = iLinesSelected;
bIsUpdateNeeded = true;
}
}
// ------------------------------------------------------
// try calculate expression of selection
if (g_iStatusbarVisible[STATUS_TINYEXPR])
{
static WCHAR tchExpression[32] = { L'\0' };
static te_xint_t s_iExErr = -3;
s_dExpression = 0.0;
tchExpression[0] = L'-';
tchExpression[1] = L'-';
tchExpression[2] = L'\0';
if (Settings.EvalTinyExprOnSelection)
{
if (bIsSelCharCountable) {
static char chSeBuf[LARGE_BUFFER];
static WCHAR wchSelBuf[LARGE_BUFFER];
DocPos const iSelSize = SciCall_GetSelText(NULL);
if (iSelSize < COUNTOF(chSeBuf)) // should be fast !
{
SciCall_GetSelText(chSeBuf);
//~StrDelChrA(chExpression, " \r\n\t\v");
StrDelChrA(chSeBuf, "\r\n");
StrTrimA(chSeBuf, "= ?");
char const defchar = (char)0x24;
MultiByteToWideChar(Encoding_SciCP, 0, chSeBuf, -1, wchSelBuf, LARGE_BUFFER);
WideCharToMultiByte(1252, (WC_COMPOSITECHECK | WC_DISCARDNS), wchSelBuf, -1, chSeBuf, LARGE_BUFFER, &defchar, NULL);
StrDelChrA(chSeBuf, chr_currency);
s_dExpression = te_interp(chSeBuf, &s_iExprError);
}
else {
s_iExprError = -1;
}
}
else if (Sci_IsMultiOrRectangleSelection() && !bIsSelectionEmpty) {
s_dExpression = _InterpMultiSelectionTinyExpr(&s_iExprError);
}
else
s_iExprError = -2;
}
else {
s_iExprError = -3;
}
if (!s_iExprError) {
if (fabs(s_dExpression) > 99999999.9999)
StringCchPrintf(tchExpression, COUNTOF(tchExpression), L"%.4E", s_dExpression);
else
StringCchPrintf(tchExpression, COUNTOF(tchExpression), L"%.6G", s_dExpression);
}
else if (s_iExprError > 0) {
StringCchPrintf(tchExpression, COUNTOF(tchExpression), L"^[" _W(TE_XINT_FMT) L"]", s_iExprError);
}
if (bForceRedraw || (!s_iExprError || (s_iExErr != s_iExprError)))
{
StringCchPrintf(tchStatusBar[STATUS_TINYEXPR], txtWidth, L"%s%s%s ",
g_mxSBPrefix[STATUS_TINYEXPR], tchExpression, g_mxSBPostfix[STATUS_TINYEXPR]);
s_iExErr = s_iExprError;
bIsUpdateNeeded = true;
}
}
// ------------------------------------------------------
static WCHAR tchOcc[32] = { L'\0' };
// number of occurrence marks found
if (g_iStatusbarVisible[STATUS_OCCURRENCE] || bIsWindowFindReplace)
{
static DocPosU s_iMarkOccurrencesCount = 0;
static bool s_bMOVisible = false;
if (bForceRedraw || ((s_bMOVisible != Settings.MarkOccurrencesMatchVisible) || (s_iMarkOccurrencesCount != Globals.iMarkOccurrencesCount)))
{
if (Globals.iMarkOccurrencesCount > 0)
{
StringCchPrintf(tchOcc, COUNTOF(tchOcc), DOCPOSFMTW, Globals.iMarkOccurrencesCount);
FormatNumberStr(tchOcc, COUNTOF(tchOcc), 0);
}
else {
StringCchCopy(tchOcc, COUNTOF(tchOcc), L"--");
}
if (Settings.MarkOccurrencesMatchVisible) {
StringCchCat(tchOcc, COUNTOF(tchOcc), L"(V)");
}
StringCchPrintf(tchStatusBar[STATUS_OCCURRENCE], txtWidth, L"%s%s%s",
g_mxSBPrefix[STATUS_OCCURRENCE], tchOcc, g_mxSBPostfix[STATUS_OCCURRENCE]);
s_bMOVisible = Settings.MarkOccurrencesMatchVisible;
s_iMarkOccurrencesCount = Globals.iMarkOccurrencesCount;
bIsUpdateNeeded = true;
}
}
// ------------------------------------------------------
// number of replaced pattern
if (g_iStatusbarVisible[STATUS_OCCREPLACE] || bIsWindowFindReplace)
{
static int s_iReplacedOccurrences = -1;
if (bForceRedraw || (s_iReplacedOccurrences != Globals.iReplacedOccurrences))
{
static WCHAR tchRepl[32] = { L'\0' };
if (Globals.iReplacedOccurrences > 0)
{
StringCchPrintf(tchRepl, COUNTOF(tchRepl), L"%i", Globals.iReplacedOccurrences);
FormatNumberStr(tchRepl, COUNTOF(tchRepl), 0);
}
else {
StringCchCopy(tchRepl, COUNTOF(tchRepl), L"--");
}
StringCchPrintf(tchStatusBar[STATUS_OCCREPLACE], txtWidth, L"%s%s%s",
g_mxSBPrefix[STATUS_OCCREPLACE], tchRepl, g_mxSBPostfix[STATUS_OCCREPLACE]);
s_iReplacedOccurrences = Globals.iReplacedOccurrences;
bIsUpdateNeeded = true;
}
}
// ------------------------------------------------------
// get number of bytes in current encoding
if (g_iStatusbarVisible[STATUS_DOCSIZE])
{
static DocPos s_iTextLength = -1;
DocPos const iTextLength = SciCall_GetTextLength();
if (bForceRedraw || (s_iTextLength != iTextLength))
{
static WCHAR tchBytes[32] = { L'\0' };
StrFormatByteSize(iTextLength, tchBytes, COUNTOF(tchBytes));
StringCchPrintf(tchStatusBar[STATUS_DOCSIZE], txtWidth, L"%s%s%s",
g_mxSBPrefix[STATUS_DOCSIZE], tchBytes, g_mxSBPostfix[STATUS_DOCSIZE]);
s_iTextLength = iTextLength;
bIsUpdateNeeded = true;
}
}
// ------------------------------------------------------
if (g_iStatusbarVisible[STATUS_CODEPAGE])
{
static cpi_enc_t s_iEncoding = CPI_NONE;
cpi_enc_t const iEncoding = Encoding_GetCurrent();
if (bForceRedraw || (s_iEncoding != iEncoding))
{
StringCchPrintf(tchStatusBar[STATUS_CODEPAGE], txtWidth, L"%s%s%s",
g_mxSBPrefix[STATUS_CODEPAGE], Encoding_GetLabel(iEncoding), g_mxSBPostfix[STATUS_CODEPAGE]);
s_iEncoding = iEncoding;
bIsUpdateNeeded = true;
}
}
// ------------------------------------------------------
const WCHAR* const _LF_f = L"%sLF%s";
const WCHAR* const _LFi_f = L"%sLF*%s";
const WCHAR* const _CR_f = L"%sCR%s";
const WCHAR* const _CRi_f = L"%sCR*%s";
const WCHAR* const _CRLF_f = L"%sCR+LF%s";
const WCHAR* const _CRLFi_f = L"%sCR+LF*%s";
if (g_iStatusbarVisible[STATUS_EOLMODE])
{
static int s_iEOLMode = -1;
int const eol_mode = SciCall_GetEOLMode();
if (bForceRedraw || (s_iEOLMode != eol_mode))
{
static WCHAR tchEOL[16] = { L'\0' };
if (eol_mode == SC_EOL_LF)
{
StringCchPrintf(tchStatusBar[STATUS_EOLMODE], txtWidth, (Globals.bDocHasInconsistentEOLs ? _LFi_f : _LF_f),
g_mxSBPrefix[STATUS_EOLMODE], g_mxSBPostfix[STATUS_EOLMODE]);
}
else if (eol_mode == SC_EOL_CR)
{
StringCchPrintf(tchStatusBar[STATUS_EOLMODE], txtWidth, (Globals.bDocHasInconsistentEOLs ? _CRi_f : _CR_f),
g_mxSBPrefix[STATUS_EOLMODE], g_mxSBPostfix[STATUS_EOLMODE]);
}
else {
StringCchPrintf(tchStatusBar[STATUS_EOLMODE], txtWidth, (Globals.bDocHasInconsistentEOLs ? _CRLFi_f : _CRLF_f),
g_mxSBPrefix[STATUS_EOLMODE], g_mxSBPostfix[STATUS_EOLMODE]);
}
s_iEOLMode = eol_mode;
bIsUpdateNeeded = true;
}
}
// ------------------------------------------------------
if (g_iStatusbarVisible[STATUS_OVRMODE])
{
static bool s_bIsOVR = -1;
bool const bIsOVR = (bool)SendMessage(Globals.hwndEdit, SCI_GETOVERTYPE, 0, 0);
if (bForceRedraw || (s_bIsOVR != bIsOVR))
{
if (bIsOVR)
{
StringCchPrintf(tchStatusBar[STATUS_OVRMODE], txtWidth, L"%sOVR%s",
g_mxSBPrefix[STATUS_OVRMODE], g_mxSBPostfix[STATUS_OVRMODE]);
}
else {
StringCchPrintf(tchStatusBar[STATUS_OVRMODE], txtWidth, L"%sINS%s",
g_mxSBPrefix[STATUS_OVRMODE], g_mxSBPostfix[STATUS_OVRMODE]);
}
s_bIsOVR = bIsOVR;
bIsUpdateNeeded = true;
}
}
// ------------------------------------------------------
if (g_iStatusbarVisible[STATUS_2ND_DEF])
{
static bool s_bUse2ndDefault = -1;
bool const bUse2ndDefault = Style_GetUse2ndDefault();
if (bForceRedraw || (s_bUse2ndDefault != bUse2ndDefault))
{
if (bUse2ndDefault)
StringCchPrintf(tchStatusBar[STATUS_2ND_DEF], txtWidth, L"%s2ND%s",
g_mxSBPrefix[STATUS_2ND_DEF], g_mxSBPostfix[STATUS_2ND_DEF]);
else
StringCchPrintf(tchStatusBar[STATUS_2ND_DEF], txtWidth, L"%sSTD%s",
g_mxSBPrefix[STATUS_2ND_DEF], g_mxSBPostfix[STATUS_2ND_DEF]);
s_bUse2ndDefault = bUse2ndDefault;
bIsUpdateNeeded = true;
}
}
// ------------------------------------------------------
if (g_iStatusbarVisible[STATUS_LEXER])
{
static int s_iCurLexer = -1;
int const iCurLexer = Style_GetCurrentLexerRID();
if (bForceRedraw || (s_iCurLexer != iCurLexer))
{
static WCHAR tchLexerName[MINI_BUFFER];
if (Style_IsCurLexerStandard())
Style_GetLexerDisplayName(NULL, tchLexerName, MINI_BUFFER); // don't distinguish between STD/2ND
else
Style_GetLexerDisplayName(Style_GetCurrentLexerPtr(), tchLexerName, MINI_BUFFER);
StringCchPrintf(tchStatusBar[STATUS_LEXER], txtWidth, L"%s%s%s",
g_mxSBPrefix[STATUS_LEXER], tchLexerName, g_mxSBPostfix[STATUS_LEXER]);
s_iCurLexer = iCurLexer;
bIsUpdateNeeded = true;
}
}
// ------------------------------------------------------
// ==== Statusbar widths ====
int g_vStatusbarSectionWidth[STATUS_SECTOR_COUNT] = SBS_INIT_MINUS;
_CalculateStatusbarSections(g_vStatusbarSectionWidth, tchStatusBar, &bIsUpdateNeeded);
if (bIsUpdateNeeded) {
int aStatusbarSections[STATUS_SECTOR_COUNT] = SBS_INIT_ZERO;
BYTE cnt = 0;
int totalWidth = 0;
for (int i = 0; i < STATUS_SECTOR_COUNT; ++i) {
int const id = g_vSBSOrder[i];
if ((id >= 0) && (g_vStatusbarSectionWidth[id] >= 0))
{
totalWidth += g_vStatusbarSectionWidth[id];
aStatusbarSections[cnt++] = totalWidth;
}
}
if (cnt > 0) { aStatusbarSections[cnt - 1] = -1; }
else { aStatusbarSections[0] = -1; Settings.ShowStatusbar = false; }
SendMessage(Globals.hwndStatus, SB_SETPARTS, (WPARAM)cnt, (LPARAM)aStatusbarSections);
cnt = 0;
for (int i = 0; i < STATUS_SECTOR_COUNT; ++i) {
int const id = g_vSBSOrder[i];
if ((id >= 0) && (g_vStatusbarSectionWidth[id] >= 0)) {
StatusSetText(Globals.hwndStatus, cnt++, tchStatusBar[id]);
}
}
}
// --------------------------------------------------------------------------
// update Find/Replace dialog (if any)
if (bIsWindowFindReplace) {
static WCHAR tchReplOccs[32] = { L'\0' };
if (Globals.iReplacedOccurrences > 0)
StringCchPrintf(tchReplOccs, COUNTOF(tchReplOccs), L"%i", Globals.iReplacedOccurrences);
else
StringCchCopy(tchReplOccs, COUNTOF(tchReplOccs), L"--");
const WCHAR* const SBFMT = L" %s%s / %s %s%s %s%s %s%s %s%s ( %s ) ";
static WCHAR tchFRStatus[128] = { L'\0' };
StringCchPrintf(tchFRStatus, COUNTOF(tchFRStatus), SBFMT,
g_mxSBPrefix[STATUS_DOCLINE], tchLn, tchLines,
g_mxSBPrefix[STATUS_DOCCOLUMN], tchCol,
g_mxSBPrefix[STATUS_SELECTION], tchSel,
g_mxSBPrefix[STATUS_OCCURRENCE], tchOcc,
g_mxSBPrefix[STATUS_OCCREPLACE], tchReplOccs,
FR_Status[Globals.FindReplaceMatchFoundState]);
SetWindowText(GetDlgItem(Globals.hwndDlgFindReplace, IDS_FR_STATUS_TEXT), tchFRStatus);
}
}
//=============================================================================
//
// UpdateMarginWidth()
//
//
void UpdateMarginWidth()
{
if (Settings.ShowLineNumbers)
{
static char chLines[32] = { '\0' };
StringCchPrintfA(chLines, COUNTOF(chLines), "_%td", (size_t)SciCall_GetLineCount());
int const iLineMarginWidthNow = SciCall_GetMarginWidthN(MARGIN_SCI_LINENUM);
int const iLineMarginWidthFit = SciCall_TextWidth(STYLE_LINENUMBER, chLines);
if (iLineMarginWidthNow != iLineMarginWidthFit) {
SciCall_SetMarginWidthN(MARGIN_SCI_LINENUM, iLineMarginWidthFit);
}
}
else {
SciCall_SetMarginWidthN(MARGIN_SCI_LINENUM, 0);
}
Style_SetBookmark(Globals.hwndEdit, Settings.ShowBookmarkMargin);
Style_SetFolding(Globals.hwndEdit, (FocusedView.CodeFoldingAvailable && FocusedView.ShowCodeFolding));
}
//=============================================================================
//
// UpdateSaveSettingsCmds()
//
//
void UpdateSaveSettingsCmds()
{
bool const bSoftLocked = Flags.bSettingsFileSoftLocked;
bool const bHaveIniFile = StrIsNotEmpty(Globals.IniFile);
bool const bHaveFallbackIniFile = StrIsNotEmpty(Globals.IniFileDefault);
CheckCmd(Globals.hMainMenu, IDM_VIEW_SAVESETTINGS, Settings.SaveSettings && !bSoftLocked);
EnableCmd(Globals.hMainMenu, IDM_VIEW_SAVESETTINGS, Globals.bCanSaveIniFile && !bSoftLocked);
EnableCmd(Globals.hMainMenu, IDM_VIEW_SAVESETTINGSNOW, (bHaveIniFile || bHaveFallbackIniFile) && !bSoftLocked);
EnableCmd(Globals.hMainMenu, CMD_OPENINIFILE, bHaveIniFile && !bSoftLocked);
DrawMenuBar(Globals.hwndMain);
}
//=============================================================================
//
// UpdateUI()
//
void UpdateUI()
{
struct SCNotification scn;
scn.nmhdr.hwndFrom = Globals.hwndEdit;
scn.nmhdr.idFrom = IDC_EDIT;
scn.nmhdr.code = SCN_UPDATEUI;
scn.updated = (SC_UPDATE_CONTENT/* | SC_UPDATE_NP3_INTERNAL_NOTIFY */);
SendMessage(Globals.hwndMain, WM_NOTIFY, IDC_EDIT, (LPARAM)&scn);
SendWMSize(Globals.hwndMain, NULL);
}
//=============================================================================
//
// UpdateTitleBar()
//
void UpdateTitleBar() {
SetWindowTitle(Globals.hwndMain, s_uidsAppTitle, s_bIsProcessElevated, IDS_MUI_UNTITLED, Globals.CurrentFile,
Settings.PathNameFormat, GetDocModified(), IDS_MUI_READONLY, s_bFileReadOnly, s_wchTitleExcerpt);
PostMessage(Globals.hwndMain, WM_NCACTIVATE, FALSE, -1);
PostMessage(Globals.hwndMain, WM_NCACTIVATE, TRUE, 0);
}
//=============================================================================
#define UNDOREDO_FREE (-1L)
#define UNDOREDO_BLOCKED (-2L)
static volatile LONG UndoActionToken = UNDOREDO_BLOCKED; // block
//=============================================================================
static bool _InUndoRedoTransaction() {
return (InterlockedOr(&UndoActionToken, 0L) != UNDOREDO_FREE);
}
//=============================================================================
//
// UndoRedoRecordingStart()
//
void UndoRedoRecordingStart()
{
InterlockedExchange(&UndoActionToken, UNDOREDO_FREE); // clear
_UndoRedoActionMap(-1, NULL);
SciCall_SetUndoCollection(true);
}
//=============================================================================
//
// UndoRedoRecordingStop()
//
void UndoRedoRecordingStop()
{
int const curToken = InterlockedOr(&UndoActionToken, 0L);
if (curToken >= 0) { EndUndoAction(curToken); }
_UndoRedoActionMap(-1, NULL);
SciCall_SetUndoCollection(false);
SciCall_EmptyUndoBuffer();
}
//=============================================================================
//
// UndoRedoReset()
//
void UndoRedoReset()
{
UndoRedoRecordingStop();
UndoRedoRecordingStart();
}
//=============================================================================
//
// _SaveUndoSelection()
//
//
static int _SaveUndoSelection()
{
static DocPosU _s_iSelection = 0; // index
UndoRedoSelection_t sel = INIT_UNDOREDOSEL;
CopyUndoRedoSelection(&sel, NULL); // init
DocPosU const numOfSel = SciCall_GetSelections();
// each single selection of a multi-selection will call thid method
// we are only interested in the first call
if (0 == _s_iSelection) {
_s_iSelection = numOfSel;
}
if ((numOfSel-1) != --_s_iSelection) {
return -1;
}
int const selMode = ((numOfSel > 1) && !SciCall_IsSelectionRectangle()) ? NP3_SEL_MULTI : SciCall_GetSelectionMode();
sel.selMode_undo = selMode;
switch (selMode)
{
case NP3_SEL_MULTI:
{
for (DocPosU i = 0; i < numOfSel; ++i) {
if (sel.anchorPos_undo && sel.curPos_undo) {
DocPos const anchorPos = SciCall_GetSelectionNAnchor(i);
utarray_push_back(sel.anchorPos_undo, &anchorPos);
DocPos const curPos = SciCall_GetSelectionNCaret(i);
utarray_push_back(sel.curPos_undo, &curPos);
}
if (!Settings2.DenyVirtualSpaceAccess && sel.anchorVS_undo && sel.curVS_undo) {
DocPos const anchorVS = SciCall_GetSelectionNAnchorVirtualSpace(i);
utarray_push_back(sel.anchorVS_undo, &anchorVS);
DocPos const curVS = SciCall_GetSelectionNCaretVirtualSpace(i);
utarray_push_back(sel.curVS_undo, &curVS);
}
}
}
break;
case SC_SEL_RECTANGLE:
case SC_SEL_THIN:
{
DocPos const anchorPos = SciCall_GetRectangularSelectionAnchor();
utarray_push_back(sel.anchorPos_undo, &anchorPos);
DocPos const curPos = SciCall_GetRectangularSelectionCaret();
utarray_push_back(sel.curPos_undo, &curPos);
if (!Settings2.DenyVirtualSpaceAccess) {
DocPos const anchorVS = SciCall_GetRectangularSelectionAnchorVirtualSpace();
utarray_push_back(sel.anchorVS_undo, &anchorVS);
DocPos const curVS = SciCall_GetRectangularSelectionCaretVirtualSpace();
utarray_push_back(sel.curVS_undo, &curVS);
}
}
break;
case SC_SEL_LINES:
case SC_SEL_STREAM:
default:
{
DocPos const anchorPos = SciCall_GetAnchor();
utarray_push_back(sel.anchorPos_undo, &anchorPos);
DocPos const curPos = SciCall_GetCurrentPos();
utarray_push_back(sel.curPos_undo, &curPos);
DocPos const dummy = (DocPos)-1;
utarray_push_back(sel.anchorVS_undo, &dummy);
utarray_push_back(sel.curVS_undo, &dummy);
}
break;
}
const UndoRedoSelection_t* pSel = &sel;
int const token = _UndoRedoActionMap(-1, &pSel);
if (token >= 0) {
//~SciCall_AddUndoAction(token, UNDO_MAY_COALESCE);
SciCall_AddUndoAction(token, UNDO_NONE);
}
_s_iSelection = 0; // reset
return token;
}
//=============================================================================
//
// _SaveRedoSelection()
//
//
static void _SaveRedoSelection(int token)
{
static DocPosU _s_iSelection = 0; // index
if (token < 0) { return; }
UndoRedoSelection_t* pSel = NULL;
DocPosU const numOfSel = SciCall_GetSelections();
// each single selection of a multi-selection will call this method
// we are only interested in the last call
if (0 == _s_iSelection) {
_s_iSelection = numOfSel;
}
if (0 != --_s_iSelection) {
return;
}
if ((_UndoRedoActionMap(token, &pSel) >= 0) && (pSel != NULL))
{
int const selMode = ((numOfSel > 1) && !SciCall_IsSelectionRectangle()) ? NP3_SEL_MULTI : SciCall_GetSelectionMode();
pSel->selMode_redo = selMode;
switch (selMode)
{
case NP3_SEL_MULTI:
{
for (DocPosU i = 0; i < numOfSel; ++i) {
DocPos const anchorPos = SciCall_GetSelectionNAnchor(i);
utarray_push_back(pSel->anchorPos_redo, &anchorPos);
DocPos const curPos = SciCall_GetSelectionNCaret(i);
utarray_push_back(pSel->curPos_redo, &curPos);
if (!Settings2.DenyVirtualSpaceAccess) {
DocPos const anchorVS = SciCall_GetSelectionNAnchorVirtualSpace(i);
utarray_push_back(pSel->anchorVS_redo, &anchorVS);
DocPos const curVS = SciCall_GetSelectionNCaretVirtualSpace(i);
utarray_push_back(pSel->curVS_redo, &curVS);
}
}
}
break;
case SC_SEL_RECTANGLE:
case SC_SEL_THIN:
{
DocPos const anchorPos = SciCall_GetRectangularSelectionAnchor();
utarray_push_back(pSel->anchorPos_redo, &anchorPos);
DocPos const curPos = SciCall_GetRectangularSelectionCaret();
utarray_push_back(pSel->curPos_redo, &curPos);
if (!Settings2.DenyVirtualSpaceAccess) {
DocPos const anchorVS = SciCall_GetRectangularSelectionAnchorVirtualSpace();
utarray_push_back(pSel->anchorVS_redo, &anchorVS);
DocPos const curVS = SciCall_GetRectangularSelectionCaretVirtualSpace();
utarray_push_back(pSel->curVS_redo, &curVS);
}
}
break;
case SC_SEL_LINES:
case SC_SEL_STREAM:
default:
{
DocPos const anchorPos = SciCall_GetAnchor();
utarray_push_back(pSel->anchorPos_redo, &anchorPos);
DocPos const curPos = SciCall_GetCurrentPos();
utarray_push_back(pSel->curPos_redo, &curPos);
//~DocPos const dummy = (DocPos)-1;
//~utarray_push_back(pSel->anchorVS_redo, &dummy);
//~utarray_push_back(pSel->curVS_redo, &dummy);
}
break;
}
}
}
//=============================================================================
//
// BeginUndoAction()
//
//
int BeginUndoAction()
{
if (_InUndoRedoTransaction()) { return -1; }
SciCall_BeginUndoAction();
int const token = _SaveUndoSelection();
InterlockedExchange(&UndoActionToken, (LONG)token);
return token;
}
//=============================================================================
//
// EndUndoAction()
//
//
void EndUndoAction(int token)
{
if ((token >= 0) && (token == (int)InterlockedOr(&UndoActionToken, 0L)))
{
_SaveRedoSelection(token);
SciCall_EndUndoAction();
InterlockedExchange(&UndoActionToken, UNDOREDO_FREE);
}
}
//=============================================================================
//
// RestoreAction()
//
//
bool RestoreAction(int token, DoAction doAct)
{
if (_InUndoRedoTransaction()) { return false; }
UndoRedoSelection_t* pSel = NULL;
if ((_UndoRedoActionMap(token, &pSel) >= 0) && (pSel != NULL))
{
// we are inside undo/redo transaction, so do delayed PostMessage() instead of SendMessage()
HWND const hwndedit = Globals.hwndEdit;
DocPos* pPosAnchor = NULL;
DocPos* pPosCur = NULL;
DocPos* pPosAnchorVS = NULL;
DocPos* pPosCurVS = NULL;
pPosAnchor = (DocPos*)((UNDO == doAct) ? utarray_front(pSel->anchorPos_undo) : utarray_front(pSel->anchorPos_redo));
pPosCur = (DocPos*)((UNDO == doAct) ? utarray_front(pSel->curPos_undo) : utarray_front(pSel->curPos_redo));
pPosAnchorVS = (DocPos*)((UNDO == doAct) ? utarray_front(pSel->anchorVS_undo) : utarray_front(pSel->anchorVS_redo));
pPosCurVS = (DocPos*)((UNDO == doAct) ? utarray_front(pSel->curVS_undo) : utarray_front(pSel->curVS_redo));
if (pPosAnchor && pPosCur)
{
// Ensure that the first and last lines of a selection are always unfolded
// This needs to be done _before_ the SCI_SETSEL message
DocLn const anchorPosLine = SciCall_LineFromPosition((*pPosAnchor));
DocLn const currPosLine = SciCall_LineFromPosition((*pPosCur));
PostMessage(hwndedit, SCI_ENSUREVISIBLE, anchorPosLine, 0);
if (anchorPosLine != currPosLine) { PostMessage(hwndedit, SCI_ENSUREVISIBLE, currPosLine, 0); }
int const selectionMode = (UNDO == doAct) ? pSel->selMode_undo : pSel->selMode_redo;
PostMessage(hwndedit, SCI_SETSELECTIONMODE, (WPARAM)((selectionMode == NP3_SEL_MULTI) ? SC_SEL_STREAM : selectionMode), 0);
switch (selectionMode)
{
case NP3_SEL_MULTI:
{
unsigned int i = 0;
DocPosU const selCount = (UNDO == doAct) ? utarray_len(pSel->anchorPos_undo) : utarray_len(pSel->anchorPos_redo);
DocPosU const selCountVS = (UNDO == doAct) ? utarray_len(pSel->anchorVS_undo) : utarray_len(pSel->anchorVS_redo);
PostMessage(hwndedit, SCI_SETSELECTION, (WPARAM)(*pPosCur), (LPARAM)(*pPosAnchor));
if (pPosAnchorVS && pPosCurVS) {
PostMessage(hwndedit, SCI_SETSELECTIONNANCHORVIRTUALSPACE, (WPARAM)0, (LPARAM)(*pPosAnchorVS));
PostMessage(hwndedit, SCI_SETSELECTIONNCARETVIRTUALSPACE, (WPARAM)0, (LPARAM)(*pPosCurVS));
}
PostMessage(hwndedit, SCI_CANCEL, 0, 0); // (!) else shift-key selection behavior is kept
++i;
while (i < selCount)
{
pPosAnchor = (DocPos*)((UNDO == doAct) ? utarray_eltptr(pSel->anchorPos_undo, i) : utarray_eltptr(pSel->anchorPos_redo, i));
pPosCur = (DocPos*)((UNDO == doAct) ? utarray_eltptr(pSel->curPos_undo, i) : utarray_eltptr(pSel->curPos_redo, i));
if (pPosAnchor && pPosCur) {
PostMessage(hwndedit, SCI_ADDSELECTION, (WPARAM)(*pPosCur), (LPARAM)(*pPosAnchor));
if (i < selCountVS) {
pPosAnchorVS = (DocPos*)((UNDO == doAct) ? utarray_eltptr(pSel->anchorVS_undo, i) : utarray_eltptr(pSel->anchorVS_redo, i));
pPosCurVS = (DocPos*)((UNDO == doAct) ? utarray_eltptr(pSel->curVS_undo, i) : utarray_eltptr(pSel->curVS_redo, i));
if (pPosAnchorVS && pPosCurVS) {
PostMessage(hwndedit, SCI_SETSELECTIONNANCHORVIRTUALSPACE, (WPARAM)i, (LPARAM)(*pPosAnchorVS));
PostMessage(hwndedit, SCI_SETSELECTIONNCARETVIRTUALSPACE, (WPARAM)i, (LPARAM)(*pPosCurVS));
}
}
}
++i;
}
//~PostMessage(hwndedit, SCI_SETMAINSELECTION, (WPARAM)0, (LPARAM)0);
}
break;
case SC_SEL_RECTANGLE:
case SC_SEL_THIN:
PostMessage(Globals.hwndEdit, SCI_SETRECTANGULARSELECTIONANCHOR, (WPARAM)(*pPosAnchor), 0);
PostMessage(Globals.hwndEdit, SCI_SETRECTANGULARSELECTIONCARET, (WPARAM)(*pPosCur), 0);
if (pPosAnchorVS && pPosCurVS) {
PostMessage(hwndedit, SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE, (WPARAM)(*pPosAnchorVS), 0);
PostMessage(hwndedit, SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE, (WPARAM)(*pPosCurVS), 0);
}
PostMessage(hwndedit, SCI_CANCEL, 0, 0); // (!) else shift-key selection behavior is kept
break;
case SC_SEL_LINES:
case SC_SEL_STREAM:
default:
PostMessage(hwndedit, SCI_SETSELECTION, (WPARAM)(*pPosCur), (LPARAM)(*pPosAnchor));
PostMessage(hwndedit, SCI_CANCEL, 0, 0); // (!) else shift-key selection behavior is kept
break;
}
}
PostMessage(hwndedit, SCI_SCROLLCARET, 0, 0);
PostMessage(hwndedit, SCI_CHOOSECARETX, 0, 0);
}
return true;
}
//=============================================================================
//
// _UndoRedoActionMap()
//
//
static int _UndoRedoActionMap(int token, const UndoRedoSelection_t** selection)
{
if (UndoRedoSelectionUTArray == NULL) { return -1; };
static unsigned int uiTokenCnt = 0U;
// indexing is unsigned
unsigned int utoken = (token >= 0) ? (unsigned int)token : 0U;
if (selection == NULL) {
// reset / clear
int const curToken = InterlockedOr(&UndoActionToken, 0L);
if (curToken >= 0) { EndUndoAction(curToken); }
utarray_clear(UndoRedoSelectionUTArray);
utarray_init(UndoRedoSelectionUTArray, &UndoRedoSelection_icd);
uiTokenCnt = 0U;
InterlockedExchange(&UndoActionToken, UNDOREDO_FREE);
return -1;
}
if (!SciCall_GetUndoCollection()) { return -1; }
// get or set map item request ?
if ((token >= 0) && (utoken < uiTokenCnt))
{
if ((*selection) == NULL) {
// this is a get request
(*selection) = (UndoRedoSelection_t*)utarray_eltptr(UndoRedoSelectionUTArray, utoken);
}
else {
// this is a set request (fill redo pos)
assert(false); // not used yet
//utarray_insert(UndoRedoSelectionUTArray, (void*)(*selection), utoken);
}
// don't clear map item here (token used in redo/undo again)
}
else if (token < 0) {
// set map new item request
token = (int)uiTokenCnt;
utarray_insert(UndoRedoSelectionUTArray, (void*)(*selection), uiTokenCnt);
uiTokenCnt = (uiTokenCnt < (unsigned int)INT_MAX) ? (uiTokenCnt + 1U) : 0U; // round robin next
}
return token;
}
//=============================================================================
//
// _SplitUndoTransaction()
//
//
static void _SplitUndoTransaction(const int iModType)
{
if (!_InUndoRedoTransaction()) {
if (!((iModType & SC_PERFORMED_UNDO) || (iModType & SC_PERFORMED_REDO))) {
SciCall_BeginUndoAction();
SciCall_EndUndoAction();
}
}
}
//=============================================================================
//
// FileIO()
//
//
bool FileIO(bool fLoad,LPWSTR pszFileName,
bool bSkipUnicodeDetect,bool bSkipANSICPDetection, bool bForceEncDetection, bool bSetSavePoint,
EditFileIOStatus* status, bool bSaveCopy, bool bPreserveTimeStamp)
{
WCHAR tch[MAX_PATH + 40];
FormatLngStringW(tch, COUNTOF(tch), (fLoad) ? IDS_MUI_LOADFILE : IDS_MUI_SAVEFILE, PathFindFileName(pszFileName));
bool fSuccess = false;
BeginWaitCursor(true,tch);
if (fLoad) {
fSuccess = EditLoadFile(Globals.hwndEdit,pszFileName,bSkipUnicodeDetect,bSkipANSICPDetection,bForceEncDetection,bSetSavePoint,status);
}
else {
int idx;
if (MRU_FindFile(Globals.pFileMRU,pszFileName,&idx)) {
Globals.pFileMRU->iEncoding[idx] = status->iEncoding;
Globals.pFileMRU->iCaretPos[idx] = (Settings.PreserveCaretPos ? SciCall_GetCurrentPos() : -1);
Globals.pFileMRU->iSelAnchPos[idx] = (Settings.PreserveCaretPos ? SciCall_GetAnchor() : -1);
WCHAR wchBookMarks[MRU_BMRK_SIZE] = { L'\0' };
EditGetBookmarkList(Globals.hwndEdit, wchBookMarks, COUNTOF(wchBookMarks));
if (Globals.pFileMRU->pszBookMarks[idx]) {
LocalFree(Globals.pFileMRU->pszBookMarks[idx]); // StrDup()
}
Globals.pFileMRU->pszBookMarks[idx] = StrDup(wchBookMarks);
}
fSuccess = EditSaveFile(Globals.hwndEdit, pszFileName, status, bSaveCopy, bPreserveTimeStamp);
}
s_bFileReadOnly = IsReadOnly(GetFileAttributes(pszFileName));
EndWaitCursor();
return(fSuccess);
}
//=============================================================================
//
// ConsistentIndentationCheck()
//
//
bool ConsistentIndentationCheck(EditFileIOStatus* status)
{
bool const hasTabOrSpaceIndent = (status->indentCount[I_TAB_LN] > 0) && (status->indentCount[I_SPC_LN] > 0);
bool const hasMixedIndents = (status->indentCount[I_MIX_LN] > 0);
//bool const hasIrregularIndentDepth = (status->indentCount[I_TAB_MOD_X] > 0) || (status->indentCount[I_SPC_MOD_X] > 0);
if (hasTabOrSpaceIndent || hasMixedIndents /*|| hasIrregularIndentDepth */)
{
if (WarnIndentationDlg(Globals.hwndMain, status))
{
bool const useTabs = SciCall_GetUseTabs();
SciCall_SetUseTabs(status->iGlobalIndent == I_TAB_LN);
bool const tabIndents = SciCall_GetTabIndents();
SciCall_SetTabIndents(true);
bool const backSpcUnindents = SciCall_GetBackSpaceUnIndents();
SciCall_SetBackSpaceUnIndents(true);
EditIndentBlock(Globals.hwndEdit, SCI_TAB, true, true);
EditIndentBlock(Globals.hwndEdit, SCI_BACKTAB, true, true);
SciCall_SetUseTabs(useTabs);
SciCall_SetTabIndents(tabIndents);
SciCall_SetBackSpaceUnIndents(backSpcUnindents);
}
else {
status->iGlobalIndent = I_MIX_LN;
return false;
}
}
return true;
}
//=============================================================================
//
// FileLoad()
//
//
bool FileLoad(bool bDontSave, bool bNew, bool bReload,
bool bSkipUnicodeDetect, bool bSkipANSICPDetection, bool bForceEncDetection, LPCWSTR lpszFile)
{
WCHAR szFilePath[MAX_PATH] = { L'\0' };
bool fSuccess = false;
EditFileIOStatus fioStatus = INIT_FILEIO_STATUS;
fioStatus.iEOLMode = Settings.DefaultEOLMode;
fioStatus.iEncoding = CPI_ANSI_DEFAULT;
if (!bDontSave)
{
if (!FileSave(false, true, false, false, Flags.bPreserveFileModTime)) {
return false;
}
}
if (!bReload) {
ResetEncryption();
}
if (bNew)
{
if (FocusedView.HideNonMatchedLines) { EditToggleView(Globals.hwndEdit); }
if (!s_IsThisAnElevatedRelaunch) {
Flags.bPreserveFileModTime = DefaultFlags.bPreserveFileModTime;
}
StringCchCopy(Globals.CurrentFile,COUNTOF(Globals.CurrentFile),L"");
SetDlgItemText(Globals.hwndMain,IDC_FILENAME,Globals.CurrentFile);
SetDlgItemInt(Globals.hwndMain,IDC_REUSELOCK,GetTickCount(),false);
if (!s_flagKeepTitleExcerpt) { StringCchCopy(s_wchTitleExcerpt, COUNTOF(s_wchTitleExcerpt), L""); }
FileVars_GetFromData(NULL,0,&Globals.fvCurFile); // init-reset
EditSetNewText(Globals.hwndEdit, "", 0, true);
SciCall_SetEOLMode(Settings.DefaultEOLMode);
Encoding_Current(Settings.DefaultEncoding);
Style_SetDefaultLexer(Globals.hwndEdit);
s_bFileReadOnly = false;
SetSavePoint();
UpdateMarginWidth();
UpdateStatusbar(true);
// Terminate file watching
if (FileWatching.ResetFileWatching) {
if (FileWatching.MonitoringLog) {
PostWMCommand(Globals.hwndMain, IDM_VIEW_CHASING_DOCTAIL);
}
FileWatching.FileWatchingMode = Settings.FileWatchingMode;
}
InstallFileWatching(NULL);
Flags.bSettingsFileSoftLocked = false;
UpdateSaveSettingsCmds();
COND_SHOW_ZOOM_CALLTIP();
return true;
}
if (StrIsEmpty(lpszFile)) {
if (!OpenFileDlg(Globals.hwndMain, szFilePath, COUNTOF(szFilePath), NULL)) {
return false;
}
}
else {
StringCchCopy(szFilePath, COUNTOF(szFilePath), lpszFile);
}
NormalizePathEx(szFilePath, COUNTOF(szFilePath), true, Flags.bSearchPathIfRelative);
// change current directory to prevent directory lock on another path
WCHAR szFolder[MAX_PATH];
if (SUCCEEDED(StringCchCopy(szFolder,COUNTOF(szFolder), szFilePath))) {
if (SUCCEEDED(PathCchRemoveFileSpec(szFolder,COUNTOF(szFolder)))) {
SetCurrentDirectory(szFolder);
}
}
// Ask to create a new file...
if (!bReload && !PathIsExistingFile(szFilePath))
{
bool bCreateFile = s_flagQuietCreate;
if (!bCreateFile) {
INT_PTR const answer = InfoBoxLng(MB_YESNO | MB_ICONQUESTION, NULL, IDS_MUI_ASK_CREATE, PathFindFileName(szFilePath));
if ((IDOK == answer) || (IDYES == answer)) {
bCreateFile = true;
}
}
if (bCreateFile) {
HANDLE hFile = CreateFile(szFilePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
Globals.dwLastError = GetLastError();
fSuccess = (hFile != INVALID_HANDLE_VALUE);
if (fSuccess) {
FileVars_GetFromData(NULL,0,&Globals.fvCurFile); // init/reset
EditSetNewText(Globals.hwndEdit,"",0, true);
Style_SetDefaultLexer(Globals.hwndEdit);
SciCall_SetEOLMode(Settings.DefaultEOLMode);
if (Encoding_IsValid(Encoding_Forced(CPI_GET))) {
fioStatus.iEncoding = Encoding_Forced(CPI_GET);
Encoding_Current(fioStatus.iEncoding);
}
else {
fioStatus.iEncoding = Globals.fvCurFile.iEncoding;
Encoding_Current(Globals.fvCurFile.iEncoding);
}
s_bFileReadOnly = false;
}
if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) {
CloseHandle(hFile);
}
}
else
return false;
}
else {
int idx;
if (!bReload && MRU_FindFile(Globals.pFileMRU,szFilePath,&idx)) {
fioStatus.iEncoding = Globals.pFileMRU->iEncoding[idx];
if (Encoding_IsValid(fioStatus.iEncoding)) {
Encoding_SrcWeak(fioStatus.iEncoding);
}
}
else {
fioStatus.iEncoding = Encoding_GetCurrent();
}
if (bReload && !FileWatching.MonitoringLog)
{
Sci_GotoPosChooseCaret(0);
_BEGIN_UNDO_ACTION_;
fSuccess = FileIO(true, szFilePath, bSkipUnicodeDetect, bSkipANSICPDetection, bForceEncDetection, !bReload , &fioStatus, false, false);
_END_UNDO_ACTION_;
}
else {
fSuccess = FileIO(true, szFilePath, bSkipUnicodeDetect, bSkipANSICPDetection, bForceEncDetection, !s_IsThisAnElevatedRelaunch, &fioStatus, false, false);
}
}
bool bUnknownLexer = s_flagLexerSpecified;
if (fSuccess)
{
BeginWaitCursor(true, L"Styling...");
Sci_GotoPosChooseCaret(0);
if (!s_IsThisAnElevatedRelaunch) {
Flags.bPreserveFileModTime = DefaultFlags.bPreserveFileModTime;
}
StringCchCopy(Globals.CurrentFile,COUNTOF(Globals.CurrentFile),szFilePath);
SetDlgItemText(Globals.hwndMain,IDC_FILENAME,Globals.CurrentFile);
SetDlgItemInt(Globals.hwndMain,IDC_REUSELOCK,GetTickCount(),false);
if (!s_flagKeepTitleExcerpt) {
StringCchCopy(s_wchTitleExcerpt, COUNTOF(s_wchTitleExcerpt), L"");
}
if (!s_flagLexerSpecified) { // flagLexerSpecified will be cleared
bUnknownLexer = !Style_SetLexerFromFile(Globals.hwndEdit, Globals.CurrentFile);
}
SciCall_SetEOLMode(fioStatus.iEOLMode);
Encoding_Current(fioStatus.iEncoding); // load may change encoding
int idx = 0;
DocPos iCaretPos = -1;
DocPos iAnchorPos = -1;
LPCWSTR pszBookMarks = L"";
if (!bReload && MRU_FindFile(Globals.pFileMRU,szFilePath,&idx)) {
iCaretPos = Globals.pFileMRU->iCaretPos[idx];
iAnchorPos = Globals.pFileMRU->iSelAnchPos[idx];
pszBookMarks = Globals.pFileMRU->pszBookMarks[idx];
}
if (!(Flags.bDoRelaunchElevated || s_IsThisAnElevatedRelaunch))
{
MRU_AddFile(Globals.pFileMRU, szFilePath, Flags.RelativeFileMRU, Flags.PortableMyDocs, fioStatus.iEncoding, iCaretPos, iAnchorPos, pszBookMarks);
}
EditSetBookmarkList(Globals.hwndEdit, pszBookMarks);
if (IsFindPatternEmpty()) {
SetFindPattern((Globals.pMRUfind ? Globals.pMRUfind->pszItems[0] : L""));
}
// Install watching of the current file
if (!bReload && FileWatching.ResetFileWatching) {
if (FileWatching.MonitoringLog) {
PostWMCommand(Globals.hwndMain, IDM_VIEW_CHASING_DOCTAIL);
}
FileWatching.FileWatchingMode = Settings.FileWatchingMode;
}
InstallFileWatching(Globals.CurrentFile);
// the .LOG feature ...
if (SciCall_GetTextLength() >= 4) {
char tchLog[5] = { '\0','\0','\0','\0','\0' };
SciCall_GetText(COUNTOF(tchLog), tchLog);
if (StringCchCompareXA(tchLog,".LOG") == 0) {
SciCall_DocumentEnd();
_BEGIN_UNDO_ACTION_;
SciCall_NewLine();
SendWMCommand(Globals.hwndMain, IDM_EDIT_INSERT_SHORTDATE);
SciCall_DocumentEnd();
SciCall_NewLine();
_END_UNDO_ACTION_;
SciCall_ScrollToEnd();
}
}
// set historic caret/selection pos
if ((iCaretPos >= 0) && (iAnchorPos >= 0) && (SciCall_GetCurrentPos() == 0))
{
EditSetSelectionEx(iAnchorPos, iCaretPos, -1, -1);
}
SetSavePoint();
// consistent settings file handling (if loaded in editor)
Flags.bSettingsFileSoftLocked = (StringCchCompareXIW(Globals.CurrentFile, Globals.IniFile) == 0);
UpdateSaveSettingsCmds();
COND_SHOW_ZOOM_CALLTIP();
// Show warning: Unicode file loaded as ANSI
if (fioStatus.bUnicodeErr) {
InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_ERR_UNICODE);
}
// Show inconsistent line endings warning
Globals.bDocHasInconsistentEOLs = fioStatus.bInconsistentEOLs;
bool const bCheckFile = !Globals.CmdLnFlag_PrintFileAndLeave
&& !fioStatus.bEncryptedRaw
&& !(fioStatus.bUnknownExt && bUnknownLexer)
&& !bReload;
//&& (fioStatus.iEncoding == CPI_ANSI_DEFAULT) ???
bool const bCheckEOL = bCheckFile && Globals.bDocHasInconsistentEOLs && Settings.WarnInconsistEOLs;
if (bCheckEOL && !Style_MaybeBinaryFile(Globals.hwndEdit, szFilePath))
{
if (WarnLineEndingDlg(Globals.hwndMain, &fioStatus)) {
SciCall_ConvertEOLs(fioStatus.iEOLMode);
Globals.bDocHasInconsistentEOLs = false;
}
SciCall_SetEOLMode(fioStatus.iEOLMode);
}
// Show inconsistent indentation
fioStatus.iGlobalIndent = I_MIX_LN; // init
bool const bCheckIndent = bCheckFile && !Flags.bLargeFileLoaded && Settings.WarnInconsistentIndents;
if (bCheckIndent && !Style_MaybeBinaryFile(Globals.hwndEdit, szFilePath))
{
EditIndentationStatistic(Globals.hwndEdit, &fioStatus);
ConsistentIndentationCheck(&fioStatus);
}
if (Settings.AutoDetectIndentSettings && !Globals.CmdLnFlag_PrintFileAndLeave)
{
if (!Settings.WarnInconsistentIndents || (fioStatus.iGlobalIndent != I_MIX_LN))
{
EditIndentationStatistic(Globals.hwndMain, &fioStatus); // new statistic needed
}
Globals.fvCurFile.bTabsAsSpaces = (fioStatus.indentCount[I_TAB_LN] < fioStatus.indentCount[I_SPC_LN]) ? true : false;
SciCall_SetUseTabs(!Globals.fvCurFile.bTabsAsSpaces);
}
EndWaitCursor();
}
else if (!(Flags.bLargeFileLoaded || fioStatus.bUnknownExt)) {
InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_ERR_LOADFILE, PathFindFileName(szFilePath));
}
UpdateTitleBar();
UpdateToolbar();
UpdateMarginWidth();
UpdateStatusbar(true);
return fSuccess;
}
//=============================================================================
//
// FileRevert()
//
//
bool FileRevert(LPCWSTR szFileName, bool bIgnoreCmdLnEnc)
{
if (StrIsEmpty(szFileName)) { return false; }
bool bPreserveView = true;
DocLn const curLineNum = Sci_GetCurrentLineNumber();
bool const bIsAtDocEnd = (curLineNum >= (Sci_GetLastDocLineNumber() - Settings2.CurrentLineVerticalSlop));
Encoding_SrcWeak(CPI_NONE);
if (bIgnoreCmdLnEnc) {
Encoding_Forced(CPI_NONE); // ignore history too
}
else {
Encoding_SrcWeak(Encoding_GetCurrent());
}
WCHAR tchFileName2[MAX_PATH] = { L'\0' };
StringCchCopyW(tchFileName2, COUNTOF(tchFileName2), szFileName);
if (!FileLoad(true, false, true, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchFileName2)) {
return false;
}
if (FileWatching.FileWatchingMode == FWM_AUTORELOAD) {
if (bIsAtDocEnd || FileWatching.MonitoringLog) {
bPreserveView = false;
SciCall_DocumentEnd();
EditEnsureSelectionVisible();
}
}
if (SciCall_GetTextLength() >= 4) {
char tch[5] = { '\0','\0','\0','\0','\0' };
SciCall_GetText(COUNTOF(tch), tch);
if (StringCchCompareXA(tch, ".LOG") == 0) {
SciCall_ClearSelections();
bPreserveView = false;
SciCall_DocumentEnd();
EditEnsureSelectionVisible();
}
}
SetSavePoint();
UpdateMarginWidth();
UpdateStatusbar(true);
if (bPreserveView) {
EditJumpTo(curLineNum + 1, 0);
}
return true;
}
//=============================================================================
//
// DoElevatedRelaunch()
//
//
bool DoElevatedRelaunch(EditFileIOStatus* pFioStatus, bool bAutoSaveOnRelaunch)
{
SaveAllSettings(false);
Flags.bDoRelaunchElevated = true;
LPWSTR lpCmdLine = GetCommandLine();
size_t const wlen = StringCchLen(lpCmdLine, 0) + 2;
LPWSTR lpExe = AllocMem(sizeof(WCHAR) * wlen, HEAP_ZERO_MEMORY);
LPWSTR lpArgs = AllocMem(sizeof(WCHAR) * wlen, HEAP_ZERO_MEMORY);
// ~ don't use original argument list (try to reconstruct current state as close as possible
#if 0
ExtractFirstArgument(lpCmdLine, lpExe, lpArgs, (int)wlen);
// remove relaunch elevated, we are doing this here already
lpArgs[StringCchLen(lpArgs, 0)] = L' '; // add a space
lpArgs = StrCutI(lpArgs, L"/u ");
lpArgs = StrCutI(lpArgs, L"-u ");
// remove forced command line encoding from argument list
WCHAR wchEncoding[80] = { L'\0' };
wchEncoding[0] = L'/';
Encoding_GetNameW(Encoding_Forced(CPI_GET), &wchEncoding[1], COUNTOF(wchEncoding)-1);
if (StrIsNotEmpty(&wchEncoding[1])) {
lpArgs = StrCutI(lpArgs, wchEncoding);
}
// remove file from argument list
if (s_lpOrigFileArg) {
lpArgs = StrCutI(lpArgs, s_lpOrigFileArg);
}
#else
lpArgs[0] = L'\0';
#endif
// ----------------------------------------------
WCHAR wchFlags[32] = { L'\0' };
if (s_flagAppIsClosing) {
StringCchCat(wchFlags, COUNTOF(wchFlags), L"/UC ");
}
if (bAutoSaveOnRelaunch) {
StringCchCat(wchFlags, COUNTOF(wchFlags), L"/QS ");
}
if (Flags.bPreserveFileModTime) {
StringCchCat(wchFlags, COUNTOF(wchFlags), L"/RP ");
}
DocPos const iCurPos = SciCall_GetCurrentPos();
int const iCurLn = (int)SciCall_LineFromPosition(iCurPos) + 1;
int const iCurCol = (int)SciCall_GetColumn(iCurPos) + 1;
WININFO const wi = GetMyWindowPlacement(Globals.hwndMain, NULL);
WCHAR szArguments[2048] = { L'\0' };
StringCchPrintf(szArguments, COUNTOF(szArguments),
L"%s/pos %i,%i,%i,%i,%i /g %i,%i %s", wchFlags, wi.x, wi.y, wi.cx, wi.cy, wi.max, iCurLn, iCurCol, lpArgs);
WCHAR lpTempPathBuffer[MAX_PATH] = { L'\0' };
WCHAR szTempFileName[MAX_PATH] = { L'\0' };
const WCHAR* szCurFile = StrIsNotEmpty(Globals.CurrentFile) ? Globals.CurrentFile : L".\\Untitled.txt";
WCHAR tchBase[MAX_PATH] = { L'\0' };
StringCchCopy(tchBase, COUNTOF(tchBase), PathFindFileName(szCurFile)); // eq. PathStripPath(tchBase);
if (GetTempPath(MAX_PATH, lpTempPathBuffer) && GetTempFileName(lpTempPathBuffer, TEXT("NP3"), 0, szTempFileName))
{
size_t const len = StringCchLen(szTempFileName, MAX_PATH); // replace possible unknown extension
LPWSTR p = PathFindExtension(szTempFileName);
LPCWSTR q = PathFindExtension(szCurFile);
if ((p && *p) && (q && *q)) {
StringCchCopy(p, (MAX_PATH - len), q);
}
if (pFioStatus && FileIO(false, szTempFileName, true, true, false, true, pFioStatus, true, false))
{
// preserve encoding
WCHAR wchEncoding[80] = { L'\0' };
Encoding_GetNameW(Encoding_GetCurrent(), wchEncoding, COUNTOF(wchEncoding));
StringCchPrintf(szArguments, COUNTOF(szArguments),
L"%s/%s /pos %i,%i,%i,%i,%i /g %i,%i /%s\"%s\" %s",
wchFlags, wchEncoding, wi.x, wi.y, wi.cx, wi.cy, wi.max, iCurLn, iCurCol, RELAUNCH_ELEVATED_BUF_ARG, szTempFileName, lpArgs);
if (!StrStrI(szArguments, tchBase)) {
if (StrIsNotEmpty(Globals.CurrentFile)) {
StringCchPrintf(szArguments, COUNTOF(szArguments), L"%s \"%s\"", szArguments, Globals.CurrentFile);
}
}
}
FreeMem(lpExe);
FreeMem(lpArgs);
}
if (RelaunchElevated(szArguments)) {
// set no change and quit
SetSavePoint();
}
else {
Globals.dwLastError = GetLastError();
if (PathFileExists(szTempFileName)) {
DeleteFile(szTempFileName);
}
Flags.bDoRelaunchElevated = false;
}
return Flags.bDoRelaunchElevated;
}
//=============================================================================
//
// FileSave()
//
//
bool FileSave(bool bSaveAlways, bool bAsk, bool bSaveAs, bool bSaveCopy, bool bPreserveTimeStamp)
{
bool fSuccess = false;
EditFileIOStatus fioStatus = INIT_FILEIO_STATUS;
fioStatus.iEncoding = Encoding_GetCurrent();
fioStatus.iEOLMode = SciCall_GetEOLMode();
#if 0
bool bIsEmptyNewFile = false;
if (StrIsEmpty(Globals.CurrentFile)) {
DocPos const cchText = SciCall_GetTextLength();
if (cchText <= 0) {
bIsEmptyNewFile = true;
}
else if (cchText < 2048) {
char chTextBuf[2048] = { '\0' };
SciCall_GetText(COUNTOF(chTextBuf), chTextBuf);
StrTrimA(chTextBuf, " \t\n\r");
if (StrIsEmptyA(chTextBuf)) {
bIsEmptyNewFile = true;
}
}
}
#else
bool const bIsEmptyNewFile = (StrIsEmpty(Globals.CurrentFile) && (SciCall_GetTextLength() <= 0LL));
#endif
if (!bSaveAlways && (!GetDocModified() || bIsEmptyNewFile) && !bSaveAs) {
int idx;
if (MRU_FindFile(Globals.pFileMRU, Globals.CurrentFile, &idx)) {
Globals.pFileMRU->iEncoding[idx] = Encoding_GetCurrent();
Globals.pFileMRU->iCaretPos[idx] = (Settings.PreserveCaretPos) ? SciCall_GetCurrentPos() : -1;
Globals.pFileMRU->iSelAnchPos[idx] = (Settings.PreserveCaretPos) ? SciCall_GetAnchor() : -1;
WCHAR wchBookMarks[MRU_BMRK_SIZE] = {L'\0'};
EditGetBookmarkList(Globals.hwndEdit, wchBookMarks, COUNTOF(wchBookMarks));
if (Globals.pFileMRU->pszBookMarks[idx]) {
LocalFree(Globals.pFileMRU->pszBookMarks[idx]); // StrDup()
}
Globals.pFileMRU->pszBookMarks[idx] = StrDup(wchBookMarks);
}
return true;
}
if (bAsk)
{
// File or "Untitled" ...
WCHAR tch[MAX_PATH] = { L'\0' };
if (StrIsNotEmpty(Globals.CurrentFile)) {
StringCchCopy(tch, COUNTOF(tch), PathFindFileName(Globals.CurrentFile)); // eq. PathStripPath(tch);
}
else {
GetLngString(IDS_MUI_UNTITLED, tch, COUNTOF(tch));
}
INT_PTR const answer = (Settings.MuteMessageBeep) ?
InfoBoxLng(MB_YESNOCANCEL | MB_ICONWARNING, NULL, IDS_MUI_ASK_SAVE, tch) :
MessageBoxLng(MB_YESNOCANCEL | MB_ICONWARNING, IDS_MUI_ASK_SAVE, tch);
switch (answer)
//switch ()
{
case IDCANCEL:
return false;
case IDNO:
return true;
default:
// proceed
break;
}
}
// Read only...
if (!bSaveAs && !bSaveCopy && StrIsNotEmpty(Globals.CurrentFile))
{
s_bFileReadOnly = IsReadOnly(GetFileAttributes(Globals.CurrentFile));
if (s_bFileReadOnly) {
INT_PTR const answer = (Settings.MuteMessageBeep) ?
InfoBoxLng(MB_YESNO | MB_ICONWARNING, NULL, IDS_MUI_READONLY_SAVE, PathFindFileName(Globals.CurrentFile)) :
MessageBoxLng(MB_YESNO | MB_ICONWARNING, IDS_MUI_READONLY_SAVE, Globals.CurrentFile);
if ((IDOK == answer) || (IDYES == answer)) {
bSaveAs = true;
}
else {
return false;
}
}
}
// Save As...
if (bSaveAs || bSaveCopy || StrIsEmpty(Globals.CurrentFile))
{
WCHAR tchFile[MAX_PATH] = { L'\0' };
WCHAR tchInitialDir[MAX_PATH] = { L'\0' };
if (bSaveCopy && StrIsNotEmpty(s_tchLastSaveCopyDir)) {
StringCchCopy(tchInitialDir, COUNTOF(tchInitialDir), s_tchLastSaveCopyDir);
StringCchCopy(tchFile, COUNTOF(tchFile), s_tchLastSaveCopyDir);
PathCchAppend(tchFile, COUNTOF(tchFile), PathFindFileName(Globals.CurrentFile));
}
else {
StringCchCopy(tchFile, COUNTOF(tchFile), Globals.CurrentFile);
}
if (SaveFileDlg(Globals.hwndMain, tchFile, COUNTOF(tchFile), tchInitialDir))
{
fSuccess = FileIO(false, tchFile, true, true, false, true, &fioStatus, bSaveCopy, bPreserveTimeStamp);
if (fSuccess)
{
if (!bSaveCopy)
{
StringCchCopy(Globals.CurrentFile, COUNTOF(Globals.CurrentFile), tchFile);
SetDlgItemText(Globals.hwndMain, IDC_FILENAME, Globals.CurrentFile);
SetDlgItemInt(Globals.hwndMain, IDC_REUSELOCK, GetTickCount(), false);
if (!s_flagKeepTitleExcerpt) {
StringCchCopy(s_wchTitleExcerpt, COUNTOF(s_wchTitleExcerpt), L"");
}
Style_SetLexerFromFile(Globals.hwndEdit, Globals.CurrentFile);
}
else {
StringCchCopy(s_tchLastSaveCopyDir, COUNTOF(s_tchLastSaveCopyDir), tchFile);
PathCchRemoveFileSpec(s_tchLastSaveCopyDir, COUNTOF(s_tchLastSaveCopyDir));
}
}
}
else {
return false;
}
}
else {
fSuccess = FileIO(false, Globals.CurrentFile, true, true, false, true, &fioStatus, false, bPreserveTimeStamp);
}
if (fSuccess)
{
if (!(bSaveCopy || Flags.bDoRelaunchElevated))
{
cpi_enc_t iCurrEnc = Encoding_GetCurrent();
const DocPos iCaretPos = SciCall_GetCurrentPos();
const DocPos iAnchorPos = Sci_IsMultiOrRectangleSelection() ? -1 : SciCall_GetAnchor();
WCHAR wchBookMarks[MRU_BMRK_SIZE] = { L'\0' };
EditGetBookmarkList(Globals.hwndEdit, wchBookMarks, COUNTOF(wchBookMarks));
MRU_AddFile(Globals.pFileMRU, Globals.CurrentFile, Flags.RelativeFileMRU, Flags.PortableMyDocs, iCurrEnc, iCaretPos, iAnchorPos, wchBookMarks);
SetSavePoint();
// Install watching of the current file
if (bSaveAs && Settings.ResetFileWatching) {
if (FileWatching.MonitoringLog) {
PostWMCommand(Globals.hwndMain, IDM_VIEW_CHASING_DOCTAIL);
}
FileWatching.FileWatchingMode = Settings.FileWatchingMode;
}
InstallFileWatching(Globals.CurrentFile);
}
// if current file is settings/config file: ask to start
if (Flags.bSettingsFileSoftLocked && !s_flagAppIsClosing)
{
//~ LoadSettings(); NOT all settings will be applied ...
INT_PTR answer = 0;
if (Settings.SaveSettings) {
WCHAR tch[256] = { L'\0' };
LoadLngStringW(IDS_MUI_RELOADCFGSEX, tch, COUNTOF(tch));
answer = InfoBoxLng(MB_YESNO | MB_ICONWARNING, L"ReloadExSavedCfg", IDS_MUI_RELOADSETTINGS, tch);
}
else {
answer = InfoBoxLng(MB_YESNO | MB_ICONINFORMATION, L"ReloadExSavedCfg", IDS_MUI_RELOADSETTINGS, L"");
}
if ((IDOK == answer) || (IDYES == answer))
{
DialogNewWindow(Globals.hwndMain, false, Globals.CurrentFile);
CloseApplication();
}
}
}
else if (!fioStatus.bCancelDataLoss)
{
LPCWSTR const currentFileName = PathFindFileName(Globals.CurrentFile);
if (!s_bIsProcessElevated && (Globals.dwLastError == ERROR_ACCESS_DENIED))
{
INT_PTR const answer = (Settings.MuteMessageBeep) ?
InfoBoxLng(MB_YESNO | MB_ICONSHIELD, NULL, IDS_MUI_ERR_ACCESSDENIED, currentFileName, _W(SAPPNAME)) :
MessageBoxLng(MB_YESNO | MB_ICONSHIELD, IDS_MUI_ERR_ACCESSDENIED, Globals.CurrentFile, _W(SAPPNAME));
if ((IDOK == answer) || (IDYES == answer))
{
if (DoElevatedRelaunch(&fioStatus, true))
{
CloseApplication();
}
else {
s_flagAppIsClosing = false;
if (Settings.MuteMessageBeep) {
InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_ERR_SAVEFILE, currentFileName);
}
else {
MessageBoxLng(MB_ICONWARNING, IDS_MUI_ERR_SAVEFILE, Globals.CurrentFile);
}
}
}
}
else {
if (Settings.MuteMessageBeep) {
InfoBoxLng(MB_ICONERROR, NULL, IDS_MUI_ERR_SAVEFILE, currentFileName);
}
else {
MessageBoxLng(MB_ICONERROR, IDS_MUI_ERR_SAVEFILE, Globals.CurrentFile);
}
}
}
return fSuccess;
}
//=============================================================================
//
// OpenFileDlg()
//
//
static WCHAR s_szFilter[NUMLEXERS * AVG_NUM_OF_STYLES_PER_LEXER * 100];
bool OpenFileDlg(HWND hwnd,LPWSTR lpstrFile,int cchFile,LPCWSTR lpstrInitialDir)
{
OPENFILENAME ofn;
WCHAR szFile[MAX_PATH] = { L'\0' };
WCHAR tchInitialDir[MAX_PATH] = { L'\0' };
Style_GetOpenDlgFilterStr(s_szFilter,COUNTOF(s_szFilter));
if (!lpstrInitialDir) {
if (StrIsNotEmpty(Globals.CurrentFile)) {
StringCchCopy(tchInitialDir,COUNTOF(tchInitialDir),Globals.CurrentFile);
PathCchRemoveFileSpec(tchInitialDir, COUNTOF(tchInitialDir));
}
else if (StrIsNotEmpty(Settings2.DefaultDirectory)) {
ExpandEnvironmentStrings(Settings2.DefaultDirectory,tchInitialDir,COUNTOF(tchInitialDir));
if (PathIsRelative(tchInitialDir)) {
WCHAR tchModule[MAX_PATH] = { L'\0' };
PathGetAppDirectory(tchModule, COUNTOF(tchModule));
PathCchAppend(tchModule,COUNTOF(tchModule),tchInitialDir);
}
}
else
StringCchCopy(tchInitialDir,COUNTOF(tchInitialDir),Globals.WorkingDirectory);
}
ZeroMemory(&ofn,sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = s_szFilter;
ofn.lpstrFile = szFile;
ofn.lpstrInitialDir = (lpstrInitialDir) ? lpstrInitialDir : tchInitialDir;
ofn.nMaxFile = COUNTOF(szFile);
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | /* OFN_NOCHANGEDIR |*/
OFN_DONTADDTORECENT | OFN_PATHMUSTEXIST |
OFN_SHAREAWARE /*| OFN_NODEREFERENCELINKS*/;
ofn.lpstrDefExt = StrIsNotEmpty(Settings2.DefaultExtension) ? Settings2.DefaultExtension : NULL;
if (GetOpenFileName(&ofn)) {
StringCchCopyN(lpstrFile,cchFile,szFile,COUNTOF(szFile));
return true;
}
return false;
}
//=============================================================================
//
// SaveFileDlg()
//
//
bool SaveFileDlg(HWND hwnd,LPWSTR lpstrFile,int cchFile,LPCWSTR lpstrInitialDir)
{
OPENFILENAME ofn;
WCHAR szNewFile[MAX_PATH] = { L'\0' };
WCHAR tchInitialDir[MAX_PATH] = { L'\0' };
StringCchCopy(szNewFile,COUNTOF(szNewFile),lpstrFile);
Style_GetOpenDlgFilterStr(s_szFilter,COUNTOF(s_szFilter));
if (StrIsNotEmpty(lpstrInitialDir)) {
StringCchCopy(tchInitialDir, COUNTOF(tchInitialDir), lpstrInitialDir);
}
else if (StrIsNotEmpty(Globals.CurrentFile)) {
StringCchCopy(tchInitialDir,COUNTOF(tchInitialDir),Globals.CurrentFile);
PathCchRemoveFileSpec(tchInitialDir, COUNTOF(tchInitialDir));
}
else if (StrIsNotEmpty(Settings2.DefaultDirectory)) {
ExpandEnvironmentStrings(Settings2.DefaultDirectory,tchInitialDir,COUNTOF(tchInitialDir));
if (PathIsRelative(tchInitialDir)) {
WCHAR tchModule[MAX_PATH] = { L'\0' };
PathGetAppDirectory(tchModule, COUNTOF(tchModule));
PathCchAppend(tchModule,COUNTOF(tchModule),tchInitialDir);
}
}
else {
StringCchCopy(tchInitialDir, COUNTOF(tchInitialDir), Globals.WorkingDirectory);
}
ZeroMemory(&ofn,sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = s_szFilter;
ofn.lpstrFile = szNewFile;
ofn.lpstrInitialDir = tchInitialDir;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_HIDEREADONLY /*| OFN_NOCHANGEDIR*/ |
/*OFN_NODEREFERENCELINKS |*/ OFN_OVERWRITEPROMPT |
OFN_DONTADDTORECENT | OFN_PATHMUSTEXIST;
ofn.lpstrDefExt = StrIsNotEmpty(Settings2.DefaultExtension) ? Settings2.DefaultExtension : NULL;
if (GetSaveFileName(&ofn)) {
StringCchCopyN(lpstrFile,cchFile,szNewFile,COUNTOF(szNewFile));
return true;
}
return false;
}
/******************************************************************************
*
* ActivatePrevInst()
*
* Tries to find and activate an already open Notepad3 Window
*
*
******************************************************************************/
BOOL CALLBACK EnumWndProc(HWND hwnd,LPARAM lParam)
{
BOOL bContinue = TRUE;
WCHAR szClassName[64] = { L'\0' };
if (GetClassName(hwnd,szClassName,COUNTOF(szClassName)))
if (StringCchCompareNIW(szClassName,COUNTOF(szClassName),s_wchWndClass,COUNTOF(s_wchWndClass)) == 0) {
DWORD const dwReuseLock = GetDlgItemInt(hwnd, IDC_REUSELOCK, NULL, FALSE);
if (GetTickCount() - dwReuseLock >= REUSEWINDOWLOCKTIMEOUT) {
*(HWND*)lParam = hwnd;
if (IsWindowEnabled(hwnd))
bContinue = FALSE;
}
}
return bContinue;
}
BOOL CALLBACK EnumWndProc2(HWND hwnd,LPARAM lParam)
{
BOOL bContinue = TRUE;
WCHAR szClassName[64] = { L'\0' };
if (GetClassName(hwnd,szClassName,COUNTOF(szClassName)))
if (StringCchCompareNIW(szClassName,COUNTOF(szClassName),s_wchWndClass,COUNTOF(s_wchWndClass)) == 0) {
DWORD const dwReuseLock = GetDlgItemInt(hwnd,IDC_REUSELOCK,NULL, FALSE);
if (GetTickCount() - dwReuseLock >= REUSEWINDOWLOCKTIMEOUT)
{
if (IsWindowEnabled(hwnd)) { bContinue = FALSE; }
WCHAR tchFileName[MAX_PATH] = { L'\0' };
GetDlgItemText(hwnd, IDC_FILENAME, tchFileName, COUNTOF(tchFileName));
if (StringCchCompareXI(tchFileName, s_lpFileArg) == 0) {
*(HWND*)lParam = hwnd;
}
else {
bContinue = TRUE;
}
}
}
return bContinue;
}
bool ActivatePrevInst()
{
HWND hwnd = NULL;
COPYDATASTRUCT cds;
if ((!Flags.bReuseWindow && !Flags.bSingleFileInstance) || s_flagStartAsTrayIcon || s_flagNewFromClipboard || s_flagPasteBoard) {
return false;
}
if (Flags.bSingleFileInstance && StrIsNotEmpty(s_lpFileArg))
{
NormalizePathEx(s_lpFileArg, COUNTOF(s_lpFileArg), true, Flags.bSearchPathIfRelative);
EnumWindows(EnumWndProc2,(LPARAM)&hwnd);
if (hwnd != NULL)
{
// Enabled
if (IsWindowEnabled(hwnd))
{
// Make sure the previous window won't pop up a change notification message
//SendMessage(hwnd,WM_CHANGENOTIFYCLEAR,0,0);
if (IsIconic(hwnd)) {
ShowWindowAsync(hwnd, SW_RESTORE);
}
if (!IsWindowVisible(hwnd)) {
SendMessage(hwnd,WM_TRAYMESSAGE,0,WM_LBUTTONDBLCLK);
SendMessage(hwnd,WM_TRAYMESSAGE,0,WM_LBUTTONUP);
}
SetForegroundWindow(hwnd);
size_t cb = sizeof(np3params);
if (s_lpSchemeArg) {
cb += ((StringCchLen(s_lpSchemeArg, 0) + 1) * sizeof(WCHAR));
}
if (!IsFindPatternEmpty()) {
cb += ((LengthOfFindPattern() + 1) * sizeof(WCHAR));
}
LPnp3params params = AllocMem(cb, HEAP_ZERO_MEMORY);
params->flagFileSpecified = false;
params->flagChangeNotify = FWM_DONT_CARE;
params->flagQuietCreate = false;
params->flagLexerSpecified = s_flagLexerSpecified ? 1 : 0;
if (s_flagLexerSpecified && s_lpSchemeArg) {
StringCchCopy(StrEnd(&params->wchData,0)+1,(StringCchLen(s_lpSchemeArg,0)+1),s_lpSchemeArg);
params->iInitialLexer = -1;
}
else {
params->iInitialLexer = s_iInitialLexer;
}
params->flagJumpTo = s_flagJumpTo ? 1 : 0;
params->iInitialLine = s_iInitialLine;
params->iInitialColumn = s_iInitialColumn;
params->flagSetEncoding = s_flagSetEncoding;
params->flagSetEOLMode = s_flagSetEOLMode;
params->flagTitleExcerpt = 0;
params->flagMatchText = g_flagMatchText;
if (!IsFindPatternEmpty()) {
StringCchCopy(StrEnd(&params->wchData, 0) + 1, (LengthOfFindPattern() + 1), GetFindPattern());
}
cds.dwData = DATA_NOTEPAD3_PARAMS;
cds.cbData = (DWORD)SizeOfMem(params);
cds.lpData = params;
SendMessage(hwnd,WM_COPYDATA,(WPARAM)NULL,(LPARAM)&cds);
FreeMem(params); params = NULL;
return true;
}
// IsWindowEnabled()
INT_PTR const answer = InfoBoxLng(MB_YESNO | MB_ICONWARNING, NULL, IDS_MUI_ERR_PREVWINDISABLED);
if ((IDOK == answer) || (IDYES == answer)) {
return false;
}
return true;
}
}
if (!Flags.bReuseWindow) {
return false;
}
hwnd = NULL;
EnumWindows(EnumWndProc,(LPARAM)&hwnd);
// Found a window
if (hwnd != NULL)
{
// Enabled
if (IsWindowEnabled(hwnd))
{
// Make sure the previous window won't pop up a change notification message
//SendMessage(hwnd,WM_CHANGENOTIFYCLEAR,0,0);
if (IsIconic(hwnd)) {
ShowWindowAsync(hwnd, SW_RESTORE);
}
if (!IsWindowVisible(hwnd)) {
SendMessage(hwnd,WM_TRAYMESSAGE,0,WM_LBUTTONDBLCLK);
SendMessage(hwnd,WM_TRAYMESSAGE,0,WM_LBUTTONUP);
}
SetForegroundWindow(hwnd);
if (StrIsNotEmpty(s_lpFileArg))
{
size_t cb = sizeof(np3params);
cb += (StringCchLenW(s_lpFileArg,0) + 1) * sizeof(WCHAR);
if (s_lpSchemeArg) {
cb += (StringCchLenW(s_lpSchemeArg, 0) + 1) * sizeof(WCHAR);
}
size_t cchTitleExcerpt = StringCchLenW(s_wchTitleExcerpt,COUNTOF(s_wchTitleExcerpt));
if (cchTitleExcerpt) {
cb += (cchTitleExcerpt + 1) * sizeof(WCHAR);
}
if (!IsFindPatternEmpty()) {
cb += ((LengthOfFindPattern() + 1) * sizeof(WCHAR));
}
LPnp3params params = AllocMem(cb, HEAP_ZERO_MEMORY);
params->flagFileSpecified = true;
StringCchCopy(&params->wchData, StringCchLenW(s_lpFileArg,0)+1,s_lpFileArg);
params->flagChangeNotify = s_flagChangeNotify;
params->flagQuietCreate = s_flagQuietCreate ? 1 : 0;
params->flagLexerSpecified = s_flagLexerSpecified ? 1 : 0;
if (s_flagLexerSpecified && s_lpSchemeArg) {
StringCchCopy(StrEnd(&params->wchData,0)+1, StringCchLen(s_lpSchemeArg,0)+1,s_lpSchemeArg);
params->iInitialLexer = -1;
}
else {
params->iInitialLexer = s_iInitialLexer;
}
params->flagJumpTo = s_flagJumpTo ? 1 : 0;
params->iInitialLine = s_iInitialLine;
params->iInitialColumn = s_iInitialColumn;
params->flagSetEncoding = s_flagSetEncoding;
params->flagSetEOLMode = s_flagSetEOLMode;
if (cchTitleExcerpt) {
StringCchCopy(StrEnd(&params->wchData,0)+1,cchTitleExcerpt+1,s_wchTitleExcerpt);
params->flagTitleExcerpt = 1;
}
else {
params->flagTitleExcerpt = 0;
}
params->flagMatchText = g_flagMatchText;
if (!IsFindPatternEmpty()) {
StringCchCopy(StrEnd(&params->wchData, 0) + 1, (LengthOfFindPattern() + 1), GetFindPattern());
}
cds.dwData = DATA_NOTEPAD3_PARAMS;
cds.cbData = (DWORD)SizeOfMem(params);
cds.lpData = params;
SendMessage(hwnd,WM_COPYDATA,(WPARAM)NULL,(LPARAM)&cds);
FreeMem(params); params = NULL;
s_lpFileArg[0] = L'\0';
}
return true;
}
// IsWindowEnabled()
INT_PTR const answer = InfoBoxLng(MB_YESNO | MB_ICONWARNING, NULL, IDS_MUI_ERR_PREVWINDISABLED);
return ((IDOK == answer) || (IDYES == answer)) ? false : true;;
}
return false;
}
//=============================================================================
//
// RelaunchMultiInst()
//
//
bool RelaunchMultiInst() {
if (Flags.MultiFileArg && (s_cFileList > 1))
{
LPWSTR lpCmdLineNew = StrDup(GetCommandLine());
size_t len = StringCchLen(lpCmdLineNew,0) + 1UL;
LPWSTR lp1 = AllocMem(sizeof(WCHAR)*len, HEAP_ZERO_MEMORY);
LPWSTR lp2 = AllocMem(sizeof(WCHAR)*len, HEAP_ZERO_MEMORY);
StrTab2Space(lpCmdLineNew);
StringCchCopy(lpCmdLineNew + s_cchiFileList,2,L"");
WCHAR* pwch = CharPrev(lpCmdLineNew,StrEnd(lpCmdLineNew,len));
int k = 0;
while (*pwch == L' ' || *pwch == L'-' || *pwch == L'+') {
*pwch = L' ';
pwch = CharPrev(lpCmdLineNew,pwch);
if (k++ > 1)
s_cchiFileList--;
}
for (int i = 0; i < s_cFileList; i++)
{
StringCchCopy(lpCmdLineNew + s_cchiFileList,8,L" /n - ");
StringCchCat(lpCmdLineNew,len,s_lpFileList[i]);
LocalFree(s_lpFileList[i]); // StrDup()
STARTUPINFO si;
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION pi;
ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
CreateProcess(NULL, lpCmdLineNew, NULL, NULL, false, CREATE_NEW_PROCESS_GROUP, NULL, Globals.WorkingDirectory, &si, &pi);
// don't wait for it to finish.
//::WaitForSingleObject(pi.hProcess, INFINITE);
// free up resources...
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
LocalFree(lpCmdLineNew); // StrDup()
FreeMem(lp1);
FreeMem(lp2);
s_lpFileArg[0] = L'\0';
return true;
}
for (int i = 0; i < s_cFileList; i++) {
LocalFree(s_lpFileList[i]); // StrDup()
}
return false;
}
//=============================================================================
//
// RelaunchElevated()
//
//
bool RelaunchElevated(LPWSTR lpNewCmdLnArgs)
{
if (!IsWindowsVistaOrGreater() || !Flags.bDoRelaunchElevated ||
s_bIsProcessElevated || s_IsThisAnElevatedRelaunch || s_bIsRunAsAdmin ||
s_flagDisplayHelp)
{
return false; // reject initial RelaunchElevated() try
}
STARTUPINFO si;
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
WCHAR lpExe[MAX_PATH] = { L'\0' };
WCHAR szOrigArgs[2032] = { L'\0' };
LPWSTR lpCmdLine = GetCommandLine();
size_t wlen = StringCchLenW(lpCmdLine, 0) + 2UL;
ExtractFirstArgument(lpCmdLine, lpExe, szOrigArgs, (int)wlen);
// override
GetModuleFileName(NULL, lpExe, COUNTOF(lpExe)); // full path
PathCanonicalizeEx(lpExe, COUNTOF(lpExe));
if (lpNewCmdLnArgs) {
StringCchCopy(szOrigArgs, COUNTOF(szOrigArgs), lpNewCmdLnArgs);
}
size_t const len = StringCchLen(szOrigArgs, 0);
szOrigArgs[len] = L' '; // add a space
szOrigArgs[len+1] = L'\0'; // ensure termination
// remove relaunch elevated, we are doing this here already
StrCutI(szOrigArgs, L"/u ");
StrCutI(szOrigArgs, L"-u ");
WCHAR szArguments[2032] = { L'\0' };
if (StrStrI(szOrigArgs, L"/f ") || StrStrI(szOrigArgs, L"-f ") || StrIsEmpty(Globals.IniFile))
{
StringCchCopy(szArguments, COUNTOF(szArguments), szOrigArgs);
}
else {
StringCchPrintf(szArguments, COUNTOF(szArguments), L"/f \"%s\" %s", Globals.IniFile, szOrigArgs);
}
if (StrIsNotEmpty(szArguments)) {
SHELLEXECUTEINFO sei;
ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO));
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_UNICODE | SEE_MASK_HMONITOR | SEE_MASK_NOZONECHECKS | SEE_MASK_WAITFORINPUTIDLE;
sei.hwnd = GetForegroundWindow();
sei.hMonitor = MonitorFromWindow(sei.hwnd, MONITOR_DEFAULTTONEAREST);
sei.lpVerb = L"runas";
sei.lpFile = lpExe;
sei.lpParameters = szArguments;
sei.lpDirectory = Globals.WorkingDirectory;
sei.nShow = si.wShowWindow ? si.wShowWindow : SW_SHOWNORMAL;
return ShellExecuteEx(&sei);
}
return false;
}
//=============================================================================
//
// SnapToWinInfoPos()
// Aligns Notepad3 to the default window position on the current screen
//
void SnapToWinInfoPos(HWND hwnd, const WININFO winInfo, SCREEN_MODE mode)
{
static bool s_bPrevShowMenubar = true;
static bool s_bPrevShowToolbar = true;
static bool s_bPrevShowStatusbar = true;
static WINDOWPLACEMENT s_wndplPrev;
s_wndplPrev.length = sizeof(WINDOWPLACEMENT);
UINT const fPrevFlags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED;
UINT const fFScrFlags = SWP_NOOWNERZORDER | SWP_FRAMECHANGED;
DWORD const dwRmvFScrStyle = WS_OVERLAPPEDWINDOW | WS_BORDER;
HWND const hWindow = hwnd ? hwnd : GetDesktopWindow();
DWORD dwStyle = GetWindowLong(hWindow, GWL_STYLE);
RECT rcCurrent; GetWindowRect(hWindow, &rcCurrent);
if ((mode == SCR_NORMAL) || s_bPrevFullScreenFlag)
{
SetWindowLong(hWindow, GWL_STYLE, dwStyle | dwRmvFScrStyle);
if (s_bPrevFullScreenFlag) {
SetWindowPlacement(hWindow, &s_wndplPrev); // 1st set correct screen (DPI Aware)
SetWindowPlacement(hWindow, &s_wndplPrev); // 2nd resize position to correct DPI settings
Settings.ShowMenubar = s_bPrevShowMenubar;
Settings.ShowToolbar = s_bPrevShowToolbar;
Settings.ShowStatusbar = s_bPrevShowStatusbar;
}
else {
WINDOWPLACEMENT wndpl = WindowPlacementFromInfo(hWindow, &winInfo, mode);
if (GetDoAnimateMinimize()) { DrawAnimatedRects(hWindow, IDANI_CAPTION, &rcCurrent, &wndpl.rcNormalPosition); }
SetWindowPlacement(hWindow, &wndpl); // 1st set correct screen (DPI Aware)
SetWindowPlacement(hWindow, &wndpl); // 2nd resize position to correct DPI settings
}
SetWindowPos(hWindow, (Settings.AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST), 0, 0, 0, 0, fPrevFlags);
s_bPrevFullScreenFlag = false;
}
else { // full screen mode
GetWindowPlacement(hWindow, &s_wndplPrev);
MONITORINFO mi = { sizeof(mi) };
GetMonitorInfo(MonitorFromWindow(hWindow, MONITOR_DEFAULTTOPRIMARY), &mi);
SetWindowLong(hWindow, GWL_STYLE, dwStyle & ~dwRmvFScrStyle);
WINDOWPLACEMENT wndpl = WindowPlacementFromInfo(hWindow, NULL, mode);
if (GetDoAnimateMinimize()) { DrawAnimatedRects(hWindow, IDANI_CAPTION, &rcCurrent, &wndpl.rcNormalPosition); }
SetWindowPlacement(hWindow, &wndpl);
SetWindowPos(hWindow, HWND_TOPMOST, mi.rcMonitor.left, mi.rcMonitor.top,
mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top, fFScrFlags);
s_bPrevShowMenubar = Settings.ShowMenubar;
s_bPrevShowToolbar = Settings.ShowToolbar;
s_bPrevShowStatusbar = Settings.ShowStatusbar;
Settings.ShowMenubar = Settings.ShowToolbar = Settings.ShowStatusbar = false;
s_bPrevFullScreenFlag = true;
}
SendWMSize(hWindow, NULL);
}
//=============================================================================
//
// ShowNotifyIcon()
//
//
void ShowNotifyIcon(HWND hwnd,bool bAdd)
{
static HICON hIcon = NULL;
if (!hIcon) {
LoadIconWithScaleDown(Globals.hInstance, MAKEINTRESOURCE(IDR_MAINWND),
GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), &hIcon);
}
NOTIFYICONDATA nid;
ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hwnd;
nid.uID = 0;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.uCallbackMessage = WM_TRAYMESSAGE;
nid.hIcon = hIcon;
StringCchCopy(nid.szTip,COUNTOF(nid.szTip), _W(SAPPNAME));
if(bAdd)
Shell_NotifyIcon(NIM_ADD,&nid);
else
Shell_NotifyIcon(NIM_DELETE,&nid);
}
//=============================================================================
//
// SetNotifyIconTitle()
//
//
void SetNotifyIconTitle(HWND hwnd)
{
NOTIFYICONDATA nid;
ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hwnd;
nid.uID = 0;
nid.uFlags = NIF_TIP;
WCHAR tchTitle[256] = { L'\0' };
if (StrIsNotEmpty(s_wchTitleExcerpt)) {
WCHAR tchFormat[32] = { L'\0' };
GetLngString(IDS_MUI_TITLEEXCERPT,tchFormat,COUNTOF(tchFormat));
StringCchPrintf(tchTitle,COUNTOF(tchTitle),tchFormat,s_wchTitleExcerpt);
}
else if (StrIsNotEmpty(Globals.CurrentFile)) {
WCHAR szDisplayName[MAX_PATH];
PathGetDisplayName(szDisplayName, COUNTOF(szDisplayName), Globals.CurrentFile);
PathCompactPathEx(tchTitle,szDisplayName,COUNTOF(tchTitle)-4,0);
}
else {
GetLngString(IDS_MUI_UNTITLED, tchTitle, COUNTOF(tchTitle) - 4);
}
if (GetDocModified()) {
StringCchCopy(nid.szTip, COUNTOF(nid.szTip), L"* ");
}
else {
StringCchCopy(nid.szTip, COUNTOF(nid.szTip), L"");
}
StringCchCat(nid.szTip,COUNTOF(nid.szTip),tchTitle);
Shell_NotifyIcon(NIM_MODIFY,&nid);
}
//=============================================================================
//
// UpdateMouseDWellTime()
//
void UpdateMouseDWellTime()
{
if (Settings.ShowHypLnkToolTip || IsColorDefHotspotEnabled() || Settings.HighlightUnicodePoints)
SciCall_SetMouseDWellTime(100);
else
Sci_DisableMouseDWellNotification();
}
//=============================================================================
//
// ShowZoomCallTip()
//
void ShowZoomCallTip()
{
int const delayClr = Settings2.ZoomTooltipTimeout;
if (delayClr >= (10*USER_TIMER_MINIMUM)) {
int const iZoomLevelPercent = SciCall_GetZoom();
char chToolTip[32] = { '\0' };
StringCchPrintfA(chToolTip, COUNTOF(chToolTip), "Zoom: %i%%", iZoomLevelPercent);
DocPos const iPos = SciCall_PositionFromLine(SciCall_GetFirstVisibleLine());
int const iXOff = SciCall_GetXOffset();
SciCall_SetXOffset(0);
SciCall_CallTipShow(iPos, chToolTip);
SciCall_SetXOffset(iXOff);
Globals.CallTipType = CT_ZOOM;
_DelayClearZoomCallTip(delayClr);
}
else {
CancelCallTip();
}
}
//=============================================================================
//
// CancelCallTip()
//
void CancelCallTip()
{
SciCall_CallTipCancel();
Globals.CallTipType = CT_NONE;
}
//=============================================================================
//
// TerminateFileWatching()
//
static void TerminateFileWatching()
{
if (s_bRunningWatch)
{
KillTimer(NULL, ID_WATCHTIMER);
if (s_hChangeHandle) {
FindCloseChangeNotification(s_hChangeHandle);
s_hChangeHandle = NULL;
}
s_bRunningWatch = false;
s_dwChangeNotifyTime = 0UL; // reset
}
}
//=============================================================================
//
// InstallFileWatching()
//
void InstallFileWatching(LPCWSTR lpszFile)
{
// Terminate
if (StrIsEmpty(lpszFile) || (FileWatching.FileWatchingMode == FWM_DONT_CARE))
{
TerminateFileWatching();
}
else // Install
{
// Terminate previous watching
TerminateFileWatching();
WCHAR tchDirectory[MAX_PATH] = { L'\0' };
StringCchCopy(tchDirectory,COUNTOF(tchDirectory),lpszFile);
PathCchRemoveFileSpec(tchDirectory, COUNTOF(tchDirectory));
// Save data of current file
HANDLE hFind = FindFirstFile(Globals.CurrentFile, &s_fdCurFile);
if (hFind != INVALID_HANDLE_VALUE) {
FindClose(hFind);
}
else {
ZeroMemory(&s_fdCurFile, sizeof(WIN32_FIND_DATA));
}
s_hChangeHandle = FindFirstChangeNotification(
tchDirectory,false,
FILE_NOTIFY_CHANGE_FILE_NAME | \
FILE_NOTIFY_CHANGE_DIR_NAME | \
FILE_NOTIFY_CHANGE_ATTRIBUTES | \
FILE_NOTIFY_CHANGE_SIZE | \
FILE_NOTIFY_CHANGE_LAST_WRITE);
// No previous watching installed, so launch the timer first
if (!s_bRunningWatch) {
SetTimer(NULL, ID_WATCHTIMER,
min_dw(FileWatching.FileCheckInverval, FileWatching.AutoReloadTimeout),
WatchTimerProc);
s_bRunningWatch = true;
}
s_dwChangeNotifyTime = GetTickCount(); // init
}
UpdateToolbar();
}
static inline bool CurrentFileChanged()
{
if (StrIsEmpty(Globals.CurrentFile)) { return false; }
// Check if the file has been changed
WIN32_FIND_DATA fdUpdated;
ZeroMemory(&fdUpdated, sizeof(WIN32_FIND_DATA));
//~HANDLE const hFind = FindFirstFile(Globals.CurrentFile, &fdUpdated);
//~if (hFind != INVALID_HANDLE_VALUE)
//~ FindClose(hFind);
//~else
//~ return true;
if (!GetFileAttributesEx(Globals.CurrentFile, GetFileExInfoStandard, &fdUpdated)) {
return true; // The current file has been removed
}
bool const changed = (s_fdCurFile.nFileSizeLow != fdUpdated.nFileSizeLow)
|| (s_fdCurFile.nFileSizeHigh != fdUpdated.nFileSizeHigh)
//|| (CompareFileTime(&s_fdCurFile.ftLastWriteTime, &fdUpdated.ftLastWriteTime) != 0)
|| (s_fdCurFile.ftLastWriteTime.dwLowDateTime != fdUpdated.ftLastWriteTime.dwLowDateTime)
|| (s_fdCurFile.ftLastWriteTime.dwHighDateTime != fdUpdated.ftLastWriteTime.dwHighDateTime);
return changed;
}
//=============================================================================
//
// WatchTimerProc()
//
//
void CALLBACK WatchTimerProc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime)
{
UNUSED(dwTime);
UNUSED(idEvent);
UNUSED(uMsg);
UNUSED(hwnd);
if (s_bRunningWatch)
{
switch (FileWatching.FileWatchingMode)
{
case FWM_AUTORELOAD:
if (((GetTickCount() - s_dwChangeNotifyTime) > FileWatching.AutoReloadTimeout)
&& //|| // TODO: OR for read only auto reload without save requester
CurrentFileChanged())
{
TerminateFileWatching();
PostMessage(Globals.hwndMain, WM_CHANGENOTIFY, 0, 0);
}
break;
case FWM_MSGBOX:
{
if (s_hChangeHandle)
{
while (WaitForSingleObject(s_hChangeHandle, 0) == WAIT_OBJECT_0) {
// Check if the changes affect the current file
if (CurrentFileChanged()) {
// Shutdown current watching and give control to main window
TerminateFileWatching();
PostMessage(Globals.hwndMain, WM_CHANGENOTIFY, 0, 0);
break; // while
}
FindNextChangeNotification(s_hChangeHandle);
}
}
}
break;
case FWM_DONT_CARE:
default:
break;
}
}
}
//=============================================================================
//
// PasteBoardTimer()
//
void CALLBACK PasteBoardTimer(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime)
{
if ((s_dwLastCopyTime > 0) && ((GetTickCount() - s_dwLastCopyTime) > 200)) {
if (SciCall_CanPaste()) {
bool bAutoIndent2 = Settings.AutoIndent;
Settings.AutoIndent = 0;
EditJumpTo(-1,0);
_BEGIN_UNDO_ACTION_;
if (!Sci_IsDocEmpty()) {
SciCall_NewLine();
}
SciCall_Paste();
SciCall_NewLine();
_END_UNDO_ACTION_;
EditEnsureSelectionVisible();
Settings.AutoIndent = bAutoIndent2;
}
s_dwLastCopyTime = 0;
}
UNUSED(dwTime);
UNUSED(idEvent);
UNUSED(uMsg);
UNUSED(hwnd);
}
//=============================================================================
//
// CloseNonModalDialogs()
//
void CloseNonModalDialogs()
{
if (IsWindow(Globals.hwndDlgFindReplace)) {
SendMessage(Globals.hwndDlgFindReplace, WM_CLOSE, 0, 0);
}
if (IsWindow(Globals.hwndDlgCustomizeSchemes)) {
SendMessage(Globals.hwndDlgCustomizeSchemes, WM_CLOSE, 0, 0);
}
}
//=============================================================================
//
// CloseApplication()
//
void CloseApplication()
{
CloseNonModalDialogs();
PostMessage(Globals.hwndMain, WM_CLOSE, 0, 0);
}
/// End of Notepad3.c ///