mirror of
https://github.com/rizonesoft/Notepad3.git
synced 2026-06-11 21:03:05 +08:00
11537 lines
371 KiB
C
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(¶ms->wchData)) {
|
|
WCHAR tchFile[MAX_PATH] = { L'\0' };
|
|
if (OpenFileDlg(Globals.hwndMain, tchFile, COUNTOF(tchFile), ¶ms->wchData))
|
|
bOpened = FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchFile);
|
|
}
|
|
else {
|
|
bOpened = FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, ¶ms->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(¶ms->wchData, 0) + 1, 31);
|
|
Style_SetLexerFromName(Globals.hwndEdit, ¶ms->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(¶ms->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(¶ms->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(¶ms->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(¶ms->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(¶ms->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(¶ms->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(¶ms->wchData,0)+1,cchTitleExcerpt+1,s_wchTitleExcerpt);
|
|
params->flagTitleExcerpt = 1;
|
|
}
|
|
else {
|
|
params->flagTitleExcerpt = 0;
|
|
}
|
|
|
|
params->flagMatchText = g_flagMatchText;
|
|
if (!IsFindPatternEmpty()) {
|
|
StringCchCopy(StrEnd(¶ms->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 ///
|