Don Ho b3f11896eb [RELEASE] Notepad++ v5.6.7 release.
[CHANGE_BEHAVIOUR] Enlarge regconition of clickable link from "http://" to any URI.

git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository/trunk@617 f5eea248-9336-0410-98b8-ebc06183d4e3
2010-02-21 18:17:54 +00:00

520 lines
14 KiB
C++

//this file is part of notepad++
//Copyright (C)2003 Don HO ( donho@altern.org )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "precompiledHeaders.h"
WcharMbcsConvertor * WcharMbcsConvertor::_pSelf = new WcharMbcsConvertor;
void systemMessage(const TCHAR *title)
{
LPVOID lpMsgBuf;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
::GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );// Process any inserts in lpMsgBuf.
MessageBox( NULL, (LPTSTR)lpMsgBuf, title, MB_OK | MB_ICONSTOP);
::LocalFree(lpMsgBuf);
}
void printInt(int int2print)
{
TCHAR str[32];
wsprintf(str, TEXT("%d"), int2print);
::MessageBox(NULL, str, TEXT(""), MB_OK);
};
void printStr(const TCHAR *str2print)
{
::MessageBox(NULL, str2print, TEXT(""), MB_OK);
};
void writeLog(const TCHAR *logFileName, const char *log2write)
{
FILE *f = generic_fopen(logFileName, TEXT("a+"));
fwrite(log2write, sizeof(log2write[0]), strlen(log2write), f);
fputc('\n', f);
fflush(f);
fclose(f);
}
// Set a call back with the handle after init to set the path.
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/callbackfunctions/browsecallbackproc.asp
static int __stdcall BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM, LPARAM pData)
{
if (uMsg == BFFM_INITIALIZED)
::SendMessage(hwnd, BFFM_SETSELECTION, TRUE, pData);
return 0;
};
void folderBrowser(HWND parent, int outputCtrlID, const TCHAR *defaultStr)
{
// This code was copied and slightly modifed from:
// http://www.bcbdev.com/faqs/faq62.htm
// SHBrowseForFolder returns a PIDL. The memory for the PIDL is
// allocated by the shell. Eventually, we will need to free this
// memory, so we need to get a pointer to the shell malloc COM
// object that will free the PIDL later on.
LPMALLOC pShellMalloc = 0;
if (::SHGetMalloc(&pShellMalloc) == NO_ERROR)
{
// If we were able to get the shell malloc object,
// then proceed by initializing the BROWSEINFO stuct
BROWSEINFO info;
memset(&info, 0, sizeof(info));
info.hwndOwner = parent;
info.pidlRoot = NULL;
TCHAR szDisplayName[MAX_PATH];
info.pszDisplayName = szDisplayName;
info.lpszTitle = TEXT("Select a folder to search from");
info.ulFlags = 0;
info.lpfn = BrowseCallbackProc;
TCHAR directory[MAX_PATH];
::GetDlgItemText(parent, outputCtrlID, directory, sizeof(directory));
if (!directory[0] && defaultStr)
info.lParam = reinterpret_cast<LPARAM>(defaultStr);
else
info.lParam = reinterpret_cast<LPARAM>(directory);
// Execute the browsing dialog.
LPITEMIDLIST pidl = ::SHBrowseForFolder(&info);
// pidl will be null if they cancel the browse dialog.
// pidl will be not null when they select a folder.
if (pidl)
{
// Try to convert the pidl to a display generic_string.
// Return is true if success.
TCHAR szDir[MAX_PATH];
if (::SHGetPathFromIDList(pidl, szDir))
// Set edit control to the directory path.
::SetDlgItemText(parent, outputCtrlID, szDir);
pShellMalloc->Free(pidl);
}
pShellMalloc->Release();
}
}
void ClientRectToScreenRect(HWND hWnd, RECT* rect)
{
POINT pt;
pt.x = rect->left;
pt.y = rect->top;
::ClientToScreen( hWnd, &pt );
rect->left = pt.x;
rect->top = pt.y;
pt.x = rect->right;
pt.y = rect->bottom;
::ClientToScreen( hWnd, &pt );
rect->right = pt.x;
rect->bottom = pt.y;
};
std::vector<generic_string> tokenizeString(const generic_string & tokenString, const char delim) {
//Vector is created on stack and copied on return
std::vector<generic_string> tokens;
// Skip delimiters at beginning.
generic_string::size_type lastPos = tokenString.find_first_not_of(delim, 0);
// Find first "non-delimiter".
generic_string::size_type pos = tokenString.find_first_of(delim, lastPos);
while (pos != std::string::npos || lastPos != std::string::npos)
{
// Found a token, add it to the vector.
tokens.push_back(tokenString.substr(lastPos, pos - lastPos));
// Skip delimiters. Note the "not_of"
lastPos = tokenString.find_first_not_of(delim, pos);
// Find next "non-delimiter"
pos = tokenString.find_first_of(delim, lastPos);
}
return tokens;
}
void ScreenRectToClientRect(HWND hWnd, RECT* rect)
{
POINT pt;
pt.x = rect->left;
pt.y = rect->top;
::ScreenToClient( hWnd, &pt );
rect->left = pt.x;
rect->top = pt.y;
pt.x = rect->right;
pt.y = rect->bottom;
::ScreenToClient( hWnd, &pt );
rect->right = pt.x;
rect->bottom = pt.y;
};
int filter(unsigned int code, struct _EXCEPTION_POINTERS *)
{
if (code == EXCEPTION_ACCESS_VIOLATION)
return EXCEPTION_EXECUTE_HANDLER;
return EXCEPTION_CONTINUE_SEARCH;
}
bool isInList(const TCHAR *token, const TCHAR *list) {
if ((!token) || (!list))
return false;
TCHAR word[64];
int i = 0;
int j = 0;
for (; i <= int(lstrlen(list)) ; i++)
{
if ((list[i] == ' ')||(list[i] == '\0'))
{
if (j != 0)
{
word[j] = '\0';
j = 0;
if (!generic_stricmp(token, word))
return true;
}
}
else
{
word[j] = list[i];
j++;
}
}
return false;
}
generic_string purgeMenuItemString(const TCHAR * menuItemStr, bool keepAmpersand)
{
TCHAR cleanedName[64] = TEXT("");
size_t j = 0;
size_t menuNameLen = lstrlen(menuItemStr);
for(size_t k = 0 ; k < menuNameLen ; k++)
{
if (menuItemStr[k] == '\t')
{
cleanedName[k] = 0;
break;
}
else if (menuItemStr[k] == '&')
{
if (keepAmpersand)
cleanedName[j++] = menuItemStr[k];
//else skip
}
else
{
cleanedName[j++] = menuItemStr[k];
}
}
cleanedName[j] = 0;
return cleanedName;
};
const wchar_t * WcharMbcsConvertor::char2wchar(const char * mbcs2Convert, UINT codepage)
{
if (!_wideCharStr)
{
_wideCharStr = new wchar_t[initSize];
_wideCharAllocLen = initSize;
}
int len = MultiByteToWideChar(codepage, 0, mbcs2Convert, -1, _wideCharStr, 0);
if (len > 0)
{
if ((size_t)len > _wideCharAllocLen)
{
delete [] _wideCharStr;
_wideCharAllocLen = len;
_wideCharStr = new wchar_t[_wideCharAllocLen];
}
MultiByteToWideChar(codepage, 0, mbcs2Convert, -1, _wideCharStr, len);
}
else
_wideCharStr[0] = 0;
return _wideCharStr;
}
// "mstart" and "mend" are pointers to indexes in mbcs2Convert,
// which are converted to the corresponding indexes in the returned wchar_t string.
const wchar_t * WcharMbcsConvertor::char2wchar(const char * mbcs2Convert, UINT codepage, int *mstart, int *mend)
{
if (!_wideCharStr)
{
_wideCharStr = new wchar_t[initSize];
_wideCharAllocLen = initSize;
}
int len = MultiByteToWideChar(codepage, 0, mbcs2Convert, -1, _wideCharStr, 0);
if (len > 0)
{
if (len > int(_wideCharAllocLen))
{
delete [] _wideCharStr;
_wideCharAllocLen = len;
_wideCharStr = new wchar_t[_wideCharAllocLen];
}
len = MultiByteToWideChar(codepage, 0, mbcs2Convert, -1, _wideCharStr, len);
if ((size_t)*mstart < strlen(mbcs2Convert) && (size_t)*mend < strlen(mbcs2Convert))
{
*mstart = MultiByteToWideChar(codepage, 0, mbcs2Convert, *mstart, _wideCharStr, 0);
*mend = MultiByteToWideChar(codepage, 0, mbcs2Convert, *mend, _wideCharStr, 0);
if (*mstart >= len || *mend >= len)
{
*mstart = 0;
*mend = 0;
}
}
else
{
*mstart = 0;
*mend = 0;
}
}
else
{
_wideCharStr[0] = 0;
*mstart = 0;
*mend = 0;
}
return _wideCharStr;
}
const char * WcharMbcsConvertor::wchar2char(const wchar_t * wcharStr2Convert, UINT codepage)
{
if (!_multiByteStr)
{
_multiByteStr = new char[initSize];
_multiByteAllocLen = initSize;
}
int len = WideCharToMultiByte(codepage, 0, wcharStr2Convert, -1, _multiByteStr, 0, NULL, NULL);
if (len > 0)
{
if ((size_t)len > _multiByteAllocLen)
{
delete [] _multiByteStr;
_multiByteAllocLen = len;
_multiByteStr = new char[_multiByteAllocLen];
}
WideCharToMultiByte(codepage, 0, wcharStr2Convert, -1, _multiByteStr, len, NULL, NULL);
}
else
_multiByteStr[0] = 0;
return _multiByteStr;
}
const char * WcharMbcsConvertor::wchar2char(const wchar_t * wcharStr2Convert, UINT codepage, long *mstart, long *mend)
{
if (!_multiByteStr)
{
_multiByteStr = new char[initSize];
_multiByteAllocLen = initSize;
}
int len = WideCharToMultiByte(codepage, 0, wcharStr2Convert, -1, _multiByteStr, 0, NULL, NULL);
if (len > 0)
{
if ((size_t)len > _multiByteAllocLen)
{
delete [] _multiByteStr;
_multiByteAllocLen = len;
_multiByteStr = new char[_multiByteAllocLen];
}
len = WideCharToMultiByte(codepage, 0, wcharStr2Convert, -1, _multiByteStr, len, NULL, NULL); // not needed?
if ((int)*mstart < lstrlenW(wcharStr2Convert) && (int)*mend < lstrlenW(wcharStr2Convert))
{
*mstart = WideCharToMultiByte(codepage, 0, wcharStr2Convert, *mstart, _multiByteStr, 0, NULL, NULL);
*mend = WideCharToMultiByte(codepage, 0, wcharStr2Convert, *mend, _multiByteStr, 0, NULL, NULL);
if (*mstart >= len || *mend >= len)
{
*mstart = 0;
*mend = 0;
}
}
else
{
*mstart = 0;
*mend = 0;
}
}
else
_multiByteStr[0] = 0;
return _multiByteStr;
}
std::wstring string2wstring(const std::string & rString, UINT codepage)
{
int len = MultiByteToWideChar(codepage, 0, rString.c_str(), -1, NULL, 0);
if(len > 0)
{
std::vector<wchar_t> vw(len);
MultiByteToWideChar(codepage, 0, rString.c_str(), -1, &vw[0], len);
return &vw[0];
}
else
return L"";
}
std::string wstring2string(const std::wstring & rwString, UINT codepage)
{
int len = WideCharToMultiByte(codepage, 0, rwString.c_str(), -1, NULL, 0, NULL, NULL);
if(len > 0)
{
std::vector<char> vw(len);
WideCharToMultiByte(codepage, 0, rwString.c_str(), -1, &vw[0], len, NULL, NULL);
return &vw[0];
}
else
return "";
}
static TCHAR* convertFileName(TCHAR *buffer, const TCHAR *filename)
{
TCHAR *b = buffer;
const TCHAR *p = filename;
while (*p)
{
if (*p == '&') *b++ = '&';
*b++ = *p++;
}
*b = 0;
return buffer;
}
TCHAR *BuildMenuFileName(TCHAR *buffer, int len, int pos, const TCHAR *filename)
{
TCHAR cwd[MAX_PATH];
buffer[0] = 0;
GetCurrentDirectory(_countof(cwd), cwd);
lstrcat(cwd, TEXT("\\"));
TCHAR *itr = buffer;
TCHAR *end = buffer + len - 1;
if (pos < 9)
{
*itr++ = '&';
*itr++ = '1' + (TCHAR)pos;
}
else if (pos == 9)
{
*itr++ = '1';
*itr++ = '&';
*itr++ = '0';
}
else
{
wsprintf(itr, TEXT("%d"), pos+1);
itr = itr + lstrlen(itr);
}
*itr++ = ':';
*itr++ = ' ';
if (0 == generic_strnicmp(filename, cwd, lstrlen(cwd)))
{
TCHAR cnvName[MAX_PATH];
const TCHAR *s1 = PathFindFileName(filename);
int len = lstrlen(s1);
if (len < (end-itr))
{
lstrcpy(cnvName, s1);
}
else
{
int n = (len-3-(itr-buffer))/2;
generic_strncpy(cnvName, s1, n);
lstrcpy(cnvName+n, TEXT("..."));
lstrcat(cnvName, s1 + lstrlen(s1) - n);
}
convertFileName(itr, cnvName);
}
else
{
TCHAR cnvName[MAX_PATH*2];
convertFileName(cnvName, filename);
PathCompactPathEx(itr, filename, len - (itr-buffer), 0);
}
return buffer;
}
generic_string PathRemoveFileSpec(generic_string & path)
{
generic_string::size_type lastBackslash = path.find_last_of(TEXT('\\'));
if (lastBackslash == generic_string::npos)
{
if (path.size() >= 2 && path[1] == TEXT(':')) // "C:foo.bar" becomes "C:"
path.erase(2);
else
path.erase();
}
else
{
if (lastBackslash == 2 && path[1] == TEXT(':') && path.size() >= 3) // "C:\foo.exe" becomes "C:\"
path.erase(3);
else if (lastBackslash == 0 && path.size() > 1) // "\foo.exe" becomes "\"
path.erase(1);
else
path.erase(lastBackslash);
}
return path;
}
generic_string PathAppend(generic_string &strDest, const generic_string str2append)
{
if (strDest == TEXT("") && str2append == TEXT("")) // "" + ""
{
strDest = TEXT("\\");
return strDest;
}
if (strDest == TEXT("") && str2append != TEXT("")) // "" + titi
{
strDest = str2append;
return strDest;
}
if (strDest[strDest.length() - 1] == '\\' && (str2append != TEXT("") && str2append[0] == '\\')) // toto\ + \titi
{
strDest.erase(strDest.length() - 1, 1);
strDest += str2append;
return strDest;
}
if ((strDest[strDest.length() - 1] == '\\' && (str2append != TEXT("") && str2append[0] != '\\')) // toto\ + titi
|| (strDest[strDest.length() - 1] != '\\' && (str2append != TEXT("") && str2append[0] == '\\'))) // toto + \titi
{
strDest += str2append;
return strDest;
}
// toto + titi
strDest += TEXT("\\");
strDest += str2append;
return strDest;
}