diff --git a/language/common_res.h b/language/common_res.h index 14079b0fd..8c1c05f89 100644 --- a/language/common_res.h +++ b/language/common_res.h @@ -665,34 +665,36 @@ #define IDM_EDIT_STREAMCOMMENT 40359 #define IDM_EDIT_URLENCODE 40360 #define IDM_EDIT_URLDECODE 40361 -#define IDM_EDIT_URL2PATH 40362 -#define IDM_EDIT_PATH2URL 40363 -#define IDM_EDIT_INVERTSLASH 40364 -#define IDM_EDIT_INVERTBACKSLASH 40365 -#define IDM_EDIT_ESCAPECCHARS 40366 -#define IDM_EDIT_UNESCAPECCHARS 40367 -#define IDM_EDIT_CHAR2HEX 40368 -#define IDM_EDIT_HEX2CHAR 40369 -#define IDM_EDIT_FINDMATCHINGBRACE 40370 -#define IDM_EDIT_SELTOMATCHINGBRACE 40371 -#define IDM_EDIT_FIND 40372 -#define IDM_EDIT_SAVEFIND 40373 -#define IDM_EDIT_FINDNEXT 40374 -#define IDM_EDIT_FINDPREV 40375 -#define IDM_EDIT_REPLACE 40376 -#define IDM_EDIT_REPLACENEXT 40377 -#define IDM_EDIT_GOTOLINE 40378 -#define IDM_EDIT_SELTONEXT 40379 -#define IDM_EDIT_SELTOPREV 40380 -#define IDM_EDIT_COMPLETEWORD 40381 -#define IDM_EDIT_JOINLN_NOSP 40382 -#define IDM_EDIT_REMOVEDUPLICATELINES 40383 -#define IDM_EDIT_REMOVEEMPTYLINES 40384 -#define IDM_EDIT_MERGEEMPTYLINES 40385 -#define IDM_EDIT_CLEAR_MARKER 40386 -#define IDM_EDIT_CUT_MARKED 40387 -#define IDM_EDIT_COPY_MARKED 40388 -#define IDM_EDIT_DELETE_MARKED 40389 +#define IDM_EDIT_BASE64ENCODE 40362 +#define IDM_EDIT_BASE64DECODE 40363 +#define IDM_EDIT_URL2PATH 40364 +#define IDM_EDIT_PATH2URL 40365 +#define IDM_EDIT_INVERTSLASH 40366 +#define IDM_EDIT_INVERTBACKSLASH 40367 +#define IDM_EDIT_ESCAPECCHARS 40368 +#define IDM_EDIT_UNESCAPECCHARS 40369 +#define IDM_EDIT_CHAR2HEX 40370 +#define IDM_EDIT_HEX2CHAR 40371 +#define IDM_EDIT_FINDMATCHINGBRACE 40372 +#define IDM_EDIT_SELTOMATCHINGBRACE 40373 +#define IDM_EDIT_FIND 40374 +#define IDM_EDIT_SAVEFIND 40375 +#define IDM_EDIT_FINDNEXT 40376 +#define IDM_EDIT_FINDPREV 40377 +#define IDM_EDIT_REPLACE 40378 +#define IDM_EDIT_REPLACENEXT 40379 +#define IDM_EDIT_GOTOLINE 40380 +#define IDM_EDIT_SELTONEXT 40381 +#define IDM_EDIT_SELTOPREV 40382 +#define IDM_EDIT_COMPLETEWORD 40383 +#define IDM_EDIT_JOINLN_NOSP 40384 +#define IDM_EDIT_REMOVEDUPLICATELINES 40385 +#define IDM_EDIT_REMOVEEMPTYLINES 40386 +#define IDM_EDIT_MERGEEMPTYLINES 40387 +#define IDM_EDIT_CLEAR_MARKER 40388 +#define IDM_EDIT_CUT_MARKED 40389 +#define IDM_EDIT_COPY_MARKED 40390 +#define IDM_EDIT_DELETE_MARKED 40391 #define IDM_VIEW_SCHEME 41000 #define IDM_VIEW_USE2NDDEFAULT 41001 diff --git a/language/np3_de_de/menu_de_de.rc b/language/np3_de_de/menu_de_de.rc index fa79b7366..701969e84 100644 --- a/language/np3_de_de/menu_de_de.rc +++ b/language/np3_de_de/menu_de_de.rc @@ -263,6 +263,9 @@ BEGIN MENUITEM "Mittels Tabulatoren einrücken\tCtrl+Alt+T", IDM_EDIT_CONVERTSPACES2 MENUITEM "Mittels Leerzeichen einrücken\tCtrl+Alt+S", IDM_EDIT_CONVERTTABS2 MENUITEM SEPARATOR + MENUITEM "Base&64 Codierung", IDM_EDIT_BASE64ENCODE + MENUITEM "Base6&4 Decodierung", IDM_EDIT_BASE64DECODE + MENUITEM SEPARATOR MENUITEM "&URL Codierung\tCtrl+Shift+E", IDM_EDIT_URLENCODE MENUITEM "URL Decodierung\tCtrl+Shift+R", IDM_EDIT_URLDECODE MENUITEM "Datei-System Pfad als URL", IDM_EDIT_PATH2URL diff --git a/language/np3_en_us/menu_en_us.rc b/language/np3_en_us/menu_en_us.rc index 90afa07e6..ba28b7cdb 100644 --- a/language/np3_en_us/menu_en_us.rc +++ b/language/np3_en_us/menu_en_us.rc @@ -263,6 +263,9 @@ BEGIN MENUITEM "Ta&bify Indent\tCtrl+Alt+T", IDM_EDIT_CONVERTSPACES2 MENUITEM "Untabi&fy Indent\tCtrl+Alt+S", IDM_EDIT_CONVERTTABS2 MENUITEM SEPARATOR + MENUITEM "Base&64 Encode", IDM_EDIT_BASE64ENCODE + MENUITEM "Base6&4 Decode", IDM_EDIT_BASE64DECODE + MENUITEM SEPARATOR MENUITEM "URL &Encode\tCtrl+Shift+E", IDM_EDIT_URLENCODE MENUITEM "URL &Decode\tCtrl+Shift+R", IDM_EDIT_URLDECODE MENUITEM "File System Path to URL", IDM_EDIT_PATH2URL diff --git a/scintilla/src/Editor.cxx b/scintilla/src/Editor.cxx index 921967961..94dbb6468 100644 --- a/scintilla/src/Editor.cxx +++ b/scintilla/src/Editor.cxx @@ -5722,26 +5722,21 @@ void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam vs.styles[wParam].back = ColourDesired(static_cast(lParam)); break; case SCI_STYLESETBOLD: - vs.fontsValid = false; vs.styles[wParam].weight = lParam != 0 ? SC_WEIGHT_BOLD : SC_WEIGHT_NORMAL; break; case SCI_STYLESETWEIGHT: - vs.fontsValid = false; vs.styles[wParam].weight = static_cast(lParam); break; case SCI_STYLESETITALIC: - vs.fontsValid = false; vs.styles[wParam].italic = lParam != 0; break; case SCI_STYLESETEOLFILLED: vs.styles[wParam].eolFilled = lParam != 0; break; case SCI_STYLESETSIZE: - vs.fontsValid = false; vs.styles[wParam].size = static_cast(lParam * SC_FONT_SIZE_MULTIPLIER); break; case SCI_STYLESETSIZEFRACTIONAL: - vs.fontsValid = false; vs.styles[wParam].size = static_cast(lParam); break; case SCI_STYLESETFONT: @@ -5762,7 +5757,6 @@ void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam vs.styles[wParam].caseForce = static_cast(lParam); break; case SCI_STYLESETCHARACTERSET: - vs.fontsValid = false; vs.styles[wParam].characterSet = static_cast(lParam); pdoc->SetCaseFolder(nullptr); break; @@ -6631,7 +6625,6 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETFONTQUALITY: vs.extraFontFlag &= ~SC_EFF_QUALITY_MASK; vs.extraFontFlag |= (wParam & SC_EFF_QUALITY_MASK); - vs.fontsValid = false; InvalidateStyleRedraw(); break; @@ -7262,7 +7255,6 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETFONTLOCALE: if (lParam) { vs.SetFontLocaleName(CharPtrFromSPtr(lParam)); - vs.fontsValid = false; InvalidateStyleRedraw(); } break; @@ -7812,7 +7804,6 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { // <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<< if (zoomLevel != vs.zoomLevel) { vs.zoomLevel = zoomLevel; - vs.fontsValid = false; InvalidateStyleRedraw(); NotifyZoom(); } diff --git a/scintilla/src/ViewStyle.cxx b/scintilla/src/ViewStyle.cxx index 548f1ce84..7d1bdcfa2 100644 --- a/scintilla/src/ViewStyle.cxx +++ b/scintilla/src/ViewStyle.cxx @@ -289,42 +289,33 @@ void ViewStyle::Init(size_t stylesSize_) { } void ViewStyle::Refresh(Surface &surface, int tabInChars) { - // >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>> - if (!fontsValid) { - - fontsValid = true; - fonts.clear(); - - // Apply the extra font flag which controls text drawing quality to each style. - for (Style &style : styles) { - style.extraFontFlag = extraFontFlag; - } - - // Create a FontRealised object for each unique font in the styles. - CreateAndAddFont(styles[STYLE_DEFAULT]); - for (const Style &style : styles) { - CreateAndAddFont(style); - } - - // Ask platform to allocate each unique font. - for (auto &font : fonts) { - font.second->Realise(surface, zoomLevel, technology, font.first, localeName.c_str()); - } - - // Set the platform font handle and measurements for each style. - for (Style &style : styles) { - const FontRealised *fr = Find(style); - style.Copy(fr->font, *fr); - } - - aveCharWidth = styles[STYLE_DEFAULT].aveCharWidth; - spaceWidth = styles[STYLE_DEFAULT].spaceWidth; - } - // <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<< + fonts.clear(); selbar = Platform::Chrome(); selbarlight = Platform::ChromeHighlight(); + // Apply the extra font flag which controls text drawing quality to each style. + for (Style &style : styles) { + style.extraFontFlag = extraFontFlag; + } + + // Create a FontRealised object for each unique font in the styles. + CreateAndAddFont(styles[STYLE_DEFAULT]); + for (const Style &style : styles) { + CreateAndAddFont(style); + } + + // Ask platform to allocate each unique font. + for (auto &font : fonts) { + font.second->Realise(surface, zoomLevel, technology, font.first, localeName.c_str()); + } + + // Set the platform font handle and measurements for each style. + for (Style &style : styles) { + const FontRealised *fr = Find(style); + style.Copy(fr->font, *fr); + } + indicatorsDynamic = std::any_of(indicators.cbegin(), indicators.cend(), [](const Indicator &indicator) noexcept { return indicator.IsDynamic(); }); @@ -383,7 +374,6 @@ void ViewStyle::EnsureStyle(size_t index) { } void ViewStyle::ResetDefaultStyle() { - fontsValid = false; styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0), ColourDesired(0xff,0xff,0xff), Platform::DefaultFontSize() * SC_FONT_SIZE_MULTIPLIER, fontNames.Save(Platform::DefaultFont()), @@ -392,7 +382,6 @@ void ViewStyle::ResetDefaultStyle() { } void ViewStyle::ClearStyles() { - fontsValid = false; // Reset all styles to be like the default style for (size_t i=0; i STYLE_DEFAULT) { diff --git a/scintilla/src/ViewStyle.h b/scintilla/src/ViewStyle.h index cc930870a..125f80b79 100644 --- a/scintilla/src/ViewStyle.h +++ b/scintilla/src/ViewStyle.h @@ -96,9 +96,6 @@ public: std::vector indicators; bool indicatorsDynamic; bool indicatorsSetFore; - // >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>> - bool fontsValid; - // <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<< int technology; int lineHeight; int lineOverlap; diff --git a/scintilla/win32/PlatWin.cxx b/scintilla/win32/PlatWin.cxx index 952548ff7..7668af348 100644 --- a/scintilla/win32/PlatWin.cxx +++ b/scintilla/win32/PlatWin.cxx @@ -242,6 +242,7 @@ constexpr BYTE Win32MapFontQuality(int extraFontFlag) noexcept { } #if defined(USE_D2D) + constexpr D2D1_TEXT_ANTIALIAS_MODE DWriteMapFontQuality(int extraFontFlag) noexcept { switch (extraFontFlag & SC_EFF_QUALITY_MASK) { @@ -259,13 +260,14 @@ constexpr D2D1_TEXT_ANTIALIAS_MODE DWriteMapFontQuality(int extraFontFlag) noexc } } // >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>> -bool GetDWriteFontProperties(const LOGFONTW& lf, std::wstring& wsFamily, +bool GetDWriteFontProperties(const LOGFONTW& lf, std::wstring& wsFamily, const std::wstring& wsLocale, DWRITE_FONT_WEIGHT& weight, DWRITE_FONT_STYLE& style, DWRITE_FONT_STRETCH& stretch) { bool success = false; if (gdiInterop) { IDWriteFont* font = nullptr; HRESULT hr = gdiInterop->CreateFontFromLOGFONT(&lf, &font); if (SUCCEEDED(hr)) { + weight = font->GetWeight(); style = font->GetStyle(); stretch = font->GetStretch(); @@ -278,29 +280,29 @@ bool GetDWriteFontProperties(const LOGFONTW& lf, std::wstring& wsFamily, if (SUCCEEDED(hr)) { UINT32 index = 0; BOOL exists = false; - names->FindLocaleName(L"en-US", &index, &exists); + names->FindLocaleName(wsLocale.c_str(), &index, &exists); + if (!exists) { + names->FindLocaleName(L"en-US", &index, &exists); // fallback en-US + } if (!exists) { index = 0; } - UINT32 length = 0; names->GetStringLength(index, &length); - wsFamily.resize(length + 1); names->GetString(index, wsFamily.data(), length + 1); ReleaseUnknown(names); - success = wsFamily[0] != L'\0'; + success = (wsFamily[0] != L'\0'); } - ReleaseUnknown(family); } - ReleaseUnknown(font); } } return success; } + // <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<< #endif @@ -323,7 +325,7 @@ void SetLogFont(LOGFONTW &lf, const char *faceName, int characterSet, XYPOSITION struct FontGDI : public FontWin { HFONT hfont = {}; FontGDI(const FontParameters &fp) { - LOGFONTW lf; + LOGFONTW lf = { 0 }; SetLogFont(lf, fp.faceName, fp.characterSet, fp.size, fp.weight, fp.italic, fp.extraFontFlag); hfont = ::CreateFontIndirectW(&lf); } @@ -366,9 +368,9 @@ struct FontDirectWrite : public FontWin { std::wstring wsFamily; DWRITE_FONT_WEIGHT weight = static_cast(fp.weight); DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL; - LOGFONTW lf; + LOGFONTW lf = { 0 }; SetLogFont(lf, fp.faceName, fp.characterSet, fp.size, fp.weight, fp.italic, fp.extraFontFlag); - if (!GetDWriteFontProperties(lf, wsFamily, weight, style, stretch)) { + if (!GetDWriteFontProperties(lf, wsFamily, wsLocale, weight, style, stretch)) { wsFamily = WStringFromUTF8(fp.faceName); } HRESULT hr = pIDWriteFactory->CreateTextFormat(wsFamily.c_str(), nullptr, diff --git a/scintilla/win32/ScintillaWin.cxx b/scintilla/win32/ScintillaWin.cxx index e2d6402c7..e6dd3babd 100644 --- a/scintilla/win32/ScintillaWin.cxx +++ b/scintilla/win32/ScintillaWin.cxx @@ -1933,7 +1933,6 @@ sptr_t ScintillaWin::SciMessage(unsigned int iMessage, uptr_t wParam, sptr_t lPa #endif technology = technologyNew; // Invalidate all cached information including layout. - vs.fontsValid = false; DropGraphics(); InvalidateStyleRedraw(); } @@ -2067,7 +2066,6 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam case WM_DPICHANGED: dpi = HIWORD(wParam); - vs.fontsValid = false; InvalidateStyleRedraw(); break; @@ -2075,7 +2073,6 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam const UINT dpiNow = DpiForWindow(wMain.GetID()); if (dpi != dpiNow) { dpi = dpiNow; - vs.fontsValid = false; InvalidateStyleRedraw(); } } diff --git a/src/Edit.c b/src/Edit.c index c075b7826..dae7f1827 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -1978,6 +1978,56 @@ void EditReplaceAllChr(const WCHAR chSearch, const WCHAR chReplace) { } +//============================================================================= +// +// EditBase64Code() +// +void EditBase64Code(HWND hwnd, const bool bEncode) { + + UNREFERENCED_PARAMETER(hwnd); + + if (SciCall_IsSelectionEmpty()) { + return; + } + if (Sci_IsMultiOrRectangleSelection()) { + InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECTORMULTI); + return; + } + + _SAVE_TARGET_RANGE_; + + DocPos const iSelStart = SciCall_GetSelectionStart(); + //DocPos const iSelEnd = SciCall_GetSelectionEnd(); + size_t const iSelSize = SciCall_GetSelText(NULL) - 1; // w/o terminating zero + bool const bStraightSel = (SciCall_GetAnchor() <= SciCall_GetCurrentPos()); + + const unsigned char *pchText = (unsigned char *)SciCall_GetRangePointer(iSelStart, (DocPos)iSelSize); + + size_t coded_size = 0; + char *const pBase64CodedTxt = (char *)(bEncode ? Encoding_Base64Encode(pchText, iSelSize, &coded_size) : + Encoding_Base64Decode(pchText, iSelSize, &coded_size)); + + UndoTransActionBegin(); + + SciCall_TargetFromSelection(); + DocPos const len = SciCall_ReplaceTarget((DocPos)coded_size, pBase64CodedTxt); + + SciCall_SetSelectionStart(iSelStart); + SciCall_SetSelectionEnd(iSelStart + len); + if (!bStraightSel) { + SciCall_SwapMainAnchorCaret(); + } + EditScrollSelectionToView(); + + EndUndoTransAction(); + + _RESTORE_TARGET_RANGE_; + + FreeMem(pBase64CodedTxt); +} + + + //============================================================================= // // EditEscapeCChars() diff --git a/src/Edit.h b/src/Edit.h index ba08b262c..782d4f096 100644 --- a/src/Edit.h +++ b/src/Edit.h @@ -48,6 +48,7 @@ void EditSentenceCase(HWND hwnd); void EditURLEncode(const bool isPathConvert); void EditURLDecode(const bool isPathConvert); void EditReplaceAllChr(const WCHAR chSearch, const WCHAR chReplace); +void EditBase64Code(HWND hwnd, const bool bEncode); void EditEscapeCChars(HWND hwnd); void EditUnescapeCChars(HWND hwnd); void EditChar2Hex(HWND hwnd); diff --git a/src/Encoding.c b/src/Encoding.c index 761f7c72b..f2f2ebfb7 100644 --- a/src/Encoding.c +++ b/src/Encoding.c @@ -980,6 +980,132 @@ bool IsValidUTF8(const char* pTest, size_t nLength) // ============================================================================ +// ---------------------------------------------------------------------------- +// https://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c +// ---------------------------------------------------------------------------- + + /** + * Base64 encoding/decoding (RFC1341) + * Copyright (c) 2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * base64_encode - Base64 encode + * @src: Data to be encoded + * @len: Length of the data to be encoded + * @out_len: Pointer to output length variable, or %NULL if not used + * Returns: Allocated buffer of out_len bytes of encoded data, + * or %NULL on failure + * + * Caller is responsible for freeing the returned buffer. Returned buffer is + * nul terminated to make it easier to use as a C string. The nul terminator is + * not included in out_len. + */ + +static const unsigned char _Base64Table[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +unsigned char * Encoding_Base64Encode(const unsigned char *src, size_t len, size_t *out_len) { + + unsigned char *out, *pos; + const unsigned char *end, *in; + size_t olen; + + olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */ + olen++; /* nul termination */ + if (olen < len) { + return NULL; /* integer overflow */ + } + out = AllocMem(olen, HEAP_ZERO_MEMORY); + if (!out) { + return NULL; + } + + end = src + len; + in = src; + pos = out; + while (end - in >= 3) { + *pos++ = _Base64Table[in[0] >> 2]; + *pos++ = _Base64Table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; + *pos++ = _Base64Table[((in[1] & 0x0F) << 2) | (in[2] >> 6)]; + *pos++ = _Base64Table[in[2] & 0x3F]; + in += 3; + } + + if (end - in) { + *pos++ = _Base64Table[in[0] >> 2]; + if (end - in == 1) { + *pos++ = _Base64Table[(in[0] & 0x03) << 4]; + *pos++ = '='; + } else { + *pos++ = _Base64Table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; + *pos++ = _Base64Table[(in[1] & 0x0F) << 2]; + } + *pos++ = '='; + } + *pos = '\0'; + if (out_len) { + *out_len = pos - out; + } + return out; +} + + +// ---------------------------------------------------------------------------- +// https://stackoverflow.com/questions/180947/base64-decode-snippet-in-c/13935718 +// ---------------------------------------------------------------------------- +// Decoder by Polfosol +// ---------------------------------------------------------------------------- + +static const unsigned char _Base64Index[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 63, + 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; + + +unsigned char * Encoding_Base64Decode(const unsigned char *src, const size_t len, size_t *out_len) { + + const unsigned char *p = src; + int const pad = len > 0 && (len % 4 || p[len - 1] == '='); + + size_t const L = ((len + 3) / 4 - pad) * 4; + size_t const olen = L / 4 * 3 + pad; + + unsigned char * out = AllocMem(olen, HEAP_ZERO_MEMORY); + if (!out) { + return NULL; + } + + size_t j = 0; + for (size_t i = 0; i < L; i += 4) { + unsigned const n = _Base64Index[p[i]] << 18 | + _Base64Index[p[i + 1]] << 12 | + _Base64Index[p[i + 2]] << 6 | + _Base64Index[p[i + 3]]; + out[j++] = (unsigned char)(n >> 16); + out[j++] = (unsigned char)(n >> 8 & 0xFF); + out[j++] = (unsigned char)(n & 0xFF); + } + if (pad) { + unsigned n = _Base64Index[p[L]] << 18 | _Base64Index[p[L + 1]] << 12; + out[j++] = (unsigned char)(n >> 16); + if (len > L + 2 && p[L + 2] != '=') { + n |= _Base64Index[p[L + 2]] << 6; + out[j++] = (unsigned char)(n >> 8 & 0xFF); + } + } + if (out_len) { + *out_len = j; + } + return out; +} + +// ============================================================================ + diff --git a/src/Encoding.h b/src/Encoding.h index a8919926b..d5754c166 100644 --- a/src/Encoding.h +++ b/src/Encoding.h @@ -208,6 +208,11 @@ ENC_DET_T Encoding_DetectEncoding(LPWSTR pszFile, const char* lpData, const size const WCHAR* Encoding_GetTitleInfo(); //const char* Encoding_GetTitleInfoA(); +// ---------------------------------------------------------------------------- + +unsigned char * Encoding_Base64Encode(const unsigned char *src, const size_t len, size_t *out_len); +unsigned char * Encoding_Base64Decode(const unsigned char *src, const size_t len, size_t *out_len); + // -------------------------------------------------------------------------------------------------------------------------------- #endif //_NP3_ENCODING_H_ diff --git a/src/Notepad3.c b/src/Notepad3.c index 1e90c96a8..d6812f59c 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -3624,6 +3624,8 @@ LRESULT MsgInitMenu(HWND hwnd, WPARAM wParam, LPARAM lParam) EnableCmd(hmenu, IDM_EDIT_URLENCODE, !se && !ro); EnableCmd(hmenu, IDM_EDIT_URLDECODE, !se && !ro); + EnableCmd(hmenu, IDM_EDIT_BASE64ENCODE, !se && !ro); + EnableCmd(hmenu, IDM_EDIT_BASE64DECODE, !se && !ro); EnableCmd(hmenu, IDM_EDIT_PATH2URL, !se && !ro); EnableCmd(hmenu, IDM_EDIT_URL2PATH, !se && !ro); EnableCmd(hmenu, IDM_EDIT_INVERTBACKSLASH, !se && !ro); @@ -4272,6 +4274,7 @@ LRESULT MsgCommand(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) } BeginWaitCursorUID(true, IDS_MUI_SB_RECODING_DOC); if (EditSetNewEncoding(Globals.hwndEdit, iNewEncoding, (s_flagSetEncoding != CPI_NONE))) { + UpdateMarginWidth(true); SetSaveNeeded(); } EndWaitCursor(); @@ -4882,6 +4885,16 @@ LRESULT MsgCommand(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) } break; + case IDM_EDIT_BASE64ENCODE: { + EditBase64Code(Globals.hwndEdit, true); + } + break; + + case IDM_EDIT_BASE64DECODE: { + EditBase64Code(Globals.hwndEdit, false); + } break; + + case IDM_EDIT_URL2PATH: { EditURLEncode(true); }